Track is now a record.

This commit is contained in:
Dennis Guse
2025-11-27 19:35:05 +01:00
parent 6a262426a5
commit 990c91f978
51 changed files with 772 additions and 523 deletions
@@ -18,6 +18,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.Statistics; 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.TrackBuilder;
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.AutoCloseableIterator;
@@ -35,11 +36,11 @@ public class TestDataUtil {
* Create a track without any trackPoints. * Create a track without any trackPoints.
*/ */
public static Track createTrack(Track.Id trackId) { public static Track createTrack(Track.Id trackId) {
Track track = new Track(Statistics.DEFAULT); TrackBuilder track = new TrackBuilder(Statistics.DEFAULT);
track.setId(trackId); track.setId(trackId);
track.setName("Test: " + trackId.id()); track.setName("Test: " + trackId.id());
return track; return track.getTrack();
} }
/** /**
@@ -138,7 +139,7 @@ public class TestDataUtil {
*/ */
public static void insertTrackWithLocations(ContentProviderUtils contentProviderUtils, Track track, List<TrackPoint> trackPoints) { public static void insertTrackWithLocations(ContentProviderUtils contentProviderUtils, Track track, List<TrackPoint> trackPoints) {
contentProviderUtils.insertTrack(track); contentProviderUtils.insertTrack(track);
contentProviderUtils.bulkInsertTrackPoint(trackPoints, track.getId()); contentProviderUtils.bulkInsertTrackPoint(trackPoints, track.id());
} }
public static Marker createMarkerWithPhoto(Context context, Track.Id trackId, TrackPoint trackPoint) throws IOException { public static Marker createMarkerWithPhoto(Context context, Track.Id trackId, TrackPoint trackPoint) throws IOException {
@@ -54,12 +54,12 @@ import de.dennisguse.opentracks.data.models.Altitude;
import de.dennisguse.opentracks.data.models.AltitudeExtremities; 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.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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
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;
@@ -130,11 +130,12 @@ public class CustomContentProviderUtilsTest {
} }
private TrackPoint.Id initializeTrack(Track.Id id, int numPoints) { private TrackPoint.Id initializeTrack(Track.Id id, int numPoints) {
Track track = new Track(Statistics.DEFAULT); TrackBuilder trackbuilder = new TrackBuilder(Statistics.DEFAULT);
track.setId(id); trackbuilder.setId(id);
track.setName("Test: " + id.id()); trackbuilder.setName("Test: " + id.id());
contentProviderUtils.insertTrack(track); contentProviderUtils.insertTrack(trackbuilder.getTrack());
track = contentProviderUtils.getTrack(id);
Track track = contentProviderUtils.getTrack(id);
assertNotNull(track); assertNotNull(track);
List<TrackPoint> trackPoints = new ArrayList<>(numPoints); List<TrackPoint> trackPoints = new ArrayList<>(numPoints);
@@ -196,8 +197,8 @@ public class CustomContentProviderUtilsTest {
when(cursorMock.getString(columnIndex)).thenReturn(name); when(cursorMock.getString(columnIndex)).thenReturn(name);
Track track = ContentProviderUtils.createTrack(cursorMock); Track track = ContentProviderUtils.createTrack(cursorMock);
assertEquals(trackId, track.getId()); assertEquals(trackId, track.id());
assertEquals(name, track.getName()); assertEquals(name, track.name());
} }
private void assertCount(int trackCount, int trackPointCount, int markerCount) { private void assertCount(int trackCount, int trackPointCount, int markerCount) {
@@ -241,7 +242,7 @@ public class CustomContentProviderUtilsTest {
public void testDeleteAllTracks_withMarkerAndPhoto() throws IOException { public void testDeleteAllTracks_withMarkerAndPhoto() throws IOException {
// Insert track, points and marker with photo at first. // Insert track, points and marker with photo at first.
Track.Id trackId = new Track.Id(System.currentTimeMillis()); Track.Id trackId = new Track.Id(System.currentTimeMillis());
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
TrackPoint trackPoint = getLastValidTrackPoint(trackId); TrackPoint trackPoint = getLastValidTrackPoint(trackId);
Marker marker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint); Marker marker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint);
@@ -350,7 +351,7 @@ public class CustomContentProviderUtilsTest {
// then // then
assertEquals(initialTrackNumber + 1, allTracks.size()); assertEquals(initialTrackNumber + 1, allTracks.size());
assertEquals(trackId, allTracks.get(allTracks.size() - 1).getId()); assertEquals(trackId, allTracks.get(allTracks.size() - 1).id());
} }
/** /**
@@ -377,27 +378,24 @@ public class CustomContentProviderUtilsTest {
contentProviderUtils.insertTrack(track); contentProviderUtils.insertTrack(track);
// when / then // when / then
assertNotNull(contentProviderUtils.getTrack(track.getUuid())); assertNotNull(contentProviderUtils.getTrack(track.uuid()));
} }
/**
* Tests the method {@link ContentProviderUtils#updateTrack(Track)}
*/
@Test @Test
public void testUpdateTrack() { public void testUpdateTrack() {
// given // given
Track.Id trackId = new Track.Id(System.currentTimeMillis()); Track.Id trackId = new Track.Id(System.currentTimeMillis());
Track track = TestDataUtil.createTrack(trackId); TrackBuilder track = new TrackBuilder(TestDataUtil.createTrack(trackId));
String nameOld = "name1"; String nameOld = "name1";
String nameNew = "name2"; String nameNew = "name2";
track.setName(nameOld); track.setName(nameOld);
// when / then // when / then
contentProviderUtils.insertTrack(track); contentProviderUtils.insertTrack(track.getTrack());
assertEquals(nameOld, contentProviderUtils.getTrack(trackId).getName()); assertEquals(nameOld, contentProviderUtils.getTrack(trackId).name());
track.setName(nameNew); track.setName(nameNew);
contentProviderUtils.updateTrack(track); contentProviderUtils.updateTrack(track.getTrack());
assertEquals(nameNew, contentProviderUtils.getTrack(trackId).getName()); assertEquals(nameNew, contentProviderUtils.getTrack(trackId).name());
} }
/** /**
@@ -408,8 +406,10 @@ public class CustomContentProviderUtilsTest {
Track.Id trackId = new Track.Id(System.currentTimeMillis()); Track.Id trackId = new Track.Id(System.currentTimeMillis());
Pair<Track, List<TrackPoint>> track = TestDataUtil.createTrack(trackId, 10); Pair<Track, List<TrackPoint>> track = TestDataUtil.createTrack(trackId, 10);
TrackBuilder trackBuilder = new TrackBuilder(track.first);
// AverageSpeed // AverageSpeed
track.first.setStatistics(new Statistics( trackBuilder.setStatistics(new Statistics(
Instant.ofEpochMilli(1000), Instant.ofEpochMilli(1000),
Instant.ofEpochMilli(2500), Instant.ofEpochMilli(2500),
Duration.ofMillis(1500), Duration.ofMillis(1500),
@@ -421,7 +421,7 @@ public class CustomContentProviderUtilsTest {
null, null,
null null
)); ));
contentProviderUtils.insertTrack(track.first); contentProviderUtils.insertTrack(trackBuilder.getTrack());
Marker marker = new Marker(trackId, track.second.get(0)); Marker marker = new Marker(trackId, track.second.get(0));
marker.setDescription(TEST_DESC); marker.setDescription(TEST_DESC);
@@ -736,7 +736,7 @@ public class CustomContentProviderUtilsTest {
public void testInsertTrackPoint() { public void testInsertTrackPoint() {
// Insert track, point at first. // Insert track, point at first.
Track.Id trackId = new Track.Id(System.currentTimeMillis()); Track.Id trackId = new Track.Id(System.currentTimeMillis());
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
contentProviderUtils.insertTrackPoint(TestDataUtil.createTrackPoint(22), trackId); contentProviderUtils.insertTrackPoint(TestDataUtil.createTrackPoint(22), trackId);
// when // when
@@ -750,7 +750,7 @@ public class CustomContentProviderUtilsTest {
public void testInsertAndLoadTrackPoint() { public void testInsertAndLoadTrackPoint() {
// given // given
Track.Id trackId = new Track.Id(System.currentTimeMillis()); Track.Id trackId = new Track.Id(System.currentTimeMillis());
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10); TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
TrackPoint trackPoint = TestDataUtil.createTrackPoint(5); TrackPoint trackPoint = TestDataUtil.createTrackPoint(5);
trackPoint.setHeartRate(1F); trackPoint.setHeartRate(1F);
@@ -776,7 +776,7 @@ public class CustomContentProviderUtilsTest {
contentProviderUtils.insertTrack(track.first); contentProviderUtils.insertTrack(track.first);
List<TrackPoint.Id> trackpointIds = track.second.stream() List<TrackPoint.Id> trackpointIds = track.second.stream()
.map(it -> ContentUris.parseId(contentProviderUtils.insertTrackPoint(it, track.first.getId()))) .map(it -> ContentUris.parseId(contentProviderUtils.insertTrackPoint(it, track.first.id())))
.map(TrackPoint.Id::new).toList(); .map(TrackPoint.Id::new).toList();
// when // when
@@ -794,7 +794,7 @@ public class CustomContentProviderUtilsTest {
contentProviderUtils.insertTrack(track.first); contentProviderUtils.insertTrack(track.first);
List<TrackPoint.Id> trackpointIds = track.second.stream() List<TrackPoint.Id> trackpointIds = track.second.stream()
.map(it -> ContentUris.parseId(contentProviderUtils.insertTrackPoint(it, track.first.getId()))) .map(it -> ContentUris.parseId(contentProviderUtils.insertTrackPoint(it, track.first.id())))
.map(TrackPoint.Id::new).toList(); .map(TrackPoint.Id::new).toList();
TrackPoint.Id startTrackPointId = trackpointIds.get(0); TrackPoint.Id startTrackPointId = trackpointIds.get(0);
@@ -5,12 +5,15 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Collection; 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.ActivityType;
import de.dennisguse.opentracks.data.models.Statistics; 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.TrackBuilder;
//TODO Merge with TrackFilenameGeneratorTest whenever Junit5 gets available. //TODO Merge with TrackFilenameGeneratorTest whenever Junit5 gets available.
//https://github.com/android/android-test/issues/224 //https://github.com/android/android-test/issues/224
@@ -34,9 +37,16 @@ public class TrackFilenameGenerator2Test {
@Test(expected = TrackFilenameGenerator.TemplateInvalidException.class) @Test(expected = TrackFilenameGenerator.TemplateInvalidException.class)
public void testFilenameTemplate() { public void testFilenameTemplate() {
// given // given
Track track = new Track(new Statistics(Instant.parse("2020-02-02T02:02:02Z"), null, null, null, null, null, null, null, null, null)); Track track = new Track(
track.setName("Best Track"); null,
track.setUuid(UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6")); UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6"),
"Berlin",
"",
"",
ActivityType.CYCLING,
ZoneOffset.UTC,
Statistics.DEFAULT
);
// when // when
subject.format(track, TrackFileFormat.GPX); subject.format(track, TrackFileFormat.GPX);
@@ -10,6 +10,7 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; import org.junit.runners.Parameterized;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.TimeZone; import java.util.TimeZone;
@@ -19,6 +20,7 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
@RunWith(Parameterized.class) @RunWith(Parameterized.class)
public class TrackFilenameGeneratorTest { public class TrackFilenameGeneratorTest {
@@ -48,9 +50,16 @@ public class TrackFilenameGeneratorTest {
@Test @Test
public void testFilenameTemplate() { public void testFilenameTemplate() {
// given // given
Track track = new Track(new Statistics(Instant.parse("2020-02-02T02:02:02Z"), null, null, null, null, null, null, null, null, null)); Track track = new Track(
track.setName("Best Track"); null,
track.setUuid(UUID.fromString("0000fee0-0000-1000-8000-00805f9b34fb")); UUID.fromString("0000fee0-0000-1000-8000-00805f9b34fb"),
"Best Track",
"",
"",
null,
ZoneOffset.UTC,
new Statistics(Instant.parse("2020-02-02T02:02:02Z"), Instant.parse("2020-02-02T02:02:02Z"), null, null, null, null, null, null, null, null)
);
// when // when
String filename = subject.format(track, TrackFileFormat.GPX); String filename = subject.format(track, TrackFileFormat.GPX);
@@ -63,6 +63,7 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
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;
@@ -187,13 +188,12 @@ public class ExportImportTest {
trackPointCreator.setClock("2020-02-02T02:04:00Z"); trackPointCreator.setClock("2020-02-02T02:04:00Z");
service.endCurrentTrack(); service.endCurrentTrack();
Track track = contentProviderUtils.getTrack(trackId); TrackBuilder trackBuilder = new TrackBuilder(contentProviderUtils.getTrack(trackId));
track.setActivityType(TRACK_ACTIVITY_TYPE); trackBuilder.setActivityType(TRACK_ACTIVITY_TYPE);
track.setActivityTypeLocalized(TRACK_ACTIVITY_TYPE_LOCALIZED); trackBuilder.setActivityTypeLocalized(TRACK_ACTIVITY_TYPE_LOCALIZED);
track.setDescription(TRACK_DESCRIPTION); trackBuilder.setDescription(TRACK_DESCRIPTION);
contentProviderUtils.updateTrack(track); contentProviderUtils.updateTrack(trackBuilder.getTrack());
track = contentProviderUtils.getTrack(trackId);
trackPoints = TestDataUtil.getTrackPoints(contentProviderUtils, trackId); trackPoints = TestDataUtil.getTrackPoints(contentProviderUtils, trackId);
markers = TestDataUtil.getMarkers(contentProviderUtils, trackId); markers = TestDataUtil.getMarkers(contentProviderUtils, trackId);
} }
@@ -204,9 +204,9 @@ public class ExportImportTest {
setUp(); setUp();
Track track = contentProviderUtils.getTrack(trackId); Track track = contentProviderUtils.getTrack(trackId);
Statistics trackStatistics = track.getStatistics(); Statistics trackStatistics = track.statistics();
assertEquals(ZoneOffset.of("+01:00"), track.getZoneOffset()); assertEquals(ZoneOffset.of("+01:00"), track.zoneOffset());
assertEquals(new Statistics( assertEquals(new Statistics(
Instant.parse("2020-02-02T02:02:02Z"), Instant.parse("2020-02-02T02:02:02Z"),
@@ -310,19 +310,19 @@ public class ExportImportTest {
// 1. track // 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId); Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack); assertNotNull(importedTrack);
assertEquals(track.getActivityType(), importedTrack.getActivityType()); assertEquals(track.activityType(), importedTrack.activityType());
assertEquals(track.getActivityTypeLocalized(), importedTrack.getActivityTypeLocalized()); assertEquals(track.activityTypeLocalized(), importedTrack.activityTypeLocalized());
assertEquals(track.getDescription(), importedTrack.getDescription()); assertEquals(track.description(), importedTrack.description());
assertEquals(track.getName(), importedTrack.getName()); assertEquals(track.name(), importedTrack.name());
// 2. trackpoints // 2. trackpoints
List<TrackPoint> actual = TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId); List<TrackPoint> actual = TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId);
new TrackPointAssert().assertEquals(trackPoints, actual); new TrackPointAssert().assertEquals(trackPoints, actual);
// 3. trackstatistics // 3. trackstatistics
Statistics importedTrackStatistics = importedTrack.getStatistics(); Statistics importedTrackStatistics = importedTrack.statistics();
assertEquals(track.getZoneOffset(), importedTrack.getZoneOffset()); assertEquals(track.zoneOffset(), importedTrack.zoneOffset());
assertEquals(new Statistics( assertEquals(new Statistics(
Instant.parse("2020-02-02T02:02:02Z"), Instant.parse("2020-02-02T02:02:02Z"),
Instant.parse("2020-02-02T02:04:00Z"), Instant.parse("2020-02-02T02:04:00Z"),
@@ -391,10 +391,10 @@ public class ExportImportTest {
// 1. track // 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId); Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack); assertNotNull(importedTrack);
assertEquals(track.getActivityType(), importedTrack.getActivityType()); assertEquals(track.activityType(), importedTrack.activityType());
assertEquals(track.getActivityTypeLocalized(), importedTrack.getActivityTypeLocalized()); assertEquals(track.activityTypeLocalized(), importedTrack.activityTypeLocalized());
assertEquals(track.getDescription(), importedTrack.getDescription()); assertEquals(track.description(), importedTrack.description());
assertEquals(track.getName(), importedTrack.getName()); assertEquals(track.name(), importedTrack.name());
// 2. trackpoints // 2. trackpoints
// The GPX exporter does not support exporting TrackPoints without lat/lng. // The GPX exporter does not support exporting TrackPoints without lat/lng.
@@ -452,9 +452,9 @@ public class ExportImportTest {
), actual); ), actual);
// 3. trackstatistics // 3. trackstatistics
assertEquals(track.getZoneOffset(), importedTrack.getZoneOffset()); assertEquals(track.zoneOffset(), importedTrack.zoneOffset());
Statistics importedTrackStatistics = importedTrack.getStatistics(); Statistics importedTrackStatistics = importedTrack.statistics();
assertEquals(new Statistics( assertEquals(new Statistics(
Instant.parse("2020-02-02T02:02:03Z"), Instant.parse("2020-02-02T02:02:03Z"),
Instant.parse("2020-02-02T02:03:50Z"), Instant.parse("2020-02-02T02:03:50Z"),
@@ -32,6 +32,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.Statistics; 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.TrackBuilder;
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;
@@ -79,11 +80,11 @@ public class GPXTrackImporterTest {
// 2. track // 2. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId); Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack); assertNotNull(importedTrack);
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType()); assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
assertEquals("the category", importedTrack.getActivityTypeLocalized()); assertEquals("the category", importedTrack.activityTypeLocalized());
assertEquals("the description", importedTrack.getDescription()); assertEquals("the description", importedTrack.description());
assertEquals("2021-01-07 22:51", importedTrack.getName()); assertEquals("2021-01-07 22:51", importedTrack.name());
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType()); assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
//TODO Check trackstatistics //TODO Check trackstatistics
@@ -143,13 +144,13 @@ public class GPXTrackImporterTest {
// 2. track // 2. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId); Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack); assertNotNull(importedTrack);
assertEquals("", importedTrack.getActivityTypeLocalized()); assertEquals("", importedTrack.activityTypeLocalized());
assertEquals("", importedTrack.getDescription()); assertEquals("", importedTrack.description());
assertEquals("20210907_213924.gpx", importedTrack.getName()); assertEquals("20210907_213924.gpx", importedTrack.name());
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType()); assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
// 3. trackstatistics // 3. trackstatistics
Statistics trackStatistics = importedTrack.getStatistics(); Statistics trackStatistics = importedTrack.statistics();
assertEquals(0.75, trackStatistics.maxSpeed().toMPS(), 0.01); assertEquals(0.75, trackStatistics.maxSpeed().toMPS(), 0.01);
assertEquals(Duration.ofSeconds(101), trackStatistics.movingDuration()); assertEquals(Duration.ofSeconds(101), trackStatistics.movingDuration());
@@ -198,13 +199,13 @@ public class GPXTrackImporterTest {
// 2. track // 2. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId); Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack); assertNotNull(importedTrack);
assertEquals("", importedTrack.getActivityTypeLocalized()); assertEquals("", importedTrack.activityTypeLocalized());
assertEquals("", importedTrack.getDescription()); assertEquals("", importedTrack.description());
assertEquals("20210907_213924.gpx", importedTrack.getName()); assertEquals("20210907_213924.gpx", importedTrack.name());
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType()); assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
// 3. trackstatistics // 3. trackstatistics
Statistics trackStatistics = importedTrack.getStatistics(); Statistics trackStatistics = importedTrack.statistics();
assertEquals(5.0, trackStatistics.maxSpeed().toMPS(), 0.01); assertEquals(5.0, trackStatistics.maxSpeed().toMPS(), 0.01);
assertEquals(Duration.ofSeconds(101), trackStatistics.movingDuration()); assertEquals(Duration.ofSeconds(101), trackStatistics.movingDuration());
@@ -28,6 +28,7 @@ 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.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
/** /**
@@ -73,10 +74,10 @@ public class KMLTrackImporterTest {
// 1. track // 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId); Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack); assertNotNull(importedTrack);
assertEquals("", importedTrack.getActivityTypeLocalized()); assertEquals("", importedTrack.activityTypeLocalized());
assertEquals("", importedTrack.getDescription()); assertEquals("", importedTrack.description());
assertEquals("", importedTrack.getName()); assertEquals("", importedTrack.name());
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType()); assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
// 2. markers // 2. markers
assertEquals(0, TestDataUtil.getMarkers(contentProviderUtils, importTrackId).size()); assertEquals(0, TestDataUtil.getMarkers(contentProviderUtils, importTrackId).size());
@@ -129,10 +130,10 @@ public class KMLTrackImporterTest {
// 1. track // 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId); Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack); assertNotNull(importedTrack);
assertEquals("", importedTrack.getActivityTypeLocalized()); assertEquals("", importedTrack.activityTypeLocalized());
assertEquals("", importedTrack.getDescription()); assertEquals("", importedTrack.description());
assertEquals("", importedTrack.getName()); assertEquals("", importedTrack.name());
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType()); assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
// 2. markers // 2. markers
assertEquals(0, TestDataUtil.getMarkers(contentProviderUtils, importTrackId).size()); assertEquals(0, TestDataUtil.getMarkers(contentProviderUtils, importTrackId).size());
@@ -170,10 +171,10 @@ public class KMLTrackImporterTest {
// 1. track // 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId); Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack); assertNotNull(importedTrack);
assertEquals("unknown", importedTrack.getActivityTypeLocalized()); assertEquals("unknown", importedTrack.activityTypeLocalized());
assertEquals("Test Track", importedTrack.getDescription()); assertEquals("Test Track", importedTrack.description());
assertEquals("2020-11-28 18:06", importedTrack.getName()); assertEquals("2020-11-28 18:06", importedTrack.name());
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType()); assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
// 2. markers // 2. markers
//TODO Check actual content (Marker should be record for this) //TODO Check actual content (Marker should be record for this)
@@ -19,6 +19,7 @@ import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.TestUtil; import de.dennisguse.opentracks.TestUtil;
import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.IntentUtils;
@@ -49,9 +50,9 @@ public class PublicApiTest {
List<Track> tracks = new ContentProviderUtils(context).getTracks(); List<Track> tracks = new ContentProviderUtils(context).getTracks();
Assert.assertEquals(1, tracks.size()); Assert.assertEquals(1, tracks.size());
Track track = tracks.get(0); Track track = tracks.get(0);
Assert.assertEquals("trackName", track.getName()); Assert.assertEquals("trackName", track.name());
Assert.assertEquals("activityTypeLocalized", track.getActivityTypeLocalized()); Assert.assertEquals("activityTypeLocalized", track.activityTypeLocalized());
Assert.assertEquals("airplane", track.getActivityType().getId()); Assert.assertEquals("airplane", track.activityType().getId());
} }
@Test @Test
@@ -16,12 +16,17 @@ import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import java.time.ZoneOffset;
import java.util.UUID;
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.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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
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;
@@ -53,18 +58,17 @@ public class TrackRecordingServiceNotificationManagerTest {
TrackRecordingServiceNotificationManager subject = new TrackRecordingServiceNotificationManager(notificationManager, notificationCompatBuilder); TrackRecordingServiceNotificationManager subject = new TrackRecordingServiceNotificationManager(notificationManager, notificationCompatBuilder);
subject.setUnitSystem(UnitSystem.METRIC); subject.setUnitSystem(UnitSystem.METRIC);
Track track = new Track(new Statistics( Track track = new Track(
null, null,
null, UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6"),
null, "Berlin",
null, "",
Distance.ZERO, "",
null, ActivityType.CYCLING,
null, ZoneOffset.UTC,
null, Statistics.DEFAULT
null, );
null
));
RecordingData data = new RecordingData(track, trackPointMock, null, null); RecordingData data = new RecordingData(track, trackPointMock, null, null);
// when // when
@@ -33,7 +33,6 @@ 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;
@@ -108,7 +107,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(startTime), Duration.ZERO, Duration.ZERO, Distance.ZERO, Speed.ZERO, null, null, null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(startTime), Duration.ZERO, Duration.ZERO, Distance.ZERO, Speed.ZERO, null, null, null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
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))
@@ -122,7 +121,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.ZERO, Speed.ZERO, null, new AltitudeGainLoss(0, 0), null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.ZERO, Speed.ZERO, null, new AltitudeGainLoss(0, 0), null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
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)),
@@ -197,7 +196,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(pauseTime), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.ZERO, Speed.ZERO, null, new AltitudeGainLoss(0, 0), null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(pauseTime), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.ZERO, Speed.ZERO, null, new AltitudeGainLoss(0, 0), null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
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)),
@@ -212,7 +211,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(resumeTime), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.ZERO, Speed.ZERO, null, new AltitudeGainLoss(0, 0), null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(resumeTime), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.ZERO, Speed.ZERO, null, new AltitudeGainLoss(0, 0), null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
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)),
@@ -340,7 +339,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps1), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.ZERO, Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps1), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.ZERO, Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
// when // when
String gps2 = "2020-02-02T02:02:06Z"; String gps2 = "2020-02-02T02:02:06Z";
@@ -348,7 +347,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps2), Duration.ofSeconds(4), Duration.ofSeconds(4), Distance.of(11.113178253173828), Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps2), Duration.ofSeconds(4), Duration.ofSeconds(4), Distance.of(11.113178253173828), Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
// when // when
String gps3 = "2020-02-02T02:02:08Z"; String gps3 = "2020-02-02T02:02:08Z";
@@ -356,7 +355,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps3), Duration.ofSeconds(6), Duration.ofSeconds(6), Distance.of(22.226356506347656), Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps3), Duration.ofSeconds(6), Duration.ofSeconds(6), Distance.of(22.226356506347656), Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
// when // when
String stopTime = "2020-02-02T02:02:12Z"; String stopTime = "2020-02-02T02:02:12Z";
@@ -365,7 +364,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(10), Duration.ofSeconds(10), Distance.of(22.226356506347656), Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(10), Duration.ofSeconds(10), Distance.of(22.226356506347656), Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
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)),
@@ -414,21 +413,21 @@ public class TrackRecordingServiceRecordingTest {
// then // then
Statistics gps1Statistics = new Statistics(Instant.parse(startTime), Instant.parse(gps1), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.ZERO, Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null); Statistics gps1Statistics = new Statistics(Instant.parse(startTime), Instant.parse(gps1), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.ZERO, Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null);
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).getStatistics()); assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).statistics());
// when // when
String gps2 = "2020-02-02T02:02:06Z"; String gps2 = "2020-02-02T02:02:06Z";
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).getStatistics()); assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).statistics());
// when // when
String gps3 = "2020-02-02T02:02:08Z"; String gps3 = "2020-02-02T02:02:08Z";
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).getStatistics()); assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).statistics());
// when // when
String stopTime = "2020-02-02T02:02:12Z"; String stopTime = "2020-02-02T02:02:12Z";
@@ -437,7 +436,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(10), Duration.ofSeconds(10), Distance.of(2.222635507583618), Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(10), Duration.ofSeconds(10), Distance.of(2.222635507583618), Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
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)),
@@ -536,7 +535,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
Statistics startStatistics = new Statistics(Instant.parse(startTime), Instant.parse(startTime), Duration.ZERO, Duration.ZERO, Distance.ZERO, Speed.ZERO, null, null, null, null); Statistics startStatistics = new Statistics(Instant.parse(startTime), Instant.parse(startTime), Duration.ZERO, Duration.ZERO, Distance.ZERO, Speed.ZERO, null, null, null, null);
assertEquals(startStatistics, contentProviderUtils.getTrack(trackId).getStatistics()); assertEquals(startStatistics, contentProviderUtils.getTrack(trackId).statistics());
// when // when
@@ -544,7 +543,7 @@ public class TrackRecordingServiceRecordingTest {
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).getStatistics()); assertEquals(startStatistics, contentProviderUtils.getTrack(trackId).statistics());
// when // when
@@ -554,7 +553,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(10), Duration.ofSeconds(10), Distance.ZERO, Speed.ZERO, null, new AltitudeGainLoss(0, 0), null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(10), Duration.ofSeconds(10), Distance.ZERO, Speed.ZERO, null, new AltitudeGainLoss(0, 0), null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
// then // then
new TrackPointAssert().assertEquals(List.of( new TrackPointAssert().assertEquals(List.of(
@@ -580,7 +579,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps1), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.ZERO, Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps1), Duration.ofSeconds(1), Duration.ofSeconds(1), Distance.ZERO, Speed.of(15), null, new AltitudeGainLoss(0, 0), null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
// when // when
String gps2 = "2020-02-02T02:02:06Z"; String gps2 = "2020-02-02T02:02:06Z";
@@ -588,7 +587,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps2), Duration.ofSeconds(4), Duration.ofSeconds(4), Distance.of(11113.275390625), Speed.of(2778.31884765625f), null, new AltitudeGainLoss(0, 0), null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(gps2), Duration.ofSeconds(4), Duration.ofSeconds(4), Distance.of(11113.275390625), Speed.of(2778.31884765625f), null, new AltitudeGainLoss(0, 0), null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
// when // when
String stopTime = "2020-02-02T02:02:12Z"; String stopTime = "2020-02-02T02:02:12Z";
@@ -597,7 +596,7 @@ public class TrackRecordingServiceRecordingTest {
// then // then
assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(10), Duration.ofSeconds(10), Distance.of(11113.275390625), Speed.of(1111.3275146484375), null, new AltitudeGainLoss(0, 0), null, null) assertEquals(new Statistics(Instant.parse(startTime), Instant.parse(stopTime), Duration.ofSeconds(10), Duration.ofSeconds(10), Distance.of(11113.275390625), Speed.of(1111.3275146484375), null, new AltitudeGainLoss(0, 0), null, null)
, contentProviderUtils.getTrack(trackId).getStatistics()); , contentProviderUtils.getTrack(trackId).statistics());
// then // then
@@ -47,6 +47,7 @@ import java.util.concurrent.TimeoutException;
import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.sensors.GpsStatusValue; import de.dennisguse.opentracks.sensors.GpsStatusValue;
/** /**
@@ -20,18 +20,21 @@ import org.mockito.Mockito;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneOffset;
import java.util.ArrayList; 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.models.ActivityType;
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.Speed; import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Statistics; 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.TrackBuilder;
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.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -62,18 +65,26 @@ public class VoiceAnnouncementUtilsTest {
@Test @Test
public void getAnnouncement_metric_speed() { public void getAnnouncement_metric_speed() {
Track track = new Track(new Statistics( Track track = new Track(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
Distance.of(20000),
Speed.of(100),
null, null,
null, null,
null, "",
null "",
)); "",
ActivityType.AIRPLANE,
ZoneOffset.UTC,
new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
Distance.of(20000),
Speed.of(100),
null,
null,
null,
null
));
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class); 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"));
@@ -87,18 +98,26 @@ public class VoiceAnnouncementUtilsTest {
@Test @Test
public void getAnnouncement_metric_speed_rounding_check() { public void getAnnouncement_metric_speed_rounding_check() {
Track track = new Track(new Statistics( Track track = new Track(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusSeconds(1),
Distance.of(20000),
Speed.of(100),
null, null,
new AltitudeGainLoss(6000, 6000),
null, null,
null "",
)); "",
"",
ActivityType.AIRPLANE,
ZoneOffset.UTC,
new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusSeconds(1),
Distance.of(20000),
Speed.of(100),
null,
new AltitudeGainLoss(6000, 6000),
null,
null
));
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class); 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,18 +131,26 @@ public class VoiceAnnouncementUtilsTest {
@Test @Test
public void getAnnouncement_metric_distance_rounding_check() { public void getAnnouncement_metric_distance_rounding_check() {
Track track = new Track(new Statistics( Track track = new Track(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.of(19999),
Speed.of(100),
null, null,
new AltitudeGainLoss(6000, 6000),
null, null,
null "",
)); "",
"",
ActivityType.AIRPLANE,
ZoneOffset.UTC,
new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.of(19999),
Speed.of(100),
null,
new AltitudeGainLoss(6000, 6000),
null,
null
));
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class); 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"));
@@ -137,18 +164,26 @@ public class VoiceAnnouncementUtilsTest {
@Test @Test
public void getAnnouncement_metric_distance_rounding_check_two() { public void getAnnouncement_metric_distance_rounding_check_two() {
Track track = new Track(new Statistics( Track track = new Track(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.of(19900),
Speed.of(100),
null, null,
new AltitudeGainLoss(6000, 6000),
null, null,
null "",
)); "",
"",
ActivityType.AIRPLANE,
ZoneOffset.UTC,
new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.of(19900),
Speed.of(100),
null,
new AltitudeGainLoss(6000, 6000),
null,
null
));
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class); 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"));
@@ -177,18 +212,26 @@ public class VoiceAnnouncementUtilsTest {
@Test @Test
public void getAnnouncement_metric_pace() { public void getAnnouncement_metric_pace() {
Track track = new Track(new Statistics( Track track = new Track(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
Distance.of(20000),
Speed.of(100),
null, null,
new AltitudeGainLoss(6000, 6000),
null, null,
null "",
)); "",
"",
ActivityType.AIRPLANE,
ZoneOffset.UTC,
new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
Distance.of(20000),
Speed.of(100),
null,
new AltitudeGainLoss(6000, 6000),
null,
null
));
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class); 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"));
@@ -217,18 +260,26 @@ public class VoiceAnnouncementUtilsTest {
@Test @Test
public void getAnnouncement_imperial_speed() { public void getAnnouncement_imperial_speed() {
Track track = new Track(new Statistics( Track track = new Track(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
Distance.of(20000),
Speed.of(100),
null, null,
new AltitudeGainLoss(6000, 6000),
null, null,
null "",
)); "",
"",
ActivityType.AIRPLANE,
ZoneOffset.UTC,
new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
Distance.of(20000),
Speed.of(100),
null,
new AltitudeGainLoss(6000, 6000),
null,
null
));
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class); 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"));
@@ -242,18 +293,26 @@ public class VoiceAnnouncementUtilsTest {
@Test @Test
public void getAnnouncement_imperial_speed_1() { public void getAnnouncement_imperial_speed_1() {
Track track = new Track(new Statistics( Track track = new Track(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.ofMile(1.1),
null, null,
null, null,
null, "",
null, "",
null "",
)); ActivityType.AIRPLANE,
ZoneOffset.UTC,
new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.ofMile(1.1),
null,
null,
null,
null,
null
));
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class); 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"));
@@ -267,18 +326,26 @@ public class VoiceAnnouncementUtilsTest {
@Test @Test
public void getAnnouncement_imperial_meter_speed_1() { public void getAnnouncement_imperial_meter_speed_1() {
Track track = new Track(new Statistics( Track track = new Track(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.ofMile(1.1),
null, null,
null, null,
null, "",
null, "",
null "",
)); ActivityType.AIRPLANE,
ZoneOffset.UTC,
new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.ofMile(1.1),
null,
null,
null,
null,
null
));
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class); 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"));
@@ -292,18 +359,26 @@ public class VoiceAnnouncementUtilsTest {
@Test @Test
public void getAnnouncement_metric_speed_1() { public void getAnnouncement_metric_speed_1() {
Track track = new Track(new Statistics( Track track = new Track(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.ofKilometer(1.1),
null, null,
null, null,
null, "",
null, "",
null "",
)); ActivityType.AIRPLANE,
ZoneOffset.UTC,
new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.ofKilometer(1.1),
null,
null,
null,
null,
null
));
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class); 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"));
@@ -332,18 +407,26 @@ public class VoiceAnnouncementUtilsTest {
@Test @Test
public void getAnnouncement_imperial_pace() { public void getAnnouncement_imperial_pace() {
Track track = new Track(new Statistics( Track track = new Track(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
Distance.of(20000),
Speed.of(100),
null, null,
new AltitudeGainLoss(6000, 6000),
null, null,
null "",
)); "",
"",
ActivityType.AIRPLANE,
ZoneOffset.UTC,
new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
Distance.of(20000),
Speed.of(100),
null,
new AltitudeGainLoss(6000, 6000),
null,
null
));
SensorDataSet dataSet = Mockito.mock(SensorDataSet.class); 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"));
@@ -443,18 +526,26 @@ public class VoiceAnnouncementUtilsTest {
intervalStatistics.addTrackPoints(trackPoints.iterator()); intervalStatistics.addTrackPoints(trackPoints.iterator());
Statistics lastInterval = intervalStatistics.getLastInterval(); Statistics lastInterval = intervalStatistics.getLastInterval();
Track track = new Track(new Statistics( Track track = new Track(
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,
null, "",
null "",
)); "",
ActivityType.AIRPLANE,
ZoneOffset.UTC,
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); return new Pair<>(track, lastInterval);
} }
@@ -30,6 +30,7 @@ import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Locale; import java.util.Locale;
import de.dennisguse.opentracks.LocaleRule; import de.dennisguse.opentracks.LocaleRule;
@@ -40,6 +41,7 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.StringUtils;
/** /**
@@ -63,19 +65,26 @@ public class TrackShareSummaryGeneratorTest {
@Test @Test
public void testGenerateTrackDescription() { public void testGenerateTrackDescription() {
Track track = new Track(new Statistics( Track track = new Track(
START_TIME,
START_TIME,
Duration.ofSeconds(600),
Duration.ofSeconds(300),
Distance.of(20000),
Speed.of(100),
new AltitudeExtremities(-500, 550),
new AltitudeGainLoss(6000, 6000),
null, null,
null null,
)); "",
track.setActivityTypeLocalized("hiking"); "",
"hiking",
null,
ZoneOffset.UTC,
new Statistics(
START_TIME,
START_TIME,
Duration.ofSeconds(600),
Duration.ofSeconds(300),
Distance.of(20000),
Speed.of(100),
new AltitudeExtremities(-500, 550),
new AltitudeGainLoss(6000, 6000),
null,
null
));
String expected = //"Created by" String expected = //"Created by"
"OpenTracks (Debug)\n\n" "OpenTracks (Debug)\n\n"
@@ -13,7 +13,9 @@ import org.junit.runners.JUnit4;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneOffset;
import java.util.List; import java.util.List;
import java.util.UUID;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.AggregatedStatistic; import de.dennisguse.opentracks.data.AggregatedStatistic;
@@ -26,6 +28,7 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
@RunWith(JUnit4.class) @RunWith(JUnit4.class)
public class AggregatedStatisticsTest { public class AggregatedStatisticsTest {
@@ -33,7 +36,15 @@ public class AggregatedStatisticsTest {
private final Context context = ApplicationProvider.getApplicationContext(); private final Context context = ApplicationProvider.getApplicationContext();
private static void createTrack(Context context, Distance totalDistance, Duration totalTime, String activityTypeLocalized) { private static void createTrack(Context context, Distance totalDistance, Duration totalTime, String activityTypeLocalized) {
Track track = new Track(new Statistics( Track track = new Track(
null,
UUID.randomUUID(), //TODO Use constant UUID
"",
"",
activityTypeLocalized,
ActivityType.findByLocalizedString(context, activityTypeLocalized),
ZoneOffset.UTC,
new Statistics(
Instant.ofEpochMilli(1000), Instant.ofEpochMilli(1000),
Instant.ofEpochMilli(1000).plus(totalTime), Instant.ofEpochMilli(1000).plus(totalTime),
totalTime, totalTime,
@@ -45,8 +56,6 @@ public class AggregatedStatisticsTest {
null, null,
null null
)); ));
track.setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
track.setActivityTypeLocalized(activityTypeLocalized);
new ContentProviderUtils(context).insertTrack(track); new ContentProviderUtils(context).insertTrack(track);
} }
@@ -34,6 +34,7 @@ import de.dennisguse.opentracks.TrackListActivity;
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.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
@LargeTest @LargeTest
@@ -51,8 +52,9 @@ public class EspressoAggregatedFilterTest {
@Before @Before
public void setUp() { public void setUp() {
Pair<Track, List<TrackPoint>> pair = TestDataUtil.createTrack(new Track.Id(System.currentTimeMillis()), 20); Pair<Track, List<TrackPoint>> pair = TestDataUtil.createTrack(new Track.Id(System.currentTimeMillis()), 20);
pair.first.setActivityTypeLocalized(CATEGORY); TrackBuilder trackBuilder = new TrackBuilder(pair.first);
TestDataUtil.insertTrackWithLocations(new ContentProviderUtils(ApplicationProvider.getApplicationContext()), pair.first, pair.second); trackBuilder.setActivityTypeLocalized(CATEGORY);
TestDataUtil.insertTrackWithLocations(new ContentProviderUtils(ApplicationProvider.getApplicationContext()), trackBuilder.getTrack(), pair.second);
} }
@Test @Test
@@ -16,6 +16,7 @@ import de.dennisguse.opentracks.content.data.TestDataUtil;
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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater; import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
@@ -106,22 +107,22 @@ public class IntervalStatisticsUpdaterTest {
} }
TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoints); TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoints);
Track dummyTrack = new Track(trackStatisticsUpdater.getTrackStatistics()); TrackBuilder dummyTrack = new TrackBuilder(trackStatisticsUpdater.getTrackStatistics());
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");
Pair<Track, List<TrackPoint>> trackWithStats = new Pair<>(dummyTrack, trackPoints); Pair<TrackBuilder, List<TrackPoint>> trackWithStats = new Pair<>(dummyTrack, trackPoints);
// when and then // when and then
whenAndThen(trackWithStats.first, trackWithStats.second, 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, List<TrackPoint>> trackWithStats = buildTrackWithTrackPoints(numberOfPoints); Pair<TrackBuilder, List<TrackPoint>> trackWithStats = buildTrackWithTrackPoints(numberOfPoints);
whenAndThen(trackWithStats.first, trackWithStats.second, numberOfPoints, distanceInterval); whenAndThen(trackWithStats.first, trackWithStats.second, numberOfPoints, distanceInterval);
} }
private void whenAndThen(Track track, List<TrackPoint> trackPoints, int numberOfPoints, float distanceInterval) { private void whenAndThen(TrackBuilder track, List<TrackPoint> trackPoints, int numberOfPoints, float distanceInterval) {
IntervalStatisticsUpdater intervalStatistics = new IntervalStatisticsUpdater(Distance.of(distanceInterval)); IntervalStatisticsUpdater intervalStatistics = new IntervalStatisticsUpdater(Distance.of(distanceInterval));
intervalStatistics.addTrackPoints(trackPoints.iterator()); intervalStatistics.addTrackPoints(trackPoints.iterator());
@@ -167,13 +168,13 @@ public class IntervalStatisticsUpdaterTest {
assertEquals(intervalList.get(intervalList.size() - 1).totalDistance().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) { private static Pair<TrackBuilder, List<TrackPoint>> buildTrackWithTrackPoints(int numberOfPoints) {
ArrayList<TrackPoint> trackPoints = new ArrayList<>(); ArrayList<TrackPoint> trackPoints = new ArrayList<>();
for (int i = 0; i < numberOfPoints; i++) { for (int i = 0; i < numberOfPoints; i++) {
trackPoints.add(TestDataUtil.createTrackPoint(i)); trackPoints.add(TestDataUtil.createTrackPoint(i));
} }
TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoints); TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoints);
return new Pair<>(new Track(trackStatisticsUpdater.getTrackStatistics()), trackPoints); return new Pair<>(new TrackBuilder(trackStatisticsUpdater.getTrackStatistics()), trackPoints);
} }
} }
@@ -28,6 +28,7 @@ import java.time.ZoneOffset;
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.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.TrackEditBinding; import de.dennisguse.opentracks.databinding.TrackEditBinding;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment; import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.ui.ZoneOffsetAdapter; import de.dennisguse.opentracks.ui.ZoneOffsetAdapter;
@@ -46,7 +47,7 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
private static final String ICON_VALUE_KEY = "icon_value_key"; private static final String ICON_VALUE_KEY = "icon_value_key";
private ContentProviderUtils contentProviderUtils; private ContentProviderUtils contentProviderUtils;
private Track track; private TrackBuilder trackBuilder;
private ActivityType activityType; private ActivityType activityType;
private TrackEditBinding viewBinding; private TrackEditBinding viewBinding;
@@ -63,16 +64,17 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
} }
contentProviderUtils = new ContentProviderUtils(this); contentProviderUtils = new ContentProviderUtils(this);
track = contentProviderUtils.getTrack(trackId); Track track = contentProviderUtils.getTrack(trackId);
if (track == null) { if (track == null) {
Log.e(TAG, "No track for " + trackId.id()); Log.e(TAG, "No track for " + trackId.id());
finish(); finish();
return; return;
} }
trackBuilder = new TrackBuilder(track);
viewBinding.trackEditName.setText(track.getName()); viewBinding.trackEditName.setText(trackBuilder.getName());
viewBinding.trackEditActivityTypeLocalized.setText(track.getActivityTypeLocalized()); viewBinding.trackEditActivityTypeLocalized.setText(trackBuilder.getActivityTypeLocalized());
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, ActivityType.getLocalizedStrings(this)); ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, ActivityType.getLocalizedStrings(this));
viewBinding.trackEditActivityTypeLocalized.setAdapter(adapter); viewBinding.trackEditActivityTypeLocalized.setAdapter(adapter);
viewBinding.trackEditActivityTypeLocalized.setOnItemClickListener((parent, view, position, id) -> { viewBinding.trackEditActivityTypeLocalized.setOnItemClickListener((parent, view, position, id) -> {
@@ -91,25 +93,25 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
activityType = (ActivityType) bundle.getSerializable(ICON_VALUE_KEY); activityType = (ActivityType) bundle.getSerializable(ICON_VALUE_KEY);
} }
if (activityType == null) { if (activityType == null) {
activityType = track.getActivityType(); activityType = trackBuilder.getActivityType();
} }
setActivityTypeIcon(activityType); setActivityTypeIcon(activityType);
viewBinding.trackEditActivityTypeIcon.setOnClickListener(v -> ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), this, viewBinding.trackEditActivityTypeLocalized.getText().toString())); viewBinding.trackEditActivityTypeIcon.setOnClickListener(v -> ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), this, viewBinding.trackEditActivityTypeLocalized.getText().toString()));
viewBinding.trackEditDescription.setText(track.getDescription()); viewBinding.trackEditDescription.setText(trackBuilder.getDescription());
final ArrayAdapter<ZoneOffset> zoneOffsetAdapter = new ZoneOffsetAdapter(this, android.R.layout.simple_dropdown_item_1line); final ArrayAdapter<ZoneOffset> zoneOffsetAdapter = new ZoneOffsetAdapter(this, android.R.layout.simple_dropdown_item_1line);
viewBinding.trackEditTimeOffset.setText(track.getZoneOffset().toString()); viewBinding.trackEditTimeOffset.setText(trackBuilder.getZoneOffset().toString());
viewBinding.trackEditTimeOffset.setAdapter(zoneOffsetAdapter); viewBinding.trackEditTimeOffset.setAdapter(zoneOffsetAdapter);
viewBinding.trackEditTimeOffset.setOnItemClickListener((parent, view, position, id) -> track.setZoneOffset(zoneOffsetAdapter.getItem(position))); viewBinding.trackEditTimeOffset.setOnItemClickListener((parent, view, position, id) -> trackBuilder.setZoneOffset(zoneOffsetAdapter.getItem(position)));
viewBinding.trackEditSave.setOnClickListener(v -> { viewBinding.trackEditSave.setOnClickListener(v -> {
track.setName(viewBinding.trackEditName.getText().toString()); trackBuilder.setName(viewBinding.trackEditName.getText().toString());
track.setDescription(viewBinding.trackEditDescription.getText().toString()); trackBuilder.setDescription(viewBinding.trackEditDescription.getText().toString());
track.setActivityTypeLocalizedAndUpdateActivityType(this, viewBinding.trackEditActivityTypeLocalized.getText().toString()); trackBuilder.setActivityTypeLocalizedAndUpdateActivityType(this, viewBinding.trackEditActivityTypeLocalized.getText().toString());
contentProviderUtils.updateTrack(track); contentProviderUtils.updateTrack(trackBuilder.getTrack());
finish(); finish();
}); });
@@ -33,6 +33,7 @@ import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.TrackDataHub; import de.dennisguse.opentracks.data.TrackDataHub;
import de.dennisguse.opentracks.data.models.ActivityType; import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.databinding.TrackRecordingBinding; import de.dennisguse.opentracks.databinding.TrackRecordingBinding;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment; import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
@@ -324,11 +325,11 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
@Override @Override
public void onChooseActivityTypeDone(ActivityType activityType) { public void onChooseActivityTypeDone(ActivityType activityType) {
Track track = contentProviderUtils.getTrack(trackId); TrackBuilder track = new TrackBuilder(contentProviderUtils.getTrack(trackId));
String activityTypeLocalized = getString(activityType.getLocalizedStringId()); String activityTypeLocalized = getString(activityType.getLocalizedStringId());
track.setActivityTypeLocalizedAndUpdateActivityType(this, activityTypeLocalized); track.setActivityTypeLocalizedAndUpdateActivityType(this, activityTypeLocalized);
contentProviderUtils.updateTrack(track); contentProviderUtils.updateTrack(track.getTrack());
} }
private class CustomFragmentPagerAdapter extends FragmentStateAdapter { private class CustomFragmentPagerAdapter extends FragmentStateAdapter {
@@ -14,6 +14,7 @@ import de.dennisguse.opentracks.data.models.ActivityType;
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.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.TrackStoppedBinding; import de.dennisguse.opentracks.databinding.TrackStoppedBinding;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment; import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.io.file.exporter.ExportUtils; import de.dennisguse.opentracks.io.file.exporter.ExportUtils;
@@ -46,9 +47,9 @@ public class TrackStoppedActivity extends AbstractTrackDeleteActivity implements
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this); ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
Track track = contentProviderUtils.getTrack(trackId); Track track = contentProviderUtils.getTrack(trackId);
viewBinding.trackEditName.setText(track.getName()); viewBinding.trackEditName.setText(track.name());
viewBinding.trackEditActivityType.setText(track.getActivityTypeLocalized()); viewBinding.trackEditActivityType.setText(track.activityTypeLocalized());
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, ActivityType.getLocalizedStrings(this)); ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, ActivityType.getLocalizedStrings(this));
viewBinding.trackEditActivityType.setAdapter(adapter); viewBinding.trackEditActivityType.setAdapter(adapter);
@@ -63,19 +64,19 @@ public class TrackStoppedActivity extends AbstractTrackDeleteActivity implements
} }
}); });
setActivityTypeIcon(track.getActivityType()); setActivityTypeIcon(track.activityType());
viewBinding.trackEditActivityTypeIcon.setOnClickListener(v -> ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), this, viewBinding.trackEditActivityType.getText().toString())); viewBinding.trackEditActivityTypeIcon.setOnClickListener(v -> ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), this, viewBinding.trackEditActivityType.getText().toString()));
viewBinding.trackEditDescription.setText(track.getDescription()); viewBinding.trackEditDescription.setText(track.description());
viewBinding.time.setText(StringUtils.formatElapsedTime(track.getStatistics().movingDuration())); viewBinding.time.setText(StringUtils.formatElapsedTime(track.statistics().movingDuration()));
{ {
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.getStatistics().getAverageMovingSpeed()); .getSpeedParts(track.statistics().getAverageMovingSpeed());
viewBinding.speed.setText(parts.first); viewBinding.speed.setText(parts.first);
viewBinding.speedUnit.setText(parts.second); viewBinding.speedUnit.setText(parts.second);
} }
@@ -84,7 +85,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.getStatistics().totalDistance()); .getDistanceParts(track.statistics().totalDistance());
viewBinding.distance.setText(parts.first); viewBinding.distance.setText(parts.first);
viewBinding.distanceUnit.setText(parts.second); viewBinding.distanceUnit.setText(parts.second);
} }
@@ -104,11 +105,12 @@ public class TrackStoppedActivity extends AbstractTrackDeleteActivity implements
} }
private void storeTrackMetaData(ContentProviderUtils contentProviderUtils, Track track) { private void storeTrackMetaData(ContentProviderUtils contentProviderUtils, Track track) {
track.setName(viewBinding.trackEditName.getText().toString()); TrackBuilder trackBuilder = new TrackBuilder(track);
track.setDescription(viewBinding.trackEditDescription.getText().toString()); trackBuilder.setName(viewBinding.trackEditName.getText().toString());
track.setActivityTypeLocalizedAndUpdateActivityType(this, viewBinding.trackEditActivityType.getText().toString()); trackBuilder.setDescription(viewBinding.trackEditDescription.getText().toString());
trackBuilder.setActivityTypeLocalizedAndUpdateActivityType(this, viewBinding.trackEditActivityType.getText().toString());
contentProviderUtils.updateTrack(track); contentProviderUtils.updateTrack(trackBuilder.getTrack());
} }
@NonNull @NonNull
@@ -35,6 +35,7 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
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;
@@ -174,14 +175,14 @@ public class ChartFragment extends Fragment implements TrackDataHub.Listener {
} }
@Override @Override
public void onTrackUpdated(Track track) { public void onTrackUpdated(@NonNull Track track) {
if (isResumed()) { if (isResumed()) {
if (track == null) { if (track == null) {
activityTypeLocalized = ""; activityTypeLocalized = "";
return; return;
} }
activityTypeLocalized = track.getActivityTypeLocalized(); activityTypeLocalized = track.activityTypeLocalized();
boolean reportSpeed = PreferencesUtils.isReportSpeed(activityTypeLocalized); boolean reportSpeed = PreferencesUtils.isReportSpeed(activityTypeLocalized);
if (reportSpeed != viewBinding.chartView.getReportSpeed()) { if (reportSpeed != viewBinding.chartView.getReportSpeed()) {
viewBinding.chartView.setReportSpeed(reportSpeed); viewBinding.chartView.setReportSpeed(reportSpeed);
@@ -50,6 +50,7 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
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;
@@ -93,11 +94,6 @@ public class ContentProviderUtils {
this.contentResolver = contentResolver; this.contentResolver = contentResolver;
} }
/**
* Creates a {@link Track} from a cursor.
*
* @param cursor the cursor pointing to the track
*/
public static Track createTrack(Cursor cursor) { public static Track createTrack(Cursor cursor) {
int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID); int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
int uuidIndex = cursor.getColumnIndexOrThrow(TracksColumns.UUID); int uuidIndex = cursor.getColumnIndexOrThrow(TracksColumns.UUID);
@@ -133,7 +129,7 @@ public class ContentProviderUtils {
null null
); );
Track track = new Track(ZoneOffset.ofTotalSeconds(cursor.getInt(startTimeOffsetIndex)), trackStatistics); TrackBuilder track = new TrackBuilder(ZoneOffset.ofTotalSeconds(cursor.getInt(startTimeOffsetIndex)), trackStatistics);
track.setId(new Track.Id(cursor.getLong(idIndex))); track.setId(new Track.Id(cursor.getLong(idIndex)));
track.setUuid(UUIDUtils.fromBytes(cursor.getBlob(uuidIndex))); track.setUuid(UUIDUtils.fromBytes(cursor.getBlob(uuidIndex)));
if (!cursor.isNull(nameIndex)) { if (!cursor.isNull(nameIndex)) {
@@ -149,7 +145,7 @@ public class ContentProviderUtils {
track.setActivityTypeLocalized(cursor.getString(activityTypeLocalizedIndex)); track.setActivityTypeLocalized(cursor.getString(activityTypeLocalizedIndex));
} }
return track; return track.getTrack();
} }
@VisibleForTesting @VisibleForTesting
@@ -273,23 +269,23 @@ public class ContentProviderUtils {
* @param track the track * @param track the track
*/ */
public void updateTrack(Track track) { public void updateTrack(Track track) {
contentResolver.update(TracksColumns.CONTENT_URI, createContentValues(track), TracksColumns._ID + "=?", new String[]{Long.toString(track.getId().id())}); contentResolver.update(TracksColumns.CONTENT_URI, createContentValues(track), TracksColumns._ID + "=?", new String[]{Long.toString(track.id().id())});
} }
private ContentValues createContentValues(Track track) { private ContentValues createContentValues(Track track) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
if (track.getId() != null) { if (track.id() != null) {
values.put(TracksColumns._ID, track.getId().id()); values.put(TracksColumns._ID, track.id().id());
} }
values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.getUuid())); values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.uuid()));
values.put(TracksColumns.NAME, track.getName()); values.put(TracksColumns.NAME, track.name());
values.put(TracksColumns.DESCRIPTION, track.getDescription()); values.put(TracksColumns.DESCRIPTION, track.description());
values.put(TracksColumns.ACTIVITY_TYPE, track.getActivityType() != null ? track.getActivityType().getId() : null); values.put(TracksColumns.ACTIVITY_TYPE, track.activityType() != null ? track.activityType().getId() : null);
values.put(TracksColumns.ACTIVITY_TYPE_LOCALIZED, track.getActivityTypeLocalized()); values.put(TracksColumns.ACTIVITY_TYPE_LOCALIZED, track.activityTypeLocalized());
values.put(TracksColumns.STARTTIME_OFFSET, track.getZoneOffset().getTotalSeconds()); values.put(TracksColumns.STARTTIME_OFFSET, track.zoneOffset().getTotalSeconds());
values.putAll(createContentValues(track.getStatistics())); values.putAll(createContentValues(track.statistics()));
return values; return values;
} }
@@ -9,7 +9,6 @@ import java.util.NoSuchElementException;
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.util.AutoCloseableIterator; import de.dennisguse.opentracks.util.AutoCloseableIterator;
class MarkerIterator extends AutoCloseableIterator<Marker> { class MarkerIterator extends AutoCloseableIterator<Marker> {
@@ -27,6 +27,7 @@ import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.tables.TracksColumns; import de.dennisguse.opentracks.data.tables.TracksColumns;
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;
@@ -19,7 +19,6 @@ package de.dennisguse.opentracks.data;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.util.Log; import android.util.Log;
@@ -34,6 +33,7 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
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;
@@ -1,164 +1,46 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks.data.models; package de.dennisguse.opentracks.data.models;
import android.content.Context;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import java.time.Duration;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.util.UUID; import java.util.UUID;
import de.dennisguse.opentracks.stats.SegmentStatisticUpdater; public record Track(
// May be null if the track was not loaded from the database.
@NonNull
Id id,
// May be null if the track was not loaded from the database.
@NonNull
UUID uuid,
@NonNull
String name,
@NonNull
String description,
/** @NonNull
* A track. String activityTypeLocalized,
* @NonNull
* @author Leif Hendrik Wilden ActivityType activityType,
* @author Rodrigo Damazio @NonNull
*/ ZoneOffset zoneOffset,
//TODO Do not default initialize attributes; might be confusing for debugging @NonNull
public class Track { Statistics statistics
) {
private Track.Id id; public OffsetDateTime startTime() {
private UUID uuid = UUID.randomUUID(); return statistics
private String name = "";
private String description = "";
private String activityTypeLocalized = "";
private ActivityType activityType;
@NonNull
private ZoneOffset zoneOffset;
@NonNull
private Statistics trackStatistics;
@VisibleForTesting
public Track(Statistics statistics) {
this(ZoneOffset.UTC, statistics);
}
public Track(@NonNull ZoneOffset zoneOffset, @NonNull Statistics trackStatistics) {
this.zoneOffset = zoneOffset;
this.trackStatistics = trackStatistics;
}
/**
* May be null if the track was not loaded from the database.
*/
@Nullable
public Id getId() {
return id;
}
public void setId(Id id) {
this.id = id;
}
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getActivityTypeLocalized() {
return activityTypeLocalized;
}
public void setActivityTypeLocalized(String activityTypeLocalized) {
this.activityTypeLocalized = activityTypeLocalized;
}
public ActivityType getActivityType() {
return activityType;
}
public void setActivityType(ActivityType activityType) {
this.activityType = activityType;
}
public void setActivityTypeLocalizedAndUpdateActivityType(Context context, String activityTypeLocalized) {
setActivityTypeLocalized(activityTypeLocalized);
setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
}
public ZoneOffset getZoneOffset() {
return zoneOffset;
}
public void setZoneOffset(@NonNull ZoneOffset zoneOffset) {
this.zoneOffset = zoneOffset;
}
public OffsetDateTime getStartTime() {
return trackStatistics
.startTime().atOffset(zoneOffset); .startTime().atOffset(zoneOffset);
} }
public OffsetDateTime getStopTime() { public OffsetDateTime stopTime() {
return trackStatistics return statistics
.stopTime().atOffset(zoneOffset); .stopTime().atOffset(zoneOffset);
} }
public Statistics getStatistics() {
return trackStatistics;
}
public void setStatistics(Statistics trackStatistics) {
this.trackStatistics = trackStatistics;
}
@NonNull
@Override
public String toString() {
return "Track{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
", activityTypeLocalized='" + activityTypeLocalized + '\'' +
", activityType=" + activityType +
'}';
}
public record Id(long id) implements Parcelable { public record Id(long id) implements Parcelable {
@Override @Override
@@ -0,0 +1,193 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package de.dennisguse.opentracks.data.models;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.UUID;
/**
* A track.
*
* @author Leif Hendrik Wilden
* @author Rodrigo Damazio
*/
//TODO Do not default initialize attributes; might be confusing for debugging
public class TrackBuilder {
private Track.Id id;
private UUID uuid = UUID.randomUUID();
private String name = "";
private String description = "";
private String activityTypeLocalized = "";
private ActivityType activityType;
@NonNull
private ZoneOffset zoneOffset;
@NonNull
private Statistics trackStatistics;
@Deprecated
@VisibleForTesting
public TrackBuilder(Statistics statistics) {
this(ZoneOffset.UTC, statistics);
}
@Deprecated
public TrackBuilder(@NonNull ZoneOffset zoneOffset, @NonNull Statistics trackStatistics) {
this.zoneOffset = zoneOffset;
this.trackStatistics = trackStatistics;
}
public TrackBuilder(Track track) {
this.id = track.id();
this.uuid = track.uuid();
this.name = track.name();
this.description = track.description();
this.activityTypeLocalized = track.activityTypeLocalized();
this.activityType = track.activityType();
this.zoneOffset = track.zoneOffset();
this.trackStatistics = track.statistics();
}
/**
* May be null if the track was not loaded from the database.
*/
@Nullable
@Deprecated
public Track.Id getId() {
return id;
}
public void setId(Track.Id id) {
this.id = id;
}
@Deprecated
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
@Deprecated
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Deprecated
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Deprecated
public String getActivityTypeLocalized() {
return activityTypeLocalized;
}
public void setActivityTypeLocalized(String activityTypeLocalized) {
this.activityTypeLocalized = activityTypeLocalized;
}
@Deprecated
public ActivityType getActivityType() {
return activityType;
}
public void setActivityType(ActivityType activityType) {
this.activityType = activityType;
}
public void setActivityTypeLocalizedAndUpdateActivityType(Context context, String activityTypeLocalized) {
setActivityTypeLocalized(activityTypeLocalized);
setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
}
@Deprecated
public ZoneOffset getZoneOffset() {
return zoneOffset;
}
public void setZoneOffset(@NonNull ZoneOffset zoneOffset) {
this.zoneOffset = zoneOffset;
}
@Deprecated
public OffsetDateTime getStartTime() {
return trackStatistics
.startTime().atOffset(zoneOffset);
}
@Deprecated
public OffsetDateTime getStopTime() {
return trackStatistics
.stopTime().atOffset(zoneOffset);
}
@Deprecated
public Statistics getStatistics() {
return trackStatistics;
}
public void setStatistics(Statistics trackStatistics) {
this.trackStatistics = trackStatistics;
}
public Track getTrack() {
return new Track(
id,
uuid,
name,
description,
activityTypeLocalized,
activityType,
zoneOffset,
trackStatistics
);
}
@NonNull
@Override
public String toString() {
return "Track{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
", activityTypeLocalized='" + activityTypeLocalized + '\'' +
", activityType=" + activityType +
'}';
}
}
@@ -35,6 +35,7 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
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;
@@ -42,7 +43,7 @@ import de.dennisguse.opentracks.stats.SensorStatistics;
import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.StringUtils;
/** /**
* A fragment to display track statistics to the user for a recorded {@link Track}. * A fragment to display track statistics to the user for a recorded {@link TrackBuilder}.
* *
* @author Sandor Dornbush * @author Sandor Dornbush
* @author Rodrigo Damazio * @author Rodrigo Damazio
@@ -147,7 +148,7 @@ public class StatisticsRecordedFragment extends Fragment {
sensorStatistics = contentProviderUtils.getSensorStats(trackId); sensorStatistics = contentProviderUtils.getSensorStats(trackId);
boolean prefsChanged = this.track == null || (!this.track.getActivityTypeLocalized().equals(track.getActivityTypeLocalized())); boolean prefsChanged = this.track == null || (!this.track.activityTypeLocalized().equals(track.activityTypeLocalized()));
this.track = track; this.track = track;
if (prefsChanged) { if (prefsChanged) {
sharedPreferenceChangeListener.onSharedPreferenceChanged(null, getString(R.string.stats_rate_key)); sharedPreferenceChangeListener.onSharedPreferenceChanged(null, getString(R.string.stats_rate_key));
@@ -162,13 +163,13 @@ public class StatisticsRecordedFragment extends Fragment {
} }
private void loadTrackDescription(@NonNull Track track) { private void loadTrackDescription(@NonNull Track track) {
viewBinding.statsNameValue.setText(track.getName()); viewBinding.statsNameValue.setText(track.name());
viewBinding.statsDescriptionValue.setText(track.getDescription()); viewBinding.statsDescriptionValue.setText(track.description());
viewBinding.statsStartDatetimeValue.setText(StringUtils.formatDateTimeWithOffsetIfDifferent(track.getStartTime())); viewBinding.statsStartDatetimeValue.setText(StringUtils.formatDateTimeWithOffsetIfDifferent(track.startTime()));
} }
private void updateUI() { private void updateUI() {
Statistics trackStatistics = track.getStatistics(); Statistics trackStatistics = track.statistics();
// Set total distance // Set total distance
{ {
Pair<String, String> parts = DistanceFormatter.Builder() Pair<String, String> parts = DistanceFormatter.Builder()
@@ -180,7 +181,7 @@ public class StatisticsRecordedFragment extends Fragment {
} }
// Set activity type // Set activity type
viewBinding.statsActivityTypeIcon.setImageDrawable(ContextCompat.getDrawable(getContext(), track.getActivityType().getIconDrawableId())); viewBinding.statsActivityTypeIcon.setImageDrawable(ContextCompat.getDrawable(getContext(), track.activityType().getIconDrawableId()));
// Set time and start datetime // Set time and start datetime
{ {
@@ -15,11 +15,11 @@ import androidx.gridlayout.widget.GridLayout;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.StatisticsRecordingBinding; import de.dennisguse.opentracks.databinding.StatisticsRecordingBinding;
import de.dennisguse.opentracks.services.RecordingData; import de.dennisguse.opentracks.services.RecordingData;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
@@ -31,7 +31,7 @@ import de.dennisguse.opentracks.viewmodels.Mapping;
import de.dennisguse.opentracks.viewmodels.StatisticViewHolder; import de.dennisguse.opentracks.viewmodels.StatisticViewHolder;
/** /**
* A fragment to display track statistics to the user for a currently recording {@link Track}. * A fragment to display track statistics to the user for a currently recording {@link TrackBuilder}.
* *
* @author Sandor Dornbush * @author Sandor Dornbush
* @author Rodrigo Damazio * @author Rodrigo Damazio
@@ -167,9 +167,9 @@ public class StatisticsRecordingFragment extends Fragment {
private void onRecordingDataChanged(RecordingData recordingData) { private void onRecordingDataChanged(RecordingData recordingData) {
Track oldTrack = this.recordingData.track(); Track oldTrack = this.recordingData.track();
String oldActivityType = oldTrack != null ? oldTrack.getActivityTypeLocalized() : ""; String oldActivityType = oldTrack != null ? oldTrack.activityTypeLocalized() : "";
Track newTrack = recordingData.track(); Track newTrack = recordingData.track();
String newActivityType = newTrack != null ? newTrack.getActivityTypeLocalized() : ""; String newActivityType = newTrack != null ? newTrack.activityTypeLocalized() : "";
this.recordingData = recordingData; this.recordingData = recordingData;
@@ -2,7 +2,6 @@ package de.dennisguse.opentracks.io.file;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import java.time.Instant;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@@ -12,8 +11,10 @@ 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.ActivityType;
import de.dennisguse.opentracks.data.models.Statistics; 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.TrackBuilder;
import de.dennisguse.opentracks.util.FileUtils; import de.dennisguse.opentracks.util.FileUtils;
public class TrackFilenameGenerator { public class TrackFilenameGenerator {
@@ -41,11 +42,11 @@ public class TrackFilenameGenerator {
public String format(@NonNull Track track, @NonNull TrackFileFormat trackFileFormat) { public String format(@NonNull Track track, @NonNull TrackFileFormat trackFileFormat) {
Map<String, String> values = new HashMap<>(); Map<String, String> values = new HashMap<>();
values.put(UUID_KEY, track.getUuid().toString().substring(0, 8)); values.put(UUID_KEY, track.uuid().toString().substring(0, 8));
values.put(TRACKNAME_KEY, track.getName()); values.put(TRACKNAME_KEY, track.name());
values.put(ACTIVITY_TYPE_KEY, track.getActivityTypeLocalized()); values.put(ACTIVITY_TYPE_KEY, track.activityTypeLocalized());
values.put(STARTTIME_TIME_KEY, track.getStartTime().toLocalTime().toString()); values.put(STARTTIME_TIME_KEY, track.startTime().toLocalTime().toString());
values.put(STARTTIME_DATE_KEY, track.getStartTime().toLocalDate().toString()); values.put(STARTTIME_DATE_KEY, track.stopTime().toLocalDate().toString());
return format(format(template, values), trackFileFormat); return format(format(template, values), trackFileFormat);
} }
@@ -90,9 +91,16 @@ public class TrackFilenameGenerator {
} }
public String getExample() { public String getExample() {
Track track = new Track(ZoneOffset.UTC, Statistics.DEFAULT); Track track = new Track(
track.setName("Berlin"); null,
track.setUuid(UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6")); UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6"),
"Berlin",
"",
"",
ActivityType.CYCLING,
ZoneOffset.UTC,
Statistics.DEFAULT
);
return format(track, TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES); return format(track, TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES);
} }
@@ -111,7 +111,7 @@ public class CSVTrackExporter implements TrackExporter {
boolean headerWritten = false; boolean headerWritten = false;
for (Track track : tracks) { for (Track track : tracks) {
columns.get(0).extractor = t -> quote(StringUtils.formatDateTimeIso8601(t.getTime(), track.getZoneOffset())); columns.get(0).extractor = t -> quote(StringUtils.formatDateTimeIso8601(t.getTime(), track.zoneOffset()));
if (!headerWritten) { if (!headerWritten) {
writeHeader(columns); writeHeader(columns);
@@ -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 (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.getId(), null)) { try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) {
while (trackPointIterator.hasNext()) { while (trackPointIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException(); if (Thread.interrupted()) throw new InterruptedException();
@@ -40,6 +40,7 @@ import de.dennisguse.opentracks.AbstractActivity;
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.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.ExportActivityBinding; import de.dennisguse.opentracks.databinding.ExportActivityBinding;
import de.dennisguse.opentracks.io.file.ErrorListDialog; import de.dennisguse.opentracks.io.file.ErrorListDialog;
import de.dennisguse.opentracks.io.file.TrackFileFormat; import de.dennisguse.opentracks.io.file.TrackFileFormat;
@@ -222,9 +223,9 @@ public class ExportActivity extends AbstractActivity {
exportTasks = new ArrayList<>(); exportTasks = new ArrayList<>();
if (allInOneFile) { if (allInOneFile) {
String filename = "OpenTracks-Backup"; String filename = "OpenTracks-Backup";
exportTasks.add(new ExportTask(filename, trackFileFormat, tracks.stream().map(Track::getId).toList())); exportTasks.add(new ExportTask(filename, trackFileFormat, tracks.stream().map(Track::id).toList()));
} else { } else {
exportTasks.addAll(tracks.stream().map(it -> new ExportTask(null, trackFileFormat, List.of(it.getId()))).toList()); exportTasks.addAll(tracks.stream().map(it -> new ExportTask(null, trackFileFormat, List.of(it.id()))).toList());
} }
trackExportTotalCount = exportTasks.size(); trackExportTotalCount = exportTasks.size();
} }
@@ -362,7 +363,7 @@ public class ExportActivity extends AbstractActivity {
if (exportTask.isMultiExport()) { if (exportTask.isMultiExport()) {
name = exportTask.getFilename(); name = exportTask.getFilename();
} else { } else {
name = contentProviderUtils.getTrack(exportTask.getTrackIds().get(0)).getName(); name = contentProviderUtils.getTrack(exportTask.getTrackIds().get(0)).name();
} }
Log.e(TAG, "Error exporting " + name + ": " + errorMessage); Log.e(TAG, "Error exporting " + name + ": " + errorMessage);
trackErrors.add(name); trackErrors.add(name);
@@ -402,7 +403,7 @@ public class ExportActivity extends AbstractActivity {
if (exportTask.isMultiExport()) { if (exportTask.isMultiExport()) {
name = exportTask.getFilename(); name = exportTask.getFilename();
} else { } else {
name = contentProviderUtils.getTrack(exportTask.getTrackIds().get(0)).getName(); name = contentProviderUtils.getTrack(exportTask.getTrackIds().get(0)).name();
} }
viewBinding.exportProgressAlertMsg.setText(getString(R.string.export_track_already_exists_msg, name)); viewBinding.exportProgressAlertMsg.setText(getString(R.string.export_track_already_exists_msg, name));
setConflictVisibility(View.VISIBLE); setConflictVisibility(View.VISIBLE);
@@ -25,6 +25,7 @@ import java.util.List;
import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.io.file.TrackFileFormat; import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.TrackFilenameGenerator; import de.dennisguse.opentracks.io.file.TrackFilenameGenerator;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -17,6 +17,7 @@
package de.dennisguse.opentracks.io.file.exporter; package de.dennisguse.opentracks.io.file.exporter;
import android.database.Cursor; import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -128,7 +129,7 @@ public class GPXTrackExporter implements TrackExporter {
LinkedList<TrackPoint> sensorPoints = new LinkedList<>(); LinkedList<TrackPoint> sensorPoints = new LinkedList<>();
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.getId(), null)) { try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) {
while (trackPointIterator.hasNext()) { while (trackPointIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException(); if (Thread.interrupted()) throw new InterruptedException();
@@ -152,7 +153,7 @@ public class GPXTrackExporter implements TrackExporter {
writeOpenSegment(); writeOpenSegment();
wroteSegment = true; wroteSegment = true;
if (trackPoint.hasLocation()) { if (trackPoint.hasLocation()) {
trackDistance = trackDistance.plus(writeTrackPoint(track.getZoneOffset(), trackPoint, sensorPoints, trackDistance)); trackDistance = trackDistance.plus(writeTrackPoint(track.zoneOffset(), trackPoint, sensorPoints, trackDistance));
sensorPoints.clear(); sensorPoints.clear();
} else { } else {
sensorPoints.add(trackPoint); sensorPoints.add(trackPoint);
@@ -165,7 +166,7 @@ public class GPXTrackExporter implements TrackExporter {
wroteSegment = true; wroteSegment = true;
} }
if (trackPoint.hasLocation()) { if (trackPoint.hasLocation()) {
trackDistance = trackDistance.plus(writeTrackPoint(track.getZoneOffset(), trackPoint, sensorPoints, trackDistance)); trackDistance = trackDistance.plus(writeTrackPoint(track.zoneOffset(), trackPoint, sensorPoints, trackDistance));
sensorPoints.clear(); sensorPoints.clear();
} else { } else {
sensorPoints.add(trackPoint); sensorPoints.add(trackPoint);
@@ -238,12 +239,12 @@ public class GPXTrackExporter implements TrackExporter {
} }
private void writeMarkers(Track track) throws InterruptedException { private void writeMarkers(Track track) throws InterruptedException {
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.getId())) { try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.id())) {
while (markerIterator.hasNext()) { while (markerIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException(); if (Thread.interrupted()) throw new InterruptedException();
writeMarker(track.getZoneOffset(), markerIterator.next()); writeMarker(track.zoneOffset(), markerIterator.next());
} }
} }
} }
@@ -262,19 +263,19 @@ public class GPXTrackExporter implements TrackExporter {
private void writeBeginTrack(Track track) { private void writeBeginTrack(Track track) {
printWriter.println("<trk>"); printWriter.println("<trk>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>"); printWriter.println("<name>" + StringUtils.formatCData(track.name()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>"); printWriter.println("<desc>" + StringUtils.formatCData(track.description()) + "</desc>");
printWriter.println("<type>" + StringUtils.formatCData(track.getActivityType().getId()) + "</type>"); printWriter.println("<type>" + StringUtils.formatCData(track.activityType().getId()) + "</type>");
printWriter.println("<extensions>"); printWriter.println("<extensions>");
printWriter.println("<topografix:color>c0c0c0</topografix:color>"); printWriter.println("<topografix:color>c0c0c0</topografix:color>");
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>"); printWriter.println("<opentracks:trackid>" + track.uuid() + "</opentracks:trackid>");
if (track.getActivityTypeLocalized() != null || !track.getActivityTypeLocalized().isBlank()) { if (!TextUtils.isEmpty(track.activityTypeLocalized())) {
printWriter.println("<opentracks:typeTranslated>" + StringUtils.formatCData(track.getActivityTypeLocalized()) + "</opentracks:typeTranslated>"); printWriter.println("<opentracks:typeTranslated>" + StringUtils.formatCData(track.activityTypeLocalized()) + "</opentracks:typeTranslated>");
} }
Statistics trackStatistics = track.getStatistics(); Statistics trackStatistics = track.statistics();
printWriter.println("<gpxtrkx:TrackStatsExtension>"); printWriter.println("<gpxtrkx:TrackStatsExtension>");
printWriter.println("<gpxtrkx:Distance>" + trackStatistics.totalDistance().toM() + "</gpxtrkx:Distance>"); printWriter.println("<gpxtrkx:Distance>" + trackStatistics.totalDistance().toM() + "</gpxtrkx:Distance>");
printWriter.println("<gpxtrkx:TimerTime>" + trackStatistics.totalDuration().getSeconds() + "</gpxtrkx:TimerTime>"); printWriter.println("<gpxtrkx:TimerTime>" + trackStatistics.totalDuration().getSeconds() + "</gpxtrkx:TimerTime>");
@@ -136,7 +136,7 @@ public class KMLTrackExporter implements TrackExporter {
private void writeMarkers(Track track) throws InterruptedException { private void writeMarkers(Track track) throws InterruptedException {
boolean hasMarkers = false; boolean hasMarkers = false;
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.getId())) { try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.id())) {
while (markerIterator.hasNext()) { while (markerIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException(); if (Thread.interrupted()) throw new InterruptedException();
@@ -145,7 +145,7 @@ public class KMLTrackExporter implements TrackExporter {
hasMarkers = true; hasMarkers = true;
} }
writeMarker(markerIterator.next(), track.getZoneOffset()); writeMarker(markerIterator.next(), track.zoneOffset());
} }
} }
if (hasMarkers) { if (hasMarkers) {
@@ -157,7 +157,7 @@ public class KMLTrackExporter implements TrackExporter {
boolean wroteTrack = false; boolean wroteTrack = false;
boolean wroteSegment = false; boolean wroteSegment = false;
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.getId(), null)) { try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(track.id(), null)) {
while (trackPointIterator.hasNext()) { while (trackPointIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException(); if (Thread.interrupted()) throw new InterruptedException();
@@ -171,12 +171,12 @@ public class KMLTrackExporter implements TrackExporter {
case SEGMENT_START_MANUAL, SEGMENT_START_AUTOMATIC -> { case SEGMENT_START_MANUAL, SEGMENT_START_AUTOMATIC -> {
if (wroteSegment) writeCloseSegment(); if (wroteSegment) writeCloseSegment();
writeOpenSegment(); writeOpenSegment();
writeTrackPoint(track.getZoneOffset(), trackPoint); writeTrackPoint(track.zoneOffset(), trackPoint);
wroteSegment = true; wroteSegment = true;
} }
case SEGMENT_END_MANUAL -> { case SEGMENT_END_MANUAL -> {
if (!wroteSegment) writeOpenSegment(); if (!wroteSegment) writeOpenSegment();
writeTrackPoint(track.getZoneOffset(), trackPoint); writeTrackPoint(track.zoneOffset(), trackPoint);
writeCloseSegment(); writeCloseSegment();
wroteSegment = false; wroteSegment = false;
} }
@@ -187,7 +187,7 @@ public class KMLTrackExporter implements TrackExporter {
wroteSegment = true; wroteSegment = true;
} }
writeTrackPoint(track.getZoneOffset(), trackPoint); writeTrackPoint(track.zoneOffset(), trackPoint);
} }
default -> default ->
throw new RuntimeException("Exporting this TrackPoint type is not implemented: " + trackPoint.getType()); throw new RuntimeException("Exporting this TrackPoint type is not implemented: " + trackPoint.getType());
@@ -239,7 +239,7 @@ public class KMLTrackExporter implements TrackExporter {
printWriter.println("<visibility>1</visibility>"); printWriter.println("<visibility>1</visibility>");
Track track = tracks.get(0); Track track = tracks.get(0);
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>"); printWriter.println("<name>" + StringUtils.formatCData(track.name()) + "</name>");
printWriter.println("<atom:generator>" + StringUtils.formatCData(context.getString(R.string.app_name)) + "</atom:generator>"); printWriter.println("<atom:generator>" + StringUtils.formatCData(context.getString(R.string.app_name)) + "</atom:generator>");
writeTrackStyle(); writeTrackStyle();
@@ -261,7 +261,7 @@ public class KMLTrackExporter implements TrackExporter {
private void writeBeginMarkers(Track track) { private void writeBeginMarkers(Track track) {
printWriter.println("<Folder>"); printWriter.println("<Folder>");
printWriter.println("<name>" + StringUtils.formatCData(context.getString(R.string.track_markers, track.getName())) + "</name>"); printWriter.println("<name>" + StringUtils.formatCData(context.getString(R.string.track_markers, track.name())) + "</name>");
printWriter.println("<open>1</open>"); printWriter.println("<open>1</open>");
} }
@@ -291,13 +291,13 @@ public class KMLTrackExporter implements TrackExporter {
private void writeBeginTrack(Track track) { private void writeBeginTrack(Track track) {
printWriter.println("<Placemark>"); printWriter.println("<Placemark>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>"); printWriter.println("<name>" + StringUtils.formatCData(track.name()) + "</name>");
printWriter.println("<description>" + StringUtils.formatCData(track.getDescription()) + "</description>"); printWriter.println("<description>" + StringUtils.formatCData(track.description()) + "</description>");
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>"); printWriter.println("<opentracks:trackid>" + track.uuid() + "</opentracks:trackid>");
printWriter.println("<styleUrl>#" + TRACK_STYLE + "</styleUrl>"); printWriter.println("<styleUrl>#" + TRACK_STYLE + "</styleUrl>");
writeActivityType(track.getActivityType()); writeActivityType(track.activityType());
writeTypeLocalized(track.getActivityTypeLocalized()); writeTypeLocalized(track.activityTypeLocalized());
printWriter.println("<MultiTrack>"); printWriter.println("<MultiTrack>");
printWriter.println("<altitudeMode>absolute</altitudeMode>"); printWriter.println("<altitudeMode>absolute</altitudeMode>");
printWriter.println("<interpolate>1</interpolate>"); printWriter.println("<interpolate>1</interpolate>");
@@ -17,7 +17,6 @@
package de.dennisguse.opentracks.io.file.exporter; package de.dennisguse.opentracks.io.file.exporter;
import android.content.Context; import android.content.Context;
import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.util.Log; import android.util.Log;
@@ -35,6 +34,7 @@ import java.util.zip.ZipOutputStream;
import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.ContentProviderUtils;
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.TrackBuilder;
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.AutoCloseableIterator;
import de.dennisguse.opentracks.util.FileUtils; import de.dennisguse.opentracks.util.FileUtils;
@@ -90,14 +90,14 @@ public class KMZTrackExporter implements TrackExporter {
private void addImages(Context context, List<Track> tracks, ZipOutputStream zipOutputStream) throws InterruptedException, IOException { private void addImages(Context context, List<Track> tracks, ZipOutputStream zipOutputStream) throws InterruptedException, IOException {
for (Track track : tracks) { for (Track track : tracks) {
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.getId())) { try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.id())) {
while (markerIterator.hasNext()) { while (markerIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException(); if (Thread.interrupted()) throw new InterruptedException();
Marker marker = markerIterator.next(); Marker marker = markerIterator.next();
if (marker.hasPhoto()) { if (marker.hasPhoto()) {
Uri uriPhoto = marker.getPhotoUrl(); Uri uriPhoto = marker.getPhotoUrl();
boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, track.getId(), uriPhoto) != null; boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, track.id(), uriPhoto) != null;
if (existsPhoto) { if (existsPhoto) {
addImage(context, zipOutputStream, uriPhoto, marker); addImage(context, zipOutputStream, uriPhoto, marker);
} }
@@ -22,6 +22,7 @@ import java.io.OutputStream;
import java.util.List; import java.util.List;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
/** /**
* Track exporting for exporting track to an {@link OutputStream}. * Track exporting for exporting track to an {@link OutputStream}.
@@ -17,7 +17,6 @@
package de.dennisguse.opentracks.io.file.importer; package de.dennisguse.opentracks.io.file.importer;
import android.content.Context; import android.content.Context;
import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.util.Log; import android.util.Log;
@@ -31,7 +30,6 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
@@ -25,6 +25,7 @@ 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.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.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater; import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
import de.dennisguse.opentracks.ui.markers.MarkerUtils; import de.dennisguse.opentracks.ui.markers.MarkerUtils;
@@ -146,12 +147,16 @@ public class TrackImporter {
adjustTrackPoints(); adjustTrackPoints();
TrackStatisticsUpdater updater = new TrackStatisticsUpdater(trackPoints); TrackStatisticsUpdater updater = new TrackStatisticsUpdater(trackPoints);
Track track = new Track(trackData.zoneOffset, updater.getTrackStatistics()); Track track = new Track(
track.setName(trackData.name); null,
track.setUuid(trackData.uuid); trackData.uuid,
track.setDescription(trackData.description); trackData.name,
track.setActivityType(trackData.activityType); trackData.description,
track.setActivityTypeLocalized(trackData.activityTypeLocalized); trackData.activityTypeLocalized,
trackData.activityType,
trackData.zoneOffset,
updater.getTrackStatistics()
);
Track.Id trackId = contentProviderUtils.insertTrack(track); Track.Id trackId = contentProviderUtils.insertTrack(track);
@@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
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.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.util.IntentDashboardUtils; import de.dennisguse.opentracks.util.IntentDashboardUtils;
@@ -39,14 +40,14 @@ public class StartRecording extends AbstractAPIActivity {
private void updateTrackMetadata(@NonNull Track.Id trackId, @NonNull Bundle bundle) { private void updateTrackMetadata(@NonNull Track.Id trackId, @NonNull Bundle bundle) {
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this); ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
Track track = contentProviderUtils.getTrack(trackId); TrackBuilder track = new TrackBuilder(contentProviderUtils.getTrack(trackId));
track.setName(bundle.getString(EXTRA_TRACK_NAME, "")); track.setName(bundle.getString(EXTRA_TRACK_NAME, ""));
track.setDescription(bundle.getString(EXTRA_TRACK_DESCRIPTION, "")); track.setDescription(bundle.getString(EXTRA_TRACK_DESCRIPTION, ""));
track.setActivityType(ActivityType.findBy(bundle.getString(EXTRA_TRACK_ACTIVITY_TYPE_ID, null))); track.setActivityType(ActivityType.findBy(bundle.getString(EXTRA_TRACK_ACTIVITY_TYPE_ID, null)));
track.setActivityTypeLocalized(bundle.getString(EXTRA_TRACK_ACTIVITY_TYPE_LOCALIZED, "")); track.setActivityTypeLocalized(bundle.getString(EXTRA_TRACK_ACTIVITY_TYPE_LOCALIZED, ""));
contentProviderUtils.updateTrack(track); contentProviderUtils.updateTrack(track.getTrack());
} }
private void startDashboardAPI(@NonNull Track.Id trackId, @NonNull Bundle bundle) { private void startDashboardAPI(@NonNull Track.Id trackId, @NonNull Bundle bundle) {
@@ -11,7 +11,7 @@ public class StopRecording extends AbstractAPIActivity {
RecordingData recordingData = service.getRecordingDataObservable().getValue(); RecordingData recordingData = service.getRecordingDataObservable().getValue();
Track.Id trackId = null; Track.Id trackId = null;
if (recordingData != null && recordingData.track() != null) { if (recordingData != null && recordingData.track() != null) {
trackId = recordingData.track().getId(); trackId = recordingData.track().id();
} }
service.endCurrentTrack(); service.endCurrentTrack();
@@ -1,14 +1,12 @@
package de.dennisguse.opentracks.services; package de.dennisguse.opentracks.services;
import androidx.annotation.NonNull;
import de.dennisguse.opentracks.data.models.Statistics; 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;
/** /**
* {@link Track} and {@link TrackPoint} must be immutable (i.e., their content does not change). * {@link TrackPoint} must be immutable (i.e., their content does not change).
*/ */
public record RecordingData( public record RecordingData(
Track track, Track track,
@@ -19,6 +17,6 @@ public record RecordingData(
public static final RecordingData NOT_RECORDING = new RecordingData(null, null, null, null); public static final RecordingData NOT_RECORDING = new RecordingData(null, null, null, null);
public Statistics trackStatistics() { public Statistics trackStatistics() {
return track.getStatistics(); return track.statistics();
} }
} }
@@ -19,6 +19,7 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
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;
@@ -71,14 +72,14 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
ZoneOffset zoneOffset = ZoneOffset.systemDefault().getRules().getOffset(segmentStartTrackPoint.getTime()); ZoneOffset zoneOffset = ZoneOffset.systemDefault().getRules().getOffset(segmentStartTrackPoint.getTime());
trackStatisticsUpdater = new TrackStatisticsUpdater(segmentStartTrackPoint); trackStatisticsUpdater = new TrackStatisticsUpdater(segmentStartTrackPoint);
Track track = new Track(zoneOffset, trackStatisticsUpdater.getTrackStatistics()); TrackBuilder track = new TrackBuilder(zoneOffset, trackStatisticsUpdater.getTrackStatistics());
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.setName(TrackNameUtils.getTrackName(context, trackId, track.getStartTime())); track.setName(TrackNameUtils.getTrackName(context, trackId, track.getStartTime()));
trackId = contentProviderUtils.insertTrack(track); trackId = contentProviderUtils.insertTrack(track.getTrack());
onNewTrackPoint(segmentStartTrackPoint); onNewTrackPoint(segmentStartTrackPoint);
@@ -96,7 +97,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
return false; return false;
} }
trackStatisticsUpdater = new TrackStatisticsUpdater(track.getStatistics()); trackStatisticsUpdater = new TrackStatisticsUpdater(track.statistics());
onNewTrackPoint(trackPointCreator.createSegmentStartManual()); onNewTrackPoint(trackPointCreator.createSegmentStartManual());
reset(); reset();
@@ -127,9 +128,10 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
return null; return null;
} }
track.setStatistics(tmpTrackStatisticsUpdater.getTrackStatistics()); TrackBuilder trackBuilder = new TrackBuilder(track);
trackBuilder.setStatistics(tmpTrackStatisticsUpdater.getTrackStatistics());
return new RecordingData(track, current.first, current.second, tmpTrackStatisticsUpdater.getCurrentSegment()); return new RecordingData(trackBuilder.getTrack(), current.first, current.second, tmpTrackStatisticsUpdater.getCurrentSegment());
} }
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
@@ -149,12 +149,12 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
} }
//TODO Avoid reloading (some) TrackPoints just to announce the last interval. //TODO Avoid reloading (some) TrackPoints just to announce the last interval.
try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(data.track().getId(), startTrackPointId)) { try (AutoCloseableIterator<TrackPoint> trackPointIterator = contentProviderUtils.getTrackPointIterator(data.track().id(), startTrackPointId)) {
startTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator); startTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator);
Statistics lastInterval = intervalStatistics.getLastInterval(); Statistics lastInterval = intervalStatistics.getLastInterval();
SensorStatistics sensorStatistics = null; SensorStatistics sensorStatistics = null;
if (data.track().getId() != null) { if (data.track().id() != null) {
sensorStatistics = contentProviderUtils.getSensorStats(data.track().getId()); sensorStatistics = contentProviderUtils.getSensorStats(data.track().id());
} }
return VoiceAnnouncementUtils.createStatistics(context, data.track(), data.sensorDataSet(), PreferencesUtils.getUnitSystem(), PreferencesUtils.isReportSpeed(data.track()), lastInterval, sensorStatistics); return VoiceAnnouncementUtils.createStatistics(context, data.track(), data.sensorDataSet(), PreferencesUtils.getUnitSystem(), PreferencesUtils.isReportSpeed(data.track()), lastInterval, sensorStatistics);
@@ -35,6 +35,7 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
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;
@@ -51,12 +52,12 @@ class VoiceAnnouncementUtils {
} }
static Spannable createStatistics(Context context, Track track, SensorDataSet sensorDataSet, UnitSystem unitSystem, boolean isReportSpeed, @Nullable Statistics currentInterval, @Nullable SensorStatistics sensorStatistics) { static Spannable createStatistics(Context context, Track track, SensorDataSet sensorDataSet, UnitSystem unitSystem, boolean isReportSpeed, @Nullable Statistics currentInterval, @Nullable SensorStatistics sensorStatistics) {
Statistics trackStatistics = track.getStatistics(); Statistics trackStatistics = track.statistics();
SpannableStringBuilder builder = new SpannableStringBuilder(); SpannableStringBuilder builder = new SpannableStringBuilder();
if (shouldVoiceAnnounceTime()) { if (shouldVoiceAnnounceTime()) {
appendTime(builder, track.getStopTime()); appendTime(builder, track.stopTime());
} }
Distance totalDistance = trackStatistics.totalDistance(); Distance totalDistance = trackStatistics.totalDistance();
@@ -48,6 +48,7 @@ import de.dennisguse.opentracks.data.models.DistanceFormatter;
import de.dennisguse.opentracks.data.models.HeartRate; import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.HeartRateZones; import de.dennisguse.opentracks.data.models.HeartRateZones;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.io.file.TrackFileFormat; import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.TrackFilenameGenerator; import de.dennisguse.opentracks.io.file.TrackFilenameGenerator;
import de.dennisguse.opentracks.sensors.SensorType; import de.dennisguse.opentracks.sensors.SensorType;
@@ -252,7 +253,7 @@ public class PreferencesUtils {
} }
public static boolean isReportSpeed(Track track) { public static boolean isReportSpeed(Track track) {
return isReportSpeed(track.getActivityTypeLocalized()); return isReportSpeed(track.activityTypeLocalized());
} }
private static String getBluetoothSensorAddressNone() { private static String getBluetoothSensorAddressNone() {
@@ -15,6 +15,7 @@ import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.ShareContentProvider; import de.dennisguse.opentracks.data.ShareContentProvider;
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.TrackBuilder;
import de.dennisguse.opentracks.io.file.TrackFileFormat; import de.dennisguse.opentracks.io.file.TrackFileFormat;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -31,6 +31,7 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.settings.UnitSystem; import de.dennisguse.opentracks.settings.UnitSystem;
import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.StringUtils;
@@ -62,10 +63,10 @@ public class TrackShareSummaryGenerator {
builder.append(TEXT_LINE_BREAK); builder.append(TEXT_LINE_BREAK);
builder.append(TEXT_LINE_BREAK); builder.append(TEXT_LINE_BREAK);
writeString(track.getName(), builder, R.string.generic_name_line); writeString(track.name(), builder, R.string.generic_name_line);
writeString(track.getActivityTypeLocalized(), builder, R.string.description_activity_type); writeString(track.activityTypeLocalized(), builder, R.string.description_activity_type);
writeString(track.getDescription(), builder, R.string.generic_description_line); writeString(track.description(), builder, R.string.generic_description_line);
builder.append(generateTrackStatisticsDescription(track.getStatistics())); builder.append(generateTrackStatisticsDescription(track.statistics()));
return builder.toString(); return builder.toString();
} }
@@ -30,11 +30,11 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.data.models.TrackPoint;
/** /**
* Statistical data about a {@link Track}. * Statistical data about a {@link TrackBuilder}.
* The data in this class should be filled out by {@link TrackStatisticsUpdater}. * The data in this class should be filled out by {@link TrackStatisticsUpdater}.
* *
* @author Rodrigo Damazio * @author Rodrigo Damazio
@@ -18,6 +18,7 @@ import java.util.Optional;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.R;
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.AltitudeGainLoss; import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Distance;
@@ -25,6 +26,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.Statistics; 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.TrackBuilder;
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;
@@ -54,7 +56,16 @@ public class SettingsCustomLayoutEditAdapter extends RecyclerView.Adapter<Recycl
null, null,
null null
); );
Track track = new Track(ZoneOffset.UTC, statistics);
Track track = new Track(
null,
null,
"",
"",
"",
ActivityType.AIRPLANE,
ZoneOffset.UTC,
statistics);
Position position = new Position( Position position = new Position(
Instant.ofEpochMilli(0), Instant.ofEpochMilli(0),
@@ -23,6 +23,7 @@ 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.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.IntervalListViewBinding; import de.dennisguse.opentracks.databinding.IntervalListViewBinding;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.settings.UnitSystem; import de.dennisguse.opentracks.settings.UnitSystem;
@@ -192,7 +192,7 @@ public class MarkerListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
viewBinding.markerListItemName.setText(marker.getName()); viewBinding.markerListItemName.setText(marker.getName());
{ {
ZoneOffset timeZone = new ContentProviderUtils(context).getTrack(marker.getTrackId()).getZoneOffset(); ZoneOffset timeZone = new ContentProviderUtils(context).getTrack(marker.getTrackId()).zoneOffset();
ListItemUtils.setDateAndTime(context, viewBinding.markerListItemDate, viewBinding.markerListItemTime, marker.getTime(), timeZone); ListItemUtils.setDateAndTime(context, viewBinding.markerListItemDate, viewBinding.markerListItemTime, marker.getTime(), timeZone);
} }