forked from upstream-mirrors/OpenTracks
Replace long time_ms with Instant and Duration, respectively.
Fixes #561.
This commit is contained in:
+12
-9
@@ -25,6 +25,9 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
@@ -40,7 +43,7 @@ import static org.junit.Assert.assertEquals;
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DescriptionGeneratorTest {
|
||||
|
||||
private static final long START_TIME = 1288721514000L;
|
||||
private static final Instant START_TIME = Instant.ofEpochMilli(1288721514000L);
|
||||
private DescriptionGenerator descriptionGenerator;
|
||||
|
||||
private final Context context = ApplicationProvider.getApplicationContext();
|
||||
@@ -58,14 +61,14 @@ public class DescriptionGeneratorTest {
|
||||
Track track = new Track();
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setTotalDistance(20000);
|
||||
stats.setTotalTime(600000);
|
||||
stats.setMovingTime(300000);
|
||||
stats.setTotalTime(Duration.ofMillis(600000));
|
||||
stats.setMovingTime(Duration.ofMillis(300000));
|
||||
stats.setMaxSpeed(100);
|
||||
stats.setMaxElevation(550);
|
||||
stats.setMinElevation(-500);
|
||||
stats.setTotalElevationGain(6000f);
|
||||
stats.setTotalElevationLoss(6000);
|
||||
stats.setStartTime_ms(START_TIME);
|
||||
stats.setStartTime(START_TIME);
|
||||
track.setTrackStatistics(stats);
|
||||
track.setCategory("hiking");
|
||||
String expected = //"Created by"
|
||||
@@ -96,14 +99,14 @@ public class DescriptionGeneratorTest {
|
||||
Track track = new Track();
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setTotalDistance(20000);
|
||||
stats.setTotalTime(600000);
|
||||
stats.setMovingTime(300000);
|
||||
stats.setTotalTime(Duration.ofMillis(600000));
|
||||
stats.setMovingTime(Duration.ofMillis(300000));
|
||||
stats.setMaxSpeed(100);
|
||||
stats.setMaxElevation(Double.POSITIVE_INFINITY);
|
||||
stats.setMinElevation(Double.NEGATIVE_INFINITY);
|
||||
stats.setTotalElevationGain(6000f);
|
||||
stats.setTotalElevationLoss(6000);
|
||||
stats.setStartTime_ms(START_TIME);
|
||||
stats.setStartTime(START_TIME);
|
||||
track.setTrackStatistics(stats);
|
||||
track.setCategory("hiking");
|
||||
String expected = //"Created by"
|
||||
@@ -139,12 +142,12 @@ public class DescriptionGeneratorTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link DescriptionGenerator#writeTime(long, StringBuilder, int, String)}.
|
||||
* Tests {@link DescriptionGenerator#writeTime(Duration, StringBuilder, int, String)}.
|
||||
*/
|
||||
@Test
|
||||
public void testWriteTime() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
descriptionGenerator.writeTime(1000, builder, R.string.description_total_time, "<br>");
|
||||
descriptionGenerator.writeTime(Duration.ofMillis(1000), builder, R.string.description_total_time, "<br>");
|
||||
assertEquals("Total time: 00:01<br>", builder.toString());
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.util.Pair;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -56,7 +57,7 @@ public class TestDataUtil {
|
||||
|
||||
int i = 0;
|
||||
List<TrackPoint> trackPoints = List.of(
|
||||
TrackPoint.createSegmentStartManualWithTime(i++ + 1),
|
||||
TrackPoint.createSegmentStartManualWithTime(Instant.ofEpochMilli(i++ + 1)),
|
||||
createTrackPoint(i++),
|
||||
createTrackPoint(i++),
|
||||
createTrackPoint(i++),
|
||||
@@ -64,13 +65,13 @@ public class TestDataUtil {
|
||||
createTrackPoint(i++),
|
||||
createTrackPoint(i++),
|
||||
createTrackPoint(i++),
|
||||
TrackPoint.createSegmentEndWithTime(i++ + 1),
|
||||
TrackPoint.createSegmentEndWithTime(Instant.ofEpochSecond(i++ + 1)),
|
||||
|
||||
TrackPoint.createSegmentStartManualWithTime(i++),
|
||||
TrackPoint.createSegmentStartManualWithTime(Instant.ofEpochSecond(i++)),
|
||||
createTrackPoint(i++),
|
||||
createTrackPoint(i++),
|
||||
createTrackPoint(i++),
|
||||
TrackPoint.createSegmentEndWithTime(i++ + 1)
|
||||
TrackPoint.createSegmentEndWithTime(Instant.ofEpochSecond(i++ + 1))
|
||||
);
|
||||
|
||||
List<Marker> markers = List.of(
|
||||
@@ -114,7 +115,7 @@ public class TestDataUtil {
|
||||
trackPoint.setLongitude(INITIAL_LONGITUDE - (double) i / 10000.0);
|
||||
trackPoint.setAccuracy((float) i / 100.0f);
|
||||
trackPoint.setAltitude(i * ALTITUDE_INTERVAL);
|
||||
trackPoint.setTime(i + 1);
|
||||
trackPoint.setTime(Instant.ofEpochSecond(i + 1));
|
||||
trackPoint.setSpeed(5f + (i / 10f));
|
||||
|
||||
trackPoint.setHeartRate_bpm(100f + i);
|
||||
|
||||
+7
-7
@@ -33,6 +33,8 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -423,14 +425,12 @@ public class CustomContentProviderUtilsTest {
|
||||
Track.Id trackId = new Track.Id(System.currentTimeMillis());
|
||||
Pair<Track, List<TrackPoint>> track = TestDataUtil.createTrack(trackId, 10);
|
||||
|
||||
// Bottom
|
||||
long startTime = 1000L;
|
||||
// AverageSpeed
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
statistics.setStartTime_ms(startTime);
|
||||
statistics.setStopTime_ms(2500L);
|
||||
statistics.setTotalTime(1500L);
|
||||
statistics.setMovingTime(700L);
|
||||
statistics.setStartTime(Instant.ofEpochMilli(1000));
|
||||
statistics.setStopTime(Instant.ofEpochMilli(2500));
|
||||
statistics.setTotalTime(Duration.ofMillis(1500));
|
||||
statistics.setMovingTime(Duration.ofMillis(700));
|
||||
statistics.setTotalDistance(750.0);
|
||||
statistics.setTotalElevationGain(50.0f);
|
||||
statistics.setMaxSpeed(60.0);
|
||||
@@ -809,7 +809,7 @@ public class CustomContentProviderUtilsTest {
|
||||
// then
|
||||
assertEquals(longitude, trackPoint.getLongitude(), 0.01);
|
||||
assertEquals(latitude, trackPoint.getLatitude(), 0.01);
|
||||
assertEquals(time, trackPoint.getTime(), 0.01);
|
||||
assertEquals(time, trackPoint.getTime().toEpochMilli());
|
||||
assertEquals(speed, trackPoint.getSpeed(), 0.01);
|
||||
assertFalse(trackPoint.hasHeartRate());
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.chart.ChartPoint;
|
||||
import de.dennisguse.opentracks.chart.ChartView;
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
@@ -61,7 +64,7 @@ public class ChartFragmentTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
boolean chartByDistance = false;
|
||||
chartFragment = (ChartFragment) ChartFragment.newInstance(chartByDistance);
|
||||
chartFragment = ChartFragment.newInstance(chartByDistance);
|
||||
chartFragment.setChartView(new ChartView(ApplicationProvider.getApplicationContext(), chartByDistance));
|
||||
}
|
||||
|
||||
@@ -193,18 +196,18 @@ public class ChartFragmentTest {
|
||||
// given
|
||||
chartFragment.setChartByDistance(false);
|
||||
TrackPoint trackPoint1 = TrackStubUtils.createDefaultTrackPoint();
|
||||
trackPoint1.setTime(TrackStubUtils.INITIAL_TIME); //Keep old TrackPoint behavior of having time=0 for this test
|
||||
trackPoint1.setTime(Instant.ofEpochMilli(TrackStubUtils.INITIAL_TIME)); //Keep old TrackPoint behavior of having time=0 for this test
|
||||
|
||||
// when
|
||||
ChartPoint point = chartFragment.createPendingPoint(trackPoint1);
|
||||
|
||||
// then
|
||||
assertEquals(0.0, point.getTimeOrDistance(), 0.01);
|
||||
long timeSpan = 222;
|
||||
Duration timeSpan = Duration.ofMillis(222);
|
||||
TrackPoint trackPoint2 = TrackStubUtils.createDefaultTrackPoint();
|
||||
trackPoint2.setTime(trackPoint1.getTime() + timeSpan);
|
||||
trackPoint2.setTime(Instant.ofEpochMilli(TrackStubUtils.INITIAL_TIME).plus(timeSpan));
|
||||
point = chartFragment.createPendingPoint(trackPoint2);
|
||||
assertEquals((double) timeSpan, point.getTimeOrDistance(), 0.01);
|
||||
assertEquals(timeSpan, Duration.ofMillis((long) point.getTimeOrDistance()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,7 +258,7 @@ public class ChartFragmentTest {
|
||||
/*
|
||||
* Add a time span here to make sure the second point is valid, the value 222 here is doesn't matter.
|
||||
*/
|
||||
trackPoint2.setTime(trackPoint1.getTime() + 222);
|
||||
trackPoint2.setTime(trackPoint1.getTime().plusMillis(222));
|
||||
trackPoint2.setSpeed(130f);
|
||||
point = chartFragment.createPendingPoint(trackPoint2);
|
||||
assertEquals(130.0 * UnitConversions.MPS_TO_KMH, point.getSpeed(), 0.01);
|
||||
@@ -280,7 +283,7 @@ public class ChartFragmentTest {
|
||||
* Add a time span here to make sure the second point and the speed is valid.
|
||||
* Speed is valid if: speedDifference > Constants.MAX_ACCELERATION * timeDifference speedDifference = 102 -100 timeDifference = 222
|
||||
*/
|
||||
trackPoint2.setTime(trackPoint2.getTime() + 222);
|
||||
trackPoint2.setTime(trackPoint2.getTime().plusMillis(222));
|
||||
trackPoint2.setSpeed(102f);
|
||||
point = chartFragment.createPendingPoint(trackPoint2);
|
||||
assertEquals(102.0 * UnitConversions.MPS_TO_KMH * UnitConversions.KM_TO_MI, point.getSpeed(), 0.01);
|
||||
@@ -305,7 +308,7 @@ public class ChartFragmentTest {
|
||||
* Add a time span here to make sure the second point and the speed is valid.
|
||||
* Speed is valid if: speedDifference > Constants.MAX_ACCELERATION * timeDifference speedDifference = 102 -100 timeDifference = 222
|
||||
*/
|
||||
trackPoint2.setTime(trackPoint2.getTime() + 222);
|
||||
trackPoint2.setTime(trackPoint2.getTime().plusMillis(222));
|
||||
trackPoint2.setSpeed(102f);
|
||||
point = chartFragment.createPendingPoint(trackPoint2);
|
||||
assertEquals(HOURS_PER_UNIT / (102.0 * UnitConversions.MPS_TO_KMH), point.getPace(), 0.01);
|
||||
|
||||
@@ -57,7 +57,7 @@ public class TrackStubUtils {
|
||||
location.setAltitude(altitude);
|
||||
location.setAccuracy(INITIAL_ACCURACY);
|
||||
location.setSpeed(INITIAL_SPEED);
|
||||
location.setTime(INITIAL_TIME);
|
||||
location.setTime(INITIAL_TIME); //TODO This is nowadays ignored as the constructor will replace the time.
|
||||
location.setBearing(INITIAL_BEARING);
|
||||
|
||||
return new TrackPoint(location);
|
||||
|
||||
+3
-3
@@ -357,7 +357,7 @@ public class ExportImportTest {
|
||||
TrackPoint trackPoint = trackPoints.get(i);
|
||||
TrackPoint importedTrackPoint = importedTrackPoints.get(i);
|
||||
|
||||
assertEquals(trackPoint.getTime(), importedTrackPoint.getTime(), 0.01);
|
||||
assertEquals(trackPoint.getTime(), importedTrackPoint.getTime());
|
||||
TrackPoint.Type type = trackPoint.getType();
|
||||
assertEquals("" + i, trackPoint.getType(), importedTrackPoint.getType());
|
||||
|
||||
@@ -410,8 +410,8 @@ public class ExportImportTest {
|
||||
TrackStatistics importedTrackStatistics = importedTrack.getTrackStatistics();
|
||||
|
||||
// Time
|
||||
assertEquals(trackStatistics.getStartTime_ms(), trackStatistics.getStartTime_ms(), 0.01);
|
||||
assertEquals(trackStatistics.getStopTime_ms(), trackStatistics.getStopTime_ms());
|
||||
assertEquals(trackStatistics.getStartTime(), trackStatistics.getStartTime());
|
||||
assertEquals(trackStatistics.getStopTime(), trackStatistics.getStopTime());
|
||||
assertEquals(trackStatistics.getTotalTime(), trackStatistics.getTotalTime());
|
||||
assertEquals(trackStatistics.getMovingTime(), trackStatistics.getMovingTime());
|
||||
|
||||
|
||||
+9
-7
@@ -20,6 +20,8 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.services.handlers.AdaptiveLocationListenerPolicy;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -32,13 +34,13 @@ import static org.junit.Assert.assertEquals;
|
||||
@RunWith(JUnit4.class)
|
||||
public class AdaptiveLocationListenerPolicyTest {
|
||||
|
||||
private static final long MIN = 1000;
|
||||
private static final long MAX = 3000;
|
||||
private static final Duration MIN = Duration.ofMillis(1000);
|
||||
private static final Duration MAX = Duration.ofMillis(3000);
|
||||
private static final int MIN_DISTANCE = 10;
|
||||
private static final long NEW_IDLE_TIME_BIG = 10000;
|
||||
private static final long NEW_IDLE_TIME_NORMAL = 5000;
|
||||
private static final long NEW_IDLE_TIME_SMALL = 2000;
|
||||
private static final long NEW_IDLE_TIME_LESS_THAN_MIN = 500;
|
||||
private static final Duration NEW_IDLE_TIME_BIG = Duration.ofMillis(10000);
|
||||
private static final Duration NEW_IDLE_TIME_NORMAL = Duration.ofMillis(5000);
|
||||
private static final Duration NEW_IDLE_TIME_SMALL = Duration.ofMillis(2000);
|
||||
private static final Duration NEW_IDLE_TIME_LESS_THAN_MIN = Duration.ofMillis(500);
|
||||
private AdaptiveLocationListenerPolicy adaptiveLocationListenerPolicy;
|
||||
|
||||
@Before
|
||||
@@ -62,7 +64,7 @@ public class AdaptiveLocationListenerPolicyTest {
|
||||
|
||||
adaptiveLocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_NORMAL);
|
||||
// First get the half of NEW_IDLE_TIME_NORMAL, and then round it to the nearest second.
|
||||
assertEquals((NEW_IDLE_TIME_NORMAL / 2 / 1000) * 1000, adaptiveLocationListenerPolicy.getDesiredPollingInterval());
|
||||
assertEquals(NEW_IDLE_TIME_NORMAL.dividedBy(2).getSeconds(), adaptiveLocationListenerPolicy.getDesiredPollingInterval().getSeconds());
|
||||
|
||||
adaptiveLocationListenerPolicy.updateIdleTime(NEW_IDLE_TIME_SMALL);
|
||||
assertEquals(MIN, adaptiveLocationListenerPolicy.getDesiredPollingInterval());
|
||||
|
||||
+3
-2
@@ -19,6 +19,7 @@ import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
@@ -239,7 +240,7 @@ public class TrackRecordingServiceTestLooper {
|
||||
assertEquals(trackId, track.getId());
|
||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||
assertNotNull(trackStatistics);
|
||||
assertTrue(trackStatistics.getStartTime_ms() > 0);
|
||||
assertTrue(trackStatistics.getStopTime_ms() >= trackStatistics.getStartTime_ms());
|
||||
assertTrue(trackStatistics.getStartTime().isAfter(Instant.ofEpochMilli(0)));
|
||||
assertTrue(trackStatistics.getStopTime().isAfter(trackStatistics.getStartTime()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
@@ -41,14 +44,14 @@ public class TrackStatisticsTest {
|
||||
@Test
|
||||
public void testMerge() {
|
||||
TrackStatistics statistics2 = new TrackStatistics();
|
||||
statistics.setStartTime_ms(1000L); // Resulting start time
|
||||
statistics.setStopTime_ms(2500L);
|
||||
statistics2.setStartTime_ms(3000L);
|
||||
statistics2.setStopTime_ms(4000L); // Resulting stop time
|
||||
statistics.setTotalTime(1500L);
|
||||
statistics2.setTotalTime(1000L); // Result: 1500+1000
|
||||
statistics.setMovingTime(700L);
|
||||
statistics2.setMovingTime(600L); // Result: 700+600
|
||||
statistics.setStartTime(Instant.ofEpochMilli(1000)); // Resulting start time
|
||||
statistics.setStopTime(Instant.ofEpochMilli(2500));
|
||||
statistics2.setStartTime(Instant.ofEpochMilli(3000));
|
||||
statistics2.setStopTime(Instant.ofEpochMilli(4000)); // Resulting stop time
|
||||
statistics.setTotalTime(Duration.ofMillis(1500));
|
||||
statistics2.setTotalTime(Duration.ofMillis(1000)); // Result: 1500+1000
|
||||
statistics.setMovingTime(Duration.ofMillis(700));
|
||||
statistics2.setMovingTime(Duration.ofMillis(600)); // Result: 700+600
|
||||
statistics.setTotalDistance(750.0);
|
||||
statistics2.setTotalDistance(350.0); // Result: 750+350
|
||||
statistics.setTotalElevationGain(50.0f);
|
||||
@@ -62,13 +65,13 @@ public class TrackStatisticsTest {
|
||||
|
||||
statistics.merge(statistics2);
|
||||
|
||||
assertEquals(1000L, statistics.getStartTime_ms());
|
||||
assertEquals(4000L, statistics.getStopTime_ms());
|
||||
assertEquals(2500L, statistics.getTotalTime());
|
||||
assertEquals(1300L, statistics.getMovingTime());
|
||||
assertEquals(Instant.ofEpochMilli(1000), statistics.getStartTime());
|
||||
assertEquals(Instant.ofEpochMilli(4000), statistics.getStopTime());
|
||||
assertEquals(Duration.ofMillis(2500), statistics.getTotalTime());
|
||||
assertEquals(Duration.ofMillis(1300), statistics.getMovingTime());
|
||||
assertEquals(1100.0, statistics.getTotalDistance(), 0.001);
|
||||
assertEquals(900.0, statistics.getTotalElevationGain(), 0.001);
|
||||
assertEquals(statistics.getTotalDistance() / (statistics.getMovingTime() / 1000.0), statistics.getMaxSpeed(), 0.001);
|
||||
assertEquals(statistics.getTotalDistance() / statistics.getMovingTime().getSeconds(), statistics.getMaxSpeed(), 0.001);
|
||||
assertEquals(1200.0, statistics.getMinElevation(), 0.001);
|
||||
assertEquals(3575.0, statistics.getMaxElevation(), 0.001);
|
||||
}
|
||||
@@ -76,14 +79,14 @@ public class TrackStatisticsTest {
|
||||
@Test
|
||||
public void testGetAverageSpeed() {
|
||||
statistics.setTotalDistance(1000.0);
|
||||
statistics.setTotalTime(50000); // in milliseconds
|
||||
statistics.setTotalTime(Duration.ofMillis(50000));
|
||||
assertEquals(20.0, statistics.getAverageSpeed(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAverageMovingSpeed() {
|
||||
statistics.setTotalDistance(1000.0);
|
||||
statistics.setMovingTime(20000); // in milliseconds
|
||||
statistics.setMovingTime(Duration.ofMillis(20000));
|
||||
assertEquals(50.0, statistics.getAverageMovingSpeed(), 0.001);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package de.dennisguse.opentracks.stats;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.TestDataUtil;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class TrackStatisticsUpdaterTest {
|
||||
|
||||
@Test
|
||||
public void addTrackPoint() {
|
||||
// given
|
||||
TestDataUtil.TrackData data = TestDataUtil.createTestingTrack(new Track.Id(1));
|
||||
|
||||
// when
|
||||
TrackStatisticsUpdater updater = new TrackStatisticsUpdater();
|
||||
data.trackPoints.forEach(it -> updater.addTrackPoint(it, 50));
|
||||
|
||||
// then
|
||||
TrackStatistics statistics = updater.getTrackStatistics();
|
||||
assertEquals(56.90, statistics.getTotalDistance(), 0.01);
|
||||
assertEquals(Duration.ofSeconds(9), statistics.getTotalTime());
|
||||
assertEquals(Duration.ofSeconds(4), statistics.getMovingTime());
|
||||
|
||||
assertEquals(2.5, statistics.getMinElevation(), 0.01);
|
||||
assertEquals(27.5, statistics.getMaxElevation(), 0.01);
|
||||
assertEquals(18.0, statistics.getTotalElevationGain(), 0.01);
|
||||
assertEquals(72.0, statistics.getTotalElevationLoss(), 0.01);
|
||||
|
||||
assertEquals(14.226, statistics.getMaxSpeed(), 0.01);
|
||||
assertEquals(14.226, statistics.getAverageMovingSpeed(), 0.01);
|
||||
assertEquals(6.322, statistics.getAverageSpeed(), 0.01);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
@@ -28,8 +29,8 @@ public class AnnouncementUtilsTest {
|
||||
public void getAnnouncement() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setTotalDistance(20000);
|
||||
stats.setTotalTime(600000);
|
||||
stats.setMovingTime(300000);
|
||||
stats.setTotalTime(Duration.ofMillis(600000));
|
||||
stats.setMovingTime(Duration.ofMillis(300000));
|
||||
stats.setMaxSpeed(100);
|
||||
stats.setTotalElevationGain(6000f);
|
||||
|
||||
@@ -44,8 +45,8 @@ public class AnnouncementUtilsTest {
|
||||
public void getAnnouncement_withInterval() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setTotalDistance(20000);
|
||||
stats.setTotalTime(600000);
|
||||
stats.setMovingTime(300000);
|
||||
stats.setTotalTime(Duration.ofMillis(600000));
|
||||
stats.setMovingTime(Duration.ofMillis(300000));
|
||||
stats.setMaxSpeed(100);
|
||||
stats.setTotalElevationGain(6000f);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@@ -40,55 +41,32 @@ public class StringUtilsTest {
|
||||
|
||||
private final Context context = ApplicationProvider.getApplicationContext();
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#formatDateTimeIso8601(long)}.
|
||||
*/
|
||||
@Test
|
||||
public void testFormatDateTimeIso8601() {
|
||||
assertEquals("1970-01-01T00:00:12.345Z", StringUtils.formatDateTimeIso8601(12345));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#formatElapsedTime(long)}.
|
||||
* Tests {@link StringUtils#formatElapsedTime(Duration)}.
|
||||
*/
|
||||
@Test
|
||||
public void testformatElapsedTime() {
|
||||
// 1 second
|
||||
assertEquals("00:01", StringUtils.formatElapsedTime(1000));
|
||||
// 10 seconds
|
||||
assertEquals("00:10", StringUtils.formatElapsedTime(10000));
|
||||
// 1 minute
|
||||
assertEquals("01:00", StringUtils.formatElapsedTime(60000));
|
||||
// 10 minutes
|
||||
assertEquals("10:00", StringUtils.formatElapsedTime(600000));
|
||||
// 1 hour
|
||||
assertEquals("1:00:00", StringUtils.formatElapsedTime(3600000));
|
||||
// 10 hours
|
||||
assertEquals("10:00:00", StringUtils.formatElapsedTime(36000000));
|
||||
// 100 hours
|
||||
assertEquals("100:00:00", StringUtils.formatElapsedTime(360000000));
|
||||
assertEquals("00:01", StringUtils.formatElapsedTime(Duration.ofMillis(1000)));
|
||||
assertEquals("00:10", StringUtils.formatElapsedTime(Duration.ofMillis(10000)));
|
||||
assertEquals("01:00", StringUtils.formatElapsedTime(Duration.ofMillis(60000)));
|
||||
assertEquals("10:00", StringUtils.formatElapsedTime(Duration.ofMillis(600000)));
|
||||
assertEquals("1:00:00", StringUtils.formatElapsedTime(Duration.ofMillis(3600000)));
|
||||
assertEquals("10:00:00", StringUtils.formatElapsedTime(Duration.ofMillis(36000000)));
|
||||
assertEquals("100:00:00", StringUtils.formatElapsedTime(Duration.ofMillis(360000000)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#formatElapsedTimeWithHour(long)}.
|
||||
* Tests {@link StringUtils#formatElapsedTimeWithHour(Duration)}.
|
||||
*/
|
||||
@Test
|
||||
public void testformatElapsedTimeWithHour() {
|
||||
// 1 second
|
||||
assertEquals("0:00:01", StringUtils.formatElapsedTimeWithHour(1000));
|
||||
// 10 seconds
|
||||
assertEquals("0:00:10", StringUtils.formatElapsedTimeWithHour(10000));
|
||||
// 1 minute
|
||||
assertEquals("0:01:00", StringUtils.formatElapsedTimeWithHour(60000));
|
||||
// 10 minutes
|
||||
assertEquals("0:10:00", StringUtils.formatElapsedTimeWithHour(600000));
|
||||
// 1 hour
|
||||
assertEquals("1:00:00", StringUtils.formatElapsedTimeWithHour(3600000));
|
||||
// 10 hours
|
||||
assertEquals("10:00:00", StringUtils.formatElapsedTimeWithHour(36000000));
|
||||
// 100 hours
|
||||
assertEquals("100:00:00", StringUtils.formatElapsedTimeWithHour(360000000));
|
||||
assertEquals("0:00:01", StringUtils.formatElapsedTimeWithHour(Duration.ofMillis(1000)));
|
||||
assertEquals("0:00:10", StringUtils.formatElapsedTimeWithHour(Duration.ofMillis(10000)));
|
||||
assertEquals("0:01:00", StringUtils.formatElapsedTimeWithHour(Duration.ofMillis(60000)));
|
||||
assertEquals("0:10:00", StringUtils.formatElapsedTimeWithHour(Duration.ofMillis(600000)));
|
||||
assertEquals("1:00:00", StringUtils.formatElapsedTimeWithHour(Duration.ofMillis(3600000)));
|
||||
assertEquals("10:00:00", StringUtils.formatElapsedTimeWithHour(Duration.ofMillis(36000000)));
|
||||
assertEquals("100:00:00", StringUtils.formatElapsedTimeWithHour(Duration.ofMillis(360000000)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,29 +148,7 @@ public class StringUtilsTest {
|
||||
|
||||
// This comparision tends to be flaky (difference of 1ms)
|
||||
// Assert.assertEquals(calendar.getTimeInMillis(), StringUtils.parseTime(xmlDateTime));
|
||||
assertTrue(calendar.getTimeInMillis() + " vs. " + StringUtils.parseTime(xmlDateTime), Math.abs(calendar.getTimeInMillis() - StringUtils.parseTime(xmlDateTime)) <= 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#getTimeParts(long)} with a positive number.
|
||||
*/
|
||||
@Test
|
||||
public void testGetTimeParts_positive() {
|
||||
int[] parts = StringUtils.getTimeParts(61000);
|
||||
assertEquals(1, parts[0]);
|
||||
assertEquals(1, parts[1]);
|
||||
assertEquals(0, parts[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link StringUtils#getTimeParts(long)} with a negative number.
|
||||
*/
|
||||
@Test
|
||||
public void testGetTimeParts_negative() {
|
||||
int[] parts = StringUtils.getTimeParts(-61000);
|
||||
assertEquals(-1, parts[0]);
|
||||
assertEquals(-1, parts[1]);
|
||||
assertEquals(0, parts[2]);
|
||||
assertTrue(calendar.getTimeInMillis() + " vs. " + StringUtils.parseTime(xmlDateTime), Math.abs(calendar.getTimeInMillis() - StringUtils.parseTime(xmlDateTime).toEpochMilli()) <= 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.time.Instant;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
@@ -42,7 +42,7 @@ import static org.junit.Assert.assertEquals;
|
||||
public class TrackNameUtilsTest {
|
||||
|
||||
private static final Track.Id TRACK_ID = new Track.Id(1L);
|
||||
private static final long START_TIME = 1288213406000L;
|
||||
private static final Instant START_TIME = Instant.ofEpochMilli(1288213406000L);
|
||||
|
||||
private static final Context CONTEXT = ApplicationProvider.getApplicationContext();
|
||||
|
||||
@@ -62,7 +62,7 @@ public class TrackNameUtilsTest {
|
||||
public void testTrackName_date_iso_8601() {
|
||||
PreferencesUtils.setString(CONTEXT, R.string.track_name_key, CONTEXT.getString(R.string.settings_recording_track_name_date_iso_8601_value));
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(TrackNameUtils.ISO_8601_FORMAT, Locale.US);
|
||||
assertEquals(simpleDateFormat.format(new Date(START_TIME)), TrackNameUtils.getTrackName(CONTEXT, TRACK_ID, START_TIME));
|
||||
assertEquals(simpleDateFormat.format(START_TIME.toEpochMilli()), TrackNameUtils.getTrackName(CONTEXT, TRACK_ID, START_TIME));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+16
-14
@@ -8,6 +8,8 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
@@ -27,15 +29,15 @@ public class AggregatedStatisticsTest {
|
||||
* Create a TrackStatistics object.
|
||||
*
|
||||
* @param totalDistance distance in meters.
|
||||
* @param totalTime total time in milliseconds.
|
||||
* @param totalTime total time in milliseconds. //TODO Duration
|
||||
* @return TrackStatistics object.
|
||||
*/
|
||||
private static Track createTrack(Context context, long totalDistance, long totalTime, String category) {
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
statistics.setStartTime_ms(1000L); // Resulting start time
|
||||
statistics.setStopTime_ms(1000L + totalTime);
|
||||
statistics.setTotalTime(totalTime);
|
||||
statistics.setMovingTime(totalTime);
|
||||
statistics.setStartTime(Instant.ofEpochMilli(1000L)); // Resulting start time
|
||||
statistics.setStopTime(Instant.ofEpochMilli(1000L + totalTime));
|
||||
statistics.setTotalTime(Duration.ofMillis(totalTime));
|
||||
statistics.setMovingTime(Duration.ofMillis(totalTime));
|
||||
statistics.setTotalDistance(totalDistance);
|
||||
statistics.setTotalElevationGain(50.0f);
|
||||
statistics.setMaxSpeed(50.0); // Resulting max speed
|
||||
@@ -68,7 +70,7 @@ public class AggregatedStatisticsTest {
|
||||
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||
assertEquals(totalDistance, statistics2.getTotalDistance(), 0);
|
||||
assertEquals(totalTime, statistics2.getMovingTime());
|
||||
assertEquals(Duration.ofMillis(totalTime), statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -122,7 +124,7 @@ public class AggregatedStatisticsTest {
|
||||
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||
assertEquals(totalDistance * 2, statistics2.getTotalDistance(), 0);
|
||||
assertEquals(totalTime * 2L, statistics2.getMovingTime());
|
||||
assertEquals(Duration.ofMillis(totalTime * 2), statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -156,19 +158,19 @@ public class AggregatedStatisticsTest {
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||
assertEquals(totalDistance, statistics2.getTotalDistance(), 0);
|
||||
assertEquals(totalTime, statistics2.getMovingTime());
|
||||
assertEquals(Duration.ofMillis(totalTime), statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(running).getTrackStatistics();
|
||||
assertEquals(totalDistance, statistics2.getTotalDistance(), 0);
|
||||
assertEquals(totalTime, statistics2.getMovingTime());
|
||||
assertEquals(Duration.ofMillis(totalTime), statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(walking).getTrackStatistics();
|
||||
assertEquals(totalDistance, statistics2.getTotalDistance(), 0);
|
||||
assertEquals(totalTime, statistics2.getMovingTime());
|
||||
assertEquals(Duration.ofMillis(totalTime), statistics2.getMovingTime());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,28 +221,28 @@ public class AggregatedStatisticsTest {
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||
assertEquals(totalDistance * 5, statistics2.getTotalDistance(), 0);
|
||||
assertEquals(totalTime * 5, statistics2.getMovingTime());
|
||||
assertEquals(Duration.ofMillis(totalTime * 5), statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
// Running.
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(running).getTrackStatistics();
|
||||
assertEquals(totalDistance * 2, statistics2.getTotalDistance(), 0);
|
||||
assertEquals(totalTime * 2, statistics2.getMovingTime());
|
||||
assertEquals(Duration.ofMillis(totalTime * 2), statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
// Walking.
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(walking).getTrackStatistics();
|
||||
assertEquals(totalDistance * 2, statistics2.getTotalDistance(), 0);
|
||||
assertEquals(totalTime * 2, statistics2.getMovingTime());
|
||||
assertEquals(Duration.ofMillis(totalTime * 2), statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
// Driving.
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(driving).getTrackStatistics();
|
||||
assertEquals(totalDistance, statistics2.getTotalDistance(), 0);
|
||||
assertEquals(totalTime, statistics2.getMovingTime());
|
||||
assertEquals(Duration.ofMillis(totalTime), statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
// Check order
|
||||
|
||||
+3
-3
@@ -116,17 +116,17 @@ public class IntervalStatisticsTest {
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(trackPoints, distanceInterval);
|
||||
List<IntervalStatistics.Interval> intervalList = intervalStatistics.getIntervalList();
|
||||
double totalDistance = 0d;
|
||||
long totalTime = 0L;
|
||||
float totalTime = 0L;
|
||||
float totalGain = 0f;
|
||||
for (IntervalStatistics.Interval i : intervalList) {
|
||||
totalDistance += i.getDistance_m();
|
||||
totalTime += ((i.getDistance_m() / i.getSpeed_ms()) * UnitConversions.S_TO_MS);
|
||||
totalTime += i.getDistance_m() / i.getSpeed_ms();
|
||||
totalGain += i.getGain_m();
|
||||
}
|
||||
|
||||
// then
|
||||
assertEquals(trackStatistics.getTotalDistance(), totalDistance, 0.01);
|
||||
assertEquals(trackStatistics.getTotalTime() * UnitConversions.MS_TO_S, totalTime * UnitConversions.MS_TO_S, 0.1);
|
||||
assertEquals(trackStatistics.getTotalTime().toMillis(), totalTime * UnitConversions.S_TO_MS, 1);
|
||||
assertEquals(intervalList.size(), (int) Math.ceil(trackStatistics.getTotalDistance() / distanceInterval));
|
||||
assertEquals(totalGain, trackPoints.size() * TestDataUtil.ELEVATION_GAIN, 0.1);
|
||||
for (int i = 0; i < intervalList.size() - 1; i++) {
|
||||
|
||||
@@ -24,6 +24,8 @@ import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.databinding.TrackControllerBinding;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingServiceInterface;
|
||||
@@ -53,8 +55,7 @@ public class TrackController implements View.OnTouchListener {
|
||||
|
||||
private boolean isRecording;
|
||||
private boolean isPaused;
|
||||
private long totalTime = 0;
|
||||
private long totalTimeTimestamp = 0;
|
||||
private Duration totalTime;
|
||||
private boolean isResumed = false;
|
||||
|
||||
private final Callback callback;
|
||||
@@ -63,7 +64,7 @@ public class TrackController implements View.OnTouchListener {
|
||||
private final Runnable updateTotalTimeRunnable = new Runnable() {
|
||||
public void run() {
|
||||
if (isResumed && isRecording && !isPaused) {
|
||||
viewBinding.trackControllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(System.currentTimeMillis() - totalTimeTimestamp + totalTime));
|
||||
viewBinding.trackControllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
|
||||
handlerUpdateTotalTime.postDelayed(this, UnitConversions.ONE_SECOND_MS);
|
||||
}
|
||||
}
|
||||
@@ -191,9 +192,10 @@ public class TrackController implements View.OnTouchListener {
|
||||
viewBinding.trackControllerTotalTime.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
|
||||
if (isRecording) {
|
||||
totalTime = getTotalTime();
|
||||
viewBinding.trackControllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
|
||||
if (totalTime != null) {
|
||||
viewBinding.trackControllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
|
||||
}
|
||||
if (!isPaused) {
|
||||
totalTimeTimestamp = System.currentTimeMillis();
|
||||
handlerUpdateTotalTime.postDelayed(updateTotalTimeRunnable, UnitConversions.ONE_SECOND_MS);
|
||||
}
|
||||
}
|
||||
@@ -220,9 +222,9 @@ public class TrackController implements View.OnTouchListener {
|
||||
/**
|
||||
* Gets the total time for the current recording track.
|
||||
*/
|
||||
private long getTotalTime() {
|
||||
private Duration getTotalTime() {
|
||||
TrackRecordingServiceInterface trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
||||
return trackRecordingService != null ? trackRecordingService.getTotalTime() : 0L;
|
||||
return trackRecordingService != null ? trackRecordingService.getTotalTime() : null;
|
||||
}
|
||||
|
||||
private void showStatusSetDefaultText() {
|
||||
|
||||
@@ -44,6 +44,8 @@ import androidx.loader.app.LoaderManager;
|
||||
import androidx.loader.content.CursorLoader;
|
||||
import androidx.loader.content.Loader;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
import de.dennisguse.opentracks.content.data.TracksColumns;
|
||||
import de.dennisguse.opentracks.databinding.TrackListBinding;
|
||||
@@ -224,7 +226,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
||||
String icon = cursor.getString(iconIndex);
|
||||
int iconId = TrackIconUtils.getIconDrawable(icon);
|
||||
String name = cursor.getString(nameIndex);
|
||||
String totalTime = StringUtils.formatElapsedTime(cursor.getLong(totalTimeIndex));
|
||||
String totalTime = StringUtils.formatElapsedTime(Duration.ofMillis(cursor.getLong(totalTimeIndex)));
|
||||
String totalDistance = StringUtils.formatDistance(TrackListActivity.this, cursor.getDouble(totalDistanceIndex), metricUnits);
|
||||
int markerCount = cursor.getInt(markerCountIndex);
|
||||
long startTime = cursor.getLong(startTimeIndex);
|
||||
|
||||
@@ -35,7 +35,7 @@ public class ChartPoint {
|
||||
}
|
||||
timeOrDistance = distance;
|
||||
} else {
|
||||
timeOrDistance = trackStatistics.getTotalTime();
|
||||
timeOrDistance = trackStatistics.getTotalTime().toMillis();
|
||||
}
|
||||
|
||||
elevation = trackStatisticsUpdater.getSmoothedElevation();
|
||||
|
||||
@@ -38,6 +38,7 @@ import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.GestureDetectorCompat;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -740,7 +741,7 @@ public class ChartView extends View {
|
||||
* @param spacing the spacing between x axis and marker
|
||||
*/
|
||||
private void drawXAxisMarker(Canvas canvas, double value, NumberFormat numberFormat, int spacing) {
|
||||
String marker = chartByDistance ? numberFormat.format(value) : StringUtils.formatElapsedTime((long) value);
|
||||
String marker = chartByDistance ? numberFormat.format(value) : StringUtils.formatElapsedTime((Duration.ofMillis((long) value)));
|
||||
Rect rect = getRect(xAxisMarkerPaint, marker);
|
||||
canvas.drawText(marker, getX(value), topBorder + effectiveHeight + spacing + rect.height(), xAxisMarkerPaint);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import android.util.Pair;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
@@ -146,7 +148,7 @@ public class DescriptionGenerator {
|
||||
}
|
||||
|
||||
// Recorded time
|
||||
builder.append(context.getString(R.string.description_recorded_time, StringUtils.formatDateTime(context, stats.getStartTime_ms())));
|
||||
builder.append(context.getString(R.string.description_recorded_time, StringUtils.formatDateTime(context, stats.getStartTime())));
|
||||
builder.append(lineBreak);
|
||||
|
||||
return builder.toString();
|
||||
@@ -177,7 +179,7 @@ public class DescriptionGenerator {
|
||||
* @param lineBreak line break string
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void writeTime(long time, StringBuilder builder, int resId, String lineBreak) {
|
||||
void writeTime(Duration time, StringBuilder builder, int resId, String lineBreak) {
|
||||
builder.append(context.getString(resId, StringUtils.formatElapsedTime(time)));
|
||||
builder.append(lineBreak);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -43,7 +44,7 @@ public final class Marker {
|
||||
private final Track.Id trackId;
|
||||
//TODO It is the distance from the track starting point; rename to something more meaningful
|
||||
private double length = 0.0;
|
||||
private long duration = 0;
|
||||
private long duration = 0; //TODO Duration
|
||||
|
||||
@Deprecated //TODO Replace by storing latitude/longitude directly.
|
||||
private final Location location;
|
||||
@@ -95,6 +96,10 @@ public final class Marker {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Instant getTime() {
|
||||
return Instant.ofEpochMilli(location.getTime());
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.os.Parcel;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -43,7 +44,7 @@ public class TrackPoint {
|
||||
|
||||
private TrackPoint.Id id;
|
||||
|
||||
private long time_ms;
|
||||
private Instant time;
|
||||
private Double latitude;
|
||||
private Double longitude;
|
||||
private Float accuracy;
|
||||
@@ -101,49 +102,49 @@ public class TrackPoint {
|
||||
this.speed_mps = location.getSpeed();
|
||||
this.accuracy = location.getAccuracy();
|
||||
|
||||
setTime(System.currentTimeMillis());
|
||||
setTime(Instant.now());
|
||||
}
|
||||
|
||||
public TrackPoint(@NonNull Type type, long time_ms) {
|
||||
public TrackPoint(@NonNull Type type, Instant time) {
|
||||
this(type);
|
||||
this.time_ms = time_ms;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public TrackPoint(double latitude, double longitude, Double altitude, long time) {
|
||||
public TrackPoint(double latitude, double longitude, Double altitude, Instant time) {
|
||||
this(Type.TRACKPOINT);
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
this.altitude_m = altitude;
|
||||
this.time_ms = time;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
@Deprecated //See #316
|
||||
public static TrackPoint createSegmentStartManual() {
|
||||
return createSegmentStartManualWithTime(System.currentTimeMillis());
|
||||
return createSegmentStartManualWithTime(Instant.now());
|
||||
}
|
||||
|
||||
public static TrackPoint createSegmentStartManualWithTime(long time) {
|
||||
public static TrackPoint createSegmentStartManualWithTime(Instant time) {
|
||||
return new TrackPoint(Type.SEGMENT_START_MANUAL, time);
|
||||
}
|
||||
|
||||
@Deprecated //See #316
|
||||
public static TrackPoint createSegmentStartAutomatic() {
|
||||
return createSegmentStartAutomaticWithTime(System.currentTimeMillis());
|
||||
return createSegmentStartAutomaticWithTime(Instant.now());
|
||||
}
|
||||
|
||||
public static TrackPoint createSegmentStartAutomaticWithTime(long time) {
|
||||
public static TrackPoint createSegmentStartAutomaticWithTime(Instant time) {
|
||||
return new TrackPoint(Type.SEGMENT_START_AUTOMATIC, time);
|
||||
}
|
||||
|
||||
public static TrackPoint createSegmentEnd() {
|
||||
return createSegmentEndWithTime(System.currentTimeMillis());
|
||||
return createSegmentEndWithTime(Instant.now());
|
||||
}
|
||||
|
||||
public static TrackPoint createSegmentEndWithTime(@NonNull TrackPoint trackPoint) {
|
||||
return createSegmentEndWithTime(trackPoint.getTime());
|
||||
}
|
||||
|
||||
public static TrackPoint createSegmentEndWithTime(long time) {
|
||||
public static TrackPoint createSegmentEndWithTime(Instant time) {
|
||||
return new TrackPoint(Type.SEGMENT_END_MANUAL, time);
|
||||
}
|
||||
|
||||
@@ -183,7 +184,7 @@ public class TrackPoint {
|
||||
@Nullable
|
||||
public Location getLocation() {
|
||||
Location location = new Location("");
|
||||
location.setTime(time_ms);
|
||||
location.setTime(time.toEpochMilli());
|
||||
if (hasLocation()) {
|
||||
location.setLatitude(latitude);
|
||||
location.setLongitude(longitude);
|
||||
@@ -241,12 +242,12 @@ public class TrackPoint {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time_ms;
|
||||
public Instant getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time_ms = time;
|
||||
public void setTime(Instant time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public boolean hasAltitude() {
|
||||
|
||||
@@ -29,6 +29,8 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
@@ -118,19 +120,19 @@ public class ContentProviderUtils {
|
||||
track.setCategory(cursor.getString(categoryIndex));
|
||||
}
|
||||
if (!cursor.isNull(startTimeIndex)) {
|
||||
trackStatistics.setStartTime_ms(cursor.getLong(startTimeIndex));
|
||||
trackStatistics.setStartTime(Instant.ofEpochMilli(cursor.getLong(startTimeIndex)));
|
||||
}
|
||||
if (!cursor.isNull(stopTimeIndex)) {
|
||||
trackStatistics.setStopTime_ms(cursor.getLong(stopTimeIndex));
|
||||
trackStatistics.setStopTime(Instant.ofEpochMilli(cursor.getLong(stopTimeIndex)));
|
||||
}
|
||||
if (!cursor.isNull(totalDistanceIndex)) {
|
||||
trackStatistics.setTotalDistance(cursor.getFloat(totalDistanceIndex));
|
||||
}
|
||||
if (!cursor.isNull(totalTimeIndex)) {
|
||||
trackStatistics.setTotalTime(cursor.getLong(totalTimeIndex));
|
||||
trackStatistics.setTotalTime(Duration.ofMillis(cursor.getLong(totalTimeIndex)));
|
||||
}
|
||||
if (!cursor.isNull(movingTimeIndex)) {
|
||||
trackStatistics.setMovingTime(cursor.getLong(movingTimeIndex));
|
||||
trackStatistics.setMovingTime(Duration.ofMillis(cursor.getLong(movingTimeIndex)));
|
||||
}
|
||||
if (!cursor.isNull(maxSpeedIndex)) {
|
||||
trackStatistics.setMaxSpeed(cursor.getFloat(maxSpeedIndex));
|
||||
@@ -270,11 +272,11 @@ public class ContentProviderUtils {
|
||||
values.put(TracksColumns.NAME, track.getName());
|
||||
values.put(TracksColumns.DESCRIPTION, track.getDescription());
|
||||
values.put(TracksColumns.CATEGORY, track.getCategory());
|
||||
values.put(TracksColumns.STARTTIME, trackStatistics.getStartTime_ms());
|
||||
values.put(TracksColumns.STOPTIME, trackStatistics.getStopTime_ms());
|
||||
values.put(TracksColumns.STARTTIME, trackStatistics.getStartTime().toEpochMilli());
|
||||
values.put(TracksColumns.STOPTIME, trackStatistics.getStopTime().toEpochMilli());
|
||||
values.put(TracksColumns.TOTALDISTANCE, trackStatistics.getTotalDistance());
|
||||
values.put(TracksColumns.TOTALTIME, trackStatistics.getTotalTime());
|
||||
values.put(TracksColumns.MOVINGTIME, trackStatistics.getMovingTime());
|
||||
values.put(TracksColumns.TOTALTIME, trackStatistics.getTotalTime().toMillis());
|
||||
values.put(TracksColumns.MOVINGTIME, trackStatistics.getMovingTime().toMillis());
|
||||
values.put(TracksColumns.AVGSPEED, trackStatistics.getAverageSpeed());
|
||||
values.put(TracksColumns.AVGMOVINGSPEED, trackStatistics.getAverageMovingSpeed());
|
||||
values.put(TracksColumns.MAXSPEED, trackStatistics.getMaxSpeed());
|
||||
@@ -533,7 +535,7 @@ public class ContentProviderUtils {
|
||||
trackPoint.setLatitude(((double) cursor.getInt(indexes.latitudeIndex)) / 1E6);
|
||||
}
|
||||
if (!cursor.isNull(indexes.timeIndex)) {
|
||||
trackPoint.setTime(cursor.getLong(indexes.timeIndex));
|
||||
trackPoint.setTime(Instant.ofEpochMilli(cursor.getLong(indexes.timeIndex)));
|
||||
}
|
||||
if (!cursor.isNull(indexes.altitudeIndex)) {
|
||||
trackPoint.setAltitude(cursor.getFloat(indexes.altitudeIndex));
|
||||
@@ -704,7 +706,7 @@ public class ContentProviderUtils {
|
||||
values.put(TrackPointsColumns.LONGITUDE, (int) (trackPoint.getLongitude() * 1E6));
|
||||
values.put(TrackPointsColumns.LATITUDE, (int) (trackPoint.getLatitude() * 1E6));
|
||||
}
|
||||
values.put(TrackPointsColumns.TIME, trackPoint.getTime());
|
||||
values.put(TrackPointsColumns.TIME, trackPoint.getTime().toEpochMilli());
|
||||
if (trackPoint.hasAltitude()) {
|
||||
values.put(TrackPointsColumns.ALTITUDE, trackPoint.getAltitude());
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class ChartFragment extends Fragment implements TrackDataListener {
|
||||
|
||||
private static final String KEY_CHART_VIEW_BY_DISTANCE_KEY = "chartViewByDistance";
|
||||
|
||||
public static Fragment newInstance(boolean chartByDistance) {
|
||||
public static ChartFragment newInstance(boolean chartByDistance) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(KEY_CHART_VIEW_BY_DISTANCE_KEY, chartByDistance);
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -407,7 +409,7 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
||||
}
|
||||
|
||||
private void updateTotalTime() {
|
||||
long totalTime;
|
||||
Duration totalTime;
|
||||
if (isSelectedTrackRecording()) {
|
||||
totalTime = calculateTotalTime();
|
||||
} else {
|
||||
@@ -420,12 +422,12 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi
|
||||
* Return time from service.
|
||||
* If service isn't bound then use lastTrackStatistics for calculate it.
|
||||
*/
|
||||
private long calculateTotalTime() {
|
||||
private Duration calculateTotalTime() {
|
||||
TrackRecordingServiceInterface trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
||||
if (trackRecordingService != null) {
|
||||
return trackRecordingService.getTotalTime();
|
||||
} else {
|
||||
return System.currentTimeMillis() - lastTrackStatistics.getStopTime_ms() + lastTrackStatistics.getTotalTime();
|
||||
return Duration.between(lastTrackStatistics.getStopTime().plus(lastTrackStatistics.getTotalTime()), Instant.now());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.Marker;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
@@ -71,9 +73,9 @@ public class FileTrackExporter implements TrackExporter {
|
||||
trackWriter.writeMultiTrackBegin();
|
||||
}
|
||||
//TODO Why use startTime of first track for the others?
|
||||
long startTime = tracks[0].getTrackStatistics().getStartTime_ms();
|
||||
Instant startTime = tracks[0].getTrackStatistics().getStartTime();
|
||||
for (Track track : tracks) {
|
||||
long offset = track.getTrackStatistics().getStartTime_ms() - startTime;
|
||||
Duration offset = Duration.between(track.getTrackStatistics().getStartTime(), startTime);
|
||||
writeLocations(track, offset);
|
||||
}
|
||||
if (hasMultipleTracks) {
|
||||
@@ -120,7 +122,7 @@ public class FileTrackExporter implements TrackExporter {
|
||||
/**
|
||||
* Writes the locations.
|
||||
*/
|
||||
private void writeLocations(Track track, long offset) throws InterruptedException {
|
||||
private void writeLocations(Track track, Duration offset) throws InterruptedException {
|
||||
boolean wroteTrack = false;
|
||||
boolean wroteSegment = false;
|
||||
|
||||
@@ -180,9 +182,9 @@ public class FileTrackExporter implements TrackExporter {
|
||||
* @param offset the time offset
|
||||
*/
|
||||
//TODO Why?
|
||||
private void setLocationTime(TrackPoint trackPoint, long offset) {
|
||||
private void setLocationTime(TrackPoint trackPoint, Duration offset) {
|
||||
if (trackPoint != null) {
|
||||
trackPoint.setTime(trackPoint.getTime() - offset);
|
||||
trackPoint.setTime(trackPoint.getTime().minus(offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.location.Location;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.NumberFormat;
|
||||
import java.time.Instant;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.Marker;
|
||||
@@ -137,7 +138,7 @@ public class GpxTrackWriter implements TrackWriter {
|
||||
if (location.hasAltitude()) {
|
||||
printWriter.println("<ele>" + ELEVATION_FORMAT.format(location.getAltitude()) + "</ele>");
|
||||
}
|
||||
printWriter.println("<time>" + StringUtils.formatDateTimeIso8601(location.getTime()) + "</time>");
|
||||
printWriter.println("<time>" + StringUtils.formatDateTimeIso8601(Instant.ofEpochMilli(location.getTime())) + "</time>");
|
||||
printWriter.println("<name>" + StringUtils.formatCData(marker.getName()) + "</name>");
|
||||
printWriter.println("<desc>" + StringUtils.formatCData(marker.getDescription()) + "</desc>");
|
||||
printWriter.println("<type>" + StringUtils.formatCData(marker.getCategory()) + "</type>");
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.location.Location;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@@ -385,9 +386,9 @@ public class KmlTrackWriter implements TrackWriter {
|
||||
*/
|
||||
private String getTime(Location location) {
|
||||
if (exportTrackDetail) {
|
||||
return StringUtils.formatDateTimeIso8601(location.getTime());
|
||||
return StringUtils.formatDateTimeIso8601(Instant.ofEpochMilli(location.getTime()));
|
||||
} else {
|
||||
return StringUtils.formatDateTimeIso8601(location.getTime() - startTrackPoint.getTime());
|
||||
return StringUtils.formatDateTimeIso8601(Instant.ofEpochMilli(location.getTime() - startTrackPoint.getTime().toEpochMilli()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-12
@@ -28,8 +28,9 @@ import org.xml.sax.helpers.DefaultHandler;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
@@ -50,7 +51,6 @@ import de.dennisguse.opentracks.util.LocationUtils;
|
||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||
import de.dennisguse.opentracks.util.UnitConversions;
|
||||
|
||||
/**
|
||||
* Abstract class for file track importers.
|
||||
@@ -185,9 +185,9 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
trackStatisticsUpdater.addTrackPoint(trackPoint, recordingDistanceInterval);
|
||||
}
|
||||
|
||||
if (marker.getLocation().getTime() > trackPoint.getTime()) {
|
||||
if ((marker.getTime()).isAfter(trackPoint.getTime())) {
|
||||
trackPoint = null;
|
||||
} else if (marker.getLocation().getTime() < trackPoint.getTime()) {
|
||||
} else if (marker.getTime().isBefore(trackPoint.getTime())) {
|
||||
Log.w(TAG, "Ignoring marker: current trackPoint was after marker.");
|
||||
marker = null;
|
||||
} else {
|
||||
@@ -203,7 +203,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
String markerDescription = marker.getDescription();
|
||||
String icon = context.getString(R.string.marker_icon_url);
|
||||
double length = trackStatisticsUpdater.getTrackStatistics().getTotalDistance();
|
||||
long duration = trackStatisticsUpdater.getTrackStatistics().getTotalTime();
|
||||
long duration = trackStatisticsUpdater.getTrackStatistics().getTotalTime().toMillis();
|
||||
|
||||
// Insert marker
|
||||
Marker newMarker = new Marker(marker.getName(), markerDescription, marker.getCategory(), icon, track.getId(), length, duration, trackPoint.getLocation(), marker.getPhotoUrl());
|
||||
@@ -338,8 +338,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
TrackPoint trackPoint = createTrackPoint();
|
||||
|
||||
if (trackPoint.hasLocation()) {
|
||||
long time = trackPoint.getTime();
|
||||
Date d = new Date(time);
|
||||
Instant time = trackPoint.getTime();
|
||||
if (trackPoint.getLatitude() == 100) {
|
||||
//TODO Remove by 31st December 2021.
|
||||
trackPoint = new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL);
|
||||
@@ -355,12 +354,12 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
}
|
||||
|
||||
// Calculate derived attributes from the previous point
|
||||
if (trackData.lastLocationInCurrentSegment != null && trackData.lastLocationInCurrentSegment.getTime() != 0) {
|
||||
if (trackData.lastLocationInCurrentSegment != null && trackData.lastLocationInCurrentSegment.getTime() == null) {
|
||||
if (!trackPoint.hasSpeed()) {
|
||||
long timeDifference = trackPoint.getTime() - trackData.lastLocationInCurrentSegment.getTime();
|
||||
Duration timeDifference = Duration.between(trackData.lastLocationInCurrentSegment.getTime(), trackPoint.getTime());
|
||||
|
||||
// Check for negative time change
|
||||
if (timeDifference <= 0) {
|
||||
if (timeDifference.isNegative()) {
|
||||
Log.w(TAG, "Time difference not positive.");
|
||||
} else {
|
||||
|
||||
@@ -368,9 +367,8 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
||||
* We don't have a speed and bearing in GPX, make something up from the last two points.
|
||||
* GPS points tend to have some inherent imprecision, speed and bearing will likely be off, so the statistics for things like max speed will also be off.
|
||||
*/
|
||||
double duration = timeDifference * UnitConversions.MS_TO_S;
|
||||
if (trackPoint.hasLocation() && trackData.lastLocationInCurrentSegment.hasLocation()) {
|
||||
double speed = trackData.lastLocationInCurrentSegment.distanceTo(trackPoint) / duration;
|
||||
float speed = trackData.lastLocationInCurrentSegment.distanceTo(trackPoint) / timeDifference.toMillis();
|
||||
trackPoint.setSpeed((float) speed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.app.TaskStackBuilder;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -228,12 +230,12 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
||||
}
|
||||
|
||||
//TODO Throw exception, when not recording.
|
||||
public long getTotalTime() {
|
||||
public Duration getTotalTime() {
|
||||
if (trackStatisticsUpdater == null) {
|
||||
return 0;
|
||||
return Duration.ofSeconds(0);
|
||||
}
|
||||
if (!isPaused()) {
|
||||
trackStatisticsUpdater.updateTime(System.currentTimeMillis());
|
||||
trackStatisticsUpdater.updateTime(Instant.now());
|
||||
}
|
||||
return trackStatisticsUpdater.getTrackStatistics().getTotalTime();
|
||||
}
|
||||
@@ -264,7 +266,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
||||
|
||||
TrackStatistics stats = trackStatisticsUpdater.getTrackStatistics();
|
||||
double length = stats.getTotalDistance();
|
||||
long duration = stats.getTotalTime();
|
||||
long duration = stats.getTotalTime().toMillis();
|
||||
|
||||
// Insert marker
|
||||
Marker marker = new Marker(name, description, category, icon, recordingTrackId, length, duration, trackPoint.getLocation(), photoUrl);
|
||||
@@ -325,7 +327,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
||||
}
|
||||
|
||||
// Sync the real time setting the stop time with current time.
|
||||
track.getTrackStatistics().setStopTime_ms(System.currentTimeMillis());
|
||||
track.getTrackStatistics().setStopTime(Instant.now());
|
||||
trackStatisticsUpdater = new TrackStatisticsUpdater(track.getTrackStatistics());
|
||||
|
||||
insertTrackPoint(track, TrackPoint.createSegmentStartManual());
|
||||
@@ -637,7 +639,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
||||
*/
|
||||
private void insertTrackPointIfNewer(@NonNull Track track, @NonNull TrackPoint trackPoint) {
|
||||
TrackPoint lastValidTrackPoint = getLastValidTrackPointInCurrentSegment(track.getId());
|
||||
if (TrackPointUtils.equalTime(trackPoint, lastValidTrackPoint)) {
|
||||
if (lastValidTrackPoint != null && trackPoint.getTime().equals(lastValidTrackPoint.getTime())) {
|
||||
// Do not insert if inserted already
|
||||
Log.w(TAG, "Ignore insertTrackPoint. trackPoint time same as last valid track point time.");
|
||||
return;
|
||||
@@ -678,7 +680,7 @@ public class TrackRecordingService extends Service implements HandlerServer.Hand
|
||||
* @param track the track
|
||||
*/
|
||||
private void updateTrackTotalTime(Track track) {
|
||||
trackStatisticsUpdater.updateTime(System.currentTimeMillis());
|
||||
trackStatisticsUpdater.updateTime(Instant.now());
|
||||
track.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
|
||||
contentProviderUtils.updateTrack(track);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package de.dennisguse.opentracks.services;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.Marker;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
@@ -85,7 +87,7 @@ class TrackRecordingServiceBinder extends android.os.Binder implements TrackReco
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalTime() {
|
||||
public Duration getTotalTime() {
|
||||
return trackRecordingService.getTotalTime();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ package de.dennisguse.opentracks.services;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.Marker;
|
||||
import de.dennisguse.opentracks.content.data.Track;
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
@@ -59,8 +61,7 @@ public interface TrackRecordingServiceInterface {
|
||||
/**
|
||||
* Gets the total time for the current recording track. Returns 0 if not recording.
|
||||
*/
|
||||
//TODO milliseconds?
|
||||
long getTotalTime();
|
||||
Duration getTotalTime();
|
||||
|
||||
Marker.Id insertMarker(String name, String category, String description, String photoUrl);
|
||||
|
||||
|
||||
+6
-4
@@ -16,6 +16,8 @@
|
||||
|
||||
package de.dennisguse.opentracks.services.handlers;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* This is a simple location listener policy that will always dictate the same polling interval.
|
||||
*
|
||||
@@ -23,19 +25,19 @@ package de.dennisguse.opentracks.services.handlers;
|
||||
*/
|
||||
public class AbsoluteLocationListenerPolicy implements LocationListenerPolicy {
|
||||
|
||||
private final long interval;
|
||||
private final Duration interval;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param interval the interval to request for gps signal
|
||||
*/
|
||||
public AbsoluteLocationListenerPolicy(long interval) {
|
||||
public AbsoluteLocationListenerPolicy(Duration interval) {
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDesiredPollingInterval() {
|
||||
public Duration getDesiredPollingInterval() {
|
||||
return interval;
|
||||
}
|
||||
|
||||
@@ -45,7 +47,7 @@ public class AbsoluteLocationListenerPolicy implements LocationListenerPolicy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateIdleTime(long idleTime) {
|
||||
public void updateIdleTime(Duration idleTime) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
+23
-15
@@ -16,6 +16,8 @@
|
||||
|
||||
package de.dennisguse.opentracks.services.handlers;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* A {@link LocationListenerPolicy} that will change based on how long the user has been stationary.
|
||||
* This policy will dictate a policy based on a min, max and idle time.
|
||||
@@ -25,35 +27,41 @@ package de.dennisguse.opentracks.services.handlers;
|
||||
*/
|
||||
public class AdaptiveLocationListenerPolicy implements LocationListenerPolicy {
|
||||
|
||||
private final long minInterval_ms;
|
||||
private final long maxInterval_ms;
|
||||
private final Duration minInterval;
|
||||
private final Duration maxInterval;
|
||||
private final int minDistance_m;
|
||||
|
||||
// The time the user has been idle at the current location, in milliseconds.
|
||||
private long idleTime;
|
||||
private Duration idleTime;
|
||||
|
||||
/**
|
||||
* Creates a policy that will be bounded by the given minInterval_ms and maxInterval_ms.
|
||||
*
|
||||
* @param minInterval_ms the smallest interval this policy will dictate
|
||||
* @param maxInterval_ms the largest interval this policy will dictate
|
||||
* @param minInterval the smallest interval this policy will dictate
|
||||
* @param maxInterval the largest interval this policy will dictate
|
||||
* @param minDistance_m the minimum distance
|
||||
*/
|
||||
public AdaptiveLocationListenerPolicy(long minInterval_ms, long maxInterval_ms, int minDistance_m) {
|
||||
this.minInterval_ms = minInterval_ms;
|
||||
this.maxInterval_ms = maxInterval_ms;
|
||||
public AdaptiveLocationListenerPolicy(Duration minInterval, Duration maxInterval, int minDistance_m) {
|
||||
this.minInterval = minInterval;
|
||||
this.maxInterval = maxInterval;
|
||||
this.minDistance_m = minDistance_m;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an interval half of the idle time, but bounded by minInterval_ms and maxInterval_ms.
|
||||
* Returns an interval half of the idle time, but bounded by minInterval and maxInterval.
|
||||
*/
|
||||
@Override
|
||||
public long getDesiredPollingInterval() {
|
||||
long desiredInterval_ms = idleTime / 2;
|
||||
public Duration getDesiredPollingInterval() {
|
||||
Duration desiredInterval = idleTime.dividedBy(2);
|
||||
|
||||
// Round to second to avoid setting the interval too often
|
||||
desiredInterval_ms = (desiredInterval_ms / 1000) * 1000;
|
||||
return Math.max(Math.min(maxInterval_ms, desiredInterval_ms), minInterval_ms);
|
||||
desiredInterval = Duration.ofSeconds(desiredInterval.getSeconds());
|
||||
|
||||
if (minInterval.compareTo(desiredInterval) > 0) {
|
||||
return minInterval;
|
||||
} else if (maxInterval.compareTo(desiredInterval) < 0) {
|
||||
return maxInterval;
|
||||
}
|
||||
return desiredInterval;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,7 +70,7 @@ public class AdaptiveLocationListenerPolicy implements LocationListenerPolicy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateIdleTime(long newIdleTime) {
|
||||
public void updateIdleTime(Duration newIdleTime) {
|
||||
idleTime = newIdleTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@ import android.os.Handler;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.util.UnitConversions;
|
||||
|
||||
/**
|
||||
* This class handle GPS status according to received locations and some thresholds.
|
||||
@@ -17,13 +19,13 @@ class GpsStatus {
|
||||
|
||||
private static final String TAG = GpsStatus.class.getSimpleName();
|
||||
|
||||
// The quantity of milliseconds that GpsStatus waits from minimal interval to consider GPS lost.
|
||||
private static final int SIGNAL_LOST_THRESHOLD = (int) (10 * UnitConversions.S_TO_MS);
|
||||
// The duration that GpsStatus waits from minimal interval to consider GPS lost.
|
||||
private static final Duration SIGNAL_LOST_THRESHOLD = Duration.ofSeconds(10);
|
||||
|
||||
// Threshold for accuracy.
|
||||
private double signalBadThreshold;
|
||||
// Threshold for time without points.
|
||||
private int signalLostThreshold;
|
||||
private Duration signalLostThreshold;
|
||||
|
||||
private GpsStatusValue gpsStatus = GpsStatusValue.GPS_NONE;
|
||||
private GpsStatusListener client;
|
||||
@@ -46,7 +48,7 @@ class GpsStatus {
|
||||
public void run() {
|
||||
if (gpsStatus != null && !stopped) {
|
||||
onLocationChanged(null);
|
||||
gpsStatusHandler.postDelayed(gpsStatusRunner, getIntervalThreshold());
|
||||
gpsStatusHandler.postDelayed(gpsStatusRunner, getIntervalThreshold().toMillis());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,11 +65,11 @@ class GpsStatus {
|
||||
* @param client The client.
|
||||
* @param minRecordingInterval Value of min recording interval preference.
|
||||
*/
|
||||
public GpsStatus(Context context, GpsStatusListener client, int minRecordingInterval) {
|
||||
public GpsStatus(Context context, GpsStatusListener client, Duration minRecordingInterval) {
|
||||
this.client = client;
|
||||
this.context = context;
|
||||
signalBadThreshold = PreferencesUtils.getRecordingDistanceInterval(context);
|
||||
signalLostThreshold = minRecordingInterval > 0 ? minRecordingInterval * (int) UnitConversions.ONE_SECOND_MS + SIGNAL_LOST_THRESHOLD : SIGNAL_LOST_THRESHOLD;
|
||||
signalLostThreshold = !minRecordingInterval.isNegative() ? SIGNAL_LOST_THRESHOLD.plus(minRecordingInterval) : SIGNAL_LOST_THRESHOLD;
|
||||
gpsStatusHandler = new Handler();
|
||||
}
|
||||
|
||||
@@ -97,7 +99,7 @@ class GpsStatus {
|
||||
* @param value Minimal recording interval preference value in seconds or an special value: -1, -2, 0.
|
||||
*/
|
||||
public void onMinRecordingIntervalChanged(int value) {
|
||||
signalLostThreshold = value > 0 ? value * (int) UnitConversions.ONE_SECOND_MS + SIGNAL_LOST_THRESHOLD : SIGNAL_LOST_THRESHOLD;
|
||||
signalLostThreshold = value > 0 ? SIGNAL_LOST_THRESHOLD.plus(Duration.ofSeconds(value)) : SIGNAL_LOST_THRESHOLD;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,7 +121,7 @@ class GpsStatus {
|
||||
|
||||
if (trackPoint != null) {
|
||||
// Update trackPoint's time to the current time millis when trackPoint has been received.
|
||||
trackPoint.setTime(System.currentTimeMillis());
|
||||
trackPoint.setTime(Instant.now());
|
||||
lastValidTrackPoint = trackPoint;
|
||||
}
|
||||
lastTrackPoint = trackPoint;
|
||||
@@ -133,7 +135,7 @@ class GpsStatus {
|
||||
* Also, it'll run the runnable if signal is bad or stop it if the signal is lost.
|
||||
*/
|
||||
private void checkStatusFromLastLocation() {
|
||||
if (System.currentTimeMillis() - lastTrackPoint.getTime() > signalLostThreshold && gpsStatus != GpsStatusValue.GPS_SIGNAL_LOST) {
|
||||
if (Duration.between(lastTrackPoint.getTime(), Instant.now()).compareTo(signalLostThreshold) > 0 && gpsStatus != GpsStatusValue.GPS_SIGNAL_LOST) {
|
||||
// Too much time without receiving signal -> signal lost.
|
||||
GpsStatusValue oldStatus = gpsStatus;
|
||||
gpsStatus = GpsStatusValue.GPS_SIGNAL_LOST;
|
||||
@@ -160,7 +162,8 @@ class GpsStatus {
|
||||
* If there is any change then it does the change.
|
||||
*/
|
||||
private void checkStatusFromLastValidLocation() {
|
||||
if (System.currentTimeMillis() - lastValidTrackPoint.getTime() > signalLostThreshold) {
|
||||
Duration elapsed = Duration.between(lastValidTrackPoint.getTime(), Instant.now());
|
||||
if (signalLostThreshold.minus(elapsed).isNegative()) {
|
||||
// Too much time without locations -> lost signal? (wait signalLostThreshold from last valid location).
|
||||
GpsStatusValue oldStatus = gpsStatus;
|
||||
gpsStatus = GpsStatusValue.GPS_SIGNAL_LOST;
|
||||
@@ -222,7 +225,7 @@ class GpsStatus {
|
||||
}
|
||||
}
|
||||
|
||||
public int getIntervalThreshold() {
|
||||
public Duration getIntervalThreshold() {
|
||||
return signalLostThreshold;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,13 @@ import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
import de.dennisguse.opentracks.util.LocationUtils;
|
||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.util.TrackPointUtils;
|
||||
import de.dennisguse.opentracks.util.UnitConversions;
|
||||
|
||||
class LocationHandler implements HandlerServer.Handler, LocationListener, GpsStatus.GpsStatusListener {
|
||||
|
||||
@@ -25,7 +26,7 @@ class LocationHandler implements HandlerServer.Handler, LocationListener, GpsSta
|
||||
private final HandlerServer handlerServer;
|
||||
private GpsStatus gpsStatus;
|
||||
private LocationListenerPolicy locationListenerPolicy;
|
||||
private long currentRecordingInterval;
|
||||
private Duration currentRecordingInterval;
|
||||
private int recordingGpsAccuracy;
|
||||
private TrackPoint lastValidTrackPoint;
|
||||
|
||||
@@ -35,7 +36,7 @@ class LocationHandler implements HandlerServer.Handler, LocationListener, GpsSta
|
||||
|
||||
@Override
|
||||
public void onStart(Context context) {
|
||||
gpsStatus = new GpsStatus(context, this, PreferencesUtils.getMinRecordingInterval(context));
|
||||
gpsStatus = new GpsStatus(context, this, Duration.ofSeconds(PreferencesUtils.getMinRecordingInterval(context)));
|
||||
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
|
||||
registerLocationListener();
|
||||
}
|
||||
@@ -56,12 +57,12 @@ class LocationHandler implements HandlerServer.Handler, LocationListener, GpsSta
|
||||
int minRecordingInterval = PreferencesUtils.getMinRecordingInterval(context);
|
||||
if (minRecordingInterval == PreferencesUtils.getMinRecordingIntervalAdaptBatteryLife(context)) {
|
||||
// Choose battery life over moving time accuracy.
|
||||
locationListenerPolicy = new AdaptiveLocationListenerPolicy(30 * UnitConversions.ONE_SECOND_MS, 5 * UnitConversions.ONE_MINUTE_MS, 5);
|
||||
locationListenerPolicy = new AdaptiveLocationListenerPolicy(Duration.ofSeconds(30), Duration.ofSeconds(5), 5);
|
||||
} else if (minRecordingInterval == PreferencesUtils.getMinRecordingIntervalAdaptAccuracy(context)) {
|
||||
// Get all the updates.
|
||||
locationListenerPolicy = new AdaptiveLocationListenerPolicy(UnitConversions.ONE_SECOND_MS, 30 * UnitConversions.ONE_SECOND_MS, 0);
|
||||
locationListenerPolicy = new AdaptiveLocationListenerPolicy(Duration.ofSeconds(1), Duration.ofSeconds(30), 0);
|
||||
} else {
|
||||
locationListenerPolicy = new AbsoluteLocationListenerPolicy(minRecordingInterval * UnitConversions.ONE_SECOND_MS);
|
||||
locationListenerPolicy = new AbsoluteLocationListenerPolicy(Duration.ofSeconds(minRecordingInterval));
|
||||
}
|
||||
|
||||
if (locationManager != null) {
|
||||
@@ -108,9 +109,9 @@ class LocationHandler implements HandlerServer.Handler, LocationListener, GpsSta
|
||||
return;
|
||||
}
|
||||
|
||||
long idleTime = 0L;
|
||||
if (TrackPointUtils.after(trackPoint, lastValidTrackPoint)) {
|
||||
idleTime = trackPoint.getTime() - lastValidTrackPoint.getTime();
|
||||
Duration idleTime = Duration.ofSeconds(0);
|
||||
if (lastValidTrackPoint != null && trackPoint.getTime().isAfter(lastValidTrackPoint.getTime())) {
|
||||
idleTime = Duration.between(lastValidTrackPoint.getTime(), trackPoint.getTime());
|
||||
}
|
||||
|
||||
locationListenerPolicy.updateIdleTime(idleTime);
|
||||
@@ -146,9 +147,9 @@ class LocationHandler implements HandlerServer.Handler, LocationListener, GpsSta
|
||||
return;
|
||||
}
|
||||
try {
|
||||
long interval = locationListenerPolicy.getDesiredPollingInterval();
|
||||
Duration interval = locationListenerPolicy.getDesiredPollingInterval();
|
||||
currentRecordingInterval = interval;
|
||||
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval, locationListenerPolicy.getMinDistance_m(), this);
|
||||
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval.toMillis(), locationListenerPolicy.getMinDistance_m(), this);
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG, "Could not register location listener; permissions not granted.", e);
|
||||
}
|
||||
|
||||
+4
-2
@@ -16,6 +16,8 @@
|
||||
|
||||
package de.dennisguse.opentracks.services.handlers;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* This is an interface for classes that will manage the location listener policy.
|
||||
*
|
||||
@@ -28,7 +30,7 @@ interface LocationListenerPolicy {
|
||||
*
|
||||
* @return the polling interval
|
||||
*/
|
||||
long getDesiredPollingInterval();
|
||||
Duration getDesiredPollingInterval();
|
||||
|
||||
/**
|
||||
* Returns the minimum distance between updates.
|
||||
@@ -40,5 +42,5 @@ interface LocationListenerPolicy {
|
||||
*
|
||||
* @param idleTime the time that the user has been idle at his current location
|
||||
*/
|
||||
void updateIdleTime(long idleTime);
|
||||
void updateIdleTime(Duration idleTime);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ package de.dennisguse.opentracks.services.tasks;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
@@ -92,7 +94,7 @@ public class PeriodicTaskExecutor {
|
||||
if (timerTaskExecutor == null) {
|
||||
timerTaskExecutor = new TimerTaskExecutor(periodicTask, trackRecordingService);
|
||||
}
|
||||
timerTaskExecutor.scheduleTask(taskFrequency * UnitConversions.ONE_MINUTE_MS);
|
||||
timerTaskExecutor.scheduleTask(Duration.ofSeconds(taskFrequency));
|
||||
} else {
|
||||
// For distance periodic task
|
||||
calculateNextTaskDistance();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package de.dennisguse.opentracks.services.tasks;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Date;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
@@ -42,15 +43,9 @@ class TimerTaskExecutor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the periodic task in milliseconds.
|
||||
*
|
||||
* @param interval_ms the interval_ms
|
||||
* Schedules the periodic task.
|
||||
*/
|
||||
void scheduleTask(long interval_ms) {
|
||||
if (interval_ms <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
void scheduleTask(Duration interval) {
|
||||
if (!trackRecordingService.isRecording() || trackRecordingService.isPaused()) {
|
||||
return;
|
||||
}
|
||||
@@ -69,8 +64,10 @@ class TimerTaskExecutor {
|
||||
}
|
||||
};
|
||||
timer = new Timer(TimerTaskExecutor.class.getSimpleName());
|
||||
long next = System.currentTimeMillis() + interval_ms - (trackStatistics.getTotalTime() % interval_ms);
|
||||
timer.scheduleAtFixedRate(timerTask, new Date(next), interval_ms);
|
||||
|
||||
//TODO Simplify: far too complicated for it's purpose
|
||||
long next = System.currentTimeMillis() + interval.toMillis() - (trackStatistics.getTotalTime().toMillis() % interval.toMillis());
|
||||
timer.scheduleAtFixedRate(timerTask, new Date(next), interval.toMillis());
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
|
||||
@@ -19,6 +19,9 @@ package de.dennisguse.opentracks.stats;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* Statistical data about a {@link de.dennisguse.opentracks.content.data.Track}.
|
||||
* The data in this class should be filled out by {@link TrackStatisticsUpdater}.
|
||||
@@ -33,15 +36,15 @@ public class TrackStatistics {
|
||||
private final ExtremityMonitor elevationExtremities = new ExtremityMonitor();
|
||||
|
||||
// The track start time.
|
||||
private long startTime_ms;
|
||||
private Instant startTime;
|
||||
// The track stop time.
|
||||
private long stopTime_ms;
|
||||
private Instant stopTime;
|
||||
|
||||
private double totalDistance_m;
|
||||
// Updated when new points are received, may be stale.
|
||||
private long totalTime_ms;
|
||||
private Duration totalTime;
|
||||
// Based on when we believe the user is traveling.
|
||||
private long movingTime_ms;
|
||||
private Duration movingTime;
|
||||
// The maximum speed (meters/second) that we believe is valid.
|
||||
private double maxSpeed_mps;
|
||||
// The total elevation gained (meters).
|
||||
@@ -60,11 +63,11 @@ public class TrackStatistics {
|
||||
* @param other another statistics data object to copy from
|
||||
*/
|
||||
public TrackStatistics(TrackStatistics other) {
|
||||
startTime_ms = other.startTime_ms;
|
||||
stopTime_ms = other.stopTime_ms;
|
||||
startTime = other.startTime;
|
||||
stopTime = other.stopTime;
|
||||
totalDistance_m = other.totalDistance_m;
|
||||
totalTime_ms = other.totalTime_ms;
|
||||
movingTime_ms = other.movingTime_ms;
|
||||
totalTime = other.totalTime;
|
||||
movingTime = other.movingTime;
|
||||
maxSpeed_mps = other.maxSpeed_mps;
|
||||
elevationExtremities.set(other.elevationExtremities.getMin(), other.elevationExtremities.getMax());
|
||||
totalElevationGain_m = other.totalElevationGain_m;
|
||||
@@ -78,11 +81,11 @@ public class TrackStatistics {
|
||||
* @param other another statistics data object
|
||||
*/
|
||||
public void merge(TrackStatistics other) {
|
||||
startTime_ms = Math.min(startTime_ms, other.startTime_ms);
|
||||
stopTime_ms = Math.max(stopTime_ms, other.stopTime_ms);
|
||||
startTime = startTime.isBefore(other.startTime) ? startTime : other.startTime;
|
||||
stopTime = stopTime.isAfter(other.stopTime) ? stopTime : other.stopTime;
|
||||
totalDistance_m += other.totalDistance_m;
|
||||
totalTime_ms += other.totalTime_ms;
|
||||
movingTime_ms += other.movingTime_ms;
|
||||
totalTime = totalTime.plus(other.totalTime);
|
||||
movingTime = movingTime.plus(other.movingTime);
|
||||
maxSpeed_mps = Math.max(maxSpeed_mps, other.maxSpeed_mps);
|
||||
if (other.elevationExtremities.hasData()) {
|
||||
elevationExtremities.update(other.elevationExtremities.getMin());
|
||||
@@ -109,44 +112,41 @@ public class TrackStatistics {
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
setStartTime_ms(0);
|
||||
setStartTime(Instant.ofEpochMilli(0)); //TODO should probably initialized with null
|
||||
|
||||
setTotalDistance(0);
|
||||
setTotalTime(0);
|
||||
setMovingTime(0);
|
||||
setTotalTime(Duration.ofSeconds(0));
|
||||
setMovingTime(Duration.ofSeconds(0));
|
||||
setMaxSpeed(0);
|
||||
setTotalElevationGain(null);
|
||||
}
|
||||
|
||||
public void reset(long startTime_ms) {
|
||||
public void reset(Instant startTime) {
|
||||
reset();
|
||||
setStartTime_ms(startTime_ms);
|
||||
setStartTime(startTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the track start time. The number of milliseconds since epoch.
|
||||
*/
|
||||
public long getStartTime_ms() {
|
||||
return startTime_ms;
|
||||
public Instant getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should only be called on start.
|
||||
*/
|
||||
public void setStartTime_ms(long startTime_ms) {
|
||||
this.startTime_ms = startTime_ms;
|
||||
setStopTime_ms(startTime_ms);
|
||||
public void setStartTime(Instant startTime) {
|
||||
this.startTime = startTime;
|
||||
setStopTime(startTime);
|
||||
}
|
||||
|
||||
public long getStopTime_ms() {
|
||||
return stopTime_ms;
|
||||
public Instant getStopTime() {
|
||||
return stopTime;
|
||||
}
|
||||
|
||||
public void setStopTime_ms(long stopTime_ms) {
|
||||
if (stopTime_ms < startTime_ms) {
|
||||
throw new RuntimeException("stopTime cannot be less than startTime: " + startTime_ms + " " + stopTime_ms);
|
||||
public void setStopTime(Instant stopTime) {
|
||||
if (stopTime.isBefore(startTime)) {
|
||||
throw new RuntimeException("stopTime cannot be less than startTime: " + startTime + " " + stopTime);
|
||||
}
|
||||
this.stopTime_ms = stopTime_ms;
|
||||
this.stopTime = stopTime;
|
||||
}
|
||||
|
||||
public double getTotalDistance() {
|
||||
@@ -164,26 +164,26 @@ public class TrackStatistics {
|
||||
/**
|
||||
* Gets the total time in milliseconds that this track has been active.
|
||||
* This statistic is only updated when a new point is added to the statistics, so it may be off.
|
||||
* If you need to calculate the proper total time, use {@link #getStartTime_ms} with the current time.
|
||||
* If you need to calculate the proper total time, use {@link #getStartTime} with the current time.
|
||||
*/
|
||||
public long getTotalTime() {
|
||||
return totalTime_ms;
|
||||
public Duration getTotalTime() {
|
||||
return totalTime;
|
||||
}
|
||||
|
||||
public void setTotalTime(long totalTime_ms) {
|
||||
this.totalTime_ms = totalTime_ms;
|
||||
public void setTotalTime(Duration totalTime) {
|
||||
this.totalTime = totalTime;
|
||||
}
|
||||
|
||||
public long getMovingTime() {
|
||||
return movingTime_ms;
|
||||
public Duration getMovingTime() {
|
||||
return movingTime;
|
||||
}
|
||||
|
||||
public void setMovingTime(long movingTime_ms) {
|
||||
this.movingTime_ms = movingTime_ms;
|
||||
public void setMovingTime(Duration movingTime) {
|
||||
this.movingTime = movingTime;
|
||||
}
|
||||
|
||||
public void addMovingTime(long time_ms) {
|
||||
movingTime_ms += time_ms;
|
||||
public void addMovingTime(Duration time) {
|
||||
movingTime = movingTime.plus(time);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,20 +191,20 @@ public class TrackStatistics {
|
||||
* This calculation only takes into account the displacement until the last point that was accounted for in statistics.
|
||||
*/
|
||||
public double getAverageSpeed() {
|
||||
if (totalTime_ms == 0L) {
|
||||
if (totalTime.isZero()) {
|
||||
return 0.0;
|
||||
}
|
||||
return totalDistance_m / ((double) totalTime_ms / 1000.0);
|
||||
return totalDistance_m / (double) totalTime.getSeconds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the average moving speed in meters/second.
|
||||
*/
|
||||
public double getAverageMovingSpeed() {
|
||||
if (movingTime_ms == 0L) {
|
||||
if (movingTime.isZero()) {
|
||||
return 0.0;
|
||||
}
|
||||
return totalDistance_m / ((double) movingTime_ms / 1000.0);
|
||||
return totalDistance_m / (double) movingTime.getSeconds();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -317,7 +317,7 @@ public class TrackStatistics {
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TrackStatistics { Start Time: " + getStartTime_ms() + "; Stop Time: " + getStopTime_ms()
|
||||
return "TrackStatistics { Start Time: " + getStartTime() + "; Stop Time: " + getStopTime()
|
||||
+ "; Total Distance: " + getTotalDistance() + "; Total Time: " + getTotalTime()
|
||||
+ "; Moving Time: " + getMovingTime() + "; Max Speed: " + getMaxSpeed()
|
||||
+ "; Min Elevation: " + getMinElevation() + "; Max Elevation: " + getMaxElevation()
|
||||
|
||||
@@ -21,6 +21,9 @@ import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
import de.dennisguse.opentracks.content.provider.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.util.TrackPointUtils;
|
||||
@@ -88,9 +91,9 @@ public class TrackStatisticsUpdater {
|
||||
trackInitialized = true;
|
||||
}
|
||||
|
||||
public void updateTime(long time_ms) {
|
||||
currentSegment.setStopTime_ms(time_ms);
|
||||
currentSegment.setTotalTime(time_ms - currentSegment.getStartTime_ms());
|
||||
public void updateTime(Instant time) {
|
||||
currentSegment.setStopTime(time);
|
||||
currentSegment.setTotalTime(Duration.between(currentSegment.getStartTime(), time));
|
||||
}
|
||||
|
||||
public TrackStatistics getTrackStatistics() {
|
||||
@@ -108,11 +111,11 @@ public class TrackStatisticsUpdater {
|
||||
*/
|
||||
public void addTrackPoint(TrackPoint trackPoint, int minRecordingDistance) {
|
||||
if (!trackInitialized) {
|
||||
trackStatistics.setStartTime_ms(trackPoint.getTime());
|
||||
trackStatistics.setStartTime(trackPoint.getTime());
|
||||
trackInitialized = true;
|
||||
}
|
||||
if (!segmentInitialized) {
|
||||
currentSegment.setStartTime_ms(trackPoint.getTime());
|
||||
currentSegment.setStartTime(trackPoint.getTime());
|
||||
segmentInitialized = true;
|
||||
}
|
||||
|
||||
@@ -162,8 +165,8 @@ public class TrackStatisticsUpdater {
|
||||
lastTrackPoint = trackPoint;
|
||||
return;
|
||||
}
|
||||
long movingTime = trackPoint.getTime() - lastTrackPoint.getTime();
|
||||
if (movingTime < 0) {
|
||||
Duration movingTime = Duration.between(lastTrackPoint.getTime(), trackPoint.getTime());
|
||||
if (movingTime.isNegative()) {
|
||||
lastTrackPoint = trackPoint;
|
||||
return;
|
||||
}
|
||||
@@ -252,9 +255,9 @@ public class TrackStatisticsUpdater {
|
||||
}
|
||||
|
||||
// See if the speed seems physically likely. Ignore any speeds that imply acceleration greater than 2g.
|
||||
long timeDifference = trackPoint.getTime() - lastTrackPoint.getTime();
|
||||
Duration timeDifference = Duration.between(lastTrackPoint.getTime(), trackPoint.getTime());
|
||||
double speedDifference = Math.abs(lastTrackPoint.getSpeed() - trackPoint.getSpeed());
|
||||
if (speedDifference > MAX_ACCELERATION * timeDifference) {
|
||||
if (speedDifference > MAX_ACCELERATION * timeDifference.toMillis()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -262,7 +265,7 @@ public class TrackStatisticsUpdater {
|
||||
if (speedBuffer_ms.isFull()) {
|
||||
double average = speedBuffer_ms.getAverage();
|
||||
double diff = Math.abs(average - trackPoint.getSpeed());
|
||||
return (trackPoint.getSpeed() < average * 10) && (diff < MAX_ACCELERATION * timeDifference);
|
||||
return (trackPoint.getSpeed() < average * 10) && (diff < MAX_ACCELERATION * timeDifference.toMillis());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -4,13 +4,16 @@ import android.content.Context;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.viewmodels.IntervalStatistics;
|
||||
|
||||
public class AnnouncementUtils {
|
||||
|
||||
private AnnouncementUtils() {}
|
||||
private AnnouncementUtils() {
|
||||
}
|
||||
|
||||
public static String getAnnouncement(Context context, TrackStatistics trackStatistics, String category, @Nullable IntervalStatistics.Interval currentInterval) {
|
||||
boolean metricUnits = PreferencesUtils.isMetricUnits(context);
|
||||
@@ -41,11 +44,11 @@ public class AnnouncementUtils {
|
||||
} else {
|
||||
double timePerDistance = distancePerTime == 0 ? 0.0 : 1 / distancePerTime;
|
||||
int paceId = metricUnits ? R.string.voice_pace_per_kilometer : R.string.voice_pace_per_mile;
|
||||
long time = Math.round(timePerDistance * UnitConversions.HR_TO_MIN * UnitConversions.MIN_TO_S * UnitConversions.S_TO_MS);
|
||||
Duration time = Duration.ofMillis((long) (timePerDistance * UnitConversions.HR_TO_MIN * UnitConversions.MIN_TO_S * UnitConversions.S_TO_MS));
|
||||
rate = context.getString(paceId, getAnnounceTime(context, time));
|
||||
|
||||
double currentTimePerDistance = currentDistancePerTime == 0 ? 0.0 : 1 / currentDistancePerTime;
|
||||
long currentTime = Math.round(currentTimePerDistance * UnitConversions.HR_TO_MIN * UnitConversions.MIN_TO_S * UnitConversions.S_TO_MS);
|
||||
Duration currentTime = Duration.ofMillis((long) (currentTimePerDistance * UnitConversions.HR_TO_MIN * UnitConversions.MIN_TO_S * UnitConversions.S_TO_MS));
|
||||
currentRate = context.getString(paceId, getAnnounceTime(context, currentTime));
|
||||
currentRateMsg = context.getString(R.string.voice_pace_lap, currentRate);
|
||||
}
|
||||
@@ -58,23 +61,25 @@ public class AnnouncementUtils {
|
||||
return context.getString(R.string.voice_template, totalDistance, getAnnounceTime(context, trackStatistics.getMovingTime()), rate) + currentRateMsg;
|
||||
}
|
||||
|
||||
private static String getAnnounceTime(Context context, long time) {
|
||||
int[] parts = StringUtils.getTimeParts(time);
|
||||
String seconds = context.getResources()
|
||||
.getQuantityString(R.plurals.voiceSeconds, parts[0], parts[0]);
|
||||
String minutes = context.getResources()
|
||||
.getQuantityString(R.plurals.voiceMinutes, parts[1], parts[1]);
|
||||
String hours = context.getResources()
|
||||
.getQuantityString(R.plurals.voiceHours, parts[2], parts[2]);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (parts[2] != 0) {
|
||||
sb.append(hours);
|
||||
sb.append(" ");
|
||||
//TODO We might need to localize this using strings.xml if order is relevant.
|
||||
private static String getAnnounceTime(Context context, Duration duration) {
|
||||
String result = "";
|
||||
|
||||
int hours = (int) (duration.getSeconds() / (60 * 60));
|
||||
int minutes = (int) (duration.getSeconds() / 60);
|
||||
int seconds = (int) (duration.getSeconds() % 60);
|
||||
|
||||
if (hours != 0) {
|
||||
String hoursText = context.getResources()
|
||||
.getQuantityString(R.plurals.voiceHours, hours, hours);
|
||||
result += hoursText + " ";
|
||||
}
|
||||
sb.append(minutes);
|
||||
sb.append(" ");
|
||||
sb.append(seconds);
|
||||
return sb.toString();
|
||||
String minutesText = context.getResources()
|
||||
.getQuantityString(R.plurals.voiceMinutes, minutes, minutes);
|
||||
String secondsText = context.getResources()
|
||||
.getQuantityString(R.plurals.voiceSeconds, seconds, seconds);
|
||||
|
||||
return result + minutesText + " " + secondsText;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,6 +17,9 @@ package de.dennisguse.opentracks.util;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.TrackPoint;
|
||||
|
||||
/**
|
||||
@@ -28,8 +31,7 @@ public class LocationUtils {
|
||||
|
||||
private static final String TAG = LocationUtils.class.getSimpleName();
|
||||
|
||||
// 1 minute in milliseconds
|
||||
private static final long MAX_LOCATION_AGE_MS = (long) (UnitConversions.MIN_TO_S * UnitConversions.S_TO_MS);
|
||||
private static final Duration MAX_LOCATION_AGE = Duration.ofMinutes(1);
|
||||
|
||||
private LocationUtils() {
|
||||
}
|
||||
@@ -48,6 +50,8 @@ public class LocationUtils {
|
||||
}
|
||||
|
||||
public static boolean isTrackPointOld(TrackPoint trackPoint) {
|
||||
return System.currentTimeMillis() - trackPoint.getTime() > MAX_LOCATION_AGE_MS;
|
||||
return Duration.between(trackPoint.getTime(), Instant.now())
|
||||
.minus(MAX_LOCATION_AGE)
|
||||
.isNegative();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,11 @@ import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
@@ -50,41 +53,32 @@ public class StringUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the date and time_ms based on user's phone date/time_ms preferences.
|
||||
*
|
||||
* @param context the context
|
||||
* @param time_ms the time_ms in milliseconds
|
||||
* Formats the date and time based on user's phone date/time preferences.
|
||||
*/
|
||||
public static String formatDateTime(Context context, long time_ms) {
|
||||
return DateUtils.formatDateTime(context, time_ms, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE)
|
||||
+ " " + DateUtils.formatDateTime(context, time_ms, DateUtils.FORMAT_SHOW_TIME);
|
||||
public static String formatDateTime(Context context, Instant time) {
|
||||
return DateUtils.formatDateTime(context, time.toEpochMilli(), DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE)
|
||||
+ " " + DateUtils.formatDateTime(context, time.toEpochMilli(), DateUtils.FORMAT_SHOW_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the time using the ISO 8601 date time_ms format with fractional seconds in UTC time zone.
|
||||
*
|
||||
* @param time_ms the time in milliseconds
|
||||
* Formats the time using the ISO 8601 date time format with fractional seconds in UTC time zone.
|
||||
*/
|
||||
public static String formatDateTimeIso8601(long time_ms) {
|
||||
return Instant.ofEpochMilli(time_ms).toString();
|
||||
public static String formatDateTimeIso8601(@NonNull Instant time) {
|
||||
return time.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the elapsed timed in the form "MM:SS" or "H:MM:SS".
|
||||
*
|
||||
* @param time_ms the time in milliseconds
|
||||
*/
|
||||
public static String formatElapsedTime(long time_ms) {
|
||||
return DateUtils.formatElapsedTime((long) (time_ms * UnitConversions.MS_TO_S));
|
||||
public static String formatElapsedTime(@NonNull Duration time) {
|
||||
return DateUtils.formatElapsedTime(time.getSeconds());
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the elapsed time in the form "H:MM:SS".
|
||||
*
|
||||
* @param time_ms the time in milliseconds
|
||||
*/
|
||||
public static String formatElapsedTimeWithHour(long time_ms) {
|
||||
String value = formatElapsedTime(time_ms);
|
||||
public static String formatElapsedTimeWithHour(@NonNull Duration time) {
|
||||
String value = formatElapsedTime(time);
|
||||
return TextUtils.split(value, ":").length == 2 ? "0:" + value : value;
|
||||
}
|
||||
|
||||
@@ -289,45 +283,20 @@ public class StringUtils {
|
||||
*
|
||||
* @param xmlDateTime the XML date time string
|
||||
*/
|
||||
public static long parseTime(String xmlDateTime) {
|
||||
public static Instant parseTime(String xmlDateTime) {
|
||||
try {
|
||||
TemporalAccessor t = DateTimeFormatter.ISO_DATE_TIME.parseBest(xmlDateTime, ZonedDateTime::from, LocalDateTime::from);
|
||||
if (t instanceof LocalDateTime) {
|
||||
Log.w(TAG, "Date does not contain timezone information: using UTC.");
|
||||
t = ((LocalDateTime) t).atZone(ZoneOffset.UTC);
|
||||
}
|
||||
return Instant.from(t).toEpochMilli();
|
||||
return Instant.from(t);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Invalid XML dateTime value");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time as an array of three integers.
|
||||
* Index 0 contains the number of seconds, index 1 contains the number of minutes, and index 2 contains the number of hours.
|
||||
*
|
||||
* @param time the time in milliseconds
|
||||
* @return an array of 3 elements.
|
||||
*/
|
||||
public static int[] getTimeParts(long time) {
|
||||
if (time < 0) {
|
||||
int[] parts = getTimeParts(time * -1);
|
||||
parts[0] *= -1;
|
||||
parts[1] *= -1;
|
||||
parts[2] *= -1;
|
||||
return parts;
|
||||
}
|
||||
int[] parts = new int[3];
|
||||
|
||||
long seconds = (long) (time * UnitConversions.MS_TO_S);
|
||||
parts[0] = (int) (seconds % 60);
|
||||
int minutes = (int) (seconds / 60);
|
||||
parts[1] = minutes % 60;
|
||||
parts[2] = minutes / 60;
|
||||
return parts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the frequency display options.
|
||||
*
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.content.Context;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
@@ -40,20 +41,13 @@ public class TrackNameUtils {
|
||||
private TrackNameUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the track name.
|
||||
*
|
||||
* @param context the context
|
||||
* @param trackId the track id
|
||||
* @param startTime the track start time
|
||||
*/
|
||||
public static String getTrackName(Context context, Track.Id trackId, long startTime) {
|
||||
public static String getTrackName(Context context, Track.Id trackId, Instant startTime) {
|
||||
String trackName = PreferencesUtils.getString(context, R.string.track_name_key, context.getString(R.string.track_name_default));
|
||||
|
||||
if (trackName.equals(context.getString(R.string.settings_recording_track_name_date_local_value))) {
|
||||
return StringUtils.formatDateTime(context, startTime);
|
||||
} else if (trackName.equals(context.getString(R.string.settings_recording_track_name_date_iso_8601_value))) {
|
||||
return new SimpleDateFormat(ISO_8601_FORMAT, Locale.US).format(startTime);
|
||||
return new SimpleDateFormat(ISO_8601_FORMAT, Locale.US).format(startTime.toEpochMilli());
|
||||
} else {
|
||||
return context.getString(R.string.track_name_format, trackId.getId());
|
||||
}
|
||||
|
||||
@@ -18,22 +18,6 @@ public class TrackPointUtils {
|
||||
return trackPoint.hasSpeed() && trackPoint.getSpeed() >= MAX_NO_MOVEMENT_SPEED;
|
||||
}
|
||||
|
||||
public static boolean equalTime(TrackPoint t1, TrackPoint t2) {
|
||||
if (t1 == null || t2 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return t1.getTime() == t2.getTime();
|
||||
}
|
||||
|
||||
public static boolean after(TrackPoint t1, TrackPoint t2) {
|
||||
if (t1 == null || t2 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return t1.getTime() > t2.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is accuracy better than threshold?
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.dennisguse.opentracks.viewmodels;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -33,7 +34,7 @@ public class IntervalStatistics {
|
||||
|
||||
if (trackPoint.hasLocation() && prevTrackPoint.hasLocation()) {
|
||||
interval.distance_m += prevTrackPoint.distanceTo(trackPoint);
|
||||
interval.time_ms += trackPoint.getTime() - prevTrackPoint.getTime();
|
||||
interval.time = interval.time.plus(Duration.between(prevTrackPoint.getTime(), trackPoint.getTime()));
|
||||
interval.gain_m += trackPoint.hasElevationGain() ? trackPoint.getElevationGain() : 0;
|
||||
interval.loss_m += trackPoint.hasElevationLoss() ? trackPoint.getElevationLoss() : 0;
|
||||
|
||||
@@ -44,7 +45,7 @@ public class IntervalStatistics {
|
||||
|
||||
intervalList.add(adjustedInterval);
|
||||
|
||||
interval = new Interval(interval.distance_m - adjustedInterval.distance_m, interval.time_ms - adjustedInterval.time_ms);
|
||||
interval = new Interval(interval.distance_m - adjustedInterval.distance_m, interval.time.minus(adjustedInterval.time));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,22 +82,21 @@ public class IntervalStatistics {
|
||||
|
||||
public static class Interval {
|
||||
private float distance_m = 0f;
|
||||
private float time_ms = 0f;
|
||||
private Duration time = Duration.ofSeconds(0);
|
||||
private float gain_m = 0f;
|
||||
private float loss_m = 0f;
|
||||
|
||||
public Interval() {}
|
||||
public Interval() {
|
||||
}
|
||||
|
||||
public Interval(float distance_m, float time_ms) {
|
||||
public Interval(float distance_m, Duration time) {
|
||||
this.distance_m = distance_m;
|
||||
this.time_ms = time_ms;
|
||||
this.gain_m = 0f;
|
||||
this.loss_m = 0f;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public Interval(Interval i) {
|
||||
distance_m = i.distance_m;
|
||||
time_ms = i.time_ms;
|
||||
time = i.time;
|
||||
gain_m = i.gain_m;
|
||||
loss_m = i.loss_m;
|
||||
}
|
||||
@@ -107,7 +107,7 @@ public class IntervalStatistics {
|
||||
|
||||
public void adjust(float adjustFactor) {
|
||||
distance_m *= adjustFactor;
|
||||
time_ms *= adjustFactor;
|
||||
time = Duration.ofMillis((long) (time.toMillis() * adjustFactor));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +117,7 @@ public class IntervalStatistics {
|
||||
if (distance_m == 0f) {
|
||||
return 0f;
|
||||
}
|
||||
return distance_m / (float) (time_ms * UnitConversions.MS_TO_S);
|
||||
return (distance_m / (time.toMillis() * (float) UnitConversions.MS_TO_S));
|
||||
}
|
||||
|
||||
public float getGain_m() {
|
||||
|
||||
Reference in New Issue
Block a user