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