forked from upstream-mirrors/OpenTracks
Merge remote-tracking branch 'origin/main'
This commit is contained in:
Generated
+6
@@ -47,6 +47,12 @@
|
||||
<MarkdownNavigatorCodeStyleSettings>
|
||||
<option name="RIGHT_MARGIN" value="72" />
|
||||
</MarkdownNavigatorCodeStyleSettings>
|
||||
<editorconfig>
|
||||
<option name="ENABLED" value="false" />
|
||||
</editorconfig>
|
||||
<codeStyleSettings language="JAVA">
|
||||
<option name="RIGHT_MARGIN" value="200" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
|
||||
@@ -13,18 +13,20 @@ import java.time.Duration;
|
||||
import de.dennisguse.opentracks.data.models.Altitude;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
|
||||
//TODO assertEquals with ChartPoint (instead of individual comparisons)
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ChartPointTest {
|
||||
|
||||
private static final Statistics STATISTIC_NULL = new Statistics(null, null, Duration.ZERO, null, null, null, null, null, null, null);
|
||||
|
||||
@Test
|
||||
public void create_by_time() {
|
||||
// given
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
statistics.setTotalTime(Duration.ofSeconds(1000));
|
||||
Statistics statistics = new Statistics(null, null, Duration.ofSeconds(1000), null, null, null, null, null, null, null);
|
||||
|
||||
// when
|
||||
ChartPoint point = ChartPoint.create(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(0), false, UnitSystem.IMPERIAL_FEET);
|
||||
@@ -36,8 +38,7 @@ public class ChartPointTest {
|
||||
@Test
|
||||
public void create_by_distance() {
|
||||
// given
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
statistics.setTotalDistance(Distance.of(1000));
|
||||
Statistics statistics = new Statistics(null, null, null, null, Distance.of(1000), null, null, null, null, null);
|
||||
|
||||
// when
|
||||
ChartPoint point = ChartPoint.create(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(0), true, UnitSystem.METRIC);
|
||||
@@ -49,12 +50,11 @@ public class ChartPointTest {
|
||||
@Test
|
||||
public void create_get_altitude_speed_and_pace() {
|
||||
// given
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint()
|
||||
.setAltitude(Altitude.EGM2008.of(50));
|
||||
|
||||
// when
|
||||
ChartPoint point = ChartPoint.create(statistics, trackPoint, Speed.of(10), false, UnitSystem.METRIC);
|
||||
ChartPoint point = ChartPoint.create(STATISTIC_NULL, trackPoint, Speed.of(10), false, UnitSystem.METRIC);
|
||||
|
||||
// then
|
||||
assertEquals(50, point.altitude(), 0.01);
|
||||
@@ -65,11 +65,10 @@ public class ChartPointTest {
|
||||
@Test
|
||||
public void create_sensorNotAvailable() {
|
||||
// given
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
TrackPoint trackPoint = TrackStubUtils.createDefaultTrackPoint()
|
||||
.setAltitude(Altitude.EGM2008.of(50));
|
||||
// when
|
||||
ChartPoint point = ChartPoint.create(statistics, trackPoint, Speed.of(10), false, UnitSystem.METRIC);
|
||||
ChartPoint point = ChartPoint.create(STATISTIC_NULL, trackPoint, Speed.of(10), false, UnitSystem.METRIC);
|
||||
|
||||
// then
|
||||
assertNull(point.heartRate());
|
||||
@@ -86,10 +85,8 @@ public class ChartPointTest {
|
||||
.setCadence(101f)
|
||||
.setPower(102f);
|
||||
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
|
||||
// when
|
||||
ChartPoint point = ChartPoint.create(statistics, trackPoint, Speed.of(10), false, UnitSystem.METRIC);
|
||||
ChartPoint point = ChartPoint.create(STATISTIC_NULL, trackPoint, Speed.of(10), false, UnitSystem.METRIC);
|
||||
|
||||
// then
|
||||
assertEquals(100.0, point.heartRate(), 0.01);
|
||||
|
||||
@@ -6,13 +6,11 @@ import android.util.Pair;
|
||||
|
||||
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 de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.data.models.Altitude;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Marker;
|
||||
@@ -20,9 +18,8 @@ import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
||||
import de.dennisguse.opentracks.ui.markers.MarkerUtils;
|
||||
import de.dennisguse.opentracks.util.AutoCloseableIterator;
|
||||
import de.dennisguse.opentracks.util.FileUtils;
|
||||
|
||||
public class TestDataUtil {
|
||||
@@ -85,10 +82,6 @@ public class TestDataUtil {
|
||||
createTrackPoint(i, TrackPoint.Type.SEGMENT_END_MANUAL)
|
||||
);
|
||||
|
||||
//TODO Use TrackStatisticsUpdater
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setTotalDistance(Distance.of(0));
|
||||
stats.setTotalTime(Duration.ofMillis(0));
|
||||
List<Marker> markers = List.of(
|
||||
new Marker(trackId, trackPoints.get(1), "Marker 1", "Marker description 1", "Marker category 3", "", null),
|
||||
new Marker(trackId, trackPoints.get(4), "Marker 2", "Marker description 2", "Marker category 3", "", null),
|
||||
@@ -126,8 +119,7 @@ public class TestDataUtil {
|
||||
trackPoint.setHeartRate(100f + i % 80);
|
||||
trackPoint.setCadence(300f + i);
|
||||
trackPoint.setPower(400f + i);
|
||||
trackPoint.setAltitudeGain(ALTITUDE_GAIN);
|
||||
trackPoint.setAltitudeLoss(ALTITUDE_LOSS);
|
||||
trackPoint.setAltitudeGainLoss(ALTITUDE_GAIN, ALTITUDE_LOSS);
|
||||
return trackPoint;
|
||||
}
|
||||
|
||||
@@ -153,16 +145,11 @@ public class TestDataUtil {
|
||||
dstFile.createNewFile();
|
||||
Uri photoUri = FileUtils.getUriForFile(context, dstFile);
|
||||
|
||||
//TODO Use TrackStatisticsUpdater
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setTotalDistance(Distance.of(0));
|
||||
stats.setTotalTime(Duration.ofMillis(0));
|
||||
|
||||
return new Marker(trackId, trackPoint, "Marker name", "Marker description", "Marker category", "", photoUri);
|
||||
}
|
||||
|
||||
public static List<TrackPoint> getTrackPoints(ContentProviderUtils contentProviderUtils, Track.Id trackId) {
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
ArrayList<TrackPoint> trackPoints = new ArrayList<>();
|
||||
while (trackPointIterator.hasNext()) {
|
||||
trackPoints.add(trackPointIterator.next());
|
||||
@@ -170,20 +157,4 @@ public class TestDataUtil {
|
||||
return trackPoints;
|
||||
}
|
||||
}
|
||||
|
||||
public static Pair<Track.Id, TrackStatistics> buildTrackWithTrackPoints(ContentProviderUtils contentProviderUtils, int numberOfPoints) {
|
||||
Track dummyTrack = new Track();
|
||||
dummyTrack.setId(new Track.Id(System.currentTimeMillis()));
|
||||
dummyTrack.setName("Dummy Track");
|
||||
contentProviderUtils.insertTrack(dummyTrack);
|
||||
TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater();
|
||||
for (int i = 0; i < numberOfPoints; i++) {
|
||||
TrackPoint tp = TestDataUtil.createTrackPoint(i);
|
||||
contentProviderUtils.insertTrackPoint(tp, dummyTrack.getId());
|
||||
trackStatisticsUpdater.addTrackPoint(tp);
|
||||
}
|
||||
dummyTrack.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
|
||||
contentProviderUtils.updateTrack(dummyTrack);
|
||||
return new Pair<>(dummyTrack.getId(), trackStatisticsUpdater.getTrackStatistics());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,7 @@ public class TestSensorDataUtil {
|
||||
if (power != null) {
|
||||
tp.setPower(power);
|
||||
}
|
||||
tp.setAltitudeGain(3f);
|
||||
tp.setAltitudeLoss(3f);
|
||||
tp.setAltitudeGainLoss(3, 3);
|
||||
trackPointList.add(tp);
|
||||
}
|
||||
|
||||
|
||||
+19
-16
@@ -51,18 +51,21 @@ import java.util.UUID;
|
||||
import de.dennisguse.opentracks.content.data.TestDataUtil;
|
||||
import de.dennisguse.opentracks.content.data.TestSensorDataUtil;
|
||||
import de.dennisguse.opentracks.data.models.Altitude;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeExtremities;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.data.tables.MarkerColumns;
|
||||
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
|
||||
import de.dennisguse.opentracks.data.tables.TracksColumns;
|
||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.AutoCloseableIterator;
|
||||
import de.dennisguse.opentracks.util.FileUtils;
|
||||
|
||||
/**
|
||||
@@ -114,7 +117,7 @@ public class CustomContentProviderUtilsTest {
|
||||
private void testIterator(Track.Id trackId, int numPoints) {
|
||||
TrackPoint.Id lastPointId = initializeTrack(trackId, numPoints);
|
||||
List<TrackPoint> locations = new ArrayList<>(numPoints);
|
||||
try (TrackPointIterator it = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
try (AutoCloseableIterator<TrackPoint> it = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
while (it.hasNext()) {
|
||||
TrackPoint trackPoint = it.next();
|
||||
assertNotNull(trackPoint);
|
||||
@@ -152,7 +155,7 @@ public class CustomContentProviderUtilsTest {
|
||||
// Load all inserted trackPoints.
|
||||
TrackPoint.Id lastPointId = null;
|
||||
int counter = 0;
|
||||
try (TrackPointIterator it = contentProviderUtils.getTrackPointLocationIterator(id, null)) {
|
||||
try (AutoCloseableIterator<TrackPoint> it = contentProviderUtils.getTrackPointLocationIterator(id, null)) {
|
||||
while (it.hasNext()) {
|
||||
TrackPoint trackPoint = it.next();
|
||||
lastPointId = trackPoint.getId();
|
||||
@@ -406,18 +409,18 @@ public class CustomContentProviderUtilsTest {
|
||||
Pair<Track, List<TrackPoint>> track = TestDataUtil.createTrack(trackId, 10);
|
||||
|
||||
// AverageSpeed
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
statistics.setStartTime(Instant.ofEpochMilli(1000));
|
||||
statistics.setStopTime(Instant.ofEpochMilli(2500));
|
||||
statistics.setTotalTime(Duration.ofMillis(1500));
|
||||
statistics.setMovingTime(Duration.ofMillis(700));
|
||||
statistics.setTotalDistance(Distance.of(750.0));
|
||||
statistics.setTotalAltitudeGain(50.0f);
|
||||
statistics.setMaxSpeed(Speed.of(60.0));
|
||||
statistics.setMaxAltitude(1250.0);
|
||||
statistics.setMinAltitude(1200.0);
|
||||
|
||||
track.first.setTrackStatistics(statistics);
|
||||
track.first.setStatistics(new Statistics(
|
||||
Instant.ofEpochMilli(1000),
|
||||
Instant.ofEpochMilli(2500),
|
||||
Duration.ofMillis(1500),
|
||||
Duration.ofMillis(700),
|
||||
Distance.of(750),
|
||||
Speed.of(60),
|
||||
new AltitudeExtremities(1250, 1200),
|
||||
new AltitudeGainLoss(50, 50),
|
||||
null,
|
||||
null
|
||||
));
|
||||
contentProviderUtils.insertTrack(track.first);
|
||||
|
||||
Marker marker = new Marker(trackId, track.second.get(0));
|
||||
@@ -854,7 +857,7 @@ public class CustomContentProviderUtilsTest {
|
||||
TrackPoint.Id startTrackPointId = trackpointIds.get(0);
|
||||
|
||||
// when
|
||||
TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, trackpointIds.get(0));
|
||||
AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, trackpointIds.get(0));
|
||||
|
||||
// then
|
||||
for (int i = 0; i < trackpointIds.size(); i++) {
|
||||
|
||||
+3
-2
@@ -9,6 +9,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
|
||||
//TODO Merge with TrackFilenameGeneratorTest whenever Junit5 gets available.
|
||||
@@ -36,9 +37,9 @@ public class TrackFilenameGenerator2Test {
|
||||
Track track = new Track();
|
||||
track.setName("Best Track");
|
||||
track.setUuid(UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6"));
|
||||
track.getTrackStatistics().setStartTime(Instant.parse("2020-02-02T02:02:02Z"));
|
||||
track.setStatistics(new Statistics(Instant.parse("2020-02-02T02:02:02Z"), null, null, null, null, null, null, null, null, null));
|
||||
|
||||
// when
|
||||
String filename = subject.format(track, TrackFileFormat.GPX);
|
||||
subject.format(track, TrackFileFormat.GPX);
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -17,6 +17,7 @@ import java.util.UUID;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.TimezoneRule;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
@@ -50,7 +51,7 @@ public class TrackFilenameGeneratorTest {
|
||||
Track track = new Track();
|
||||
track.setName("Best Track");
|
||||
track.setUuid(UUID.fromString("0000fee0-0000-1000-8000-00805f9b34fb"));
|
||||
track.getTrackStatistics().setStartTime(Instant.parse("2020-02-02T02:02:02Z"));
|
||||
track.setStatistics(new Statistics(Instant.parse("2020-02-02T02:02:02Z"), null, null, null, null, null, null, null, null, null));
|
||||
|
||||
// when
|
||||
String filename = subject.format(track, TrackFileFormat.GPX);
|
||||
|
||||
+40
-53
@@ -60,6 +60,7 @@ import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||
@@ -75,7 +76,6 @@ import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
|
||||
/**
|
||||
* Export a track to {@link TrackFileFormat} and verify that the import is identical.
|
||||
@@ -203,20 +203,20 @@ public class ExportImportTest {
|
||||
setUp();
|
||||
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||
Statistics trackStatistics = track.getStatistics();
|
||||
|
||||
assertEquals(ZoneOffset.of("+01:00"), track.getZoneOffset());
|
||||
assertEquals(Instant.parse("2020-02-02T02:02:02Z"), trackStatistics.getStartTime());
|
||||
assertEquals(Instant.parse("2020-02-02T02:04:00Z"), trackStatistics.getStopTime());
|
||||
assertEquals(Instant.parse("2020-02-02T02:02:02Z"), trackStatistics.startTime());
|
||||
assertEquals(Instant.parse("2020-02-02T02:04:00Z"), trackStatistics.stopTime());
|
||||
|
||||
assertEquals(Duration.ofSeconds(56), trackStatistics.getTotalTime());
|
||||
assertEquals(Duration.ofSeconds(26), trackStatistics.getMovingTime()); //TODO Likely too low
|
||||
assertEquals(Duration.ofSeconds(56), trackStatistics.totalTime());
|
||||
assertEquals(Duration.ofSeconds(26), trackStatistics.movingTime()); //TODO Likely too low
|
||||
|
||||
// Distance
|
||||
assertEquals(222049.34375, trackStatistics.getTotalDistance().toM(), 0.01); //TODO Too low
|
||||
assertEquals(222049.34375, trackStatistics.totalDistance().toM(), 0.01); //TODO Too low
|
||||
|
||||
// Speed
|
||||
assertEquals(8540.359, trackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||
assertEquals(8540.359, trackStatistics.maxSpeed().toMPS(), 0.01);
|
||||
assertEquals(3965.166, trackStatistics.getAverageSpeed().toMPS(), 0.01);
|
||||
assertEquals(8540.359, trackStatistics.getAverageMovingSpeed().toMPS(), 0.01);
|
||||
|
||||
@@ -224,8 +224,8 @@ public class ExportImportTest {
|
||||
assertEquals(999.122, trackStatistics.getMinAltitude(), 0.01);
|
||||
assertEquals(1020.25, trackStatistics.getMaxAltitude(), 0.01);
|
||||
|
||||
assertEquals(2, trackStatistics.getTotalAltitudeGain(), 0.01);
|
||||
assertEquals(2, trackStatistics.getTotalAltitudeLoss(), 0.01);
|
||||
assertEquals(2, trackStatistics.altitudeGainLoss().gain_m(), 0.01);
|
||||
assertEquals(2, trackStatistics.altitudeGainLoss().loss_m(), 0.01);
|
||||
|
||||
List<TrackPoint> actual = TestDataUtil.getTrackPoints(contentProviderUtils, trackId);
|
||||
new TrackPointAssert().assertEquals(List.of(
|
||||
@@ -237,17 +237,14 @@ public class ExportImportTest {
|
||||
Altitude.WGS84.of(1020.25), null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeLoss(1f)
|
||||
.setAltitudeGain(1f),
|
||||
.setAltitudeGainLoss(1, 1),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
Instant.parse("2020-02-02T02:02:04Z"))
|
||||
.setSensorDistance(Distance.of(10))
|
||||
.setSpeed(Speed.of(15))
|
||||
.setHeartRate(HeartRate.of(66))
|
||||
.setCadence(3)
|
||||
.setPower(50)
|
||||
.setAltitudeLoss(1f)
|
||||
.setAltitudeGain(1f),
|
||||
.setPower(50).setAltitudeGainLoss(1, 1),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT, Instant.parse("2020-02-02T02:02:15Z"))
|
||||
.setHeartRate(HeartRate.of(68))
|
||||
.setCadence(3)
|
||||
@@ -260,8 +257,7 @@ public class ExportImportTest {
|
||||
null,
|
||||
Speed.of(5)))
|
||||
.setSensorDistance(Distance.of(2))
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
.setHeartRate(HeartRate.of(69))
|
||||
.setCadence(3)
|
||||
.setPower(50),
|
||||
@@ -274,27 +270,23 @@ public class ExportImportTest {
|
||||
Altitude.WGS84.of(999.1229858398438), null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGain(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC,
|
||||
new Position(Instant.parse("2020-02-02T02:03:22Z"),
|
||||
3.123456, 16d, Distance.of(10),
|
||||
Altitude.WGS84.of(999.1229858398438), null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGain(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.IDLE, Instant.parse("2020-02-02T02:03:30Z"))
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGain(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse("2020-02-02T02:03:50Z"),
|
||||
3.123456, 16.001, Distance.of(10),
|
||||
Altitude.WGS84.of(999.1229858398438), null,
|
||||
null, Speed.of(15)))
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGain(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.parse("2020-02-02T02:04:00Z"))
|
||||
), actual);
|
||||
}
|
||||
@@ -334,29 +326,29 @@ public class ExportImportTest {
|
||||
a.assertEquals(trackPoints, actual);
|
||||
|
||||
// 3. trackstatistics
|
||||
TrackStatistics importedTrackStatistics = importedTrack.getTrackStatistics();
|
||||
Statistics importedTrackStatistics = importedTrack.getStatistics();
|
||||
|
||||
// Time
|
||||
assertEquals(track.getZoneOffset(), importedTrack.getZoneOffset());
|
||||
assertEquals(Instant.parse("2020-02-02T02:02:02Z"), importedTrackStatistics.getStartTime());
|
||||
assertEquals(Instant.parse("2020-02-02T02:04:00Z"), importedTrackStatistics.getStopTime());
|
||||
assertEquals(Instant.parse("2020-02-02T02:02:02Z"), importedTrackStatistics.startTime());
|
||||
assertEquals(Instant.parse("2020-02-02T02:04:00Z"), importedTrackStatistics.stopTime());
|
||||
|
||||
assertEquals(Duration.ofSeconds(56), importedTrackStatistics.getTotalTime());
|
||||
assertEquals(Duration.ofSeconds(26), importedTrackStatistics.getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(56), importedTrackStatistics.totalTime());
|
||||
assertEquals(Duration.ofSeconds(26), importedTrackStatistics.movingTime());
|
||||
|
||||
// Distance
|
||||
assertEquals(222049.421, importedTrackStatistics.getTotalDistance().toM(), 0.01);
|
||||
assertEquals(222049.421, importedTrackStatistics.totalDistance().toM(), 0.01);
|
||||
|
||||
// Speed
|
||||
assertEquals(8540.362, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||
assertEquals(8540.362, importedTrackStatistics.maxSpeed().toMPS(), 0.01);
|
||||
assertEquals(3965.168, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
|
||||
assertEquals(8540.362, importedTrackStatistics.getAverageMovingSpeed().toMPS(), 0.01);
|
||||
|
||||
// Altitude
|
||||
assertEquals(999.122, importedTrackStatistics.getMinAltitude(), 0.01);
|
||||
assertEquals(1020.25, importedTrackStatistics.getMaxAltitude(), 0.01);
|
||||
assertEquals(2, importedTrackStatistics.getTotalAltitudeGain(), 0.01);
|
||||
assertEquals(2, importedTrackStatistics.getTotalAltitudeLoss(), 0.01);
|
||||
assertEquals(2, importedTrackStatistics.altitudeGainLoss().gain_m(), 0.01);
|
||||
assertEquals(2, importedTrackStatistics.altitudeGainLoss().loss_m(), 0.01);
|
||||
|
||||
|
||||
// 4. markers
|
||||
@@ -433,8 +425,7 @@ public class ExportImportTest {
|
||||
Altitude.WGS84.of(1020.2), null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeLoss(1f)
|
||||
.setAltitudeGain(1f),
|
||||
.setAltitudeGainLoss(1, 1),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse("2020-02-02T02:02:17Z"),
|
||||
@@ -442,8 +433,7 @@ public class ExportImportTest {
|
||||
Altitude.WGS84.of(1020.2), null,
|
||||
null,
|
||||
Speed.of(5)))
|
||||
.setAltitudeLoss(1f)
|
||||
.setAltitudeGain(1f)
|
||||
.setAltitudeGainLoss(1, 1)
|
||||
.setSensorDistance(Distance.of(12))
|
||||
.setHeartRate(69)
|
||||
.setPower(50f)
|
||||
@@ -455,8 +445,7 @@ public class ExportImportTest {
|
||||
Altitude.WGS84.of(999.0999755859375), null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGain(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC,
|
||||
new Position(
|
||||
Instant.parse("2020-02-02T02:03:22Z"),
|
||||
@@ -464,8 +453,7 @@ public class ExportImportTest {
|
||||
Altitude.WGS84.of(999.0999755859375), null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGain(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse("2020-02-02T02:03:50Z"),
|
||||
@@ -473,35 +461,34 @@ public class ExportImportTest {
|
||||
Altitude.WGS84.of(999.0999755859375), null,
|
||||
null,
|
||||
Speed.of(10)))
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
.setSpeed(Speed.of(15))
|
||||
), actual);
|
||||
|
||||
// 3. trackstatistics
|
||||
TrackStatistics importedTrackStatistics = importedTrack.getTrackStatistics();
|
||||
Statistics importedTrackStatistics = importedTrack.getStatistics();
|
||||
|
||||
// Time
|
||||
assertEquals(track.getZoneOffset(), importedTrack.getZoneOffset());
|
||||
assertEquals(Instant.parse("2020-02-02T02:02:03Z"), importedTrackStatistics.getStartTime());
|
||||
assertEquals(Instant.parse("2020-02-02T02:03:50Z"), importedTrackStatistics.getStopTime());
|
||||
assertEquals(Instant.parse("2020-02-02T02:02:03Z"), importedTrackStatistics.startTime());
|
||||
assertEquals(Instant.parse("2020-02-02T02:03:50Z"), importedTrackStatistics.stopTime());
|
||||
|
||||
assertEquals(Duration.ofSeconds(107), importedTrackStatistics.getTotalTime());
|
||||
assertEquals(Duration.ofSeconds(107), importedTrackStatistics.getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(107), importedTrackStatistics.totalTime());
|
||||
assertEquals(Duration.ofSeconds(107), importedTrackStatistics.movingTime());
|
||||
|
||||
// Distance
|
||||
assertEquals(222271.734, importedTrackStatistics.getTotalDistance().toM(), 0.01);
|
||||
assertEquals(222271.734, importedTrackStatistics.totalDistance().toM(), 0.01);
|
||||
|
||||
// Speed
|
||||
assertEquals(2077.305, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||
assertEquals(2077.305, importedTrackStatistics.maxSpeed().toMPS(), 0.01);
|
||||
assertEquals(2077.305, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
|
||||
assertEquals(2077.305, importedTrackStatistics.getAverageMovingSpeed().toMPS(), 0.01);
|
||||
|
||||
// Altitude
|
||||
assertEquals(999.099, importedTrackStatistics.getMinAltitude(), 0.01);
|
||||
assertEquals(1020.2, importedTrackStatistics.getMaxAltitude(), 0.01);
|
||||
assertEquals(2, importedTrackStatistics.getTotalAltitudeGain(), 0.01);
|
||||
assertEquals(2, importedTrackStatistics.getTotalAltitudeLoss(), 0.01);
|
||||
assertEquals(2, importedTrackStatistics.altitudeGainLoss().gain_m(), 0.01);
|
||||
assertEquals(2, importedTrackStatistics.altitudeGainLoss().loss_m(), 0.01);
|
||||
|
||||
// 4. markers
|
||||
assertMarkers();
|
||||
|
||||
+12
-17
@@ -30,11 +30,11 @@ import de.dennisguse.opentracks.data.models.Altitude;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
|
||||
/**
|
||||
* Test that legacy KML/GPX formats can still be imported.
|
||||
@@ -149,9 +149,9 @@ public class GPXTrackImporterTest {
|
||||
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType());
|
||||
|
||||
// 3. trackstatistics
|
||||
TrackStatistics trackStatistics = importedTrack.getTrackStatistics();
|
||||
assertEquals(0.75, trackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||
assertEquals(Duration.ofSeconds(101), trackStatistics.getMovingTime());
|
||||
Statistics trackStatistics = importedTrack.getStatistics();
|
||||
assertEquals(0.75, trackStatistics.maxSpeed().toMPS(), 0.01);
|
||||
assertEquals(Duration.ofSeconds(101), trackStatistics.movingTime());
|
||||
|
||||
// 4. trackpoints
|
||||
List<TrackPoint> importedTrackPoints = TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId);
|
||||
@@ -204,9 +204,9 @@ public class GPXTrackImporterTest {
|
||||
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType());
|
||||
|
||||
// 3. trackstatistics
|
||||
TrackStatistics trackStatistics = importedTrack.getTrackStatistics();
|
||||
assertEquals(5.0, trackStatistics.getMaxSpeed().toMPS(), 0.01);
|
||||
assertEquals(Duration.ofSeconds(101), trackStatistics.getMovingTime());
|
||||
Statistics trackStatistics = importedTrack.getStatistics();
|
||||
assertEquals(5.0, trackStatistics.maxSpeed().toMPS(), 0.01);
|
||||
assertEquals(Duration.ofSeconds(101), trackStatistics.movingTime());
|
||||
|
||||
// 4. trackpoints
|
||||
List<TrackPoint> importedTrackPoints = TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId);
|
||||
@@ -267,8 +267,7 @@ public class GPXTrackImporterTest {
|
||||
Altitude.WGS84.of(10), null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeLoss(1f)
|
||||
.setAltitudeGain(1f),
|
||||
.setAltitudeGainLoss(1, 1),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse("2020-02-02T02:02:17Z"),
|
||||
@@ -276,8 +275,7 @@ public class GPXTrackImporterTest {
|
||||
Altitude.WGS84.of(10), null,
|
||||
null,
|
||||
Speed.of(5)))
|
||||
.setAltitudeLoss(1f)
|
||||
.setAltitudeGain(1f)
|
||||
.setAltitudeGainLoss(1, 1)
|
||||
.setSensorDistance(Distance.of(12))
|
||||
.setHeartRate(69)
|
||||
.setPower(50f)
|
||||
@@ -289,8 +287,7 @@ public class GPXTrackImporterTest {
|
||||
Altitude.WGS84.of(10), null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGain(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC,
|
||||
new Position(
|
||||
Instant.parse("2020-02-02T02:03:22Z"),
|
||||
@@ -298,8 +295,7 @@ public class GPXTrackImporterTest {
|
||||
Altitude.WGS84.of(10), null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGain(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse("2020-02-02T02:03:50Z"),
|
||||
@@ -307,8 +303,7 @@ public class GPXTrackImporterTest {
|
||||
Altitude.WGS84.of(10), null,
|
||||
null,
|
||||
Speed.of(10)))
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
.setSpeed(Speed.of(15))
|
||||
), actual);
|
||||
}
|
||||
|
||||
+5
-11
@@ -189,24 +189,21 @@ public class KMLTrackImporterTest {
|
||||
12.340097, 1.234156, null,
|
||||
Altitude.WGS84.of(469.286376953125), null,
|
||||
null,
|
||||
Speed.of(0.539)))
|
||||
.setAltitudeGain(0f),
|
||||
Speed.of(0.539))),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse("2020-11-28T17:06:25.448Z"),
|
||||
12.340036, 1.23415, null,
|
||||
Altitude.WGS84.of(439.1626281738281), null,
|
||||
null,
|
||||
Speed.of(0.1577)))
|
||||
.setAltitudeGain(0f),
|
||||
Speed.of(0.1577))),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse("2020-11-28T17:06:47.888Z"),
|
||||
12.340057, 1.23405, null,
|
||||
Altitude.WGS84.of(421.8070983886719), null,
|
||||
null,
|
||||
Speed.of(0)))
|
||||
.setAltitudeGain(0f),
|
||||
Speed.of(0))),
|
||||
// created resume trackpoint with time of next valid trackpoint
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC,
|
||||
new Position(
|
||||
@@ -214,16 +211,14 @@ public class KMLTrackImporterTest {
|
||||
12.340057, 1.23405, null,
|
||||
Altitude.WGS84.of(419.93902587890625), null,
|
||||
null,
|
||||
Speed.of(0)))
|
||||
.setAltitudeGain(0f),
|
||||
Speed.of(0))),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse("2020-11-28T17:06:56.905Z"),
|
||||
12.340057, 1.23405, null,
|
||||
Altitude.WGS84.of(419.9036560058594), null,
|
||||
null,
|
||||
Speed.of(0)))
|
||||
.setAltitudeGain(0f),
|
||||
Speed.of(0))),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse("2020-11-28T17:07:20.870Z"),
|
||||
@@ -231,7 +226,6 @@ public class KMLTrackImporterTest {
|
||||
Altitude.WGS84.of(417.99432373046875), null,
|
||||
null,
|
||||
Speed.of(0)))
|
||||
.setAltitudeGain(0f)
|
||||
), importedTrackPoints);
|
||||
}
|
||||
|
||||
|
||||
+3
-7
@@ -29,13 +29,9 @@ public class TrackPointAssert {
|
||||
Assert.assertEquals("altitude", expected.getAltitude().toM(), actual.getAltitude().toM(), delta);
|
||||
}
|
||||
|
||||
Assert.assertEquals("has altitudeGain", expected.hasAltitudeGain(), actual.hasAltitudeGain());
|
||||
if (expected.hasAltitudeGain()) {
|
||||
Assert.assertEquals("altitudeGain", expected.getAltitudeGain(), actual.getAltitudeGain(), delta);
|
||||
}
|
||||
Assert.assertEquals("has altitudeLoss", expected.hasAltitudeLoss(), actual.hasAltitudeLoss());
|
||||
if (expected.hasAltitudeLoss()) {
|
||||
Assert.assertEquals("altitudeLoss", expected.getAltitudeLoss(), actual.getAltitudeLoss(), delta);
|
||||
Assert.assertEquals("has altitudeGainLoss", expected.hasAltitudeGainLoss(), actual.hasAltitudeGainLoss());
|
||||
if (expected.hasAltitudeGainLoss()) {
|
||||
Assert.assertEquals("altitudeGainLoss", expected.getAltitudeGainLoss(), actual.getAltitudeGainLoss());
|
||||
}
|
||||
|
||||
Assert.assertEquals("has speed", expected.hasSpeed(), actual.hasSpeed());
|
||||
|
||||
+24
-13
@@ -16,24 +16,20 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Altitude;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class TrackRecordingServiceNotificationManagerTest {
|
||||
|
||||
private final Context context = ApplicationProvider.getApplicationContext();
|
||||
|
||||
@Mock
|
||||
private TrackPoint trackPointMock;
|
||||
|
||||
@Mock
|
||||
private TrackStatistics trackStatisticsMock;
|
||||
|
||||
@Mock
|
||||
private NotificationCompat.Builder notificationCompatBuilder;
|
||||
|
||||
@@ -42,18 +38,33 @@ public class TrackRecordingServiceNotificationManagerTest {
|
||||
|
||||
@Test
|
||||
public void updateLocation_triggersAlertOnlyOnFirstInaccurateLocation() {
|
||||
when(trackPointMock.hasHorizontalAccuracy()).thenReturn(true);
|
||||
when(trackPointMock.getHorizontalAccuracy()).thenReturn(Distance.of(999f));
|
||||
when(trackPointMock.getSpeed()).thenReturn(Speed.of(0));
|
||||
when(trackStatisticsMock.getTotalDistance()).thenReturn(Distance.of(0));
|
||||
TrackPoint trackPointMock = new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
null,
|
||||
null, null, Distance.of(999f),
|
||||
Altitude.WGS84.of(10), null,
|
||||
null,
|
||||
Speed.of(0))
|
||||
);
|
||||
|
||||
when(notificationCompatBuilder.setOnlyAlertOnce(anyBoolean()))
|
||||
.thenReturn(notificationCompatBuilder);
|
||||
|
||||
TrackRecordingServiceNotificationManager subject = new TrackRecordingServiceNotificationManager(notificationManager, notificationCompatBuilder);
|
||||
subject.setUnitSystem(UnitSystem.METRIC);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(trackStatisticsMock);
|
||||
Track track = new Track(new Statistics(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
Distance.of(0),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
));
|
||||
RecordingData data = new RecordingData(track, trackPointMock, null, null);
|
||||
|
||||
// when
|
||||
|
||||
+94
-95
@@ -5,8 +5,11 @@ import static org.junit.Assert.assertFalse;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.core.location.LocationManagerCompat;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.MediumTest;
|
||||
@@ -30,11 +33,13 @@ import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.TestUtil;
|
||||
import de.dennisguse.opentracks.content.data.TestDataUtil;
|
||||
import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeExtremities;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.io.file.importer.TrackPointAssert;
|
||||
@@ -46,7 +51,6 @@ import de.dennisguse.opentracks.sensors.sensorData.AggregatorRunning;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
|
||||
/**
|
||||
* Tests insert location.
|
||||
@@ -106,8 +110,8 @@ public class TrackRecordingServiceRecordingTest {
|
||||
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, startTime, 0, 0, 0, 0, null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(startTime), Duration.ZERO, Duration.ZERO, Distance.of(0), Speed.zero(), new AltitudeExtremities(0.0, 0.0), null, null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
new TrackPointAssert().assertEquals(List.of(
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime))
|
||||
@@ -120,14 +124,13 @@ public class TrackRecordingServiceRecordingTest {
|
||||
service.endCurrentTrack();
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, stopTime, 0, 1, 1, 0, 0f, 0f)
|
||||
, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.of(0), Speed.zero(), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
new TrackPointAssert().assertEquals(List.of(
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.parse(stopTime))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
|
||||
@@ -143,10 +146,14 @@ public class TrackRecordingServiceRecordingTest {
|
||||
String startTime = "2020-02-02T02:02:02Z";
|
||||
trackPointCreator.setClock(startTime);
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
|
||||
//We do not want the real GPS to interfere.
|
||||
LocationManagerCompat.removeUpdates((LocationManager) context.getSystemService(Context.LOCATION_SERVICE), trackPointCreator.getSensorManager().getGpsManager());
|
||||
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 1, 15);
|
||||
String gps2 = "2020-02-02T02:02:04Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps2, 45.0, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps2, 45.0, 35.0, 1, 15);
|
||||
|
||||
// when
|
||||
String idleTime = "2020-02-02T02:02:17Z";
|
||||
@@ -192,14 +199,13 @@ public class TrackRecordingServiceRecordingTest {
|
||||
service.endCurrentTrack();
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, pauseTime, 0, 1, 1, 0, 0f, 0f)
|
||||
, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(pauseTime), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.of(0), Speed.zero(), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
new TrackPointAssert().assertEquals(List.of(
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.parse(pauseTime))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
|
||||
//when
|
||||
@@ -208,14 +214,13 @@ public class TrackRecordingServiceRecordingTest {
|
||||
service.resumeTrack(trackId);
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, resumeTime, 0, 1, 1, 0, 0f, 0f)
|
||||
, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(resumeTime), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.of(0), Speed.zero(), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
new TrackPointAssert().assertEquals(List.of(
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.parse(pauseTime))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(resumeTime))
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
@@ -248,8 +253,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
new TrackPointAssert().assertEquals(List.of(
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(starTime)),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.parse(pauseTime))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
), trackPoints);
|
||||
}
|
||||
|
||||
@@ -278,8 +282,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
new TrackPointAssert().assertEquals(List.of(
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.parse(stopTime))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(resumeTime))
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
@@ -315,12 +318,10 @@ public class TrackRecordingServiceRecordingTest {
|
||||
new TrackPointAssert().assertEquals(List.of(
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT, Instant.parse(sensor3))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
.setHeartRate(HeartRate.of(7)),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.parse(stopTime))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
.setHeartRate(HeartRate.of(7))
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
@@ -338,28 +339,27 @@ public class TrackRecordingServiceRecordingTest {
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 1, 15);
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, gps1, 0, 1, 1, 15, 0f, 0f)
|
||||
, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps1), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.of(0), Speed.of(15), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
// when
|
||||
String gps2 = "2020-02-02T02:02:06Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps2, 45.0001, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps2, 45.0001, 35.0, 1, 15);
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, gps2, 11.113178253173828f, 4, 4, 15, 0f, 0f)
|
||||
, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps2), Duration.ofSeconds(4), Duration.ofSeconds(4), Distance.of(11.113178253173828), Speed.of(15), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
// when
|
||||
String gps3 = "2020-02-02T02:02:08Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps3, 45.0002, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps3, 45.0002, 35.0, 1, 15);
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, gps3, 22.226356506347656, 6, 6, 15, 0f, 0f)
|
||||
, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps3), Duration.ofSeconds(6), Duration.ofSeconds(6), Distance.of(22.226356506347656), Speed.of(15), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
// when
|
||||
String stopTime = "2020-02-02T02:02:12Z";
|
||||
@@ -367,8 +367,8 @@ public class TrackRecordingServiceRecordingTest {
|
||||
service.endCurrentTrack();
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, stopTime, 22.226356506347656, 10, 10, 15, 0f, 0f)
|
||||
, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(10), Duration.ofSeconds(10), Distance.of(22.226356506347656), Speed.of(15), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
new TrackPointAssert().assertEquals(List.of(
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
|
||||
@@ -379,8 +379,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null, null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse(gps2),
|
||||
@@ -388,8 +387,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null, null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse(gps3),
|
||||
@@ -397,11 +395,9 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null, null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.parse(stopTime))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
|
||||
@@ -417,25 +413,25 @@ public class TrackRecordingServiceRecordingTest {
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 1, 15);
|
||||
|
||||
// then
|
||||
TrackStatistics gps1Statistics = new TrackStatistics(startTime, gps1, 0, 1, 1, 15, 0f, 0f);
|
||||
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
Statistics gps1Statistics = new Statistics(Instant.parse(startTime), Instant.parse(gps1), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.of(0), Speed.of(15), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null);
|
||||
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
// when
|
||||
String gps2 = "2020-02-02T02:02:06Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps2, 45.00001, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps2, 45.00001, 35.0, 1, 15);
|
||||
|
||||
// then
|
||||
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
// when
|
||||
String gps3 = "2020-02-02T02:02:08Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps3, 45.00002, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps3, 45.00002, 35.0, 1, 15);
|
||||
|
||||
// then
|
||||
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
// when
|
||||
String stopTime = "2020-02-02T02:02:12Z";
|
||||
@@ -443,8 +439,8 @@ public class TrackRecordingServiceRecordingTest {
|
||||
service.endCurrentTrack();
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, stopTime, 2.222635507583618, 10, 10, 15, 0f, 0f)
|
||||
, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(10), Duration.ofSeconds(10), Distance.of(2.222635507583618), Speed.of(15), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
new TrackPointAssert().assertEquals(List.of(
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
|
||||
@@ -455,8 +451,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null, null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse(gps3),
|
||||
@@ -464,8 +459,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null, null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL,
|
||||
new Position(
|
||||
Instant.parse(stopTime),
|
||||
@@ -473,8 +467,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null, null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
|
||||
@@ -491,15 +484,15 @@ public class TrackRecordingServiceRecordingTest {
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 1, 15);
|
||||
|
||||
// when - will be ignored
|
||||
String gps2 = "2020-02-02T02:02:04Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps2, 45.0, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps2, 45.0, 35.0, 1, 15);
|
||||
|
||||
// when
|
||||
String gps3 = "2020-02-02T02:02:05Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps3, 45.0001, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps3, 45.0001, 35.0, 1, 15);
|
||||
|
||||
// when
|
||||
String stopTime = "2020-02-02T02:02:12Z";
|
||||
@@ -516,8 +509,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null, null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse(gps3),
|
||||
@@ -525,11 +517,9 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null, null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.parse(stopTime))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
|
||||
@@ -545,19 +535,19 @@ public class TrackRecordingServiceRecordingTest {
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 100, 15);
|
||||
sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 100, 15);
|
||||
|
||||
// then
|
||||
TrackStatistics startStatistics = new TrackStatistics(startTime, startTime, 0, 0, 0, 0, null, null);
|
||||
assertEquals(startStatistics, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
Statistics startStatistics = new Statistics(Instant.parse(startTime), Instant.parse(startTime), Duration.ofSeconds(0), Duration.ofSeconds(0), Distance.of(0), Speed.of(0), new AltitudeExtremities(0.0, 0.0), null, null, null);
|
||||
assertEquals(startStatistics, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
|
||||
// when
|
||||
String gps2 = "2020-02-02T02:02:06Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps2, 45.1, 35.0, 100, 15);
|
||||
sendGPSLocation(trackPointCreator, gps2, 45.1, 35.0, 100, 15);
|
||||
|
||||
// then
|
||||
assertEquals(startStatistics, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(startStatistics, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
|
||||
// when
|
||||
@@ -566,16 +556,14 @@ public class TrackRecordingServiceRecordingTest {
|
||||
service.endCurrentTrack();
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, stopTime, 0, 10, 10, 0, 0f, 0f)
|
||||
, contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(10), Duration.ofSeconds(10), Distance.of(0), Speed.of(0), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
// then
|
||||
new TrackPointAssert().assertEquals(List.of(
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.parse(stopTime))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
|
||||
@@ -591,18 +579,19 @@ public class TrackRecordingServiceRecordingTest {
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:03Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 1, 15);
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, gps1, 0, 1, 1, 15, 0f, 0f), contentProviderUtils.getTrack(trackId).getTrackStatistics());
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps1), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.of(0), Speed.of(15), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
// when
|
||||
String gps2 = "2020-02-02T02:02:06Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps2, 45.1, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps2, 45.1, 35.0, 1, 15);
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, gps2, 11113.275390625, 4, 4, 2778.31884765625f, 0f, 0f).toString(), contentProviderUtils.getTrack(trackId).getTrackStatistics().toString());
|
||||
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps2), Duration.ofSeconds(4), Duration.ofSeconds(4), Distance.of(11113.275390625), Speed.of(2778.31884765625f), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
// when
|
||||
String stopTime = "2020-02-02T02:02:12Z";
|
||||
@@ -610,7 +599,8 @@ public class TrackRecordingServiceRecordingTest {
|
||||
service.endCurrentTrack();
|
||||
|
||||
// then
|
||||
assertEquals(new TrackStatistics(startTime, stopTime, 11113.275390625, 10, 10, 1111.3275390625f, 0f, 0f).toString(), contentProviderUtils.getTrack(trackId).getTrackStatistics().toString());
|
||||
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(10), Duration.ofSeconds(10), Distance.of(11113.275390625), Speed.of(1111.3275146484375), new AltitudeExtremities(0.0, 0.0), new AltitudeGainLoss(0, 0), null, null)
|
||||
, contentProviderUtils.getTrack(trackId).getStatistics());
|
||||
|
||||
|
||||
// then
|
||||
@@ -623,8 +613,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null, null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC,
|
||||
new Position(
|
||||
Instant.parse(gps2),
|
||||
@@ -632,11 +621,9 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null, null,
|
||||
null,
|
||||
Speed.of(15)))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f),
|
||||
.setAltitudeGainLoss(0, 0),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.parse(stopTime))
|
||||
.setAltitudeGain(0f)
|
||||
.setAltitudeLoss(0f)
|
||||
.setAltitudeGainLoss(0, 0)
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
|
||||
@@ -669,7 +656,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:05Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps1, 45.0, 35.0, 1, 15);
|
||||
|
||||
// when
|
||||
String sensor3 = "2020-02-02T02:02:06Z";
|
||||
@@ -683,7 +670,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
|
||||
// when
|
||||
String gps2 = "2020-02-02T02:02:08Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps2, 45.0, 35.0, 4, 15); //Should be ignored
|
||||
sendGPSLocation(trackPointCreator, gps2, 45.0, 35.0, 4, 15); //Should be ignored
|
||||
|
||||
// when
|
||||
String sensor5 = "2020-02-02T02:02:10Z";
|
||||
@@ -692,11 +679,11 @@ public class TrackRecordingServiceRecordingTest {
|
||||
|
||||
// when
|
||||
String gps3 = "2020-02-02T02:02:12Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps3, 45.001, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps3, 45.001, 35.0, 1, 15);
|
||||
|
||||
// when
|
||||
String gps4 = "2020-02-02T02:02:14Z";
|
||||
TrackRecordingServiceTestUtils.sendGPSLocation(trackPointCreator, gps4, 45.001, 35.0, 1, 15);
|
||||
sendGPSLocation(trackPointCreator, gps4, 45.001, 35.0, 1, 15);
|
||||
|
||||
|
||||
// when
|
||||
@@ -761,4 +748,16 @@ public class TrackRecordingServiceRecordingTest {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void sendGPSLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, long speed) {
|
||||
Location location = new Location("mock");
|
||||
location.setTime(1L); // Should be ignored anyhow.
|
||||
location.setLatitude(latitude);
|
||||
location.setLongitude(longitude);
|
||||
location.setAccuracy(accuracy);
|
||||
location.setSpeed(speed);
|
||||
|
||||
trackPointCreator.setClock(time);
|
||||
trackPointCreator.getSensorManager().getGpsManager().onLocationChanged(location);
|
||||
}
|
||||
}
|
||||
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package de.dennisguse.opentracks.services;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||
|
||||
public class TrackRecordingServiceTestUtils {
|
||||
|
||||
static void sendGPSLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, long speed) {
|
||||
Location location = new Location("mock");
|
||||
location.setTime(1L); // Should be ignored anyhow.
|
||||
location.setLatitude(latitude);
|
||||
location.setLongitude(longitude);
|
||||
location.setAccuracy(accuracy);
|
||||
location.setSpeed(speed);
|
||||
|
||||
trackPointCreator.setClock(time);
|
||||
trackPointCreator.getSensorManager().getGpsManager().onLocationChanged(location);
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -22,7 +22,7 @@ import java.util.concurrent.TimeoutException;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.stats.SegmentStatisticUpdater;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class VoiceAnnouncementManagerTest {
|
||||
@@ -54,13 +54,13 @@ public class VoiceAnnouncementManagerTest {
|
||||
voiceAnnouncementManager.setFrequency(Distance.ofKilometer(5));
|
||||
|
||||
// when
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
SegmentStatisticUpdater statistics = new SegmentStatisticUpdater();
|
||||
statistics.setTotalDistance(Distance.ofKilometer(13));
|
||||
voiceAnnouncementManager.start(statistics);
|
||||
voiceAnnouncementManager.start(statistics.getStatistics());
|
||||
assertEquals(Distance.of(15000), voiceAnnouncementManager.getNextTotalDistance());
|
||||
|
||||
statistics.setTotalDistance(Distance.of(15100));
|
||||
voiceAnnouncementManager.start(statistics);
|
||||
voiceAnnouncementManager.start(statistics.getStatistics());
|
||||
assertEquals(Distance.of(20000), voiceAnnouncementManager.getNextTotalDistance());
|
||||
}
|
||||
|
||||
@@ -74,13 +74,13 @@ public class VoiceAnnouncementManagerTest {
|
||||
voiceAnnouncementManager.setFrequency(Duration.ofSeconds(5));
|
||||
|
||||
// when
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
SegmentStatisticUpdater statistics = new SegmentStatisticUpdater();
|
||||
statistics.setTotalTime(Duration.ofSeconds(91));
|
||||
voiceAnnouncementManager.start(statistics);
|
||||
voiceAnnouncementManager.start(statistics.getStatistics());
|
||||
assertEquals(Duration.ofSeconds(95), voiceAnnouncementManager.getNextTotalTime());
|
||||
|
||||
statistics.setTotalTime(Duration.ofSeconds(95));
|
||||
voiceAnnouncementManager.start(statistics);
|
||||
voiceAnnouncementManager.start(statistics.getStatistics());
|
||||
assertEquals(Duration.ofSeconds(100), voiceAnnouncementManager.getNextTotalTime());
|
||||
}
|
||||
|
||||
|
||||
+168
-192
@@ -19,23 +19,24 @@ import org.mockito.Mockito;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import de.dennisguse.opentracks.LocaleRule;
|
||||
import de.dennisguse.opentracks.content.data.TestDataUtil;
|
||||
import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
|
||||
import de.dennisguse.opentracks.ui.intervals.IntervalStatisticsUpdater;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class VoiceAnnouncementUtilsTest {
|
||||
@@ -44,12 +45,9 @@ public class VoiceAnnouncementUtilsTest {
|
||||
public final LocaleRule mLocaleRule = new LocaleRule(Locale.ENGLISH);
|
||||
|
||||
private final Context context = ApplicationProvider.getApplicationContext();
|
||||
private ContentProviderUtils contentProviderUtils;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
contentProviderUtils = new ContentProviderUtils(context);
|
||||
|
||||
PreferencesUtils.setVoiceAnnounceHeartRateCurrent(false);
|
||||
PreferencesUtils.setVoiceAnnounceLapHeartRate(false);
|
||||
PreferencesUtils.setVoiceAnnounceAverageHeartRate(false);
|
||||
@@ -66,16 +64,18 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_speed() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(20000));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Track track = new Track(new Statistics(
|
||||
Instant.EPOCH,
|
||||
Instant.EPOCH,
|
||||
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
|
||||
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
|
||||
Distance.of(20000),
|
||||
Speed.of(100),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
));
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
@@ -89,16 +89,18 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_speed_rounding_check() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(20000));
|
||||
stats.setTotalTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1).plusSeconds(1));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Track track = new Track(new Statistics(
|
||||
Instant.EPOCH,
|
||||
Instant.EPOCH,
|
||||
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
|
||||
Duration.ofHours(1).plusSeconds(1),
|
||||
Distance.of(20000),
|
||||
Speed.of(100),
|
||||
null,
|
||||
new AltitudeGainLoss(6000, 6000),
|
||||
null,
|
||||
null
|
||||
));
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
@@ -112,16 +114,18 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_distance_rounding_check() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(19999));
|
||||
stats.setTotalTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Track track = new Track(new Statistics(
|
||||
Instant.EPOCH,
|
||||
Instant.EPOCH,
|
||||
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
|
||||
Duration.ofHours(1),
|
||||
Distance.of(19999),
|
||||
Speed.of(100),
|
||||
null,
|
||||
new AltitudeGainLoss(6000, 6000),
|
||||
null,
|
||||
null
|
||||
));
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
@@ -135,16 +139,18 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_distance_rounding_check_two() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(19900));
|
||||
stats.setTotalTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Track track = new Track(new Statistics(
|
||||
Instant.EPOCH,
|
||||
Instant.EPOCH,
|
||||
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
|
||||
Duration.ofHours(1),
|
||||
Distance.of(19900),
|
||||
Speed.of(100),
|
||||
null,
|
||||
new AltitudeGainLoss(6000, 6000),
|
||||
null,
|
||||
null
|
||||
));
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
@@ -159,26 +165,13 @@ public class VoiceAnnouncementUtilsTest {
|
||||
@Test
|
||||
public void getAnnouncement_withInterval_metric_speed() {
|
||||
// given
|
||||
int numberOfPoints = 1000;
|
||||
Pair<Track.Id, TrackStatistics> trackWithStats = TestDataUtil.buildTrackWithTrackPoints(contentProviderUtils, numberOfPoints);
|
||||
Track.Id trackId = trackWithStats.first;
|
||||
TrackStatistics stats = trackWithStats.second;
|
||||
IntervalStatistics.Interval lastInterval;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
assertEquals(numberOfPoints, trackPointIterator.getCount());
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
|
||||
intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
|
||||
Pair<Track, Statistics> data = buildTrackWithTrackPoints();
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, lastInterval, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, data.first, dataSet, UnitSystem.METRIC, true, data.second, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("12:16 AM. Total distance 14.2 kilometers. 16 minutes 39 seconds. Average moving speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour.", announcement);
|
||||
@@ -186,16 +179,18 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_pace() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(20000));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Track track = new Track(new Statistics(
|
||||
Instant.EPOCH,
|
||||
Instant.EPOCH,
|
||||
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
|
||||
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
|
||||
Distance.of(20000),
|
||||
Speed.of(100),
|
||||
null,
|
||||
new AltitudeGainLoss(6000, 6000),
|
||||
null,
|
||||
null
|
||||
));
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
@@ -210,26 +205,13 @@ public class VoiceAnnouncementUtilsTest {
|
||||
@Test
|
||||
public void getAnnouncement_withInterval_metric_pace() {
|
||||
// given
|
||||
int numberOfPoints = 1000;
|
||||
Pair<Track.Id, TrackStatistics> trackWithStats = TestDataUtil.buildTrackWithTrackPoints(contentProviderUtils, numberOfPoints);
|
||||
Track.Id trackId = trackWithStats.first;
|
||||
TrackStatistics stats = trackWithStats.second;
|
||||
IntervalStatistics.Interval lastInterval;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
assertEquals(numberOfPoints, trackPointIterator.getCount());
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
|
||||
intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Pair<Track, Statistics> data = buildTrackWithTrackPoints();
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, false, lastInterval, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, data.first, dataSet, UnitSystem.METRIC, false, data.second, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("12:16 AM. Total distance 14.2 kilometers. 16 minutes 39 seconds. Pace 1 minute 10 seconds per kilometer. Lap time 1 minute 10 seconds per kilometer.", announcement);
|
||||
@@ -237,16 +219,18 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_imperial_speed() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(20000));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Track track = new Track(new Statistics(
|
||||
Instant.EPOCH,
|
||||
Instant.EPOCH,
|
||||
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
|
||||
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
|
||||
Distance.of(20000),
|
||||
Speed.of(100),
|
||||
null,
|
||||
new AltitudeGainLoss(6000, 6000),
|
||||
null,
|
||||
null
|
||||
));
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
@@ -260,14 +244,18 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_imperial_speed_1() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.ofMile(1.1));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1));
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Track track = new Track(new Statistics(
|
||||
Instant.EPOCH,
|
||||
Instant.EPOCH,
|
||||
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
|
||||
Duration.ofHours(1),
|
||||
Distance.ofMile(1.1),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
));
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
@@ -281,14 +269,18 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_imperial_meter_speed_1() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.ofMile(1.1));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1));
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Track track = new Track(new Statistics(
|
||||
Instant.EPOCH,
|
||||
Instant.EPOCH,
|
||||
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
|
||||
Duration.ofHours(1),
|
||||
Distance.ofMile(1.1),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
));
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
@@ -302,14 +294,18 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_metric_speed_1() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.ofKilometer(1.1));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1));
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Track track = new Track(new Statistics(
|
||||
Instant.EPOCH,
|
||||
Instant.EPOCH,
|
||||
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
|
||||
Duration.ofHours(1),
|
||||
Distance.ofKilometer(1.1),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
));
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
@@ -324,26 +320,13 @@ public class VoiceAnnouncementUtilsTest {
|
||||
@Test
|
||||
public void getAnnouncement_withInterval_imperial_speed() {
|
||||
// given
|
||||
int numberOfPoints = 1000;
|
||||
Pair<Track.Id, TrackStatistics> trackWithStats = TestDataUtil.buildTrackWithTrackPoints(contentProviderUtils, numberOfPoints);
|
||||
Track.Id trackId = trackWithStats.first;
|
||||
TrackStatistics stats = trackWithStats.second;
|
||||
IntervalStatistics.Interval lastInterval;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
assertEquals(numberOfPoints, trackPointIterator.getCount());
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
|
||||
intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Pair<Track, Statistics> data = buildTrackWithTrackPoints();
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_FEET, true, lastInterval, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, data.first, dataSet, UnitSystem.IMPERIAL_FEET, true, data.second, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("12:16 AM. Total distance 8.8 miles. 16 minutes 39 seconds. Average moving speed 31.8 miles per hour. Lap speed 31.8 miles per hour.", announcement);
|
||||
@@ -351,16 +334,18 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_imperial_pace() {
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setStartTime(Instant.EPOCH);
|
||||
stats.setTotalDistance(Distance.of(20000));
|
||||
stats.setTotalTime(Duration.ofHours(2).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMovingTime(Duration.ofHours(1).plusMinutes(5).plusSeconds(10));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Track track = new Track(new Statistics(
|
||||
Instant.EPOCH,
|
||||
Instant.EPOCH,
|
||||
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
|
||||
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
|
||||
Distance.of(20000),
|
||||
Speed.of(100),
|
||||
null,
|
||||
new AltitudeGainLoss(6000, 6000),
|
||||
null,
|
||||
null
|
||||
));
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
@@ -375,26 +360,13 @@ public class VoiceAnnouncementUtilsTest {
|
||||
@Test
|
||||
public void getAnnouncement_withInterval_imperial_pace() {
|
||||
// given
|
||||
int numberOfPoints = 1000;
|
||||
Pair<Track.Id, TrackStatistics> trackWithStats = TestDataUtil.buildTrackWithTrackPoints(contentProviderUtils, numberOfPoints);
|
||||
Track.Id trackId = trackWithStats.first;
|
||||
TrackStatistics stats = trackWithStats.second;
|
||||
IntervalStatistics.Interval lastInterval;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
assertEquals(numberOfPoints, trackPointIterator.getCount());
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
|
||||
intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
Pair<Track, Statistics> data = buildTrackWithTrackPoints();
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.IMPERIAL_FEET, false, lastInterval, null).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, data.first, dataSet, UnitSystem.IMPERIAL_FEET, false, data.second, null).toString();
|
||||
|
||||
// then
|
||||
assertEquals("12:16 AM. Total distance 8.8 miles. 16 minutes 39 seconds. Pace 1 minute 53 seconds per mile. Lap time 1 minute 53 seconds per mile.", announcement);
|
||||
@@ -402,31 +374,19 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_heart_rate_and_sensor_statistics() {
|
||||
// given
|
||||
PreferencesUtils.setVoiceAnnounceAverageHeartRate(true);
|
||||
PreferencesUtils.setVoiceAnnounceLapHeartRate(true);
|
||||
|
||||
int numberOfPoints = 1000;
|
||||
Pair<Track.Id, TrackStatistics> trackWithStats = TestDataUtil.buildTrackWithTrackPoints(contentProviderUtils, numberOfPoints);
|
||||
Track.Id trackId = trackWithStats.first;
|
||||
TrackStatistics stats = trackWithStats.second;
|
||||
IntervalStatistics.Interval lastInterval;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
assertEquals(numberOfPoints, trackPointIterator.getCount());
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
|
||||
intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
Pair<Track, Statistics> data = buildTrackWithTrackPoints();
|
||||
|
||||
SensorStatistics sensorStatistics = new SensorStatistics(HeartRate.of(180f), HeartRate.of(180f), null, null, null, null);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, lastInterval, sensorStatistics).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, data.first, dataSet, UnitSystem.METRIC, true, data.second, sensorStatistics).toString();
|
||||
|
||||
// then
|
||||
assertEquals("12:16 AM. Total distance 14.2 kilometers. 16 minutes 39 seconds. Average moving speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour. Average heart rate 180 bpm. Lap heart rate 133 bpm.", announcement);
|
||||
@@ -434,6 +394,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getAnnouncement_heart_rate() {
|
||||
// given
|
||||
PreferencesUtils.setVoiceAnnounceHeartRateCurrent(true);
|
||||
PreferencesUtils.setVoiceAnnounceLapHeartRate(true);
|
||||
PreferencesUtils.setVoiceAnnounceAverageHeartRate(true);
|
||||
@@ -443,28 +404,15 @@ public class VoiceAnnouncementUtilsTest {
|
||||
PreferencesUtils.setVoiceAnnounceAverageSpeedPace(false);
|
||||
PreferencesUtils.setVoiceAnnounceLapSpeedPace(false);
|
||||
|
||||
int numberOfPoints = 1000;
|
||||
Pair<Track.Id, TrackStatistics> trackWithStats = TestDataUtil.buildTrackWithTrackPoints(contentProviderUtils, numberOfPoints);
|
||||
Track.Id trackId = trackWithStats.first;
|
||||
TrackStatistics stats = trackWithStats.second;
|
||||
IntervalStatistics.Interval lastInterval;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
assertEquals(numberOfPoints, trackPointIterator.getCount());
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(1000));
|
||||
intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
lastInterval = intervalStatistics.getIntervalList().get(intervalStatistics.getIntervalList().size() - 1);
|
||||
}
|
||||
Pair<Track, Statistics> data = buildTrackWithTrackPoints();
|
||||
|
||||
SensorStatistics sensorStatistics = new SensorStatistics(HeartRate.of(180f), HeartRate.of(180f), null, null, null, null);
|
||||
|
||||
Track track = new Track();
|
||||
track.setTrackStatistics(stats);
|
||||
|
||||
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class);
|
||||
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
|
||||
|
||||
// when
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, track, dataSet, UnitSystem.METRIC, true, lastInterval, sensorStatistics).toString();
|
||||
String announcement = VoiceAnnouncementUtils.createStatistics(context, data.first, dataSet, UnitSystem.METRIC, true, data.second, sensorStatistics).toString();
|
||||
|
||||
// then
|
||||
assertEquals("12:16 AM. Current heart rate 60 bpm. Average heart rate 180 bpm. Lap heart rate 133 bpm.", announcement);
|
||||
@@ -484,4 +432,32 @@ public class VoiceAnnouncementUtilsTest {
|
||||
assertEquals("1.1 miles", MessageFormat.format(template, Map.of("n", 1.11)));
|
||||
assertEquals("1.2 miles", MessageFormat.format(template, Map.of("n", 1.18)));
|
||||
}
|
||||
|
||||
private static Pair<Track, Statistics> buildTrackWithTrackPoints() {
|
||||
int numberOfPoints = 1000;
|
||||
|
||||
ArrayList<TrackPoint> trackPoints = new ArrayList<>();
|
||||
for (int i = 0; i < numberOfPoints; i++) {
|
||||
trackPoints.add(TestDataUtil.createTrackPoint(i));
|
||||
}
|
||||
|
||||
IntervalStatisticsUpdater intervalStatistics = new IntervalStatisticsUpdater(Distance.of(1000));
|
||||
intervalStatistics.addTrackPoints(trackPoints.iterator());
|
||||
Statistics lastInterval = intervalStatistics.getLastInterval();
|
||||
|
||||
Track track = new Track(new Statistics(
|
||||
Instant.EPOCH,
|
||||
Instant.EPOCH.plusSeconds(999),
|
||||
Duration.ofMinutes(16).plusSeconds(39),
|
||||
Duration.ofMinutes(16).plusSeconds(39),
|
||||
Distance.of(14208),
|
||||
Speed.of(104),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
));
|
||||
|
||||
return new Pair<>(track, lastInterval);
|
||||
}
|
||||
}
|
||||
|
||||
+16
-17
@@ -18,8 +18,6 @@ package de.dennisguse.opentracks.share;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
@@ -36,10 +34,12 @@ import java.util.Locale;
|
||||
|
||||
import de.dennisguse.opentracks.LocaleRule;
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeExtremities;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -56,8 +56,6 @@ public class TrackShareSummaryGeneratorTest {
|
||||
private static final Instant START_TIME = Instant.ofEpochMilli(1288721514000L);
|
||||
private TrackShareSummaryGenerator descriptionGenerator;
|
||||
|
||||
private final Context context = ApplicationProvider.getApplicationContext();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
descriptionGenerator = new TrackShareSummaryGenerator(ApplicationProvider.getApplicationContext());
|
||||
@@ -65,19 +63,20 @@ public class TrackShareSummaryGeneratorTest {
|
||||
|
||||
@Test
|
||||
public void testGenerateTrackDescription() {
|
||||
Track track = new Track();
|
||||
TrackStatistics stats = new TrackStatistics();
|
||||
stats.setTotalDistance(Distance.of(20000));
|
||||
stats.setTotalTime(Duration.ofMillis(600000));
|
||||
stats.setMovingTime(Duration.ofMillis(300000));
|
||||
stats.setMaxSpeed(Speed.of(100));
|
||||
stats.setMaxAltitude(550);
|
||||
stats.setMinAltitude(-500);
|
||||
stats.setTotalAltitudeGain(6000f);
|
||||
stats.setTotalAltitudeLoss(6000f);
|
||||
stats.setStartTime(START_TIME);
|
||||
track.setTrackStatistics(stats);
|
||||
Track track = new Track(new Statistics(
|
||||
START_TIME,
|
||||
START_TIME,
|
||||
Duration.ofSeconds(600),
|
||||
Duration.ofSeconds(300),
|
||||
Distance.of(20000),
|
||||
Speed.of(100),
|
||||
new AltitudeExtremities(-500, 550),
|
||||
new AltitudeGainLoss(6000, 6000),
|
||||
null,
|
||||
null
|
||||
));
|
||||
track.setActivityTypeLocalized("hiking");
|
||||
|
||||
String expected = //"Created by"
|
||||
"OpenTracks (Debug)\n\n"
|
||||
+ "Name: -\n"
|
||||
|
||||
+6
-6
@@ -32,25 +32,25 @@ import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
|
||||
/**
|
||||
* Tests for {@link TrackStatistics}.
|
||||
* Tests for {@link SegmentStatisticUpdater}.
|
||||
* This only tests non-trivial pieces of that class.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TrackStatisticsTest {
|
||||
public class SegmentStatisticUpdaterTest {
|
||||
|
||||
private TrackStatistics statistics;
|
||||
private SegmentStatisticUpdater statistics;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
statistics = new TrackStatistics();
|
||||
statistics = new SegmentStatisticUpdater();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMerge_no_data() {
|
||||
// given
|
||||
TrackStatistics statistics2 = new TrackStatistics();
|
||||
SegmentStatisticUpdater statistics2 = new SegmentStatisticUpdater();
|
||||
|
||||
// when
|
||||
statistics.merge(statistics2);
|
||||
@@ -74,7 +74,7 @@ public class TrackStatisticsTest {
|
||||
@Test
|
||||
public void testMerge() {
|
||||
// given
|
||||
TrackStatistics statistics2 = new TrackStatistics();
|
||||
SegmentStatisticUpdater statistics2 = new SegmentStatisticUpdater();
|
||||
statistics.setStartTime(Instant.ofEpochMilli(1000)); // Resulting start time
|
||||
statistics.setStopTime(Instant.ofEpochMilli(2500));
|
||||
statistics2.setStartTime(Instant.ofEpochMilli(3000));
|
||||
+36
-36
@@ -31,7 +31,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
TrackStatisticsUpdater subject = new TrackStatisticsUpdater();
|
||||
|
||||
// then
|
||||
TrackStatistics statistics = subject.getTrackStatistics();
|
||||
SegmentStatisticUpdater statistics = subject.getSegmentStatisticUpdater();
|
||||
assertNull(statistics.getStartTime());
|
||||
assertNull(statistics.getStopTime());
|
||||
assertEquals(Duration.ZERO, statistics.getTotalTime());
|
||||
@@ -58,7 +58,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
subject.addTrackPoint(tp);
|
||||
|
||||
// then
|
||||
TrackStatistics statistics = subject.getTrackStatistics();
|
||||
SegmentStatisticUpdater statistics = subject.getSegmentStatisticUpdater();
|
||||
assertEquals(startTime, statistics.getStartTime());
|
||||
assertEquals(startTime, statistics.getStopTime());
|
||||
assertEquals(Duration.ZERO, statistics.getTotalTime());
|
||||
@@ -83,7 +83,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
data.trackPoints().forEach(subject::addTrackPoint);
|
||||
|
||||
// then
|
||||
TrackStatistics statistics = subject.getTrackStatistics();
|
||||
SegmentStatisticUpdater statistics = subject.getSegmentStatisticUpdater();
|
||||
assertEquals(142.26, statistics.getTotalDistance().toM(), 0.01);
|
||||
assertEquals(Duration.ofSeconds(12), statistics.getTotalTime());
|
||||
assertEquals(Duration.ofSeconds(12), statistics.getMovingTime());
|
||||
@@ -115,7 +115,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
subject.addTrackPoint(tp3);
|
||||
|
||||
// then
|
||||
assertEquals(1.10, subject.getTrackStatistics().getTotalDistance().toM(), 0.01);
|
||||
assertEquals(1.10, subject.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -140,14 +140,14 @@ public class TrackStatisticsUpdaterTest {
|
||||
subject.addTrackPoint(tp3);
|
||||
|
||||
// then
|
||||
assertEquals(110.57, subject.getTrackStatistics().getTotalDistance().toM(), 0.01);
|
||||
assertEquals(110.57, subject.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01);
|
||||
|
||||
// when
|
||||
subject.addTrackPoint(tp4);
|
||||
subject.addTrackPoint(tp5);
|
||||
|
||||
// then
|
||||
assertEquals(125.57, subject.getTrackStatistics().getTotalDistance().toM(), 0.01);
|
||||
assertEquals(125.57, subject.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -171,20 +171,20 @@ public class TrackStatisticsUpdaterTest {
|
||||
subject.addTrackPoint(tp3);
|
||||
|
||||
// then
|
||||
assertEquals(5, subject.getTrackStatistics().getTotalDistance().toM(), 0.01);
|
||||
assertEquals(5, subject.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01);
|
||||
|
||||
// when
|
||||
subject.addTrackPoint(tp4);
|
||||
subject.addTrackPoint(tp5);
|
||||
|
||||
// then
|
||||
assertEquals(59.18, subject.getTrackStatistics().getTotalDistance().toM(), 0.01);
|
||||
assertEquals(59.18, subject.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addTrackPoint_maxSpeed_multiple_segments() {
|
||||
TrackStatisticsUpdater subject = new TrackStatisticsUpdater();
|
||||
assertEquals(Speed.of(0f), subject.getTrackStatistics().getMaxSpeed());
|
||||
assertEquals(Speed.of(0f), subject.getSegmentStatisticUpdater().getMaxSpeed());
|
||||
|
||||
subject.addTrackPoints(List.of(
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.ofEpochSecond(0)),
|
||||
@@ -194,7 +194,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
.setSpeed(Speed.of(2f)),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.ofEpochSecond(4))
|
||||
));
|
||||
assertEquals(Speed.of(2f), subject.getTrackStatistics().getMaxSpeed());
|
||||
assertEquals(Speed.of(2f), subject.getSegmentStatisticUpdater().getMaxSpeed());
|
||||
|
||||
// when
|
||||
subject.addTrackPoints(List.of(
|
||||
@@ -207,7 +207,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
));
|
||||
|
||||
// then
|
||||
assertEquals(Speed.of(2f), subject.getTrackStatistics().getMaxSpeed());
|
||||
assertEquals(Speed.of(2f), subject.getSegmentStatisticUpdater().getMaxSpeed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -234,7 +234,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
));
|
||||
|
||||
// then
|
||||
assertEquals(Duration.ofSeconds(35), subject.getTrackStatistics().getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(35), subject.getSegmentStatisticUpdater().getMovingTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -264,8 +264,8 @@ public class TrackStatisticsUpdaterTest {
|
||||
));
|
||||
|
||||
// then
|
||||
assertEquals(Duration.ofSeconds(40), subject.getTrackStatistics().getMovingTime());
|
||||
assertEquals(Distance.of(1040), subject.getTrackStatistics().getTotalDistance());
|
||||
assertEquals(Duration.ofSeconds(40), subject.getSegmentStatisticUpdater().getMovingTime());
|
||||
assertEquals(Distance.of(1040), subject.getSegmentStatisticUpdater().getTotalDistance());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -280,49 +280,49 @@ public class TrackStatisticsUpdaterTest {
|
||||
|
||||
subject.addTrackPoint(new TrackPoint(TrackPoint.Type.IDLE, Instant.ofEpochSecond(30)));
|
||||
// then
|
||||
assertTrue(subject.getTrackStatistics().isIdle());
|
||||
assertEquals(Duration.ofSeconds(30), subject.getTrackStatistics().getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(30), subject.getTrackStatistics().getTotalTime());
|
||||
assertEquals(Distance.of(10), subject.getTrackStatistics().getTotalDistance());
|
||||
assertTrue(subject.getSegmentStatisticUpdater().isIdle());
|
||||
assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getTotalTime());
|
||||
assertEquals(Distance.of(10), subject.getSegmentStatisticUpdater().getTotalDistance());
|
||||
|
||||
// when
|
||||
subject.addTrackPoint(
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT, Instant.ofEpochSecond(40))
|
||||
.setSensorDistance(Distance.of(0)));
|
||||
// then
|
||||
assertTrue(subject.getTrackStatistics().isIdle());
|
||||
assertEquals(Duration.ofSeconds(30), subject.getTrackStatistics().getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(40), subject.getTrackStatistics().getTotalTime());
|
||||
assertEquals(Distance.of(10), subject.getTrackStatistics().getTotalDistance());
|
||||
assertTrue(subject.getSegmentStatisticUpdater().isIdle());
|
||||
assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(40), subject.getSegmentStatisticUpdater().getTotalTime());
|
||||
assertEquals(Distance.of(10), subject.getSegmentStatisticUpdater().getTotalDistance());
|
||||
|
||||
// when
|
||||
subject.addTrackPoint(
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT, Instant.ofEpochSecond(45))
|
||||
.setSensorDistance(Distance.of(1)));
|
||||
// then
|
||||
assertTrue(subject.getTrackStatistics().isIdle());
|
||||
assertEquals(Duration.ofSeconds(30), subject.getTrackStatistics().getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(45), subject.getTrackStatistics().getTotalTime());
|
||||
assertEquals(Distance.of(11), subject.getTrackStatistics().getTotalDistance());
|
||||
assertTrue(subject.getSegmentStatisticUpdater().isIdle());
|
||||
assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(45), subject.getSegmentStatisticUpdater().getTotalTime());
|
||||
assertEquals(Distance.of(11), subject.getSegmentStatisticUpdater().getTotalDistance());
|
||||
|
||||
// when
|
||||
subject.addTrackPoint(
|
||||
new TrackPoint(TrackPoint.Type.TRACKPOINT, Instant.ofEpochSecond(50))
|
||||
.setSensorDistance(Distance.of(10)));
|
||||
// then
|
||||
assertFalse(subject.getTrackStatistics().isIdle());
|
||||
assertEquals(Duration.ofSeconds(30), subject.getTrackStatistics().getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(50), subject.getTrackStatistics().getTotalTime());
|
||||
assertEquals(Distance.of(21), subject.getTrackStatistics().getTotalDistance());
|
||||
assertFalse(subject.getSegmentStatisticUpdater().isIdle());
|
||||
assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(50), subject.getSegmentStatisticUpdater().getTotalTime());
|
||||
assertEquals(Distance.of(21), subject.getSegmentStatisticUpdater().getTotalDistance());
|
||||
|
||||
// when
|
||||
subject.addTrackPoint(new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.ofEpochSecond(60)));
|
||||
|
||||
// then
|
||||
assertFalse(subject.getTrackStatistics().isIdle());
|
||||
assertEquals(Duration.ofSeconds(40), subject.getTrackStatistics().getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(60), subject.getTrackStatistics().getTotalTime());
|
||||
assertEquals(Distance.of(21), subject.getTrackStatistics().getTotalDistance());
|
||||
assertFalse(subject.getSegmentStatisticUpdater().isIdle());
|
||||
assertEquals(Duration.ofSeconds(40), subject.getSegmentStatisticUpdater().getMovingTime());
|
||||
assertEquals(Duration.ofSeconds(60), subject.getSegmentStatisticUpdater().getTotalTime());
|
||||
assertEquals(Distance.of(21), subject.getSegmentStatisticUpdater().getTotalDistance());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -350,8 +350,8 @@ public class TrackStatisticsUpdaterTest {
|
||||
copy.addTrackPoint(tp5);
|
||||
|
||||
// then
|
||||
assertEquals(55.287, subject.getTrackStatistics().getTotalDistance().toM(), 0.01);
|
||||
assertEquals(55.287, copy.getTrackStatistics().getTotalDistance().toM(), 0.01);
|
||||
assertEquals(55.287, subject.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01);
|
||||
assertEquals(55.287, copy.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01);
|
||||
}
|
||||
|
||||
public TrackPoint createTrackPoint(double latitude, double longitude, Altitude altitude, Instant time) {
|
||||
|
||||
+25
-23
@@ -17,10 +17,13 @@ import java.util.List;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.models.ActivityType;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeExtremities;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.stats.SegmentStatisticUpdater;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public class AggregatedStatisticsTest {
|
||||
@@ -28,21 +31,20 @@ public class AggregatedStatisticsTest {
|
||||
private final Context context = ApplicationProvider.getApplicationContext();
|
||||
|
||||
private static Track createTrack(Context context, Distance totalDistance, Duration totalTime, String activityTypeLocalized) {
|
||||
TrackStatistics statistics = new TrackStatistics();
|
||||
statistics.setStartTime(Instant.ofEpochMilli(1000L)); // Resulting start time
|
||||
statistics.setStopTime(statistics.getStartTime().plus(totalTime));
|
||||
statistics.setTotalTime(totalTime);
|
||||
statistics.setMovingTime(totalTime);
|
||||
statistics.setTotalDistance(totalDistance);
|
||||
statistics.setTotalAltitudeGain(50.0f);
|
||||
statistics.setMaxSpeed(Speed.of(50.0)); // Resulting max speed
|
||||
statistics.setMaxAltitude(1250.0);
|
||||
statistics.setMinAltitude(1200.0); // Resulting min altitude
|
||||
|
||||
Track track = new Track();
|
||||
Track track = new Track(new Statistics(
|
||||
Instant.ofEpochMilli(1000),
|
||||
Instant.ofEpochMilli(1000).plus(totalTime),
|
||||
totalTime,
|
||||
totalTime,
|
||||
totalDistance,
|
||||
Speed.of(50),
|
||||
new AltitudeExtremities(1250, 1250),
|
||||
new AltitudeGainLoss(50, 50),
|
||||
null,
|
||||
null
|
||||
));
|
||||
track.setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
|
||||
track.setActivityTypeLocalized(activityTypeLocalized);
|
||||
track.setTrackStatistics(statistics);
|
||||
return track;
|
||||
}
|
||||
|
||||
@@ -63,7 +65,7 @@ public class AggregatedStatisticsTest {
|
||||
assertNotNull(aggregatedStatistics.get(biking));
|
||||
assertEquals(1, aggregatedStatistics.get(biking).getCountTracks());
|
||||
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||
SegmentStatisticUpdater statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||
assertEquals(totalDistance, statistics2.getTotalDistance());
|
||||
assertEquals(totalTime, statistics2.getMovingTime());
|
||||
}
|
||||
@@ -117,7 +119,7 @@ public class AggregatedStatisticsTest {
|
||||
assertNotNull(aggregatedStatistics.get(biking));
|
||||
assertEquals(2, aggregatedStatistics.get(biking).getCountTracks());
|
||||
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||
SegmentStatisticUpdater statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||
assertEquals(totalDistance.multipliedBy(2), statistics2.getTotalDistance());
|
||||
assertEquals(totalTime.multipliedBy(2), statistics2.getMovingTime());
|
||||
}
|
||||
@@ -151,19 +153,19 @@ public class AggregatedStatisticsTest {
|
||||
assertEquals(1, aggregatedStatistics.get(walking).getCountTracks());
|
||||
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||
SegmentStatisticUpdater statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||
assertEquals(totalDistance, statistics2.getTotalDistance());
|
||||
assertEquals(totalTime, statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(running).getTrackStatistics();
|
||||
SegmentStatisticUpdater statistics2 = aggregatedStatistics.get(running).getTrackStatistics();
|
||||
assertEquals(totalDistance, statistics2.getTotalDistance());
|
||||
assertEquals(totalTime, statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(walking).getTrackStatistics();
|
||||
SegmentStatisticUpdater statistics2 = aggregatedStatistics.get(walking).getTrackStatistics();
|
||||
assertEquals(totalDistance, statistics2.getTotalDistance());
|
||||
assertEquals(totalTime, statistics2.getMovingTime());
|
||||
}
|
||||
@@ -214,28 +216,28 @@ public class AggregatedStatisticsTest {
|
||||
|
||||
// Biking.
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||
SegmentStatisticUpdater statistics2 = aggregatedStatistics.get(biking).getTrackStatistics();
|
||||
assertEquals(totalDistance.multipliedBy(5), statistics2.getTotalDistance());
|
||||
assertEquals(totalTime.multipliedBy(5), statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
// Running.
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(running).getTrackStatistics();
|
||||
SegmentStatisticUpdater statistics2 = aggregatedStatistics.get(running).getTrackStatistics();
|
||||
assertEquals(totalDistance.multipliedBy(2), statistics2.getTotalDistance());
|
||||
assertEquals(totalTime.multipliedBy(2), statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
// Walking.
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(walking).getTrackStatistics();
|
||||
SegmentStatisticUpdater statistics2 = aggregatedStatistics.get(walking).getTrackStatistics();
|
||||
assertEquals(totalDistance.multipliedBy(2), statistics2.getTotalDistance());
|
||||
assertEquals(totalTime.multipliedBy(2), statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
// Driving.
|
||||
{
|
||||
TrackStatistics statistics2 = aggregatedStatistics.get(driving).getTrackStatistics();
|
||||
SegmentStatisticUpdater statistics2 = aggregatedStatistics.get(driving).getTrackStatistics();
|
||||
assertEquals(totalDistance, statistics2.getTotalDistance());
|
||||
assertEquals(totalTime, statistics2.getMovingTime());
|
||||
}
|
||||
|
||||
+49
-68
@@ -3,47 +3,24 @@ package de.dennisguse.opentracks.ui.intervals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.dennisguse.opentracks.content.data.TestDataUtil;
|
||||
import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public class IntervalStatisticsTest {
|
||||
|
||||
private static final String TAG = IntervalStatisticsTest.class.getSimpleName();
|
||||
|
||||
private final Context context = ApplicationProvider.getApplicationContext();
|
||||
private ContentProviderUtils contentProviderUtils;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
contentProviderUtils = new ContentProviderUtils(context);
|
||||
}
|
||||
|
||||
private TrackStatistics buildTrackStatistics(List<TrackPoint> trackPoints) {
|
||||
TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater();
|
||||
for (TrackPoint tp : trackPoints) {
|
||||
trackStatisticsUpdater.addTrackPoint(tp);
|
||||
}
|
||||
return trackStatisticsUpdater.getTrackStatistics();
|
||||
}
|
||||
public class IntervalStatisticsUpdaterTest {
|
||||
|
||||
/**
|
||||
* Tests that build method compute the distance correctly comparing the result with TrackStatisticsUpdater result.
|
||||
@@ -125,77 +102,81 @@ public class IntervalStatisticsTest {
|
||||
Track dummyTrack = new Track();
|
||||
dummyTrack.setId(new Track.Id(System.currentTimeMillis()));
|
||||
dummyTrack.setName("Dummy Track Without Elevation Loss");
|
||||
contentProviderUtils.insertTrack(dummyTrack);
|
||||
TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater();
|
||||
|
||||
ArrayList<TrackPoint> trackPoints = new ArrayList<>();
|
||||
for (int i = 0; i < numberOfPoints; i++) {
|
||||
TrackPoint tp = TestDataUtil.createTrackPoint(i);
|
||||
tp.setAltitudeLoss(null);
|
||||
contentProviderUtils.insertTrackPoint(tp, dummyTrack.getId());
|
||||
trackStatisticsUpdater.addTrackPoint(tp);
|
||||
trackPoints.add(TestDataUtil.createTrackPoint(i).setAltitudeGainLoss(null));
|
||||
}
|
||||
dummyTrack.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
|
||||
contentProviderUtils.updateTrack(dummyTrack);
|
||||
Pair<Track.Id, TrackStatistics> trackWithStats = new Pair<>(dummyTrack.getId(), trackStatisticsUpdater.getTrackStatistics());
|
||||
trackStatisticsUpdater.addTrackPoints(trackPoints);
|
||||
|
||||
dummyTrack.setStatistics(trackStatisticsUpdater.getTrackStatistics());
|
||||
Pair<Track, List<TrackPoint>> trackWithStats = new Pair<>(dummyTrack, trackPoints);
|
||||
|
||||
// when and then
|
||||
whenAndThen(trackWithStats, numberOfPoints, distanceInterval);
|
||||
whenAndThen(trackWithStats.first, trackWithStats.second, numberOfPoints, distanceInterval);
|
||||
}
|
||||
|
||||
private void whenAndThen(int numberOfPoints, float distanceInterval) {
|
||||
Pair<Track.Id, TrackStatistics> trackWithStats = TestDataUtil.buildTrackWithTrackPoints(contentProviderUtils, numberOfPoints);
|
||||
whenAndThen(trackWithStats, numberOfPoints, distanceInterval);
|
||||
|
||||
Pair<Track, List<TrackPoint>> trackWithStats = buildTrackWithTrackPoints(numberOfPoints);
|
||||
whenAndThen(trackWithStats.first, trackWithStats.second, numberOfPoints, distanceInterval);
|
||||
}
|
||||
|
||||
private void whenAndThen(Pair<Track.Id, TrackStatistics> trackWithStats, int numberOfPoints, float distanceInterval) {
|
||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.of(distanceInterval));
|
||||
Track.Id trackId = trackWithStats.first;
|
||||
TrackStatistics trackStatistics = trackWithStats.second;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, null)) {
|
||||
assertEquals(trackPointIterator.getCount(), numberOfPoints);
|
||||
intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
}
|
||||
List<IntervalStatistics.Interval> intervalList = intervalStatistics.getIntervalList();
|
||||
private void whenAndThen(Track track, List<TrackPoint> trackPoints, int numberOfPoints, float distanceInterval) {
|
||||
IntervalStatisticsUpdater intervalStatistics = new IntervalStatisticsUpdater(Distance.of(distanceInterval));
|
||||
|
||||
intervalStatistics.addTrackPoints(trackPoints.iterator());
|
||||
|
||||
List<Statistics> intervalList = intervalStatistics.getIntervalList();
|
||||
Distance totalDistance = Distance.of(0);
|
||||
float totalTime = 0L;
|
||||
Float totalGain = null;
|
||||
Float totalLoss = null;
|
||||
for (IntervalStatistics.Interval i : intervalList) {
|
||||
totalDistance = totalDistance.plus(i.getDistance());
|
||||
totalTime += i.getDistance().toM() / i.getSpeed().toMPS();
|
||||
for (Statistics i : intervalList) {
|
||||
totalDistance = totalDistance.plus(i.totalDistance());
|
||||
totalTime += i.totalDistance().toM() / i.getAverageSpeed().toMPS();
|
||||
|
||||
if (totalGain == null) {
|
||||
totalGain = i.getGain_m();
|
||||
} else if (i.getGain_m() != null) {
|
||||
totalGain += i.getGain_m();
|
||||
totalGain = i.altitudeGainLoss() != null ? i.altitudeGainLoss().gain_m() : null;
|
||||
} else if (i.altitudeGainLoss() != null) {
|
||||
totalGain += i.altitudeGainLoss().gain_m();
|
||||
}
|
||||
|
||||
if (totalLoss == null) {
|
||||
totalLoss = i.getLoss_m();
|
||||
} else if (i.getLoss_m() != null) {
|
||||
totalLoss += i.getLoss_m();
|
||||
totalLoss = i.altitudeGainLoss() != null ? i.altitudeGainLoss().loss_m() : null;
|
||||
} else if (i.altitudeGainLoss() != null) {
|
||||
totalLoss += i.altitudeGainLoss().loss_m();
|
||||
}
|
||||
}
|
||||
|
||||
// then
|
||||
assertEquals(trackStatistics.getTotalDistance().toM(), totalDistance.toM(), 0.01);
|
||||
assertEquals(trackStatistics.getTotalTime().toSeconds(), totalTime, 0.01);
|
||||
assertEquals(intervalList.size(), (int) Math.ceil(trackStatistics.getTotalDistance().toM() / distanceInterval));
|
||||
if (totalGain != null) {
|
||||
assertEquals(track.getStatistics().totalTime().toSeconds(), totalTime, 0.01);
|
||||
assertEquals(track.getStatistics().totalDistance().toM(), totalDistance.toM(), 0.01);
|
||||
assertEquals(intervalList.size(), (int) Math.ceil(track.getStatistics().totalDistance().toM() / distanceInterval));
|
||||
if (totalGain != null && totalLoss != null) {
|
||||
assertEquals(totalGain, numberOfPoints * TestDataUtil.ALTITUDE_GAIN, 0.1);
|
||||
} else {
|
||||
assertTrue(intervalStatistics.getIntervalList().stream().noneMatch(IntervalStatistics.Interval::hasGain));
|
||||
}
|
||||
if (totalLoss != null) {
|
||||
assertEquals(totalLoss, numberOfPoints * TestDataUtil.ALTITUDE_LOSS, 0.1);
|
||||
|
||||
} else {
|
||||
assertTrue(intervalStatistics.getIntervalList().stream().noneMatch(IntervalStatistics.Interval::hasLoss));
|
||||
assertTrue(intervalStatistics.getIntervalList().stream().noneMatch(i -> i.altitudeGainLoss() != null));
|
||||
}
|
||||
|
||||
for (int i = 0; i < intervalList.size() - 1; i++) {
|
||||
assertEquals(intervalList.get(i).getDistance().toM(), distanceInterval, 0.001);
|
||||
totalDistance = totalDistance.minus(intervalList.get(i).getDistance());
|
||||
assertEquals(intervalList.get(i).totalDistance().toM(), distanceInterval, 0.001);
|
||||
totalDistance = totalDistance.minus(intervalList.get(i).totalDistance());
|
||||
}
|
||||
assertEquals(intervalList.get(intervalList.size() - 1).getDistance().toM(), totalDistance.toM(), 0.01);
|
||||
assertEquals(intervalList.get(intervalList.size() - 1).totalDistance().toM(), totalDistance.toM(), 0.01);
|
||||
}
|
||||
|
||||
private static Pair<Track, List<TrackPoint>> buildTrackWithTrackPoints(int numberOfPoints) {
|
||||
TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater();
|
||||
|
||||
ArrayList<TrackPoint> trackPoints = new ArrayList<>();
|
||||
for (int i = 0; i < numberOfPoints; i++) {
|
||||
trackPoints.add(TestDataUtil.createTrackPoint(i));
|
||||
}
|
||||
trackStatisticsUpdater.addTrackPoints(trackPoints);
|
||||
|
||||
return new Pair<>(new Track(trackStatisticsUpdater.getTrackStatistics()), trackPoints);
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,6 @@ Average moving pace: 0:00 min/km (0:00 min/mi)
|
||||
Fastest pace: 0:00 min/km (0:00 min/mi)
|
||||
Max elevation: -9223372036854775808 m (-9223372036854775808 ft)
|
||||
Min elevation: 9223372036854775807 m (9223372036854775807 ft)
|
||||
Elevation gain: 0 m (0 ft)
|
||||
Max grade: 0 %
|
||||
Min grade: 0 %
|
||||
Recorded: 6/23 11:29]]></description>
|
||||
@@ -126,11 +125,6 @@ Recorded: 6/23 11:29]]></description>
|
||||
<gx:value>0.15777911</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
</gx:SimpleArrayData>
|
||||
<gx:SimpleArrayData name="elevation_gain">
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
</gx:SimpleArrayData>
|
||||
</SchemaData>
|
||||
</ExtendedData>
|
||||
</gx:Track>
|
||||
@@ -148,14 +142,6 @@ Recorded: 6/23 11:29]]></description>
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
</gx:SimpleArrayData>
|
||||
<gx:SimpleArrayData name="elevation_gain">
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
<gx:value>0.0</gx:value>
|
||||
</gx:SimpleArrayData>
|
||||
</SchemaData>
|
||||
</ExtendedData>
|
||||
</gx:Track>
|
||||
@@ -179,7 +165,6 @@ Average moving pace: 0:00 min/km (0:00 min/mi)
|
||||
Fastest pace: 0:00 min/km (0:00 min/mi)
|
||||
Max elevation: 469 m (1540 ft)
|
||||
Min elevation: 419 m (1376 ft)
|
||||
Elevation gain: 0 m (0 ft)
|
||||
Recorded: 11/28 18:06]]></description>
|
||||
<TimeStamp>
|
||||
<when>2020-11-28T17:07:20.870Z</when>
|
||||
|
||||
@@ -25,7 +25,6 @@ import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
@@ -60,8 +59,6 @@ public class TrackRecordedActivity extends AbstractTrackDeleteActivity implement
|
||||
|
||||
private static final String TAG = TrackRecordedActivity.class.getSimpleName();
|
||||
|
||||
public static final String VIEW_TRACK_ICON = "track_icon";
|
||||
|
||||
public static final String EXTRA_TRACK_ID = "track_id";
|
||||
|
||||
private static final String CURRENT_TAB_TAG_KEY = "current_tab_tag_key";
|
||||
@@ -98,8 +95,6 @@ public class TrackRecordedActivity extends AbstractTrackDeleteActivity implement
|
||||
|
||||
viewBinding.bottomAppBarLayout.bottomAppBar.replaceMenu(R.menu.track_detail);
|
||||
setSupportActionBar(viewBinding.bottomAppBarLayout.bottomAppBar);
|
||||
|
||||
postponeEnterTransition();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -284,11 +279,6 @@ public class TrackRecordedActivity extends AbstractTrackDeleteActivity implement
|
||||
}
|
||||
}
|
||||
|
||||
public void startPostponedEnterTransitionWith(View viewIcon) {
|
||||
ViewCompat.setTransitionName(viewIcon, TrackRecordedActivity.VIEW_TRACK_ICON);
|
||||
startPostponedEnterTransition();
|
||||
}
|
||||
|
||||
private void onRecordingStatusChanged(RecordingStatus status) {
|
||||
recordingStatus = status;
|
||||
}
|
||||
|
||||
@@ -68,14 +68,14 @@ public class TrackStoppedActivity extends AbstractTrackDeleteActivity implements
|
||||
|
||||
viewBinding.trackEditDescription.setText(track.getDescription());
|
||||
|
||||
viewBinding.time.setText(StringUtils.formatElapsedTime(track.getTrackStatistics().getMovingTime()));
|
||||
viewBinding.time.setText(StringUtils.formatElapsedTime(track.getStatistics().movingTime()));
|
||||
|
||||
{
|
||||
Pair<String, String> parts = SpeedFormatter.Builder()
|
||||
.setUnit(PreferencesUtils.getUnitSystem())
|
||||
.setReportSpeedOrPace(PreferencesUtils.isReportSpeed(track))
|
||||
.build(this)
|
||||
.getSpeedParts(track.getTrackStatistics().getAverageMovingSpeed());
|
||||
.getSpeedParts(track.getStatistics().getAverageMovingSpeed());
|
||||
viewBinding.speed.setText(parts.first);
|
||||
viewBinding.speedUnit.setText(parts.second);
|
||||
}
|
||||
@@ -84,7 +84,7 @@ public class TrackStoppedActivity extends AbstractTrackDeleteActivity implements
|
||||
Pair<String, String> parts = DistanceFormatter.Builder()
|
||||
.setUnit(PreferencesUtils.getUnitSystem())
|
||||
.build(this)
|
||||
.getDistanceParts(track.getTrackStatistics().getTotalDistance());
|
||||
.getDistanceParts(track.getStatistics().totalDistance());
|
||||
viewBinding.distance.setText(parts.first);
|
||||
viewBinding.distanceUnit.setText(parts.second);
|
||||
}
|
||||
|
||||
@@ -33,17 +33,18 @@ import java.util.List;
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.TrackDataHub;
|
||||
import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.databinding.ChartBinding;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.stats.SegmentStatisticUpdater;
|
||||
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
||||
|
||||
/**
|
||||
* A fragment to display track chart to the user.
|
||||
* ChartFragment uses a {@link TrackStatisticsUpdater} internally and recomputes the {@link TrackStatistics} from the beginning.
|
||||
* ChartFragment uses a {@link TrackStatisticsUpdater} internally and recomputes the {@link SegmentStatisticUpdater} from the beginning.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
* @author Rodrigo Damazio
|
||||
@@ -202,7 +203,7 @@ public class ChartFragment extends Fragment implements TrackDataHub.Listener {
|
||||
}
|
||||
}
|
||||
|
||||
public void onSampledInTrackPoint(@NonNull TrackPoint trackPoint, @NonNull TrackStatistics trackStatistics) {
|
||||
public void onSampledInTrackPoint(@NonNull TrackPoint trackPoint, @NonNull Statistics trackStatistics) {
|
||||
if (isResumed()) {
|
||||
ChartPoint point = ChartPoint.create(trackStatistics, trackPoint, trackPoint.getSpeed(), chartByDistance, viewBinding.chartView.getUnitSystem());
|
||||
pendingPoints.add(point);
|
||||
|
||||
@@ -4,9 +4,9 @@ import androidx.annotation.NonNull;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
|
||||
public record ChartPoint(
|
||||
//X-axis
|
||||
@@ -22,11 +22,11 @@ public record ChartPoint(
|
||||
) {
|
||||
|
||||
|
||||
public static ChartPoint create(@NonNull TrackStatistics trackStatistics, @NonNull TrackPoint trackPoint, Speed smoothedSpeed, boolean chartByDistance, UnitSystem unitSystem) {
|
||||
public static ChartPoint create(@NonNull Statistics trackStatistics, @NonNull TrackPoint trackPoint, Speed smoothedSpeed, boolean chartByDistance, UnitSystem unitSystem) {
|
||||
return new ChartPoint(
|
||||
chartByDistance
|
||||
? trackStatistics.getTotalDistance().toKM_Miles(unitSystem)
|
||||
: trackStatistics.getTotalTime().toMillis(),
|
||||
? trackStatistics.totalDistance().toKM_Miles(unitSystem)
|
||||
: trackStatistics.totalTime().toMillis(),
|
||||
trackPoint.hasAltitude()
|
||||
? Distance.of(trackPoint.getAltitude().toM()).toM_FT(unitSystem)
|
||||
: null,
|
||||
|
||||
@@ -41,6 +41,8 @@ import java.util.UUID;
|
||||
import de.dennisguse.opentracks.BuildConfig;
|
||||
import de.dennisguse.opentracks.data.models.ActivityType;
|
||||
import de.dennisguse.opentracks.data.models.Altitude;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeExtremities;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.Cadence;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
@@ -48,14 +50,15 @@ import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.data.tables.MarkerColumns;
|
||||
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
|
||||
import de.dennisguse.opentracks.data.tables.TracksColumns;
|
||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.ui.markers.MarkerUtils;
|
||||
import de.dennisguse.opentracks.util.AutoCloseableIterator;
|
||||
import de.dennisguse.opentracks.util.FileUtils;
|
||||
|
||||
/**
|
||||
@@ -116,7 +119,6 @@ public class ContentProviderUtils {
|
||||
int altitudeLossIndex = cursor.getColumnIndexOrThrow(TracksColumns.ALTITUDE_LOSS);
|
||||
|
||||
Track track = new Track(ZoneOffset.ofTotalSeconds(cursor.getInt(startTimeOffsetIndex)));
|
||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||
if (!cursor.isNull(idIndex)) {
|
||||
track.setId(new Track.Id(cursor.getLong(idIndex)));
|
||||
}
|
||||
@@ -136,37 +138,23 @@ public class ContentProviderUtils {
|
||||
track.setActivityTypeLocalized(cursor.getString(activityTypeLocalizedIndex));
|
||||
}
|
||||
|
||||
if (!cursor.isNull(startTimeIndex)) {
|
||||
trackStatistics.setStartTime(Instant.ofEpochMilli(cursor.getLong(startTimeIndex)));
|
||||
}
|
||||
if (!cursor.isNull(stopTimeIndex)) {
|
||||
trackStatistics.setStopTime(Instant.ofEpochMilli(cursor.getLong(stopTimeIndex)));
|
||||
}
|
||||
if (!cursor.isNull(totalDistanceIndex)) {
|
||||
trackStatistics.setTotalDistance(Distance.of(cursor.getFloat(totalDistanceIndex)));
|
||||
}
|
||||
if (!cursor.isNull(totalTimeIndex)) {
|
||||
trackStatistics.setTotalTime(Duration.ofMillis(cursor.getLong(totalTimeIndex)));
|
||||
}
|
||||
if (!cursor.isNull(movingTimeIndex)) {
|
||||
trackStatistics.setMovingTime(Duration.ofMillis(cursor.getLong(movingTimeIndex)));
|
||||
}
|
||||
if (!cursor.isNull(maxSpeedIndex)) {
|
||||
trackStatistics.setMaxSpeed(Speed.of(cursor.getFloat(maxSpeedIndex)));
|
||||
}
|
||||
if (!cursor.isNull(minAltitudeIndex)) {
|
||||
trackStatistics.setMinAltitude(cursor.getFloat(minAltitudeIndex));
|
||||
}
|
||||
if (!cursor.isNull(maxAltitudeIndex)) {
|
||||
trackStatistics.setMaxAltitude(cursor.getFloat(maxAltitudeIndex));
|
||||
}
|
||||
if (!cursor.isNull(altitudeGainIndex)) {
|
||||
trackStatistics.setTotalAltitudeGain(cursor.getFloat(altitudeGainIndex));
|
||||
}
|
||||
if (!cursor.isNull(altitudeLossIndex)) {
|
||||
trackStatistics.setTotalAltitudeLoss(cursor.getFloat(altitudeLossIndex));
|
||||
}
|
||||
Statistics trackStatistics = new Statistics(
|
||||
cursor.isNull(startTimeIndex) ? null : Instant.ofEpochMilli(cursor.getLong(startTimeIndex)),
|
||||
cursor.isNull(stopTimeIndex) ? null : Instant.ofEpochMilli(cursor.getLong(stopTimeIndex)),
|
||||
cursor.isNull(totalTimeIndex) ? null : Duration.ofMillis(cursor.getLong(totalTimeIndex)),
|
||||
cursor.isNull(movingTimeIndex) ? null : Duration.ofMillis(cursor.getLong(movingTimeIndex)),
|
||||
|
||||
cursor.isNull(totalDistanceIndex) ? null : Distance.of(cursor.getFloat(totalDistanceIndex)),
|
||||
|
||||
cursor.isNull(maxSpeedIndex) ? null : Speed.of(cursor.getFloat(maxSpeedIndex)),
|
||||
cursor.isNull(minAltitudeIndex) || cursor.isNull(maxAltitudeIndex) ? null : new AltitudeExtremities(cursor.getFloat(minAltitudeIndex), cursor.getFloat(maxAltitudeIndex)),
|
||||
cursor.isNull(altitudeGainIndex) || cursor.isNull(altitudeLossIndex) ? null : new AltitudeGainLoss(cursor.getFloat(altitudeGainIndex), cursor.getFloat(altitudeLossIndex)),
|
||||
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
track.setStatistics(trackStatistics);
|
||||
return track;
|
||||
}
|
||||
|
||||
@@ -314,7 +302,7 @@ public class ContentProviderUtils {
|
||||
|
||||
private ContentValues createContentValues(Track track) {
|
||||
ContentValues values = new ContentValues();
|
||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||
Statistics trackStatistics = track.getStatistics();
|
||||
|
||||
if (track.getId() != null) {
|
||||
values.put(TracksColumns._ID, track.getId().id());
|
||||
@@ -325,48 +313,56 @@ public class ContentProviderUtils {
|
||||
values.put(TracksColumns.ACTIVITY_TYPE, track.getActivityType() != null ? track.getActivityType().getId() : null);
|
||||
values.put(TracksColumns.ACTIVITY_TYPE_LOCALIZED, track.getActivityTypeLocalized());
|
||||
values.put(TracksColumns.STARTTIME_OFFSET, track.getZoneOffset().getTotalSeconds());
|
||||
if (trackStatistics.getStartTime() != null) {
|
||||
values.put(TracksColumns.STARTTIME, trackStatistics.getStartTime().toEpochMilli());
|
||||
if (trackStatistics.startTime() != null) {
|
||||
values.put(TracksColumns.STARTTIME, trackStatistics.startTime().toEpochMilli());
|
||||
}
|
||||
if (trackStatistics.getStopTime() != null) {
|
||||
values.put(TracksColumns.STOPTIME, trackStatistics.getStopTime().toEpochMilli());
|
||||
if (trackStatistics.stopTime() != null) {
|
||||
values.put(TracksColumns.STOPTIME, trackStatistics.stopTime().toEpochMilli());
|
||||
}
|
||||
values.put(TracksColumns.TOTALDISTANCE, trackStatistics.getTotalDistance().toM());
|
||||
values.put(TracksColumns.TOTALTIME, trackStatistics.getTotalTime().toMillis());
|
||||
values.put(TracksColumns.MOVINGTIME, trackStatistics.getMovingTime().toMillis());
|
||||
values.put(TracksColumns.TOTALDISTANCE, trackStatistics.totalDistance().toM());
|
||||
values.put(TracksColumns.TOTALTIME, trackStatistics.totalTime().toMillis());
|
||||
values.put(TracksColumns.MOVINGTIME, trackStatistics.movingTime().toMillis());
|
||||
values.put(TracksColumns.AVGSPEED, trackStatistics.getAverageSpeed().toMPS());
|
||||
values.put(TracksColumns.AVGMOVINGSPEED, trackStatistics.getAverageMovingSpeed().toMPS());
|
||||
values.put(TracksColumns.MAXSPEED, trackStatistics.getMaxSpeed().toMPS());
|
||||
values.put(TracksColumns.MIN_ALTITUDE, trackStatistics.getMinAltitude());
|
||||
values.put(TracksColumns.MAX_ALTITUDE, trackStatistics.getMaxAltitude());
|
||||
values.put(TracksColumns.ALTITUDE_GAIN, trackStatistics.getTotalAltitudeGain());
|
||||
values.put(TracksColumns.ALTITUDE_LOSS, trackStatistics.getTotalAltitudeLoss());
|
||||
values.put(TracksColumns.MAXSPEED, trackStatistics.maxSpeed().toMPS());
|
||||
|
||||
if (trackStatistics.altitudeExtremities() != null) {
|
||||
values.put(TracksColumns.MIN_ALTITUDE, trackStatistics.getMinAltitude());
|
||||
values.put(TracksColumns.MAX_ALTITUDE, trackStatistics.getMaxAltitude());
|
||||
}
|
||||
|
||||
if (trackStatistics.altitudeGainLoss() != null) {
|
||||
values.put(TracksColumns.ALTITUDE_GAIN, trackStatistics.altitudeGainLoss().gain_m());
|
||||
values.put(TracksColumns.ALTITUDE_LOSS, trackStatistics.altitudeGainLoss().loss_m());
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
public void updateTrackStatistics(@NonNull Track.Id trackId, @NonNull TrackStatistics trackStatistics) {
|
||||
public void updateTrackStatistics(@NonNull Track.Id trackId, @NonNull Statistics trackStatistics) {
|
||||
contentResolver.update(TracksColumns.CONTENT_URI, createContentValues(trackStatistics), TracksColumns._ID + "=?", new String[]{Long.toString(trackId.id())});
|
||||
}
|
||||
|
||||
private ContentValues createContentValues(TrackStatistics trackStatistics) {
|
||||
private ContentValues createContentValues(Statistics trackStatistics) {
|
||||
ContentValues values = new ContentValues();
|
||||
if (trackStatistics.getStartTime() != null) {
|
||||
values.put(TracksColumns.STARTTIME, trackStatistics.getStartTime().toEpochMilli());
|
||||
if (trackStatistics.startTime() != null) {
|
||||
values.put(TracksColumns.STARTTIME, trackStatistics.startTime().toEpochMilli());
|
||||
}
|
||||
if (trackStatistics.getStopTime() != null) {
|
||||
values.put(TracksColumns.STOPTIME, trackStatistics.getStopTime().toEpochMilli());
|
||||
if (trackStatistics.stopTime() != null) {
|
||||
values.put(TracksColumns.STOPTIME, trackStatistics.stopTime().toEpochMilli());
|
||||
}
|
||||
values.put(TracksColumns.TOTALDISTANCE, trackStatistics.getTotalDistance().toM());
|
||||
values.put(TracksColumns.TOTALTIME, trackStatistics.getTotalTime().toMillis());
|
||||
values.put(TracksColumns.MOVINGTIME, trackStatistics.getMovingTime().toMillis());
|
||||
values.put(TracksColumns.TOTALDISTANCE, trackStatistics.totalDistance().toM());
|
||||
values.put(TracksColumns.TOTALTIME, trackStatistics.totalTime().toMillis());
|
||||
values.put(TracksColumns.MOVINGTIME, trackStatistics.movingTime().toMillis());
|
||||
values.put(TracksColumns.AVGSPEED, trackStatistics.getAverageSpeed().toMPS());
|
||||
values.put(TracksColumns.AVGMOVINGSPEED, trackStatistics.getAverageMovingSpeed().toMPS());
|
||||
values.put(TracksColumns.MAXSPEED, trackStatistics.getMaxSpeed().toMPS());
|
||||
values.put(TracksColumns.MAXSPEED, trackStatistics.maxSpeed().toMPS());
|
||||
values.put(TracksColumns.MIN_ALTITUDE, trackStatistics.getMinAltitude());
|
||||
values.put(TracksColumns.MAX_ALTITUDE, trackStatistics.getMaxAltitude());
|
||||
values.put(TracksColumns.ALTITUDE_GAIN, trackStatistics.getTotalAltitudeGain());
|
||||
values.put(TracksColumns.ALTITUDE_LOSS, trackStatistics.getTotalAltitudeLoss());
|
||||
if (trackStatistics.altitudeGainLoss() != null) {
|
||||
values.put(TracksColumns.ALTITUDE_GAIN, trackStatistics.altitudeGainLoss().gain_m());
|
||||
values.put(TracksColumns.ALTITUDE_LOSS, trackStatistics.altitudeGainLoss().loss_m());
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
@@ -656,11 +652,8 @@ public class ContentProviderUtils {
|
||||
trackPoint.setPower(cursor.getFloat(indexes.sensorPowerIndex));
|
||||
}
|
||||
|
||||
if (!cursor.isNull(indexes.altitudeGainIndex)) {
|
||||
trackPoint.setAltitudeGain(cursor.getFloat(indexes.altitudeGainIndex));
|
||||
}
|
||||
if (!cursor.isNull(indexes.altitudeLossIndex)) {
|
||||
trackPoint.setAltitudeLoss(cursor.getFloat(indexes.altitudeLossIndex));
|
||||
if (!cursor.isNull(indexes.altitudeGainIndex) && !cursor.isNull(indexes.altitudeLossIndex)) {
|
||||
trackPoint.setAltitudeGainLoss(cursor.getFloat(indexes.altitudeGainIndex), cursor.getFloat(indexes.altitudeLossIndex));
|
||||
}
|
||||
|
||||
return trackPoint;
|
||||
@@ -814,13 +807,10 @@ public class ContentProviderUtils {
|
||||
values.put(TrackPointsColumns.SENSOR_POWER, trackPoint.getPower().getW());
|
||||
}
|
||||
|
||||
if (trackPoint.hasAltitudeGain()) {
|
||||
values.put(TrackPointsColumns.ALTITUDE_GAIN, trackPoint.getAltitudeGain());
|
||||
if (trackPoint.hasAltitudeGainLoss()) {
|
||||
values.put(TrackPointsColumns.ALTITUDE_GAIN, trackPoint.getAltitudeGainLoss().gain_m());
|
||||
values.put(TrackPointsColumns.ALTITUDE_LOSS, trackPoint.getAltitudeGainLoss().loss_m());
|
||||
}
|
||||
if (trackPoint.hasAltitudeLoss()) {
|
||||
values.put(TrackPointsColumns.ALTITUDE_LOSS, trackPoint.getAltitudeLoss());
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
@@ -834,7 +824,7 @@ public class ContentProviderUtils {
|
||||
* @param trackId the track id
|
||||
* @param startTrackPointId the starting trackPoint id. `null` to ignore
|
||||
*/
|
||||
public TrackPointIterator getTrackPointLocationIterator(final Track.Id trackId, final TrackPoint.Id startTrackPointId) {
|
||||
public AutoCloseableIterator<TrackPoint> getTrackPointLocationIterator(final Track.Id trackId, final TrackPoint.Id startTrackPointId) {
|
||||
return new TrackPointIterator(this, trackId, startTrackPointId);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.data.tables.MarkerColumns;
|
||||
@@ -40,8 +41,8 @@ import de.dennisguse.opentracks.data.tables.TracksColumns;
|
||||
import de.dennisguse.opentracks.services.RecordingStatus;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.handlers.AltitudeCorrectionManager;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
||||
import de.dennisguse.opentracks.util.AutoCloseableIterator;
|
||||
|
||||
/**
|
||||
* Track data hub.
|
||||
@@ -330,7 +331,7 @@ public class TrackDataHub {
|
||||
}
|
||||
|
||||
TrackPoint trackPoint = null;
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(selectedTrackId, next)) {
|
||||
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(selectedTrackId, next)) {
|
||||
|
||||
while (trackPointIterator.hasNext()) {
|
||||
//Prevents a NPE if stop() is happening while notifyTrackPointsTableUpdate()
|
||||
@@ -428,7 +429,7 @@ public class TrackDataHub {
|
||||
*
|
||||
* @param trackPoint the trackPoint
|
||||
*/
|
||||
default void onSampledInTrackPoint(@NonNull TrackPoint trackPoint, @NonNull TrackStatistics trackStatistics) {
|
||||
default void onSampledInTrackPoint(@NonNull TrackPoint trackPoint, @NonNull Statistics trackStatistics) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -436,7 +437,7 @@ public class TrackDataHub {
|
||||
*
|
||||
* @param trackPoint the trackPoint
|
||||
*/
|
||||
default void onSampledOutTrackPoint(@NonNull TrackPoint trackPoint, @NonNull TrackStatistics trackStatistics) {
|
||||
default void onSampledOutTrackPoint(@NonNull TrackPoint trackPoint, @NonNull Statistics trackStatistics) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,16 +5,16 @@ import android.database.Cursor;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.util.AutoCloseableIterator;
|
||||
|
||||
/**
|
||||
* A lightweight wrapper around the original {@link Cursor}.
|
||||
*/
|
||||
public class TrackPointIterator implements Iterator<TrackPoint>, AutoCloseable {
|
||||
class TrackPointIterator extends AutoCloseableIterator<TrackPoint> {
|
||||
|
||||
private static final String TAG = TrackPointIterator.class.getSimpleName();
|
||||
|
||||
@@ -23,7 +23,7 @@ public class TrackPointIterator implements Iterator<TrackPoint>, AutoCloseable {
|
||||
private final CachedTrackPointsIndexes indexes;
|
||||
private Cursor cursor;
|
||||
|
||||
public TrackPointIterator(ContentProviderUtils contentProviderUtils, Track.Id trackId, TrackPoint.Id startTrackPointId) {
|
||||
TrackPointIterator(ContentProviderUtils contentProviderUtils, Track.Id trackId, TrackPoint.Id startTrackPointId) {
|
||||
this.contentProviderUtils = contentProviderUtils;
|
||||
this.trackId = trackId;
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
package de.dennisguse.opentracks.data.models;
|
||||
|
||||
public record AltitudeExtremities(double min_m, double max_m) {
|
||||
}
|
||||
@@ -26,6 +26,7 @@ public record Speed(double speed_mps) {
|
||||
return of(Distance.ofKilometer(speed_kmh), Duration.ofHours(1));
|
||||
}
|
||||
|
||||
//TODO Like Duration.ZERO
|
||||
public static Speed zero() {
|
||||
return of(0.0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package de.dennisguse.opentracks.data.models;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
public record Statistics(
|
||||
Instant startTime,
|
||||
Instant stopTime,
|
||||
//TODO Rename to totalDuration
|
||||
Duration totalTime,
|
||||
//TODO Rename to movingDuration
|
||||
Duration movingTime, // Based on when we believe the user is traveling
|
||||
|
||||
Distance totalDistance,
|
||||
//TODO Check if this is persisted; if not: remove
|
||||
Speed maxSpeed,
|
||||
|
||||
@Nullable
|
||||
AltitudeExtremities altitudeExtremities,
|
||||
|
||||
@Nullable
|
||||
AltitudeGainLoss altitudeGainLoss,
|
||||
|
||||
//NOTE: The following values are not persisted.
|
||||
@Nullable
|
||||
HeartRate avgHeartRate,
|
||||
@Nullable
|
||||
Power avgPower
|
||||
) {
|
||||
|
||||
public Duration getStoppedTime() {
|
||||
return totalTime.minus(movingTime);
|
||||
}
|
||||
|
||||
public Speed getAverageSpeed() {
|
||||
if (totalTime.isZero()) {
|
||||
return Speed.of(0);
|
||||
}
|
||||
return Speed.of(totalDistance, totalTime);
|
||||
}
|
||||
|
||||
public Speed getAverageMovingSpeed() {
|
||||
return Speed.of(totalDistance, movingTime);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
//TODO null should be return (need adjusting ContentPtoviderUtils.createContentValues()
|
||||
public double getMinAltitude() {
|
||||
if (altitudeExtremities == null) return 0;
|
||||
return altitudeExtremities.min_m();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
//TODO null should be return (need adjusting ContentPtoviderUtils.createContentValues()
|
||||
public double getMaxAltitude() {
|
||||
if (altitudeExtremities == null) return 0;
|
||||
return altitudeExtremities.max_m();
|
||||
}
|
||||
}
|
||||
@@ -26,10 +26,9 @@ import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.stats.SegmentStatisticUpdater;
|
||||
|
||||
/**
|
||||
* A track.
|
||||
@@ -49,17 +48,31 @@ public class Track {
|
||||
|
||||
private ActivityType activityType;
|
||||
|
||||
//TODO Move to Statistics?
|
||||
private ZoneOffset zoneOffset;
|
||||
|
||||
private TrackStatistics trackStatistics = new TrackStatistics();
|
||||
@NonNull
|
||||
private Statistics trackStatistics;
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
public Track() {
|
||||
this(ZoneOffset.UTC);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public Track(Statistics statistics) {
|
||||
this(ZoneOffset.UTC, statistics);
|
||||
}
|
||||
|
||||
@Deprecated //TODO Remove
|
||||
public Track(@NonNull ZoneOffset zoneOffset) {
|
||||
setZoneOffset(zoneOffset);
|
||||
this(zoneOffset, new SegmentStatisticUpdater().getStatistics());
|
||||
}
|
||||
|
||||
public Track(@NonNull ZoneOffset zoneOffset, @NonNull Statistics trackStatistics) {
|
||||
this.zoneOffset = zoneOffset;
|
||||
this.trackStatistics = trackStatistics;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,23 +142,23 @@ public class Track {
|
||||
|
||||
public OffsetDateTime getStartTime() {
|
||||
return trackStatistics
|
||||
.getStartTime().atOffset(zoneOffset);
|
||||
.startTime().atOffset(zoneOffset);
|
||||
}
|
||||
|
||||
public OffsetDateTime getStopTime() {
|
||||
return trackStatistics
|
||||
.getStopTime().atOffset(zoneOffset);
|
||||
.stopTime().atOffset(zoneOffset);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TrackStatistics getTrackStatistics() {
|
||||
public Statistics getStatistics() {
|
||||
return trackStatistics;
|
||||
}
|
||||
|
||||
public void setTrackStatistics(@NonNull TrackStatistics trackStatistics) {
|
||||
public void setStatistics(Statistics trackStatistics) {
|
||||
this.trackStatistics = trackStatistics;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Track{" +
|
||||
@@ -156,20 +169,6 @@ public class Track {
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Track track = (Track) o;
|
||||
return id.equals(track.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
|
||||
|
||||
public record Id(long id) implements Parcelable {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -83,8 +83,7 @@ public class TrackPoint {
|
||||
private HeartRate heartRate = null;
|
||||
private Cadence cadence = null;
|
||||
private Power power = null;
|
||||
private Float altitudeGain_m = null;
|
||||
private Float altitudeLoss_m = null;
|
||||
private AltitudeGainLoss altitudeGainLoss = null;
|
||||
|
||||
public TrackPoint(@Nullable TrackPoint.Id id, @NonNull Type type, @NonNull Position position) {
|
||||
this.id = id;
|
||||
@@ -163,31 +162,21 @@ public class TrackPoint {
|
||||
return getPosition().toLocation();
|
||||
}
|
||||
|
||||
public boolean hasAltitudeGain() {
|
||||
return altitudeGain_m != null;
|
||||
public boolean hasAltitudeGainLoss() {
|
||||
return altitudeGainLoss != null;
|
||||
}
|
||||
|
||||
public float getAltitudeGain() {
|
||||
return altitudeGain_m;
|
||||
public AltitudeGainLoss getAltitudeGainLoss() {
|
||||
return altitudeGainLoss;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public TrackPoint setAltitudeGain(Float altitudeGain_m) {
|
||||
this.altitudeGain_m = altitudeGain_m;
|
||||
public TrackPoint setAltitudeGainLoss(AltitudeGainLoss altitudeGainLoss) {
|
||||
this.altitudeGainLoss = altitudeGainLoss;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasAltitudeLoss() {
|
||||
return altitudeLoss_m != null;
|
||||
}
|
||||
|
||||
public float getAltitudeLoss() {
|
||||
return altitudeLoss_m;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public TrackPoint setAltitudeLoss(Float altitudeLoss_m) {
|
||||
this.altitudeLoss_m = altitudeLoss_m;
|
||||
public TrackPoint setAltitudeGainLoss(float altitudeGain_m, float altitudeLoss_m) {
|
||||
setAltitudeGainLoss(new AltitudeGainLoss(altitudeGain_m, altitudeLoss_m));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -326,11 +315,10 @@ public class TrackPoint {
|
||||
if (hasSensorDistance() && lastTrackPoint.hasSensorDistance()) {
|
||||
sensorDistance = sensorDistance.minus(lastTrackPoint.getSensorDistance());
|
||||
}
|
||||
if (hasAltitudeGain() && lastTrackPoint.hasAltitudeGain()) {
|
||||
altitudeGain_m -= lastTrackPoint.altitudeGain_m;
|
||||
}
|
||||
if (hasAltitudeLoss() && lastTrackPoint.hasAltitudeLoss()) {
|
||||
altitudeLoss_m -= lastTrackPoint.altitudeLoss_m;
|
||||
if (hasAltitudeGainLoss() && lastTrackPoint.hasAltitudeGainLoss()) {
|
||||
altitudeGainLoss = new AltitudeGainLoss(
|
||||
altitudeGainLoss.gain_m() - lastTrackPoint.altitudeGainLoss.gain_m(),
|
||||
altitudeGainLoss.loss_m() - lastTrackPoint.altitudeGainLoss.loss_m());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -391,14 +379,13 @@ public class TrackPoint {
|
||||
public String toString() {
|
||||
return "TrackPoint{" +
|
||||
"id=" + id +
|
||||
", type=" + type +
|
||||
", position=" + position +
|
||||
", sensorDistance=" + sensorDistance +
|
||||
", type=" + type +
|
||||
", heartRate=" + heartRate +
|
||||
", cadence=" + cadence +
|
||||
", power=" + power +
|
||||
", altitudeGain_m=" + altitudeGain_m +
|
||||
", altitudeLoss_m=" + altitudeLoss_m +
|
||||
", altitudeGainLoss=" + altitudeGainLoss +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
@@ -30,16 +30,15 @@ import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.TrackRecordedActivity;
|
||||
import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.models.DistanceFormatter;
|
||||
import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.databinding.StatisticsRecordedBinding;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -157,8 +156,6 @@ public class StatisticsRecordedFragment extends Fragment {
|
||||
loadTrackDescription(track);
|
||||
updateUI();
|
||||
updateSensorUI();
|
||||
|
||||
((TrackRecordedActivity) getActivity()).startPostponedEnterTransitionWith(viewBinding.statsActivityTypeIcon);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -171,12 +168,12 @@ public class StatisticsRecordedFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||
Statistics trackStatistics = track.getStatistics();
|
||||
// Set total distance
|
||||
{
|
||||
Pair<String, String> parts = DistanceFormatter.Builder()
|
||||
.setUnit(unitSystem)
|
||||
.build(getContext()).getDistanceParts(trackStatistics.getTotalDistance());
|
||||
.build(getContext()).getDistanceParts(trackStatistics.totalDistance());
|
||||
|
||||
viewBinding.statsDistanceValue.setText(parts.first);
|
||||
viewBinding.statsDistanceUnit.setText(parts.second);
|
||||
@@ -187,8 +184,8 @@ public class StatisticsRecordedFragment extends Fragment {
|
||||
|
||||
// Set time and start datetime
|
||||
{
|
||||
viewBinding.statsMovingTimeValue.setText(StringUtils.formatElapsedTime(trackStatistics.getMovingTime()));
|
||||
viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(trackStatistics.getTotalTime()));
|
||||
viewBinding.statsMovingTimeValue.setText(StringUtils.formatElapsedTime(trackStatistics.movingTime()));
|
||||
viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(trackStatistics.totalTime()));
|
||||
}
|
||||
|
||||
SpeedFormatter formatter = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(preferenceReportSpeed).build(getContext());
|
||||
@@ -205,7 +202,7 @@ public class StatisticsRecordedFragment extends Fragment {
|
||||
{
|
||||
viewBinding.statsMaxSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_max_speed : R.string.stats_fastest_pace);
|
||||
|
||||
Pair<String, String> parts = formatter.getSpeedParts(trackStatistics.getMaxSpeed());
|
||||
Pair<String, String> parts = formatter.getSpeedParts(trackStatistics.maxSpeed());
|
||||
viewBinding.statsMaxSpeedValue.setText(parts.first);
|
||||
viewBinding.statsMaxSpeedUnit.setText(parts.second);
|
||||
}
|
||||
@@ -221,8 +218,8 @@ public class StatisticsRecordedFragment extends Fragment {
|
||||
|
||||
// Set altitude gain and loss
|
||||
{
|
||||
Float altitudeGain_m = trackStatistics.getTotalAltitudeGain();
|
||||
Float altitudeLoss_m = trackStatistics.getTotalAltitudeLoss();
|
||||
Float altitudeGain_m = trackStatistics.altitudeGainLoss() != null ? trackStatistics.altitudeGainLoss().gain_m() : null;
|
||||
Float altitudeLoss_m = trackStatistics.altitudeGainLoss() != null ? trackStatistics.altitudeGainLoss().loss_m() : null;
|
||||
|
||||
Pair<String, String> parts;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.util.FileUtils;
|
||||
|
||||
@@ -91,7 +92,7 @@ public class TrackFilenameGenerator {
|
||||
Track track = new Track();
|
||||
track.setName("Berlin");
|
||||
track.setUuid(UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6"));
|
||||
track.getTrackStatistics().setStartTime(Instant.ofEpochMilli(0));
|
||||
track.setStatistics(new Statistics(Instant.MIN, null, null, null, null, null, null, null, null, null));
|
||||
|
||||
return format(track, TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES);
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ import java.util.Locale;
|
||||
import java.util.function.Function;
|
||||
|
||||
import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.util.AutoCloseableIterator;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -98,8 +98,8 @@ public class CSVTrackExporter implements TrackExporter {
|
||||
new Column("accuracy_vertical", t -> t.hasVerticalAccuracy() ? DISTANCE_FORMAT.format(t.getVerticalAccuracy().toM()) : ""),
|
||||
|
||||
new Column("speed", t -> t.hasSpeed() ? SPEED_FORMAT.format(t.getSpeed().toKMH()) : ""),
|
||||
new Column("altitude_gain", t -> t.hasAltitudeGain() ? ALTITUDE_FORMAT.format(t.getAltitudeGain()) : ""),
|
||||
new Column("altitude_loss", t -> t.hasAltitudeLoss() ? ALTITUDE_FORMAT.format(t.getAltitudeLoss()) : ""),
|
||||
new Column("altitude_gain", t -> t.hasAltitudeGainLoss() ? ALTITUDE_FORMAT.format(t.getAltitudeGainLoss().gain_m()) : ""),
|
||||
new Column("altitude_loss", t -> t.hasAltitudeGainLoss() ? ALTITUDE_FORMAT.format(t.getAltitudeGainLoss().loss_m()) : ""),
|
||||
new Column("sensor_distance", t -> t.hasSensorDistance() ? DISTANCE_FORMAT.format(t.getSensorDistance().toM()) : ""),
|
||||
new Column("heartrate", t -> t.hasHeartRate() ? HEARTRATE_FORMAT.format(t.getHeartRate().getBPM()) : ""),
|
||||
new Column("cadence", t -> t.hasCadence() ? CADENCE_FORMAT.format(t.getCadence().getRPM()) : ""),
|
||||
@@ -131,7 +131,7 @@ public class CSVTrackExporter implements TrackExporter {
|
||||
}
|
||||
|
||||
private void writeTrackPoints(List<Column> columns, Track track) throws InterruptedException {
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null)) {
|
||||
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null)) {
|
||||
while (trackPointIterator.hasNext()) {
|
||||
if (Thread.interrupted()) throw new InterruptedException();
|
||||
|
||||
|
||||
@@ -33,13 +33,13 @@ import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.AutoCloseableIterator;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -128,7 +128,7 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
|
||||
LinkedList<TrackPoint> sensorPoints = new LinkedList<>();
|
||||
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null)) {
|
||||
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null)) {
|
||||
while (trackPointIterator.hasNext()) {
|
||||
if (Thread.interrupted()) throw new InterruptedException();
|
||||
|
||||
@@ -279,18 +279,16 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
printWriter.println("<opentracks:typeTranslated>" + StringUtils.formatCData(track.getActivityTypeLocalized()) + "</opentracks:typeTranslated>");
|
||||
}
|
||||
|
||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||
Statistics trackStatistics = track.getStatistics();
|
||||
printWriter.println("<gpxtrkx:TrackStatsExtension>");
|
||||
printWriter.println("<gpxtrkx:Distance>" + trackStatistics.getTotalDistance().toM() + "</gpxtrkx:Distance>");
|
||||
printWriter.println("<gpxtrkx:TimerTime>" + trackStatistics.getTotalTime().getSeconds() + "</gpxtrkx:TimerTime>");
|
||||
printWriter.println("<gpxtrkx:MovingTime>" + trackStatistics.getMovingTime().getSeconds() + "</gpxtrkx:MovingTime>");
|
||||
printWriter.println("<gpxtrkx:Distance>" + trackStatistics.totalDistance().toM() + "</gpxtrkx:Distance>");
|
||||
printWriter.println("<gpxtrkx:TimerTime>" + trackStatistics.totalTime().getSeconds() + "</gpxtrkx:TimerTime>");
|
||||
printWriter.println("<gpxtrkx:MovingTime>" + trackStatistics.movingTime().getSeconds() + "</gpxtrkx:MovingTime>");
|
||||
printWriter.println("<gpxtrkx:StoppedTime>" + trackStatistics.getStoppedTime().getSeconds() + "</gpxtrkx:StoppedTime>");
|
||||
printWriter.println("<gpxtrkx:MaxSpeed>" + trackStatistics.getMaxSpeed().toMPS() + "</gpxtrkx:MaxSpeed>");
|
||||
if (trackStatistics.hasTotalAltitudeGain()) {
|
||||
printWriter.println("<gpxtrkx:Ascent>" + trackStatistics.getTotalAltitudeGain() + "</gpxtrkx:Ascent>");
|
||||
}
|
||||
if (trackStatistics.hasTotalAltitudeLoss()) {
|
||||
printWriter.println("<gpxtrkx:Descent>" + trackStatistics.getTotalAltitudeLoss() + "</gpxtrkx:Descent>");
|
||||
printWriter.println("<gpxtrkx:MaxSpeed>" + trackStatistics.maxSpeed().toMPS() + "</gpxtrkx:MaxSpeed>");
|
||||
if (trackStatistics.altitudeGainLoss() != null) {
|
||||
printWriter.println("<gpxtrkx:Ascent>" + trackStatistics.altitudeGainLoss().gain_m() + "</gpxtrkx:Ascent>");
|
||||
printWriter.println("<gpxtrkx:Descent>" + trackStatistics.altitudeGainLoss().loss_m() + "</gpxtrkx:Descent>");
|
||||
}
|
||||
printWriter.println("</gpxtrkx:TrackStatsExtension>");
|
||||
|
||||
@@ -340,12 +338,12 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
extensionContent += "<pwr:PowerInWatts>" + POWER_FORMAT.format(trackPoint.getPower().getW()) + "</pwr:PowerInWatts>\n";
|
||||
}
|
||||
|
||||
Double cumulativeGain = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasAltitudeGain() ? (double) tp.getAltitudeGain() : null);
|
||||
Double cumulativeGain = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasAltitudeGainLoss() ? (double) tp.getAltitudeGainLoss().gain_m() : null);
|
||||
if (cumulativeGain != null) {
|
||||
extensionContent += ("<opentracks:gain>" + ALTITUDE_FORMAT.format(cumulativeGain) + "</opentracks:gain>\n");
|
||||
}
|
||||
|
||||
Double cumulativeLoss = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasAltitudeLoss() ? (double) tp.getAltitudeLoss() : null);
|
||||
Double cumulativeLoss = cumulateSensorData(trackPoint, sensorPoints, (tp) -> tp.hasAltitudeGainLoss() ? (double) tp.getAltitudeGainLoss().loss_m() : null);
|
||||
if (cumulativeLoss != null) {
|
||||
extensionContent += ("<opentracks:loss>" + ALTITUDE_FORMAT.format(cumulativeLoss) + "</opentracks:loss>\n");
|
||||
}
|
||||
|
||||
@@ -36,13 +36,13 @@ import java.util.Objects;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.data.models.ActivityType;
|
||||
import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.ui.markers.MarkerUtils;
|
||||
import de.dennisguse.opentracks.util.AutoCloseableIterator;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -162,7 +162,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
boolean wroteTrack = false;
|
||||
boolean wroteSegment = false;
|
||||
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null)) {
|
||||
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null)) {
|
||||
while (trackPointIterator.hasNext()) {
|
||||
if (Thread.interrupted()) throw new InterruptedException();
|
||||
|
||||
@@ -384,9 +384,13 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
heartRateList.add(trackPoint.hasHeartRate() ? trackPoint.getHeartRate().getBPM() : null);
|
||||
cadenceList.add(trackPoint.hasCadence() ? trackPoint.getCadence().getRPM() : null);
|
||||
powerList.add(trackPoint.hasPower() ? trackPoint.getPower().getW() : null);
|
||||
|
||||
altitudeGainList.add(trackPoint.hasAltitudeGain() ? trackPoint.getAltitudeGain() : null);
|
||||
altitudeLossList.add(trackPoint.hasAltitudeLoss() ? trackPoint.getAltitudeLoss() : null);
|
||||
if (trackPoint.hasAltitudeGainLoss()) {
|
||||
altitudeGainList.add(trackPoint.getAltitudeGainLoss().loss_m());
|
||||
altitudeLossList.add(trackPoint.getAltitudeGainLoss().loss_m());
|
||||
} else {
|
||||
altitudeGainList.add(null);
|
||||
altitudeLossList.add(null);
|
||||
}
|
||||
accuracyHorizontal.add(trackPoint.hasHorizontalAccuracy() ? (float) trackPoint.getHorizontalAccuracy().toM() : null);
|
||||
accuracyVertical.add(trackPoint.hasVerticalAccuracy() ? (float) trackPoint.getVerticalAccuracy().toM() : null);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.stats.SegmentStatisticUpdater;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -48,7 +49,7 @@ import de.dennisguse.opentracks.util.StringUtils;
|
||||
* <p>
|
||||
* {@link de.dennisguse.opentracks.io.file.exporter.GPXTrackExporter} does not export information if a segment was started automatic or manually.
|
||||
* Therefore, all segments starts are marked as SEGMENT_START_AUTOMATIC.
|
||||
* Thus, the {@link de.dennisguse.opentracks.stats.TrackStatistics} cannot be restored correctly.
|
||||
* Thus, the {@link SegmentStatisticUpdater} cannot be restored correctly.
|
||||
*
|
||||
* @author Jimmy Shih
|
||||
*/
|
||||
@@ -368,18 +369,11 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
}
|
||||
}
|
||||
|
||||
if (gain != null) {
|
||||
if (gain != null && loss != null) {
|
||||
try {
|
||||
trackPoint.setAltitudeGain(Float.parseFloat(gain));
|
||||
trackPoint.setAltitudeGainLoss(Float.parseFloat(gain), Float.parseFloat(loss));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse altitude gain: %s", gain)), e);
|
||||
}
|
||||
}
|
||||
if (loss != null) {
|
||||
try {
|
||||
trackPoint.setAltitudeLoss(Float.parseFloat(loss));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse altitude loss: %s", loss)), e);
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse altitude gain: %s or los: %s", gain, loss)), e);
|
||||
}
|
||||
}
|
||||
if (sensorDistance != null) {
|
||||
|
||||
@@ -342,11 +342,10 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
if (i < sensorPowerList.size() && sensorPowerList.get(i) != null) {
|
||||
trackPoint.setPower(sensorPowerList.get(i));
|
||||
}
|
||||
if (i < altitudeGainList.size()) {
|
||||
trackPoint.setAltitudeGain(altitudeGainList.get(i));
|
||||
}
|
||||
if (i < altitudeLossList.size()) {
|
||||
trackPoint.setAltitudeLoss(altitudeLossList.get(i));
|
||||
if (i < altitudeGainList.size() && i < altitudeLossList.size()) {
|
||||
if (altitudeGainList.get(i) != null && altitudeLossList.get(i) != null) {
|
||||
trackPoint.setAltitudeGainLoss(altitudeGainList.get(i), altitudeLossList.get(i));
|
||||
}
|
||||
}
|
||||
if (i < accuracyHorizontal.size() && accuracyHorizontal.get(i) != null) {
|
||||
trackPoint.setHorizontalAccuracy(Distance.of(accuracyHorizontal.get(i)));
|
||||
|
||||
@@ -147,7 +147,7 @@ public class TrackImporter {
|
||||
|
||||
TrackStatisticsUpdater updater = new TrackStatisticsUpdater();
|
||||
updater.addTrackPoints(trackPoints);
|
||||
track.setTrackStatistics(updater.getTrackStatistics());
|
||||
track.setStatistics(updater.getTrackStatistics());
|
||||
|
||||
Track.Id trackId = contentProviderUtils.insertTrack(track);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package de.dennisguse.opentracks.sensors;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -15,6 +16,7 @@ import de.dennisguse.opentracks.sensors.sensorData.Aggregator;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||
import de.dennisguse.opentracks.util.SystemUtils;
|
||||
|
||||
public class SensorManager implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
@@ -24,6 +26,8 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
@VisibleForTesting
|
||||
public SensorDataSet sensorDataSet;
|
||||
|
||||
private PowerManager.WakeLock wakeLock;
|
||||
|
||||
private final TrackPointCreator observer;
|
||||
|
||||
private final SensorDataChangedObserver listener = new SensorDataChangedObserver() {
|
||||
@@ -71,6 +75,8 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
throw new RuntimeException("SensorManager cannot be started twice; stop first.");
|
||||
}
|
||||
|
||||
wakeLock = SystemUtils.acquireWakeLock(context, wakeLock);
|
||||
|
||||
gpsManager = new GpsManager(observer, listener);
|
||||
altitudeSumManager = new GainManager(listener);
|
||||
bluetoothSensorManager = new BluetoothRemoteSensorManager(context, handler, listener);
|
||||
@@ -83,6 +89,8 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
}
|
||||
|
||||
public void stop(Context context) {
|
||||
wakeLock = SystemUtils.releaseWakeLock(wakeLock);
|
||||
|
||||
bluetoothSensorManager.stop(context);
|
||||
bluetoothSensorManager = null;
|
||||
|
||||
|
||||
@@ -185,8 +185,7 @@ public class SensorDataSet {
|
||||
}
|
||||
|
||||
if (barometer != null && barometer.hasReceivedData()) {
|
||||
trackPoint.setAltitudeGain(barometer.getAggregatedValue(trackPointCreator.createNow()).gain_m());
|
||||
trackPoint.setAltitudeLoss(barometer.getAggregatedValue(trackPointCreator.createNow()).loss_m());
|
||||
trackPoint.setAltitudeGainLoss(barometer.getAggregatedValue(trackPointCreator.createNow()).gain_m(), barometer.getAggregatedValue(trackPointCreator.createNow()).loss_m());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,15 +2,16 @@ package de.dennisguse.opentracks.services;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.stats.SegmentStatisticUpdater;
|
||||
|
||||
/**
|
||||
* {@link Track} and {@link TrackPoint} must be immutable (i.e., their content does not change).
|
||||
*/
|
||||
public record RecordingData(Track track, TrackPoint latestTrackPoint, SensorDataSet sensorDataSet, TrackStatistics currentSegment) {
|
||||
public record RecordingData(Track track, TrackPoint latestTrackPoint, SensorDataSet sensorDataSet, Statistics currentSegment) {
|
||||
public String getTrackCategory() {
|
||||
if (track == null) {
|
||||
return "";
|
||||
@@ -18,22 +19,13 @@ public record RecordingData(Track track, TrackPoint latestTrackPoint, SensorData
|
||||
return track.getActivityTypeLocalized();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@NonNull
|
||||
public TrackStatistics getStatisticsTrack() {
|
||||
public Statistics getStatisticsTrack() {
|
||||
if (track == null) {
|
||||
return new TrackStatistics();
|
||||
return new SegmentStatisticUpdater().getStatistics();
|
||||
}
|
||||
|
||||
return track.getTrackStatistics();
|
||||
return track.getStatistics();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TrackStatistics getStatisticsCurrentSegment() {
|
||||
if (currentSegment == null) {
|
||||
return new TrackStatistics();
|
||||
}
|
||||
|
||||
return currentSegment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,13 +17,13 @@ import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.models.ActivityType;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.services.handlers.AltitudeCorrectionManager;
|
||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
||||
import de.dennisguse.opentracks.util.TrackNameUtils;
|
||||
|
||||
@@ -80,7 +80,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
|
||||
String activityTypeLocalized = PreferencesUtils.getDefaultActivityTypeLocalized();
|
||||
track.setActivityTypeLocalized(activityTypeLocalized);
|
||||
track.setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
|
||||
track.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
|
||||
track.setStatistics(trackStatisticsUpdater.getTrackStatistics());
|
||||
track.setName(TrackNameUtils.getTrackName(context, trackId, track.getStartTime()));
|
||||
contentProviderUtils.updateTrack(track);
|
||||
|
||||
@@ -98,7 +98,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
|
||||
return false;
|
||||
}
|
||||
|
||||
trackStatisticsUpdater = new TrackStatisticsUpdater(track.getTrackStatistics());
|
||||
trackStatisticsUpdater = new TrackStatisticsUpdater(track.getStatistics());
|
||||
onNewTrackPoint(trackPointCreator.createSegmentStartManual());
|
||||
|
||||
reset();
|
||||
@@ -124,16 +124,15 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
|
||||
|
||||
ALTITUDE_CORRECTION_MANAGER.correctAltitude(context, current.first);
|
||||
|
||||
Track track = contentProviderUtils.getTrack(trackId); //Get copy
|
||||
Track track = contentProviderUtils.getTrack(trackId); //Get copy TODO: Avoid re-loading data from DB
|
||||
if (track == null) {
|
||||
Log.w(TAG, "Requesting data if not recording is taking place, should not be done.");
|
||||
return null;
|
||||
}
|
||||
|
||||
track.setTrackStatistics(tmpTrackStatisticsUpdater.getTrackStatistics());
|
||||
TrackStatistics currentSegment = tmpTrackStatisticsUpdater.getCurrentSegment();
|
||||
track.setStatistics(tmpTrackStatisticsUpdater.getTrackStatistics());
|
||||
|
||||
return new RecordingData(track, current.first, current.second, currentSegment);
|
||||
return new RecordingData(track, current.first, current.second, tmpTrackStatisticsUpdater.getCurrentSegment());
|
||||
}
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
@@ -225,7 +224,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
|
||||
handler.postDelayed(ON_IDLE, idleDuration.toMillis());
|
||||
}
|
||||
|
||||
TrackStatistics getTrackStatistics() {
|
||||
Statistics getTrackStatistics() {
|
||||
return trackStatisticsUpdater == null ? null : trackStatisticsUpdater.getTrackStatistics();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.content.SharedPreferences;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.PowerManager.WakeLock;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -44,7 +43,6 @@ import de.dennisguse.opentracks.sensors.GpsStatusValue;
|
||||
import de.dennisguse.opentracks.services.announcement.VoiceAnnouncementManager;
|
||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.util.SystemUtils;
|
||||
|
||||
public class TrackRecordingService extends Service implements TrackPointCreator.Callback, SharedPreferences.OnSharedPreferenceChangeListener, TrackRecordingManager.IdleObserver {
|
||||
|
||||
@@ -89,7 +87,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
private MutableLiveData<RecordingData> recordingDataObservable;
|
||||
|
||||
// The following variables are set when recording:
|
||||
private WakeLock wakeLock; //TODO Move to SensorManager
|
||||
private Handler handler;
|
||||
|
||||
private TrackPointCreator trackPointCreator;
|
||||
@@ -125,7 +122,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
if (isRecording()) {
|
||||
endCurrentTrack();
|
||||
}
|
||||
if (isSensorStarted()) {
|
||||
if (trackPointCreator != null && trackPointCreator.isStarted()) {
|
||||
stopSensors();
|
||||
}
|
||||
|
||||
@@ -200,7 +197,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
}
|
||||
|
||||
public void tryStartSensors() {
|
||||
if (isSensorStarted()) return;
|
||||
if (trackPointCreator.isStarted()) return;
|
||||
|
||||
Log.i(TAG, "tryStartSensors");
|
||||
|
||||
@@ -208,12 +205,11 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
}
|
||||
|
||||
private synchronized void startSensors() {
|
||||
if (isSensorStarted()) {
|
||||
if (trackPointCreator.isStarted()) {
|
||||
Log.i(TAG, "sensors already started; skipping");
|
||||
return;
|
||||
}
|
||||
Log.i(TAG, "startSensors");
|
||||
wakeLock = SystemUtils.acquireWakeLock(this, wakeLock);
|
||||
trackPointCreator.start(this, handler);
|
||||
|
||||
ServiceCompat.startForeground(this, TrackRecordingServiceNotificationManager.NOTIFICATION_ID, notificationManager.onSensorsStarted(this), ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION + ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE);
|
||||
@@ -241,7 +237,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
trackPointCreator.stop();
|
||||
stopForeground(true);
|
||||
notificationManager.stop();
|
||||
wakeLock = SystemUtils.releaseWakeLock(wakeLock);
|
||||
gpsStatusObservable.postValue(STATUS_GPS_DEFAULT);
|
||||
}
|
||||
|
||||
@@ -318,7 +313,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
// Compute temporary track statistics using sensorData and update time.
|
||||
RecordingData data = trackRecordingManager.getDataForUI();
|
||||
|
||||
voiceAnnouncementManager.announceStatisticsIfNeeded(data.track(), data.sensorDataSet());
|
||||
voiceAnnouncementManager.announceStatisticsIfNeeded(data);
|
||||
|
||||
recordingDataObservable.postValue(data);
|
||||
}
|
||||
@@ -347,9 +342,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
return recordingStatus.isRecording();
|
||||
}
|
||||
|
||||
private boolean isSensorStarted() {
|
||||
return wakeLock != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, @Nullable String key) {
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
|
||||
previousLocationWasAccurate = currentLocationWasAccurate;
|
||||
}
|
||||
|
||||
notificationBuilder.setContentTitle(context.getString(R.string.track_distance_notification, formatter.formatDistance(recordingData.getStatisticsTrack().getTotalDistance())));
|
||||
notificationBuilder.setContentTitle(context.getString(R.string.track_distance_notification, formatter.formatDistance(recordingData.getStatisticsTrack().totalDistance())));
|
||||
String formattedSpeed = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(true).build(context).formatSpeed(recordingData.latestTrackPoint().getSpeed());
|
||||
notificationBuilder.setContentText(context.getString(R.string.track_speed_notification, formattedSpeed));
|
||||
notificationBuilder.setSubText(context.getString(R.string.track_recording_notification_accuracy, formattedAccuracy));
|
||||
|
||||
+29
-29
@@ -30,15 +30,14 @@ import java.util.List;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.services.RecordingData;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
|
||||
import de.dennisguse.opentracks.ui.intervals.IntervalStatisticsUpdater;
|
||||
import de.dennisguse.opentracks.util.AutoCloseableIterator;
|
||||
|
||||
/**
|
||||
* Execute a periodic task on a time or distance schedule.
|
||||
@@ -53,7 +52,7 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
|
||||
|
||||
private TTSManager voiceAnnouncement;
|
||||
|
||||
private TrackStatistics trackStatistics;
|
||||
private Statistics trackStatistics;
|
||||
|
||||
private static final Distance DISTANCE_OFF = Distance.of(Double.MAX_VALUE);
|
||||
private Distance distanceFrequency = DISTANCE_OFF;
|
||||
@@ -69,23 +68,23 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
|
||||
private final ContentProviderUtils contentProviderUtils;
|
||||
private TrackPoint.Id startTrackPointId = null;
|
||||
|
||||
private IntervalStatistics intervalStatistics;
|
||||
private IntervalStatisticsUpdater intervalStatistics;
|
||||
private Distance intervalDistance;
|
||||
|
||||
public VoiceAnnouncementManager(@NonNull Context context) {
|
||||
this.context = context;
|
||||
contentProviderUtils = new ContentProviderUtils(context);
|
||||
intervalDistance = PreferencesUtils.getVoiceAnnouncementDistance();
|
||||
intervalStatistics = new IntervalStatistics(intervalDistance);
|
||||
intervalStatistics = new IntervalStatisticsUpdater(intervalDistance);
|
||||
}
|
||||
|
||||
public void start(@Nullable TrackStatistics trackStatistics) {
|
||||
public void start(@Nullable Statistics trackStatistics) {
|
||||
voiceAnnouncement = new TTSManager(context);
|
||||
voiceAnnouncement.start();
|
||||
update(trackStatistics);
|
||||
}
|
||||
|
||||
void update(@Nullable TrackStatistics trackStatistics) {
|
||||
void update(@Nullable Statistics trackStatistics) {
|
||||
this.trackStatistics = trackStatistics;
|
||||
updateNextDuration();
|
||||
updateNextTaskDistance();
|
||||
@@ -120,44 +119,46 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
|
||||
voiceAnnouncement.speak(VoiceAnnouncementUtils.createIdle(context));
|
||||
}
|
||||
|
||||
public void announceStatisticsIfNeeded(@NonNull Track track, @NonNull SensorDataSet sensorDataSet) {
|
||||
public void announceStatisticsIfNeeded(@NonNull RecordingData data) {
|
||||
if (shouldNotAnnounce()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean announce = false;
|
||||
this.trackStatistics = track.getTrackStatistics();
|
||||
if (trackStatistics.getTotalDistance().greaterThan(nextTotalDistance)) {
|
||||
this.trackStatistics = data.track().getStatistics();
|
||||
if (trackStatistics.totalDistance().greaterThan(nextTotalDistance)) {
|
||||
updateNextTaskDistance();
|
||||
announce = true;
|
||||
}
|
||||
if (!trackStatistics.getTotalTime().minus(nextTotalTime).isNegative()) {
|
||||
if (!trackStatistics.totalTime().minus(nextTotalTime).isNegative()) {
|
||||
updateNextDuration();
|
||||
announce = true;
|
||||
}
|
||||
|
||||
if (announce) {
|
||||
voiceAnnouncement.speak(createAnnouncement(track, sensorDataSet));
|
||||
voiceAnnouncement.speak(createAnnouncement(data));
|
||||
}
|
||||
}
|
||||
|
||||
private Spannable createAnnouncement(Track track, SensorDataSet sensorDataSet) {
|
||||
private Spannable createAnnouncement(RecordingData data) {
|
||||
Distance currentIntervalDistance = PreferencesUtils.getVoiceAnnouncementDistance();
|
||||
if (currentIntervalDistance != intervalDistance) {
|
||||
intervalStatistics = new IntervalStatistics(currentIntervalDistance);
|
||||
intervalStatistics = new IntervalStatisticsUpdater(currentIntervalDistance);
|
||||
intervalDistance = currentIntervalDistance;
|
||||
startTrackPointId = null;
|
||||
}
|
||||
|
||||
TrackPointIterator trackPointIterator = new TrackPointIterator(contentProviderUtils, track.getId(), startTrackPointId);
|
||||
startTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
IntervalStatistics.Interval lastInterval = intervalStatistics.getLastInterval();
|
||||
SensorStatistics sensorStatistics = null;
|
||||
if (track.getId() != null) {
|
||||
sensorStatistics = contentProviderUtils.getSensorStats(track.getId());
|
||||
}
|
||||
//TODO Avoid reloading (some) TrackPoints just to announce the last interval.
|
||||
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(data.track().getId(), startTrackPointId)) {
|
||||
startTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
Statistics lastInterval = intervalStatistics.getLastInterval();
|
||||
SensorStatistics sensorStatistics = null;
|
||||
if (data.track().getId() != null) {
|
||||
sensorStatistics = contentProviderUtils.getSensorStats(data.track().getId());
|
||||
}
|
||||
|
||||
return VoiceAnnouncementUtils.createStatistics(context, track, sensorDataSet, PreferencesUtils.getUnitSystem(), PreferencesUtils.isReportSpeed(track), lastInterval, sensorStatistics);
|
||||
return VoiceAnnouncementUtils.createStatistics(context, data.track(), data.sensorDataSet(), PreferencesUtils.getUnitSystem(), PreferencesUtils.isReportSpeed(data.track()), lastInterval, sensorStatistics);
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
@@ -182,7 +183,7 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
|
||||
nextTotalDistance = DISTANCE_OFF;
|
||||
} else {
|
||||
|
||||
Distance distance = trackStatistics.getTotalDistance();
|
||||
Distance distance = trackStatistics.totalDistance();
|
||||
|
||||
int index = (int) (distance.dividedBy(distanceFrequency));
|
||||
nextTotalDistance = distanceFrequency.multipliedBy(index + 1);
|
||||
@@ -195,10 +196,9 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
|
||||
nextTotalTime = TOTALTIME_OFF;
|
||||
} else {
|
||||
|
||||
Duration totalTime = trackStatistics.getTotalTime();
|
||||
Duration intervalMod = Duration.ofMillis(trackStatistics.getTotalTime().toMillis() % totalTimeFrequency.toMillis());
|
||||
Duration intervalMod = Duration.ofMillis(trackStatistics.totalTime().toMillis() % totalTimeFrequency.toMillis());
|
||||
|
||||
nextTotalTime = totalTime.plus(totalTimeFrequency.minus(intervalMod));
|
||||
nextTotalTime = trackStatistics.totalTime().plus(totalTimeFrequency.minus(intervalMod));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-11
@@ -33,12 +33,11 @@ import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
class VoiceAnnouncementUtils {
|
||||
@@ -51,8 +50,8 @@ class VoiceAnnouncementUtils {
|
||||
.append(context.getString(R.string.voiceIdle));
|
||||
}
|
||||
|
||||
static Spannable createStatistics(Context context, Track track, SensorDataSet sensorDataSet, UnitSystem unitSystem, boolean isReportSpeed, @Nullable IntervalStatistics.Interval currentInterval, @Nullable SensorStatistics sensorStatistics) {
|
||||
TrackStatistics trackStatistics = track.getTrackStatistics();
|
||||
static Spannable createStatistics(Context context, Track track, SensorDataSet sensorDataSet, UnitSystem unitSystem, boolean isReportSpeed, @Nullable Statistics currentInterval, @Nullable SensorStatistics sensorStatistics) {
|
||||
Statistics trackStatistics = track.getStatistics();
|
||||
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||
|
||||
@@ -60,9 +59,9 @@ class VoiceAnnouncementUtils {
|
||||
appendTime(builder, track.getStopTime());
|
||||
}
|
||||
|
||||
Distance totalDistance = trackStatistics.getTotalDistance();
|
||||
Distance totalDistance = trackStatistics.totalDistance();
|
||||
Speed averageMovingSpeed = trackStatistics.getAverageMovingSpeed();
|
||||
Speed currentDistancePerTime = currentInterval != null ? currentInterval.getSpeed() : null;
|
||||
Speed currentDistancePerTime = currentInterval != null ? currentInterval.getAverageSpeed() : null;
|
||||
|
||||
int perUnitStringId = R.string.empty;
|
||||
int distanceId = R.string.voiceDistance;
|
||||
@@ -112,7 +111,7 @@ class VoiceAnnouncementUtils {
|
||||
boolean hasTravelledDistance = !totalDistance.isZero();
|
||||
|
||||
// Announce time
|
||||
Duration movingTime = trackStatistics.getMovingTime();
|
||||
Duration movingTime = trackStatistics.movingTime();
|
||||
if (shouldVoiceAnnounceMovingTime() && hasTravelledDistance && !movingTime.isZero()) {
|
||||
appendDuration(context, builder, movingTime);
|
||||
builder.append(".");
|
||||
@@ -179,8 +178,8 @@ class VoiceAnnouncementUtils {
|
||||
appendCardinal(builder, context.getString(R.string.sensor_state_heart_rate_value, averageHeartRate), averageHeartRate);
|
||||
builder.append(".");
|
||||
}
|
||||
if (shouldVoiceAnnounceLapHeartRate() && currentInterval != null && currentInterval.hasAverageHeartRate()) {
|
||||
int currentHeartRate = Math.round(currentInterval.getAverageHeartRate().getBPM());
|
||||
if (shouldVoiceAnnounceLapHeartRate() && currentInterval != null && currentInterval.avgHeartRate() != null) {
|
||||
int currentHeartRate = Math.round(currentInterval.avgHeartRate().getBPM());
|
||||
|
||||
builder.append(" ")
|
||||
.append(context.getString(R.string.lap_heart_rate));
|
||||
@@ -188,8 +187,8 @@ class VoiceAnnouncementUtils {
|
||||
builder.append(".");
|
||||
}
|
||||
|
||||
if (shouldVoiceAnnounceLapPower() && currentInterval != null && currentInterval.hasAveragePower()) {
|
||||
int currentPower = Math.round(currentInterval.getAveragePower().getW());
|
||||
if (shouldVoiceAnnounceLapPower() && currentInterval != null && currentInterval.avgPower() != null) {
|
||||
int currentPower = Math.round(currentInterval.avgPower().getW());
|
||||
if (shouldVoiceAnnounceUnit()) {
|
||||
String template = context.getResources().getString(R.string.power_x_watt);
|
||||
builder.append(" ")
|
||||
|
||||
@@ -47,7 +47,7 @@ public class TrackPointCreator implements SharedPreferences.OnSharedPreferenceCh
|
||||
sensorManager.start(context, handler);
|
||||
}
|
||||
|
||||
private boolean isStarted() {
|
||||
public boolean isStarted() {
|
||||
return context != null;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -65,7 +65,7 @@ public class TrackShareSummaryGenerator {
|
||||
writeString(track.getName(), builder, R.string.generic_name_line);
|
||||
writeString(track.getActivityTypeLocalized(), builder, R.string.description_activity_type);
|
||||
writeString(track.getDescription(), builder, R.string.generic_description_line);
|
||||
builder.append(generateTrackStatisticsDescription(track.getTrackStatistics()));
|
||||
builder.append(generateTrackStatisticsDescription(track.getStatistics()));
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
@@ -78,17 +78,17 @@ public class TrackShareSummaryGenerator {
|
||||
builder.append(TrackShareSummaryGenerator.TEXT_LINE_BREAK);
|
||||
}
|
||||
|
||||
private String generateTrackStatisticsDescription(TrackStatistics stats) {
|
||||
private String generateTrackStatisticsDescription(Statistics stats) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
// Total distance
|
||||
writeDistance(stats.getTotalDistance(), builder, R.string.description_total_distance);
|
||||
writeDistance(stats.totalDistance(), builder, R.string.description_total_distance);
|
||||
|
||||
// Total time
|
||||
writeTime(stats.getTotalTime(), builder, R.string.description_total_time);
|
||||
writeTime(stats.totalTime(), builder, R.string.description_total_time);
|
||||
|
||||
// Moving time
|
||||
writeTime(stats.getMovingTime(), builder, R.string.description_moving_time);
|
||||
writeTime(stats.movingTime(), builder, R.string.description_moving_time);
|
||||
|
||||
// Average speed
|
||||
writeSpeed(stats.getAverageSpeed(), builder, R.string.description_average_speed);
|
||||
@@ -97,7 +97,7 @@ public class TrackShareSummaryGenerator {
|
||||
writeSpeed(stats.getAverageMovingSpeed(), builder, R.string.description_average_moving_speed);
|
||||
|
||||
// Max speed
|
||||
writeSpeed(stats.getMaxSpeed(), builder, R.string.description_max_speed);
|
||||
writeSpeed(stats.maxSpeed(), builder, R.string.description_max_speed);
|
||||
|
||||
// Average pace
|
||||
writePace(stats.getAverageSpeed(), builder, R.string.description_average_pace_in_minute);
|
||||
@@ -106,26 +106,22 @@ public class TrackShareSummaryGenerator {
|
||||
writePace(stats.getAverageMovingSpeed(), builder, R.string.description_average_moving_pace_in_minute);
|
||||
|
||||
// Fastest pace
|
||||
writePace(stats.getMaxSpeed(), builder, R.string.description_fastest_pace_in_minute);
|
||||
writePace(stats.maxSpeed(), builder, R.string.description_fastest_pace_in_minute);
|
||||
|
||||
// Min and Max altitude
|
||||
if (stats.hasAltitudeExtremities()) {
|
||||
writeAltitude(stats.getMaxAltitude(), builder, R.string.description_max_altitude);
|
||||
writeAltitude(stats.getMinAltitude(), builder, R.string.description_min_altitude);
|
||||
if (stats.altitudeExtremities() != null) {
|
||||
writeAltitude(stats.altitudeExtremities().max_m(), builder, R.string.description_max_altitude);
|
||||
writeAltitude(stats.altitudeExtremities().min_m(), builder, R.string.description_min_altitude);
|
||||
}
|
||||
|
||||
// Altitude gain
|
||||
if (stats.hasTotalAltitudeGain()) {
|
||||
writeAltitude(stats.getTotalAltitudeGain(), builder, R.string.description_altitude_gain);
|
||||
}
|
||||
|
||||
// Altitude loss
|
||||
if (stats.hasTotalAltitudeLoss()) {
|
||||
writeAltitude(stats.getTotalAltitudeLoss(), builder, R.string.description_altitude_loss);
|
||||
// Altitude gain & loss
|
||||
if (stats.altitudeGainLoss() != null) {
|
||||
writeAltitude(stats.altitudeGainLoss().gain_m(), builder, R.string.description_altitude_gain);
|
||||
writeAltitude(stats.altitudeGainLoss().loss_m(), builder, R.string.description_altitude_loss);
|
||||
}
|
||||
|
||||
// Recorded time
|
||||
builder.append(context.getString(R.string.description_recorded_time, StringUtils.formatDateTimeWithOffset(OffsetDateTime.ofInstant(stats.getStartTime(), ZoneId.systemDefault()))));
|
||||
builder.append(context.getString(R.string.description_recorded_time, StringUtils.formatDateTimeWithOffset(OffsetDateTime.ofInstant(stats.startTime(), ZoneId.systemDefault()))));
|
||||
builder.append(TEXT_LINE_BREAK);
|
||||
|
||||
return builder.toString();
|
||||
|
||||
@@ -100,14 +100,15 @@ public class ExtremityMonitor {
|
||||
* @param min the minimum value
|
||||
* @param max the maximum value
|
||||
*/
|
||||
public void set(double min, double max) {
|
||||
public void set(Double min, Double max) {
|
||||
if (min == null || max == null) {
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if has data.
|
||||
*/
|
||||
public boolean hasData() {
|
||||
return min != Double.POSITIVE_INFINITY && max != Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
+67
-91
@@ -24,10 +24,13 @@ import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Altitude;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeExtremities;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
|
||||
@@ -38,8 +41,7 @@ import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
//TODO Check that data ranges are valid (not less than zero etc.)
|
||||
//TODO Should be a Java record
|
||||
public class TrackStatistics {
|
||||
public class SegmentStatisticUpdater {
|
||||
|
||||
// The min and max altitude (meters) seen on this track.
|
||||
private final ExtremityMonitor altitudeExtremities = new ExtremityMonitor();
|
||||
@@ -50,7 +52,11 @@ public class TrackStatistics {
|
||||
private Instant stopTime; //TODO Should never be null!
|
||||
|
||||
private Distance totalDistance;
|
||||
// Updated when new points are received, may be stale.
|
||||
/**
|
||||
* Updated when new points are received, may be stale.
|
||||
* 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 totalTime, use startTime with the current time.
|
||||
*/
|
||||
private Duration totalTime;
|
||||
// Based on when we believe the user is traveling.
|
||||
private Duration movingTime;
|
||||
@@ -64,7 +70,7 @@ public class TrackStatistics {
|
||||
|
||||
private boolean isIdle;
|
||||
|
||||
public TrackStatistics() {
|
||||
public SegmentStatisticUpdater() {
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -73,31 +79,27 @@ public class TrackStatistics {
|
||||
*
|
||||
* @param other another statistics data object to copy from
|
||||
*/
|
||||
public TrackStatistics(TrackStatistics other) {
|
||||
startTime = other.startTime;
|
||||
stopTime = other.stopTime;
|
||||
totalDistance = other.totalDistance;
|
||||
totalTime = other.totalTime;
|
||||
movingTime = other.movingTime;
|
||||
maxSpeed = other.maxSpeed;
|
||||
altitudeExtremities.set(other.altitudeExtremities.getMin(), other.altitudeExtremities.getMax());
|
||||
totalAltitudeGain_m = other.totalAltitudeGain_m;
|
||||
totalAltitudeLoss_m = other.totalAltitudeLoss_m;
|
||||
avgHeartRate = other.avgHeartRate;
|
||||
avgPower = other.avgPower;
|
||||
isIdle = other.isIdle;
|
||||
public SegmentStatisticUpdater(SegmentStatisticUpdater other) {
|
||||
this(other.getStatistics());
|
||||
this.isIdle = other.isIdle();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public TrackStatistics(String startTime, String stopTime, double totalDistance_m, int totalTime_s, int movingTime_s, float maxSpeed_mps, Float totalAltitudeGain_m, Float totalAltitudeLoss_m) {
|
||||
this.startTime = Instant.parse(startTime);
|
||||
this.stopTime = Instant.parse(stopTime);
|
||||
this.totalDistance = Distance.of(totalDistance_m);
|
||||
this.totalTime = Duration.ofSeconds(totalTime_s);
|
||||
this.movingTime = Duration.ofSeconds(movingTime_s);
|
||||
this.maxSpeed = Speed.of(maxSpeed_mps);
|
||||
this.totalAltitudeGain_m = totalAltitudeGain_m;
|
||||
this.totalAltitudeLoss_m = totalAltitudeLoss_m;
|
||||
public SegmentStatisticUpdater(Statistics statistics) {
|
||||
startTime = statistics.startTime();
|
||||
stopTime = statistics.stopTime();
|
||||
totalDistance = statistics.totalDistance();
|
||||
totalTime = statistics.totalTime();
|
||||
movingTime = statistics.movingTime();
|
||||
maxSpeed = statistics.maxSpeed();
|
||||
if (statistics.altitudeExtremities() != null) {
|
||||
altitudeExtremities.set(statistics.altitudeExtremities().min_m(), statistics.altitudeExtremities().max_m());
|
||||
}
|
||||
if (statistics.altitudeGainLoss() != null) {
|
||||
totalAltitudeGain_m = statistics.altitudeGainLoss().gain_m();
|
||||
totalAltitudeLoss_m = statistics.altitudeGainLoss().loss_m();
|
||||
}
|
||||
avgHeartRate = statistics.avgHeartRate();
|
||||
avgPower = statistics.avgPower();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +109,7 @@ public class TrackStatistics {
|
||||
* @param other another statistics data object
|
||||
*/
|
||||
//TODO Should be refactored to append only [mainly due to isIdle] (NOTE: This requires to use a custom value object for AggregatedStatistics; this is anyhow recommended).
|
||||
public void merge(TrackStatistics other) {
|
||||
public void merge(SegmentStatisticUpdater other) {
|
||||
if (startTime == null) {
|
||||
startTime = other.startTime;
|
||||
} else {
|
||||
@@ -183,12 +185,12 @@ public class TrackStatistics {
|
||||
startTime = null;
|
||||
stopTime = null;
|
||||
|
||||
setTotalDistance(Distance.of(0));
|
||||
setTotalTime(Duration.ofSeconds(0));
|
||||
setMovingTime(Duration.ofSeconds(0));
|
||||
setMaxSpeed(Speed.zero());
|
||||
setTotalAltitudeGain(null);
|
||||
setTotalAltitudeLoss(null);
|
||||
totalTime = Duration.ofSeconds(0);
|
||||
movingTime = Duration.ofSeconds(0);
|
||||
totalDistance = Distance.of(0);
|
||||
maxSpeed = Speed.zero();
|
||||
totalAltitudeGain_m = null;
|
||||
totalAltitudeLoss_m = null;
|
||||
|
||||
isIdle = false;
|
||||
}
|
||||
@@ -198,6 +200,22 @@ public class TrackStatistics {
|
||||
setStartTime(startTime);
|
||||
}
|
||||
|
||||
public Statistics getStatistics() {
|
||||
return new Statistics(
|
||||
startTime,
|
||||
stopTime,
|
||||
totalTime,
|
||||
movingTime,
|
||||
|
||||
totalDistance,
|
||||
getMaxSpeed(),
|
||||
altitudeExtremities.hasData() ? new AltitudeExtremities(altitudeExtremities.getMin(), altitudeExtremities.getMax()) : null,
|
||||
totalAltitudeGain_m != null && totalAltitudeLoss_m != null ? new AltitudeGainLoss(totalAltitudeGain_m, totalAltitudeLoss_m) : null,
|
||||
avgHeartRate,
|
||||
avgPower
|
||||
);
|
||||
}
|
||||
|
||||
public Instant getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
@@ -226,6 +244,7 @@ public class TrackStatistics {
|
||||
return totalDistance;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void setTotalDistance(Distance totalDistance_m) {
|
||||
this.totalDistance = totalDistance_m;
|
||||
}
|
||||
@@ -234,11 +253,6 @@ public class TrackStatistics {
|
||||
totalDistance = totalDistance.plus(distance_m);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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} with the current time.
|
||||
*/
|
||||
public Duration getTotalTime() {
|
||||
return totalTime;
|
||||
}
|
||||
@@ -267,10 +281,6 @@ public class TrackStatistics {
|
||||
movingTime = movingTime.plus(time);
|
||||
}
|
||||
|
||||
public Duration getStoppedTime() {
|
||||
return totalTime.minus(movingTime);
|
||||
}
|
||||
|
||||
public boolean isIdle() {
|
||||
return isIdle;
|
||||
}
|
||||
@@ -279,19 +289,11 @@ public class TrackStatistics {
|
||||
isIdle = idle;
|
||||
}
|
||||
|
||||
public boolean hasAverageHeartRate() {
|
||||
return avgHeartRate != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public HeartRate getAverageHeartRate() {
|
||||
return avgHeartRate;
|
||||
}
|
||||
|
||||
public boolean hasPower() {
|
||||
return avgPower != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Power getAveragePower() {
|
||||
return avgPower;
|
||||
@@ -320,10 +322,6 @@ public class TrackStatistics {
|
||||
this.maxSpeed = maxSpeed;
|
||||
}
|
||||
|
||||
public boolean hasAltitudeExtremities() {
|
||||
return altitudeExtremities.hasData();
|
||||
}
|
||||
|
||||
public double getMinAltitude() {
|
||||
return altitudeExtremities.getMin();
|
||||
}
|
||||
@@ -362,64 +360,42 @@ public class TrackStatistics {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasTotalAltitudeGain() {
|
||||
return totalAltitudeGain_m != null;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public Float getTotalAltitudeGain() {
|
||||
return totalAltitudeGain_m;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@Deprecated
|
||||
public void setTotalAltitudeGain(Float totalAltitudeGain_m) {
|
||||
this.totalAltitudeGain_m = totalAltitudeGain_m;
|
||||
}
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
public void addTotalAltitudeGain(float gain_m) {
|
||||
if (totalAltitudeGain_m == null) {
|
||||
totalAltitudeGain_m = 0f;
|
||||
}
|
||||
totalAltitudeGain_m += gain_m;
|
||||
}
|
||||
|
||||
public boolean hasTotalAltitudeLoss() {
|
||||
return totalAltitudeLoss_m != null;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public Float getTotalAltitudeLoss() {
|
||||
return totalAltitudeLoss_m;
|
||||
}
|
||||
|
||||
public void setTotalAltitudeLoss(Float totalAltitudeLoss_m) {
|
||||
this.totalAltitudeLoss_m = totalAltitudeLoss_m;
|
||||
}
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
public void addTotalAltitudeLoss(float loss_m) {
|
||||
public void addTotalAltitudeGainLoss(AltitudeGainLoss altitudeGainLoss) {
|
||||
if (totalAltitudeGain_m == null) {
|
||||
totalAltitudeGain_m = 0f;
|
||||
}
|
||||
totalAltitudeGain_m += altitudeGainLoss.gain_m();
|
||||
|
||||
if (totalAltitudeLoss_m == null) {
|
||||
totalAltitudeLoss_m = 0f;
|
||||
}
|
||||
totalAltitudeLoss_m += loss_m;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof TrackStatistics)) return false;
|
||||
|
||||
return toString().equals(o.toString());
|
||||
totalAltitudeLoss_m += altitudeGainLoss.loss_m();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TrackStatistics { Start Time: " + getStartTime() + "; Stop Time: " + getStopTime()
|
||||
+ "; Total Distance: " + getTotalDistance() + "; Total Time: " + getTotalTime()
|
||||
+ "; Moving Time: " + getMovingTime() + "; Max Speed: " + getMaxSpeed()
|
||||
+ "; Min Altitude: " + getMinAltitude() + "; Max Altitude: " + getMaxAltitude()
|
||||
+ "; Altitude Gain: " + getTotalAltitudeGain()
|
||||
+ "; Altitude Loss: " + getTotalAltitudeLoss() + "}";
|
||||
return "SegmentStatisticUpdater{" + getStatistics() + "}";
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package de.dennisguse.opentracks.stats;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
@@ -25,12 +26,13 @@ import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
|
||||
/**
|
||||
* Updater for {@link TrackStatistics}.
|
||||
* For updating track {@link TrackStatistics} as new {@link TrackPoint}s are added.
|
||||
* Updater for {@link SegmentStatisticUpdater}.
|
||||
* For updating track {@link SegmentStatisticUpdater} as new {@link TrackPoint}s are added.
|
||||
* NOTE: Some of the locations represent pause/resume separator.
|
||||
* NOTE: Has still support for segments (at the moment unused).
|
||||
*
|
||||
@@ -41,7 +43,7 @@ public class TrackStatisticsUpdater {
|
||||
|
||||
private static final String TAG = TrackStatisticsUpdater.class.getSimpleName();
|
||||
|
||||
private final TrackStatistics trackStatistics;
|
||||
private final SegmentStatisticUpdater segmentStatisticUpdater;
|
||||
|
||||
private float averageHeartRateBPM;
|
||||
private Duration totalHeartRateDuration = Duration.ZERO;
|
||||
@@ -49,38 +51,49 @@ public class TrackStatisticsUpdater {
|
||||
private Duration totalPowerDuration = Duration.ZERO;
|
||||
|
||||
// The current segment's statistics
|
||||
private final TrackStatistics currentSegment;
|
||||
private final SegmentStatisticUpdater currentSegment;
|
||||
// Current segment's last trackPoint
|
||||
private TrackPoint lastTrackPoint;
|
||||
|
||||
public TrackStatisticsUpdater() {
|
||||
this(new TrackStatistics());
|
||||
this(new SegmentStatisticUpdater());
|
||||
}
|
||||
|
||||
public TrackStatisticsUpdater(TrackStatistics trackStatistics) {
|
||||
this.trackStatistics = trackStatistics;
|
||||
this.currentSegment = new TrackStatistics();
|
||||
public TrackStatisticsUpdater(Statistics statistics) {
|
||||
this(new SegmentStatisticUpdater(statistics));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private TrackStatisticsUpdater(SegmentStatisticUpdater segmentStatisticUpdater) {
|
||||
this.segmentStatisticUpdater = segmentStatisticUpdater;
|
||||
this.currentSegment = new SegmentStatisticUpdater();
|
||||
|
||||
resetAverageHeartRate();
|
||||
}
|
||||
|
||||
public TrackStatisticsUpdater(TrackStatisticsUpdater toCopy) {
|
||||
this.currentSegment = new TrackStatistics(toCopy.currentSegment);
|
||||
this.trackStatistics = new TrackStatistics(toCopy.trackStatistics);
|
||||
this.currentSegment = new SegmentStatisticUpdater(toCopy.currentSegment);
|
||||
this.segmentStatisticUpdater = new SegmentStatisticUpdater(toCopy.segmentStatisticUpdater);
|
||||
|
||||
this.lastTrackPoint = toCopy.lastTrackPoint;
|
||||
resetAverageHeartRate();
|
||||
}
|
||||
|
||||
public TrackStatistics getTrackStatistics() {
|
||||
@Deprecated //TODO Remove
|
||||
@VisibleForTesting
|
||||
public SegmentStatisticUpdater getSegmentStatisticUpdater() {
|
||||
// Take a snapshot - we don't want anyone messing with our trackStatistics
|
||||
TrackStatistics stats = new TrackStatistics(trackStatistics);
|
||||
SegmentStatisticUpdater stats = new SegmentStatisticUpdater(segmentStatisticUpdater);
|
||||
stats.merge(currentSegment);
|
||||
return stats;
|
||||
}
|
||||
public TrackStatistics getCurrentSegment() {
|
||||
// Take a snapshot - we don't want anyone messing with our currentSegment
|
||||
return new TrackStatistics(currentSegment);
|
||||
|
||||
public Statistics getTrackStatistics() {
|
||||
return getSegmentStatisticUpdater().getStatistics();
|
||||
}
|
||||
|
||||
public Statistics getCurrentSegment() {
|
||||
return currentSegment.getStatistics();
|
||||
}
|
||||
|
||||
public void addTrackPoints(List<TrackPoint> trackPoints) {
|
||||
@@ -101,12 +114,8 @@ public class TrackStatisticsUpdater {
|
||||
currentSegment.setTotalTime(Duration.between(currentSegment.getStartTime(), trackPoint.getTime()));
|
||||
|
||||
// Process sensor data: barometer
|
||||
if (trackPoint.hasAltitudeGain()) {
|
||||
currentSegment.addTotalAltitudeGain(trackPoint.getAltitudeGain());
|
||||
}
|
||||
|
||||
if (trackPoint.hasAltitudeLoss()) {
|
||||
currentSegment.addTotalAltitudeLoss(trackPoint.getAltitudeLoss());
|
||||
if (trackPoint.hasAltitudeGainLoss()) {
|
||||
currentSegment.addTotalAltitudeGainLoss(trackPoint.getAltitudeGainLoss());
|
||||
}
|
||||
|
||||
//Update absolute (GPS-based) altitude
|
||||
@@ -182,7 +191,7 @@ public class TrackStatisticsUpdater {
|
||||
|
||||
private void reset(TrackPoint trackPoint) {
|
||||
if (currentSegment.isInitialized()) {
|
||||
trackStatistics.merge(currentSegment);
|
||||
segmentStatisticUpdater.merge(currentSegment);
|
||||
}
|
||||
currentSegment.reset(trackPoint.getTime());
|
||||
|
||||
@@ -209,7 +218,7 @@ public class TrackStatisticsUpdater {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TrackStatisticsUpdater{" +
|
||||
"trackStatistics=" + trackStatistics +
|
||||
"trackStatistics=" + segmentStatisticUpdater +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package de.dennisguse.opentracks.ui;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.util.Pair;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
@@ -269,10 +267,7 @@ public class TrackListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
||||
// Not recording -> open detail activity.
|
||||
Intent newIntent = IntentUtils.newIntent(context, TrackRecordedActivity.class)
|
||||
.putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId);
|
||||
ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(
|
||||
context,
|
||||
new Pair<>(viewBinding.getRoot().findViewById(R.id.track_list_item_icon), TrackRecordedActivity.VIEW_TRACK_ICON));
|
||||
context.startActivity(newIntent, activityOptions.toBundle());
|
||||
context.startActivity(newIntent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-9
@@ -8,8 +8,9 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.stats.SegmentStatisticUpdater;
|
||||
|
||||
public class AggregatedStatistics {
|
||||
|
||||
@@ -35,9 +36,9 @@ public class AggregatedStatistics {
|
||||
public void aggregate(@NonNull Track track) {
|
||||
String activityTypeLocalized = track.getActivityTypeLocalized();
|
||||
if (dataMap.containsKey(activityTypeLocalized)) {
|
||||
dataMap.get(activityTypeLocalized).add(track.getTrackStatistics());
|
||||
dataMap.get(activityTypeLocalized).add(track.getStatistics());
|
||||
} else {
|
||||
dataMap.put(activityTypeLocalized, new AggregatedStatistic(activityTypeLocalized, track.getTrackStatistics()));
|
||||
dataMap.put(activityTypeLocalized, new AggregatedStatistic(activityTypeLocalized, track.getStatistics()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,19 +56,19 @@ public class AggregatedStatistics {
|
||||
|
||||
public static class AggregatedStatistic {
|
||||
private final String activityTypeLocalized;
|
||||
private final TrackStatistics trackStatistics;
|
||||
private final SegmentStatisticUpdater trackStatistics;
|
||||
private int countTracks = 1;
|
||||
|
||||
public AggregatedStatistic(String activityTypeLocalized, TrackStatistics trackStatistics) {
|
||||
public AggregatedStatistic(String activityTypeLocalized, Statistics trackStatistics) {
|
||||
this.activityTypeLocalized = activityTypeLocalized;
|
||||
this.trackStatistics = trackStatistics;
|
||||
this.trackStatistics = new SegmentStatisticUpdater(trackStatistics);
|
||||
}
|
||||
|
||||
public String getActivityTypeLocalized() {
|
||||
return activityTypeLocalized;
|
||||
}
|
||||
|
||||
public TrackStatistics getTrackStatistics() {
|
||||
public SegmentStatisticUpdater getTrackStatistics() {
|
||||
return trackStatistics;
|
||||
}
|
||||
|
||||
@@ -75,8 +76,8 @@ public class AggregatedStatistics {
|
||||
return countTracks;
|
||||
}
|
||||
|
||||
void add(TrackStatistics statistics) {
|
||||
trackStatistics.merge(statistics);
|
||||
void add(Statistics statistics) {
|
||||
trackStatistics.merge(new SegmentStatisticUpdater(statistics));
|
||||
countTracks++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.stream.Collectors;
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
|
||||
//TODO Migrate to DataStore.
|
||||
public class RecordingLayoutIO {
|
||||
|
||||
private static final String TAG = RecordingLayout.class.getSimpleName();
|
||||
|
||||
+17
-11
@@ -19,15 +19,16 @@ import java.util.concurrent.Callable;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.models.Altitude;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.databinding.CustomStatsItemBinding;
|
||||
import de.dennisguse.opentracks.services.RecordingData;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.viewmodels.Mapping;
|
||||
import de.dennisguse.opentracks.viewmodels.StatisticViewHolder;
|
||||
|
||||
@@ -38,17 +39,22 @@ public class SettingsCustomLayoutEditAdapter extends RecyclerView.Adapter<Recycl
|
||||
private static final RecordingData demoData;
|
||||
|
||||
static {
|
||||
TrackStatistics trackStatistics = new TrackStatistics();
|
||||
trackStatistics.setStartTime(Instant.ofEpochMilli(0));
|
||||
trackStatistics.setMovingTime(Duration.ofMinutes(0));
|
||||
trackStatistics.setTotalTime(Duration.ofMinutes(0));
|
||||
Statistics statistics = new Statistics(
|
||||
Instant.ofEpochMilli(0),
|
||||
Instant.ofEpochMilli(0),
|
||||
Duration.ofMinutes(0),
|
||||
Duration.ofMinutes(0),
|
||||
|
||||
trackStatistics.setTotalDistance(Distance.of(0));
|
||||
Distance.of(0),
|
||||
Speed.of(0),
|
||||
null,
|
||||
|
||||
trackStatistics.setTotalAltitudeGain(0f);
|
||||
trackStatistics.setTotalAltitudeLoss(0f);
|
||||
Track track = new Track(ZoneOffset.UTC);
|
||||
track.setTrackStatistics(trackStatistics);
|
||||
new AltitudeGainLoss(0f, 0f),
|
||||
|
||||
null,
|
||||
null
|
||||
);
|
||||
Track track = new Track(ZoneOffset.UTC); //TODO Pass statistics as well
|
||||
|
||||
Position position = new Position(
|
||||
Instant.ofEpochMilli(0),
|
||||
@@ -61,7 +67,7 @@ public class SettingsCustomLayoutEditAdapter extends RecyclerView.Adapter<Recycl
|
||||
Speed.zero()
|
||||
);
|
||||
|
||||
demoData = new RecordingData(track, new TrackPoint(TrackPoint.Type.TRACKPOINT, position), null, trackStatistics) ;
|
||||
demoData = new RecordingData(track, new TrackPoint(TrackPoint.Type.TRACKPOINT, position), null, statistics);
|
||||
}
|
||||
|
||||
private RecordingLayout recordingLayout;
|
||||
|
||||
+12
-17
@@ -7,18 +7,20 @@ import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.DistanceFormatter;
|
||||
import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.databinding.IntervalStatsListItemBinding;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.util.StringUtils;
|
||||
|
||||
public class IntervalStatisticsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
private List<IntervalStatistics.Interval> intervalList;
|
||||
private List<Statistics> intervalList = new ArrayList<>();
|
||||
private final Context context;
|
||||
private final StackMode stackMode;
|
||||
private UnitSystem unitSystem;
|
||||
@@ -43,46 +45,39 @@ public class IntervalStatisticsAdapter extends RecyclerView.Adapter<RecyclerView
|
||||
int nextPosition = actualPosition + 1;
|
||||
boolean isLast = actualPosition == getItemCount() - 1;
|
||||
IntervalStatisticsAdapter.ViewHolder viewHolder = (IntervalStatisticsAdapter.ViewHolder) holder;
|
||||
IntervalStatistics.Interval interval = intervalList.get(actualPosition);
|
||||
Statistics interval = intervalList.get(actualPosition);
|
||||
viewHolder.itemView.setTag(actualPosition);
|
||||
|
||||
Distance sumDistance;
|
||||
if (isLast && actualPosition > 0) {
|
||||
sumDistance = intervalList.get(actualPosition - 1).getDistance()
|
||||
sumDistance = intervalList.get(actualPosition - 1).totalDistance()
|
||||
.multipliedBy(actualPosition)
|
||||
.plus(interval.getDistance());
|
||||
.plus(interval.totalDistance());
|
||||
} else {
|
||||
sumDistance = interval.getDistance().multipliedBy(nextPosition);
|
||||
sumDistance = interval.totalDistance().multipliedBy(nextPosition);
|
||||
}
|
||||
viewHolder.viewBinding.intervalItemDistance.setText(DistanceFormatter.Builder()
|
||||
.setUnit(unitSystem)
|
||||
.build(context).formatDistance(sumDistance));
|
||||
|
||||
SpeedFormatter formatter = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(isReportSpeed).build(context);
|
||||
viewHolder.viewBinding.intervalItemRate.setText(formatter.formatSpeed(interval.getSpeed()));
|
||||
viewHolder.viewBinding.intervalItemRate.setText(formatter.formatSpeed(interval.getAverageSpeed()));
|
||||
|
||||
viewHolder.viewBinding.intervalItemGain.setText(StringUtils.formatAltitude(context, interval.getGain_m(), unitSystem));
|
||||
viewHolder.viewBinding.intervalItemLoss.setText(StringUtils.formatAltitude(context, interval.getLoss_m(), unitSystem));
|
||||
viewHolder.viewBinding.intervalItemGain.setText(StringUtils.formatAltitude(context, interval.altitudeGainLoss() != null ? interval.altitudeGainLoss().gain_m() : null, unitSystem));
|
||||
viewHolder.viewBinding.intervalItemLoss.setText(StringUtils.formatAltitude(context, interval.altitudeGainLoss() != null ? interval.altitudeGainLoss().loss_m() : null, unitSystem));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
if (intervalList == null) {
|
||||
return 0;
|
||||
}
|
||||
return intervalList.size();
|
||||
}
|
||||
|
||||
public List<IntervalStatistics.Interval> swapData(List<IntervalStatistics.Interval> data, UnitSystem unitSystem, boolean isReportSpeed) {
|
||||
public void swapData(@NonNull List<Statistics> data, UnitSystem unitSystem, boolean isReportSpeed) {
|
||||
this.unitSystem = unitSystem;
|
||||
this.isReportSpeed = isReportSpeed;
|
||||
intervalList = data;
|
||||
|
||||
if (data != null) {
|
||||
this.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
return data;
|
||||
this.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,12 +17,13 @@ import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
import de.dennisguse.opentracks.util.AutoCloseableIterator;
|
||||
|
||||
/**
|
||||
* This model is used to load intervals for a track.
|
||||
@@ -32,8 +33,8 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
|
||||
private static final String TAG = IntervalStatisticsModel.class.getSimpleName();
|
||||
|
||||
private MutableLiveData<List<IntervalStatistics.Interval>> intervalsLiveData;
|
||||
private IntervalStatistics intervalStatistics;
|
||||
private MutableLiveData<List<Statistics>> intervalsLiveData;
|
||||
private IntervalStatisticsUpdater intervalStatistics;
|
||||
private Distance distanceInterval;
|
||||
private final ContentResolver contentResolver;
|
||||
private ContentObserver trackPointsTableObserver;
|
||||
@@ -65,7 +66,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
handler = null;
|
||||
}
|
||||
|
||||
public MutableLiveData<List<IntervalStatistics.Interval>> getIntervalStats(Track.Id trackId, UnitSystem unitSystem, @Nullable IntervalOption interval) {
|
||||
public MutableLiveData<List<Statistics>> getIntervalStats(Track.Id trackId, UnitSystem unitSystem, @Nullable IntervalOption interval) {
|
||||
if (intervalsLiveData == null) {
|
||||
if (interval == null) {
|
||||
interval = IntervalOption.OPTION_1;
|
||||
@@ -73,7 +74,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
|
||||
intervalsLiveData = new MutableLiveData<>();
|
||||
distanceInterval = interval.getDistance(unitSystem);
|
||||
intervalStatistics = new IntervalStatistics(distanceInterval);
|
||||
intervalStatistics = new IntervalStatisticsUpdater(distanceInterval);
|
||||
|
||||
loadIntervalStatistics(trackId);
|
||||
}
|
||||
@@ -92,7 +93,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
private void loadIntervalStatistics(Track.Id trackId) {
|
||||
executor.execute(() -> {
|
||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(getApplication());
|
||||
try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, lastTrackPointId)) {
|
||||
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, lastTrackPointId)) {
|
||||
lastTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator);
|
||||
intervalsLiveData.postValue(intervalStatistics.getIntervalList());
|
||||
}
|
||||
@@ -112,7 +113,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
||||
|
||||
lastTrackPointId = null;
|
||||
distanceInterval = interval.getDistance(unitSystem);
|
||||
intervalStatistics = new IntervalStatistics(distanceInterval);
|
||||
intervalStatistics = new IntervalStatisticsUpdater(distanceInterval);
|
||||
loadIntervalStatistics(trackId);
|
||||
}
|
||||
|
||||
|
||||
+51
-42
@@ -4,18 +4,19 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import de.dennisguse.opentracks.data.TrackPointIterator;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
||||
|
||||
public class IntervalStatistics {
|
||||
public class IntervalStatisticsUpdater {
|
||||
private TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater();
|
||||
private final List<Interval> intervalList;
|
||||
private final Distance distanceInterval;
|
||||
@@ -24,7 +25,7 @@ public class IntervalStatistics {
|
||||
/**
|
||||
* @param distanceInterval distance of every interval.
|
||||
*/
|
||||
public IntervalStatistics(Distance distanceInterval) {
|
||||
public IntervalStatisticsUpdater(Distance distanceInterval) {
|
||||
this.distanceInterval = distanceInterval;
|
||||
|
||||
interval = new Interval();
|
||||
@@ -38,7 +39,7 @@ public class IntervalStatistics {
|
||||
*
|
||||
* @return the last track point's id used to compute the intervals.
|
||||
*/
|
||||
public TrackPoint.Id addTrackPoints(TrackPointIterator trackPointIterator) {
|
||||
public TrackPoint.Id addTrackPoints(Iterator<TrackPoint> trackPointIterator) {
|
||||
boolean newIntervalAdded = false;
|
||||
TrackPoint trackPoint = null;
|
||||
|
||||
@@ -46,7 +47,7 @@ public class IntervalStatistics {
|
||||
trackPoint = trackPointIterator.next();
|
||||
trackStatisticsUpdater.addTrackPoint(trackPoint);
|
||||
|
||||
if (trackStatisticsUpdater.getTrackStatistics().getTotalDistance().plus(interval.distance).greaterOrEqualThan(distanceInterval)) {
|
||||
if (trackStatisticsUpdater.getTrackStatistics().totalDistance().plus(interval.distance).greaterOrEqualThan(distanceInterval)) {
|
||||
interval.add(trackStatisticsUpdater.getTrackStatistics(), trackPoint);
|
||||
|
||||
double adjustFactor = distanceInterval.dividedBy(interval.distance);
|
||||
@@ -74,8 +75,8 @@ public class IntervalStatistics {
|
||||
return trackPoint != null ? trackPoint.getId() : null;
|
||||
}
|
||||
|
||||
public List<Interval> getIntervalList() {
|
||||
return intervalList;
|
||||
public List<Statistics> getIntervalList() {
|
||||
return intervalList.stream().map(Interval::toStatistics).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,21 +85,24 @@ public class IntervalStatistics {
|
||||
*
|
||||
* @return the interval object or null if any interval is completed.
|
||||
*/
|
||||
public Interval getLastInterval() {
|
||||
@Nullable
|
||||
public Statistics getLastInterval() {
|
||||
if (intervalList.size() == 1 && intervalList.get(0).getDistance().lessThan(distanceInterval)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = intervalList.size() - 1; i >= 0; i--) {
|
||||
if (intervalList.get(i).getDistance().greaterOrEqualThan(distanceInterval)) {
|
||||
return this.intervalList.get(i);
|
||||
return this.intervalList.get(i).toStatistics();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class Interval {
|
||||
//TODO Could be replaced with Statistics?
|
||||
@Deprecated
|
||||
private static class Interval {
|
||||
private Distance distance = Distance.of(0);
|
||||
private Duration time = Duration.ofSeconds(0);
|
||||
private Float gain_m;
|
||||
@@ -144,18 +148,6 @@ public class IntervalStatistics {
|
||||
return gain_m != null;
|
||||
}
|
||||
|
||||
public Float getGain_m() {
|
||||
return gain_m;
|
||||
}
|
||||
|
||||
public boolean hasLoss() {
|
||||
return loss_m != null;
|
||||
}
|
||||
|
||||
public Float getLoss_m() {
|
||||
return loss_m;
|
||||
}
|
||||
|
||||
public boolean hasAverageHeartRate() {
|
||||
return avgHeartRate != null;
|
||||
}
|
||||
@@ -172,31 +164,48 @@ public class IntervalStatistics {
|
||||
return avgPower;
|
||||
}
|
||||
|
||||
private void add(TrackStatistics trackStatistics, @Nullable TrackPoint lastTrackPoint) {
|
||||
distance = distance.plus(trackStatistics.getTotalDistance());
|
||||
time = time.plus(trackStatistics.getTotalTime());
|
||||
gain_m = trackStatistics.hasTotalAltitudeGain() ? trackStatistics.getTotalAltitudeGain() : gain_m;
|
||||
loss_m = trackStatistics.hasTotalAltitudeLoss() ? trackStatistics.getTotalAltitudeLoss() : loss_m;
|
||||
avgHeartRate = trackStatistics.getAverageHeartRate();
|
||||
avgPower = trackStatistics.getAveragePower();
|
||||
private void add(Statistics trackStatistics, @Nullable TrackPoint lastTrackPoint) {
|
||||
distance = distance.plus(trackStatistics.totalDistance());
|
||||
time = time.plus(trackStatistics.totalTime());
|
||||
if (trackStatistics.altitudeGainLoss() != null) {
|
||||
gain_m = trackStatistics.altitudeGainLoss().gain_m();
|
||||
loss_m = trackStatistics.altitudeGainLoss().loss_m();
|
||||
}
|
||||
avgHeartRate = trackStatistics.avgHeartRate();
|
||||
avgPower = trackStatistics.avgPower();
|
||||
if (lastTrackPoint == null) {
|
||||
return;
|
||||
}
|
||||
if (hasGain() && lastTrackPoint.hasAltitudeGain()) {
|
||||
gain_m = gain_m - lastTrackPoint.getAltitudeGain();
|
||||
}
|
||||
if (hasLoss() && lastTrackPoint.hasAltitudeLoss()) {
|
||||
loss_m = loss_m - lastTrackPoint.getAltitudeLoss();
|
||||
if (hasGain() && lastTrackPoint.hasAltitudeGainLoss()) {
|
||||
gain_m = gain_m - lastTrackPoint.getAltitudeGainLoss().gain_m();
|
||||
loss_m = loss_m - lastTrackPoint.getAltitudeGainLoss().loss_m();
|
||||
}
|
||||
}
|
||||
|
||||
private void set(TrackStatistics trackStatistics) {
|
||||
distance = trackStatistics.getTotalDistance();
|
||||
time = trackStatistics.getTotalTime();
|
||||
gain_m = trackStatistics.hasTotalAltitudeGain() ? trackStatistics.getTotalAltitudeGain() : gain_m;
|
||||
loss_m = trackStatistics.hasTotalAltitudeLoss() ? trackStatistics.getTotalAltitudeLoss() : loss_m;
|
||||
avgHeartRate = trackStatistics.getAverageHeartRate();
|
||||
avgPower = trackStatistics.getAveragePower();
|
||||
private void set(Statistics trackStatistics) {
|
||||
distance = trackStatistics.totalDistance();
|
||||
time = trackStatistics.totalTime();
|
||||
if (trackStatistics.altitudeGainLoss() != null) {
|
||||
gain_m = trackStatistics.altitudeGainLoss().gain_m();
|
||||
loss_m = trackStatistics.altitudeGainLoss().loss_m();
|
||||
}
|
||||
avgHeartRate = trackStatistics.avgHeartRate();
|
||||
avgPower = trackStatistics.avgPower();
|
||||
}
|
||||
|
||||
private Statistics toStatistics() {
|
||||
return new Statistics(
|
||||
null,
|
||||
null,
|
||||
time,
|
||||
null,
|
||||
distance,
|
||||
null,
|
||||
null,
|
||||
gain_m != null ? new AltitudeGainLoss(gain_m, loss_m) : null,
|
||||
avgHeartRate,
|
||||
avgPower
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import java.util.Objects;
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.data.ContentProviderUtils;
|
||||
import de.dennisguse.opentracks.data.models.DistanceFormatter;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.databinding.IntervalListViewBinding;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
@@ -192,7 +193,7 @@ public class IntervalsFragment extends Fragment {
|
||||
}
|
||||
|
||||
viewBinding.intervalRate.setText(isReportSpeed ? getString(R.string.stats_speed) : getString(R.string.stats_pace));
|
||||
LiveData<List<IntervalStatistics.Interval>> liveData = viewModel.getIntervalStats(trackId, unitSystem, selectedInterval);
|
||||
LiveData<List<Statistics>> liveData = viewModel.getIntervalStats(trackId, unitSystem, selectedInterval);
|
||||
liveData.observe(getActivity(), intervalList -> adapter.swapData(intervalList, unitSystem, isReportSpeed));
|
||||
|
||||
setIntervalsDropdownText();
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.dennisguse.opentracks.util;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public abstract class AutoCloseableIterator<T> implements Iterator<T>, AutoCloseable {
|
||||
|
||||
/**
|
||||
* Override: AutoClosable.close() throws Exception.
|
||||
*/
|
||||
public abstract void close();
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
Pair<String, String> valueAndUnit = DistanceFormatter.Builder()
|
||||
.setUnit(unitSystem)
|
||||
.build(getContext()).getDistanceParts(data.getStatisticsTrack().getTotalDistance());
|
||||
.build(getContext()).getDistanceParts(data.getStatisticsTrack().totalDistance());
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
@@ -46,7 +46,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
|
||||
|
||||
@Override
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
Pair<String, String> valueAndUnit = new Pair<>(StringUtils.formatElapsedTime(data.getStatisticsTrack().getTotalTime()), null);
|
||||
Pair<String, String> valueAndUnit = new Pair<>(StringUtils.formatElapsedTime(data.getStatisticsTrack().totalTime()), null);
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
@@ -58,7 +58,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
|
||||
|
||||
@Override
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
String value = StringUtils.formatElapsedTime(data.getStatisticsTrack().getMovingTime());
|
||||
String value = StringUtils.formatElapsedTime(data.getStatisticsTrack().movingTime());
|
||||
|
||||
getBinding().statsValue.setText(value);
|
||||
getBinding().statsDescriptionMain.setText(getContext().getString(R.string.stats_moving_time));
|
||||
@@ -157,7 +157,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
|
||||
.setReportSpeedOrPace(true)
|
||||
.build(getContext());
|
||||
|
||||
Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getMaxSpeed());
|
||||
Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().maxSpeed());
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
@@ -208,7 +208,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
|
||||
.setReportSpeedOrPace(false)
|
||||
.build(getContext());
|
||||
|
||||
Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsCurrentSegment().getAverageMovingSpeed());
|
||||
Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.currentSegment().getAverageMovingSpeed());
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
@@ -220,7 +220,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
|
||||
|
||||
@Override
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
String value = StringUtils.formatElapsedTime(data.getStatisticsCurrentSegment().getTotalTime());
|
||||
String value = StringUtils.formatElapsedTime(data.currentSegment().totalTime());
|
||||
|
||||
getBinding().statsValue.setText(value);
|
||||
getBinding().statsDescriptionMain.setText(getContext().getString(R.string.stats_elapsed_segment_time));
|
||||
@@ -236,7 +236,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
|
||||
.setReportSpeedOrPace(false)
|
||||
.build(getContext());
|
||||
|
||||
Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getMaxSpeed());
|
||||
Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().maxSpeed());
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
@@ -264,8 +264,9 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
|
||||
|
||||
@Override
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
Float gain = data.getStatisticsTrack().altitudeGainLoss() != null ? data.getStatisticsTrack().altitudeGainLoss().gain_m() : null;
|
||||
|
||||
Pair<String, String> valueAndUnit = StringUtils.getAltitudeParts(getContext(), data.getStatisticsTrack().getTotalAltitudeGain(), unitSystem);
|
||||
Pair<String, String> valueAndUnit = StringUtils.getAltitudeParts(getContext(), gain, unitSystem);
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
@@ -277,8 +278,9 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
|
||||
|
||||
@Override
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
Float loss = data.getStatisticsTrack().altitudeGainLoss() != null ? data.getStatisticsTrack().altitudeGainLoss().loss_m() : null;
|
||||
|
||||
Pair<String, String> valueAndUnit = StringUtils.getAltitudeParts(getContext(), data.getStatisticsTrack().getTotalAltitudeLoss(), unitSystem);
|
||||
Pair<String, String> valueAndUnit = StringUtils.getAltitudeParts(getContext(), loss, unitSystem);
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
|
||||
Reference in New Issue
Block a user