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.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.ui.markers.MarkerUtils;
import de.dennisguse.opentracks.util.AutoCloseableIterator;
@@ -35,11 +36,11 @@ public class TestDataUtil {
* Create a track without any trackPoints.
*/
public static Track createTrack(Track.Id trackId) {
Track track = new Track(Statistics.DEFAULT);
TrackBuilder track = new TrackBuilder(Statistics.DEFAULT);
track.setId(trackId);
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) {
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 {
@@ -54,12 +54,12 @@ import de.dennisguse.opentracks.data.models.Altitude;
import de.dennisguse.opentracks.data.models.AltitudeExtremities;
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Position;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.data.tables.MarkerColumns;
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
@@ -130,11 +130,12 @@ public class CustomContentProviderUtilsTest {
}
private TrackPoint.Id initializeTrack(Track.Id id, int numPoints) {
Track track = new Track(Statistics.DEFAULT);
track.setId(id);
track.setName("Test: " + id.id());
contentProviderUtils.insertTrack(track);
track = contentProviderUtils.getTrack(id);
TrackBuilder trackbuilder = new TrackBuilder(Statistics.DEFAULT);
trackbuilder.setId(id);
trackbuilder.setName("Test: " + id.id());
contentProviderUtils.insertTrack(trackbuilder.getTrack());
Track track = contentProviderUtils.getTrack(id);
assertNotNull(track);
List<TrackPoint> trackPoints = new ArrayList<>(numPoints);
@@ -196,8 +197,8 @@ public class CustomContentProviderUtilsTest {
when(cursorMock.getString(columnIndex)).thenReturn(name);
Track track = ContentProviderUtils.createTrack(cursorMock);
assertEquals(trackId, track.getId());
assertEquals(name, track.getName());
assertEquals(trackId, track.id());
assertEquals(name, track.name());
}
private void assertCount(int trackCount, int trackPointCount, int markerCount) {
@@ -241,7 +242,7 @@ public class CustomContentProviderUtilsTest {
public void testDeleteAllTracks_withMarkerAndPhoto() throws IOException {
// Insert track, points and marker with photo at first.
Track.Id trackId = new Track.Id(System.currentTimeMillis());
Track track = TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
TestDataUtil.createTrackAndInsert(contentProviderUtils, trackId, 10);
TrackPoint trackPoint = getLastValidTrackPoint(trackId);
Marker marker = TestDataUtil.createMarkerWithPhoto(context, trackId, trackPoint);
@@ -350,7 +351,7 @@ public class CustomContentProviderUtilsTest {
// then
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);
// when / then
assertNotNull(contentProviderUtils.getTrack(track.getUuid()));
assertNotNull(contentProviderUtils.getTrack(track.uuid()));
}
/**
* Tests the method {@link ContentProviderUtils#updateTrack(Track)}
*/
@Test
public void testUpdateTrack() {
// given
Track.Id trackId = new Track.Id(System.currentTimeMillis());
Track track = TestDataUtil.createTrack(trackId);
TrackBuilder track = new TrackBuilder(TestDataUtil.createTrack(trackId));
String nameOld = "name1";
String nameNew = "name2";
track.setName(nameOld);
// when / then
contentProviderUtils.insertTrack(track);
assertEquals(nameOld, contentProviderUtils.getTrack(trackId).getName());
contentProviderUtils.insertTrack(track.getTrack());
assertEquals(nameOld, contentProviderUtils.getTrack(trackId).name());
track.setName(nameNew);
contentProviderUtils.updateTrack(track);
assertEquals(nameNew, contentProviderUtils.getTrack(trackId).getName());
contentProviderUtils.updateTrack(track.getTrack());
assertEquals(nameNew, contentProviderUtils.getTrack(trackId).name());
}
/**
@@ -408,8 +406,10 @@ public class CustomContentProviderUtilsTest {
Track.Id trackId = new Track.Id(System.currentTimeMillis());
Pair<Track, List<TrackPoint>> track = TestDataUtil.createTrack(trackId, 10);
TrackBuilder trackBuilder = new TrackBuilder(track.first);
// AverageSpeed
track.first.setStatistics(new Statistics(
trackBuilder.setStatistics(new Statistics(
Instant.ofEpochMilli(1000),
Instant.ofEpochMilli(2500),
Duration.ofMillis(1500),
@@ -421,7 +421,7 @@ public class CustomContentProviderUtilsTest {
null,
null
));
contentProviderUtils.insertTrack(track.first);
contentProviderUtils.insertTrack(trackBuilder.getTrack());
Marker marker = new Marker(trackId, track.second.get(0));
marker.setDescription(TEST_DESC);
@@ -736,7 +736,7 @@ public class CustomContentProviderUtilsTest {
public void testInsertTrackPoint() {
// Insert track, point at first.
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);
// when
@@ -750,7 +750,7 @@ public class CustomContentProviderUtilsTest {
public void testInsertAndLoadTrackPoint() {
// given
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.setHeartRate(1F);
@@ -776,7 +776,7 @@ public class CustomContentProviderUtilsTest {
contentProviderUtils.insertTrack(track.first);
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();
// when
@@ -794,7 +794,7 @@ public class CustomContentProviderUtilsTest {
contentProviderUtils.insertTrack(track.first);
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();
TrackPoint.Id startTrackPointId = trackpointIds.get(0);
@@ -5,12 +5,15 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
//TODO Merge with TrackFilenameGeneratorTest whenever Junit5 gets available.
//https://github.com/android/android-test/issues/224
@@ -34,9 +37,16 @@ public class TrackFilenameGenerator2Test {
@Test(expected = TrackFilenameGenerator.TemplateInvalidException.class)
public void testFilenameTemplate() {
// given
Track track = new Track(new Statistics(Instant.parse("2020-02-02T02:02:02Z"), null, null, null, null, null, null, null, null, null));
track.setName("Best Track");
track.setUuid(UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6"));
Track track = new Track(
null,
UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6"),
"Berlin",
"",
"",
ActivityType.CYCLING,
ZoneOffset.UTC,
Statistics.DEFAULT
);
// when
subject.format(track, TrackFileFormat.GPX);
@@ -10,6 +10,7 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.Collection;
import java.util.TimeZone;
@@ -19,6 +20,7 @@ import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.TimezoneRule;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
@RunWith(Parameterized.class)
public class TrackFilenameGeneratorTest {
@@ -48,9 +50,16 @@ public class TrackFilenameGeneratorTest {
@Test
public void testFilenameTemplate() {
// given
Track track = new Track(new Statistics(Instant.parse("2020-02-02T02:02:02Z"), null, null, null, null, null, null, null, null, null));
track.setName("Best Track");
track.setUuid(UUID.fromString("0000fee0-0000-1000-8000-00805f9b34fb"));
Track track = new Track(
null,
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
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.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.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
@@ -187,13 +188,12 @@ public class ExportImportTest {
trackPointCreator.setClock("2020-02-02T02:04:00Z");
service.endCurrentTrack();
Track track = contentProviderUtils.getTrack(trackId);
track.setActivityType(TRACK_ACTIVITY_TYPE);
track.setActivityTypeLocalized(TRACK_ACTIVITY_TYPE_LOCALIZED);
track.setDescription(TRACK_DESCRIPTION);
contentProviderUtils.updateTrack(track);
TrackBuilder trackBuilder = new TrackBuilder(contentProviderUtils.getTrack(trackId));
trackBuilder.setActivityType(TRACK_ACTIVITY_TYPE);
trackBuilder.setActivityTypeLocalized(TRACK_ACTIVITY_TYPE_LOCALIZED);
trackBuilder.setDescription(TRACK_DESCRIPTION);
contentProviderUtils.updateTrack(trackBuilder.getTrack());
track = contentProviderUtils.getTrack(trackId);
trackPoints = TestDataUtil.getTrackPoints(contentProviderUtils, trackId);
markers = TestDataUtil.getMarkers(contentProviderUtils, trackId);
}
@@ -204,9 +204,9 @@ public class ExportImportTest {
setUp();
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(
Instant.parse("2020-02-02T02:02:02Z"),
@@ -310,19 +310,19 @@ public class ExportImportTest {
// 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack);
assertEquals(track.getActivityType(), importedTrack.getActivityType());
assertEquals(track.getActivityTypeLocalized(), importedTrack.getActivityTypeLocalized());
assertEquals(track.getDescription(), importedTrack.getDescription());
assertEquals(track.getName(), importedTrack.getName());
assertEquals(track.activityType(), importedTrack.activityType());
assertEquals(track.activityTypeLocalized(), importedTrack.activityTypeLocalized());
assertEquals(track.description(), importedTrack.description());
assertEquals(track.name(), importedTrack.name());
// 2. trackpoints
List<TrackPoint> actual = TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId);
new TrackPointAssert().assertEquals(trackPoints, actual);
// 3. trackstatistics
Statistics importedTrackStatistics = importedTrack.getStatistics();
Statistics importedTrackStatistics = importedTrack.statistics();
assertEquals(track.getZoneOffset(), importedTrack.getZoneOffset());
assertEquals(track.zoneOffset(), importedTrack.zoneOffset());
assertEquals(new Statistics(
Instant.parse("2020-02-02T02:02:02Z"),
Instant.parse("2020-02-02T02:04:00Z"),
@@ -391,10 +391,10 @@ public class ExportImportTest {
// 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack);
assertEquals(track.getActivityType(), importedTrack.getActivityType());
assertEquals(track.getActivityTypeLocalized(), importedTrack.getActivityTypeLocalized());
assertEquals(track.getDescription(), importedTrack.getDescription());
assertEquals(track.getName(), importedTrack.getName());
assertEquals(track.activityType(), importedTrack.activityType());
assertEquals(track.activityTypeLocalized(), importedTrack.activityTypeLocalized());
assertEquals(track.description(), importedTrack.description());
assertEquals(track.name(), importedTrack.name());
// 2. trackpoints
// The GPX exporter does not support exporting TrackPoints without lat/lng.
@@ -452,9 +452,9 @@ public class ExportImportTest {
), actual);
// 3. trackstatistics
assertEquals(track.getZoneOffset(), importedTrack.getZoneOffset());
assertEquals(track.zoneOffset(), importedTrack.zoneOffset());
Statistics importedTrackStatistics = importedTrack.getStatistics();
Statistics importedTrackStatistics = importedTrack.statistics();
assertEquals(new Statistics(
Instant.parse("2020-02-02T02:02:03Z"),
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.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.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
@@ -79,11 +80,11 @@ public class GPXTrackImporterTest {
// 2. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack);
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType());
assertEquals("the category", importedTrack.getActivityTypeLocalized());
assertEquals("the description", importedTrack.getDescription());
assertEquals("2021-01-07 22:51", importedTrack.getName());
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType());
assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
assertEquals("the category", importedTrack.activityTypeLocalized());
assertEquals("the description", importedTrack.description());
assertEquals("2021-01-07 22:51", importedTrack.name());
assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
//TODO Check trackstatistics
@@ -143,13 +144,13 @@ public class GPXTrackImporterTest {
// 2. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack);
assertEquals("", importedTrack.getActivityTypeLocalized());
assertEquals("", importedTrack.getDescription());
assertEquals("20210907_213924.gpx", importedTrack.getName());
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType());
assertEquals("", importedTrack.activityTypeLocalized());
assertEquals("", importedTrack.description());
assertEquals("20210907_213924.gpx", importedTrack.name());
assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
// 3. trackstatistics
Statistics trackStatistics = importedTrack.getStatistics();
Statistics trackStatistics = importedTrack.statistics();
assertEquals(0.75, trackStatistics.maxSpeed().toMPS(), 0.01);
assertEquals(Duration.ofSeconds(101), trackStatistics.movingDuration());
@@ -198,13 +199,13 @@ public class GPXTrackImporterTest {
// 2. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack);
assertEquals("", importedTrack.getActivityTypeLocalized());
assertEquals("", importedTrack.getDescription());
assertEquals("20210907_213924.gpx", importedTrack.getName());
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType());
assertEquals("", importedTrack.activityTypeLocalized());
assertEquals("", importedTrack.description());
assertEquals("20210907_213924.gpx", importedTrack.name());
assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
// 3. trackstatistics
Statistics trackStatistics = importedTrack.getStatistics();
Statistics trackStatistics = importedTrack.statistics();
assertEquals(5.0, trackStatistics.maxSpeed().toMPS(), 0.01);
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.Speed;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
/**
@@ -73,10 +74,10 @@ public class KMLTrackImporterTest {
// 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack);
assertEquals("", importedTrack.getActivityTypeLocalized());
assertEquals("", importedTrack.getDescription());
assertEquals("", importedTrack.getName());
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType());
assertEquals("", importedTrack.activityTypeLocalized());
assertEquals("", importedTrack.description());
assertEquals("", importedTrack.name());
assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
// 2. markers
assertEquals(0, TestDataUtil.getMarkers(contentProviderUtils, importTrackId).size());
@@ -129,10 +130,10 @@ public class KMLTrackImporterTest {
// 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack);
assertEquals("", importedTrack.getActivityTypeLocalized());
assertEquals("", importedTrack.getDescription());
assertEquals("", importedTrack.getName());
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType());
assertEquals("", importedTrack.activityTypeLocalized());
assertEquals("", importedTrack.description());
assertEquals("", importedTrack.name());
assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
// 2. markers
assertEquals(0, TestDataUtil.getMarkers(contentProviderUtils, importTrackId).size());
@@ -170,10 +171,10 @@ public class KMLTrackImporterTest {
// 1. track
Track importedTrack = contentProviderUtils.getTrack(importTrackId);
assertNotNull(importedTrack);
assertEquals("unknown", importedTrack.getActivityTypeLocalized());
assertEquals("Test Track", importedTrack.getDescription());
assertEquals("2020-11-28 18:06", importedTrack.getName());
assertEquals(ActivityType.UNKNOWN, importedTrack.getActivityType());
assertEquals("unknown", importedTrack.activityTypeLocalized());
assertEquals("Test Track", importedTrack.description());
assertEquals("2020-11-28 18:06", importedTrack.name());
assertEquals(ActivityType.UNKNOWN, importedTrack.activityType());
// 2. markers
//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.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.util.IntentUtils;
@@ -49,9 +50,9 @@ public class PublicApiTest {
List<Track> tracks = new ContentProviderUtils(context).getTracks();
Assert.assertEquals(1, tracks.size());
Track track = tracks.get(0);
Assert.assertEquals("trackName", track.getName());
Assert.assertEquals("activityTypeLocalized", track.getActivityTypeLocalized());
Assert.assertEquals("airplane", track.getActivityType().getId());
Assert.assertEquals("trackName", track.name());
Assert.assertEquals("activityTypeLocalized", track.activityTypeLocalized());
Assert.assertEquals("airplane", track.activityType().getId());
}
@Test
@@ -16,12 +16,17 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
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.Distance;
import de.dennisguse.opentracks.data.models.Position;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.settings.UnitSystem;
@@ -53,18 +58,17 @@ public class TrackRecordingServiceNotificationManagerTest {
TrackRecordingServiceNotificationManager subject = new TrackRecordingServiceNotificationManager(notificationManager, notificationCompatBuilder);
subject.setUnitSystem(UnitSystem.METRIC);
Track track = new Track(new Statistics(
Track track = new Track(
null,
null,
null,
null,
Distance.ZERO,
null,
null,
null,
null,
null
));
UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6"),
"Berlin",
"",
"",
ActivityType.CYCLING,
ZoneOffset.UTC,
Statistics.DEFAULT
);
RecordingData data = new RecordingData(track, trackPointMock, null, null);
// when
@@ -33,7 +33,6 @@ import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.TestUtil;
import de.dennisguse.opentracks.content.data.TestDataUtil;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.AltitudeExtremities;
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.HeartRate;
@@ -108,7 +107,7 @@ public class TrackRecordingServiceRecordingTest {
// then
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 TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime))
@@ -122,7 +121,7 @@ public class TrackRecordingServiceRecordingTest {
// 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)
, contentProviderUtils.getTrack(trackId).getStatistics());
, contentProviderUtils.getTrack(trackId).statistics());
new TrackPointAssert().assertEquals(List.of(
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
@@ -197,7 +196,7 @@ public class TrackRecordingServiceRecordingTest {
// 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)
, contentProviderUtils.getTrack(trackId).getStatistics());
, contentProviderUtils.getTrack(trackId).statistics());
new TrackPointAssert().assertEquals(List.of(
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
@@ -212,7 +211,7 @@ public class TrackRecordingServiceRecordingTest {
// 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)
, contentProviderUtils.getTrack(trackId).getStatistics());
, contentProviderUtils.getTrack(trackId).statistics());
new TrackPointAssert().assertEquals(List.of(
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
@@ -340,7 +339,7 @@ public class TrackRecordingServiceRecordingTest {
// 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)
, contentProviderUtils.getTrack(trackId).getStatistics());
, contentProviderUtils.getTrack(trackId).statistics());
// when
String gps2 = "2020-02-02T02:02:06Z";
@@ -348,7 +347,7 @@ public class TrackRecordingServiceRecordingTest {
// 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)
, contentProviderUtils.getTrack(trackId).getStatistics());
, contentProviderUtils.getTrack(trackId).statistics());
// when
String gps3 = "2020-02-02T02:02:08Z";
@@ -356,7 +355,7 @@ public class TrackRecordingServiceRecordingTest {
// 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)
, contentProviderUtils.getTrack(trackId).getStatistics());
, contentProviderUtils.getTrack(trackId).statistics());
// when
String stopTime = "2020-02-02T02:02:12Z";
@@ -365,7 +364,7 @@ public class TrackRecordingServiceRecordingTest {
// 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)
, contentProviderUtils.getTrack(trackId).getStatistics());
, contentProviderUtils.getTrack(trackId).statistics());
new TrackPointAssert().assertEquals(List.of(
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
@@ -414,21 +413,21 @@ public class TrackRecordingServiceRecordingTest {
// 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);
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).getStatistics());
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).statistics());
// when
String gps2 = "2020-02-02T02:02:06Z";
sendGPSLocation(trackPointCreator, gps2, 45.00001, 35.0, 1, 15);
// then
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).getStatistics());
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).statistics());
// when
String gps3 = "2020-02-02T02:02:08Z";
sendGPSLocation(trackPointCreator, gps3, 45.00002, 35.0, 1, 15);
// then
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).getStatistics());
assertEquals(gps1Statistics, contentProviderUtils.getTrack(trackId).statistics());
// when
String stopTime = "2020-02-02T02:02:12Z";
@@ -437,7 +436,7 @@ public class TrackRecordingServiceRecordingTest {
// 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)
, contentProviderUtils.getTrack(trackId).getStatistics());
, contentProviderUtils.getTrack(trackId).statistics());
new TrackPointAssert().assertEquals(List.of(
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(startTime)),
@@ -536,7 +535,7 @@ public class TrackRecordingServiceRecordingTest {
// then
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
@@ -544,7 +543,7 @@ public class TrackRecordingServiceRecordingTest {
sendGPSLocation(trackPointCreator, gps2, 45.1, 35.0, 100, 15);
// then
assertEquals(startStatistics, contentProviderUtils.getTrack(trackId).getStatistics());
assertEquals(startStatistics, contentProviderUtils.getTrack(trackId).statistics());
// when
@@ -554,7 +553,7 @@ public class TrackRecordingServiceRecordingTest {
// 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)
, contentProviderUtils.getTrack(trackId).getStatistics());
, contentProviderUtils.getTrack(trackId).statistics());
// then
new TrackPointAssert().assertEquals(List.of(
@@ -580,7 +579,7 @@ public class TrackRecordingServiceRecordingTest {
// 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)
, contentProviderUtils.getTrack(trackId).getStatistics());
, contentProviderUtils.getTrack(trackId).statistics());
// when
String gps2 = "2020-02-02T02:02:06Z";
@@ -588,7 +587,7 @@ public class TrackRecordingServiceRecordingTest {
// 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)
, contentProviderUtils.getTrack(trackId).getStatistics());
, contentProviderUtils.getTrack(trackId).statistics());
// when
String stopTime = "2020-02-02T02:02:12Z";
@@ -597,7 +596,7 @@ public class TrackRecordingServiceRecordingTest {
// 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)
, contentProviderUtils.getTrack(trackId).getStatistics());
, contentProviderUtils.getTrack(trackId).statistics());
// then
@@ -47,6 +47,7 @@ import java.util.concurrent.TimeoutException;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.sensors.GpsStatusValue;
/**
@@ -20,18 +20,21 @@ import org.mockito.Mockito;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Map;
import de.dennisguse.opentracks.LocaleRule;
import de.dennisguse.opentracks.content.data.TestDataUtil;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -62,18 +65,26 @@ public class VoiceAnnouncementUtilsTest {
@Test
public void getAnnouncement_metric_speed() {
Track track = new Track(new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
Distance.of(20000),
Speed.of(100),
Track track = new Track(
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);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
@@ -87,18 +98,26 @@ public class VoiceAnnouncementUtilsTest {
@Test
public void getAnnouncement_metric_speed_rounding_check() {
Track track = new Track(new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusSeconds(1),
Distance.of(20000),
Speed.of(100),
Track track = new Track(
null,
new AltitudeGainLoss(6000, 6000),
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);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
@@ -112,18 +131,26 @@ public class VoiceAnnouncementUtilsTest {
@Test
public void getAnnouncement_metric_distance_rounding_check() {
Track track = new Track(new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.of(19999),
Speed.of(100),
Track track = new Track(
null,
new AltitudeGainLoss(6000, 6000),
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);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
@@ -137,18 +164,26 @@ public class VoiceAnnouncementUtilsTest {
@Test
public void getAnnouncement_metric_distance_rounding_check_two() {
Track track = new Track(new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.of(19900),
Speed.of(100),
Track track = new Track(
null,
new AltitudeGainLoss(6000, 6000),
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);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
@@ -177,18 +212,26 @@ public class VoiceAnnouncementUtilsTest {
@Test
public void getAnnouncement_metric_pace() {
Track track = new Track(new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
Distance.of(20000),
Speed.of(100),
Track track = new Track(
null,
new AltitudeGainLoss(6000, 6000),
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);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
@@ -217,18 +260,26 @@ public class VoiceAnnouncementUtilsTest {
@Test
public void getAnnouncement_imperial_speed() {
Track track = new Track(new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
Distance.of(20000),
Speed.of(100),
Track track = new Track(
null,
new AltitudeGainLoss(6000, 6000),
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);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
@@ -242,18 +293,26 @@ public class VoiceAnnouncementUtilsTest {
@Test
public void getAnnouncement_imperial_speed_1() {
Track track = new Track(new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.ofMile(1.1),
Track track = new Track(
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);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
@@ -267,18 +326,26 @@ public class VoiceAnnouncementUtilsTest {
@Test
public void getAnnouncement_imperial_meter_speed_1() {
Track track = new Track(new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.ofMile(1.1),
Track track = new Track(
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);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
@@ -292,18 +359,26 @@ public class VoiceAnnouncementUtilsTest {
@Test
public void getAnnouncement_metric_speed_1() {
Track track = new Track(new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1),
Distance.ofKilometer(1.1),
Track track = new Track(
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);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
@@ -332,18 +407,26 @@ public class VoiceAnnouncementUtilsTest {
@Test
public void getAnnouncement_imperial_pace() {
Track track = new Track(new Statistics(
Instant.EPOCH,
Instant.EPOCH,
Duration.ofHours(2).plusMinutes(5).plusSeconds(10),
Duration.ofHours(1).plusMinutes(5).plusSeconds(10),
Distance.of(20000),
Speed.of(100),
Track track = new Track(
null,
new AltitudeGainLoss(6000, 6000),
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);
Mockito.when(dataSet.getHeartRate()).thenReturn(new Pair<>(HeartRate.of(60), "unused"));
@@ -443,18 +526,26 @@ public class VoiceAnnouncementUtilsTest {
intervalStatistics.addTrackPoints(trackPoints.iterator());
Statistics lastInterval = intervalStatistics.getLastInterval();
Track track = new Track(new Statistics(
Instant.EPOCH,
Instant.EPOCH.plusSeconds(999),
Duration.ofMinutes(16).plusSeconds(39),
Duration.ofMinutes(16).plusSeconds(39),
Distance.of(14208),
Speed.of(104),
Track track = new Track(
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);
}
@@ -30,6 +30,7 @@ import java.time.Duration;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Locale;
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.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.util.StringUtils;
/**
@@ -63,19 +65,26 @@ public class TrackShareSummaryGeneratorTest {
@Test
public void testGenerateTrackDescription() {
Track track = new Track(new Statistics(
START_TIME,
START_TIME,
Duration.ofSeconds(600),
Duration.ofSeconds(300),
Distance.of(20000),
Speed.of(100),
new AltitudeExtremities(-500, 550),
new AltitudeGainLoss(6000, 6000),
Track track = new Track(
null,
null
));
track.setActivityTypeLocalized("hiking");
null,
"",
"",
"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"
"OpenTracks (Debug)\n\n"
@@ -13,7 +13,9 @@ import org.junit.runners.JUnit4;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.List;
import java.util.UUID;
import de.dennisguse.opentracks.R;
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.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
@RunWith(JUnit4.class)
public class AggregatedStatisticsTest {
@@ -33,7 +36,15 @@ public class AggregatedStatisticsTest {
private final Context context = ApplicationProvider.getApplicationContext();
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).plus(totalTime),
totalTime,
@@ -45,8 +56,6 @@ public class AggregatedStatisticsTest {
null,
null
));
track.setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
track.setActivityTypeLocalized(activityTypeLocalized);
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.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
@LargeTest
@@ -51,8 +52,9 @@ public class EspressoAggregatedFilterTest {
@Before
public void setUp() {
Pair<Track, List<TrackPoint>> pair = TestDataUtil.createTrack(new Track.Id(System.currentTimeMillis()), 20);
pair.first.setActivityTypeLocalized(CATEGORY);
TestDataUtil.insertTrackWithLocations(new ContentProviderUtils(ApplicationProvider.getApplicationContext()), pair.first, pair.second);
TrackBuilder trackBuilder = new TrackBuilder(pair.first);
trackBuilder.setActivityTypeLocalized(CATEGORY);
TestDataUtil.insertTrackWithLocations(new ContentProviderUtils(ApplicationProvider.getApplicationContext()), trackBuilder.getTrack(), pair.second);
}
@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.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.stats.TrackStatisticsUpdater;
@@ -106,22 +107,22 @@ public class IntervalStatisticsUpdaterTest {
}
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.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
whenAndThen(trackWithStats.first, trackWithStats.second, numberOfPoints, 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);
}
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));
intervalStatistics.addTrackPoints(trackPoints.iterator());
@@ -167,13 +168,13 @@ public class IntervalStatisticsUpdaterTest {
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<>();
for (int i = 0; i < numberOfPoints; i++) {
trackPoints.add(TestDataUtil.createTrackPoint(i));
}
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.models.ActivityType;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.TrackEditBinding;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
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 ContentProviderUtils contentProviderUtils;
private Track track;
private TrackBuilder trackBuilder;
private ActivityType activityType;
private TrackEditBinding viewBinding;
@@ -63,16 +64,17 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
}
contentProviderUtils = new ContentProviderUtils(this);
track = contentProviderUtils.getTrack(trackId);
Track track = contentProviderUtils.getTrack(trackId);
if (track == null) {
Log.e(TAG, "No track for " + trackId.id());
finish();
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));
viewBinding.trackEditActivityTypeLocalized.setAdapter(adapter);
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);
}
if (activityType == null) {
activityType = track.getActivityType();
activityType = trackBuilder.getActivityType();
}
setActivityTypeIcon(activityType);
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);
viewBinding.trackEditTimeOffset.setText(track.getZoneOffset().toString());
viewBinding.trackEditTimeOffset.setText(trackBuilder.getZoneOffset().toString());
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 -> {
track.setName(viewBinding.trackEditName.getText().toString());
track.setDescription(viewBinding.trackEditDescription.getText().toString());
trackBuilder.setName(viewBinding.trackEditName.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();
});
@@ -33,6 +33,7 @@ import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.TrackDataHub;
import de.dennisguse.opentracks.data.models.ActivityType;
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.databinding.TrackRecordingBinding;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
@@ -324,11 +325,11 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
@Override
public void onChooseActivityTypeDone(ActivityType activityType) {
Track track = contentProviderUtils.getTrack(trackId);
TrackBuilder track = new TrackBuilder(contentProviderUtils.getTrack(trackId));
String activityTypeLocalized = getString(activityType.getLocalizedStringId());
track.setActivityTypeLocalizedAndUpdateActivityType(this, activityTypeLocalized);
contentProviderUtils.updateTrack(track);
contentProviderUtils.updateTrack(track.getTrack());
}
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.SpeedFormatter;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.TrackStoppedBinding;
import de.dennisguse.opentracks.fragments.ChooseActivityTypeDialogFragment;
import de.dennisguse.opentracks.io.file.exporter.ExportUtils;
@@ -46,9 +47,9 @@ public class TrackStoppedActivity extends AbstractTrackDeleteActivity implements
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(this);
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));
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.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()
.setUnit(PreferencesUtils.getUnitSystem())
.setReportSpeedOrPace(PreferencesUtils.isReportSpeed(track))
.build(this)
.getSpeedParts(track.getStatistics().getAverageMovingSpeed());
.getSpeedParts(track.statistics().getAverageMovingSpeed());
viewBinding.speed.setText(parts.first);
viewBinding.speedUnit.setText(parts.second);
}
@@ -84,7 +85,7 @@ public class TrackStoppedActivity extends AbstractTrackDeleteActivity implements
Pair<String, String> parts = DistanceFormatter.Builder()
.setUnit(PreferencesUtils.getUnitSystem())
.build(this)
.getDistanceParts(track.getStatistics().totalDistance());
.getDistanceParts(track.statistics().totalDistance());
viewBinding.distance.setText(parts.first);
viewBinding.distanceUnit.setText(parts.second);
}
@@ -104,11 +105,12 @@ public class TrackStoppedActivity extends AbstractTrackDeleteActivity implements
}
private void storeTrackMetaData(ContentProviderUtils contentProviderUtils, Track track) {
track.setName(viewBinding.trackEditName.getText().toString());
track.setDescription(viewBinding.trackEditDescription.getText().toString());
track.setActivityTypeLocalizedAndUpdateActivityType(this, viewBinding.trackEditActivityType.getText().toString());
TrackBuilder trackBuilder = new TrackBuilder(track);
trackBuilder.setName(viewBinding.trackEditName.getText().toString());
trackBuilder.setDescription(viewBinding.trackEditDescription.getText().toString());
trackBuilder.setActivityTypeLocalizedAndUpdateActivityType(this, viewBinding.trackEditActivityType.getText().toString());
contentProviderUtils.updateTrack(track);
contentProviderUtils.updateTrack(trackBuilder.getTrack());
}
@NonNull
@@ -35,6 +35,7 @@ import de.dennisguse.opentracks.data.TrackDataHub;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.databinding.ChartBinding;
import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -174,14 +175,14 @@ public class ChartFragment extends Fragment implements TrackDataHub.Listener {
}
@Override
public void onTrackUpdated(Track track) {
public void onTrackUpdated(@NonNull Track track) {
if (isResumed()) {
if (track == null) {
activityTypeLocalized = "";
return;
}
activityTypeLocalized = track.getActivityTypeLocalized();
activityTypeLocalized = track.activityTypeLocalized();
boolean reportSpeed = PreferencesUtils.isReportSpeed(activityTypeLocalized);
if (reportSpeed != viewBinding.chartView.getReportSpeed()) {
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.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.tables.MarkerColumns;
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
@@ -93,11 +94,6 @@ public class ContentProviderUtils {
this.contentResolver = contentResolver;
}
/**
* Creates a {@link Track} from a cursor.
*
* @param cursor the cursor pointing to the track
*/
public static Track createTrack(Cursor cursor) {
int idIndex = cursor.getColumnIndexOrThrow(TracksColumns._ID);
int uuidIndex = cursor.getColumnIndexOrThrow(TracksColumns.UUID);
@@ -133,7 +129,7 @@ public class ContentProviderUtils {
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.setUuid(UUIDUtils.fromBytes(cursor.getBlob(uuidIndex)));
if (!cursor.isNull(nameIndex)) {
@@ -149,7 +145,7 @@ public class ContentProviderUtils {
track.setActivityTypeLocalized(cursor.getString(activityTypeLocalizedIndex));
}
return track;
return track.getTrack();
}
@VisibleForTesting
@@ -273,23 +269,23 @@ public class ContentProviderUtils {
* @param track the 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) {
ContentValues values = new ContentValues();
if (track.getId() != null) {
values.put(TracksColumns._ID, track.getId().id());
if (track.id() != null) {
values.put(TracksColumns._ID, track.id().id());
}
values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.getUuid()));
values.put(TracksColumns.NAME, track.getName());
values.put(TracksColumns.DESCRIPTION, track.getDescription());
values.put(TracksColumns.ACTIVITY_TYPE, track.getActivityType() != null ? track.getActivityType().getId() : null);
values.put(TracksColumns.ACTIVITY_TYPE_LOCALIZED, track.getActivityTypeLocalized());
values.put(TracksColumns.STARTTIME_OFFSET, track.getZoneOffset().getTotalSeconds());
values.put(TracksColumns.UUID, UUIDUtils.toBytes(track.uuid()));
values.put(TracksColumns.NAME, track.name());
values.put(TracksColumns.DESCRIPTION, track.description());
values.put(TracksColumns.ACTIVITY_TYPE, track.activityType() != null ? track.activityType().getId() : null);
values.put(TracksColumns.ACTIVITY_TYPE_LOCALIZED, track.activityTypeLocalized());
values.put(TracksColumns.STARTTIME_OFFSET, track.zoneOffset().getTotalSeconds());
values.putAll(createContentValues(track.getStatistics()));
values.putAll(createContentValues(track.statistics()));
return values;
}
@@ -9,7 +9,6 @@ import java.util.NoSuchElementException;
import de.dennisguse.opentracks.data.models.Marker;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.util.AutoCloseableIterator;
class MarkerIterator extends AutoCloseableIterator<Marker> {
@@ -27,6 +27,7 @@ import java.util.Set;
import java.util.stream.Collectors;
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.io.file.TrackFileFormat;
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
@@ -19,7 +19,6 @@ package de.dennisguse.opentracks.data;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Handler;
import android.os.HandlerThread;
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.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.tables.MarkerColumns;
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;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
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,
/**
* A track.
*
* @author Leif Hendrik Wilden
* @author Rodrigo Damazio
*/
//TODO Do not default initialize attributes; might be confusing for debugging
public class Track {
@NonNull
String activityTypeLocalized,
@NonNull
ActivityType activityType,
@NonNull
ZoneOffset zoneOffset,
@NonNull
Statistics statistics
) {
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;
@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
public OffsetDateTime startTime() {
return statistics
.startTime().atOffset(zoneOffset);
}
public OffsetDateTime getStopTime() {
return trackStatistics
public OffsetDateTime stopTime() {
return statistics
.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 {
@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.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.StatisticsRecordedBinding;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.settings.UnitSystem;
@@ -42,7 +43,7 @@ import de.dennisguse.opentracks.stats.SensorStatistics;
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 Rodrigo Damazio
@@ -147,7 +148,7 @@ public class StatisticsRecordedFragment extends Fragment {
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;
if (prefsChanged) {
sharedPreferenceChangeListener.onSharedPreferenceChanged(null, getString(R.string.stats_rate_key));
@@ -162,13 +163,13 @@ public class StatisticsRecordedFragment extends Fragment {
}
private void loadTrackDescription(@NonNull Track track) {
viewBinding.statsNameValue.setText(track.getName());
viewBinding.statsDescriptionValue.setText(track.getDescription());
viewBinding.statsStartDatetimeValue.setText(StringUtils.formatDateTimeWithOffsetIfDifferent(track.getStartTime()));
viewBinding.statsNameValue.setText(track.name());
viewBinding.statsDescriptionValue.setText(track.description());
viewBinding.statsStartDatetimeValue.setText(StringUtils.formatDateTimeWithOffsetIfDifferent(track.startTime()));
}
private void updateUI() {
Statistics trackStatistics = track.getStatistics();
Statistics trackStatistics = track.statistics();
// Set total distance
{
Pair<String, String> parts = DistanceFormatter.Builder()
@@ -180,7 +181,7 @@ public class StatisticsRecordedFragment extends Fragment {
}
// 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
{
@@ -15,11 +15,11 @@ import androidx.gridlayout.widget.GridLayout;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Callable;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.StatisticsRecordingBinding;
import de.dennisguse.opentracks.services.RecordingData;
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
@@ -31,7 +31,7 @@ import de.dennisguse.opentracks.viewmodels.Mapping;
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 Rodrigo Damazio
@@ -167,9 +167,9 @@ public class StatisticsRecordingFragment extends Fragment {
private void onRecordingDataChanged(RecordingData recordingData) {
Track oldTrack = this.recordingData.track();
String oldActivityType = oldTrack != null ? oldTrack.getActivityTypeLocalized() : "";
String oldActivityType = oldTrack != null ? oldTrack.activityTypeLocalized() : "";
Track newTrack = recordingData.track();
String newActivityType = newTrack != null ? newTrack.getActivityTypeLocalized() : "";
String newActivityType = newTrack != null ? newTrack.activityTypeLocalized() : "";
this.recordingData = recordingData;
@@ -2,7 +2,6 @@ package de.dennisguse.opentracks.io.file;
import androidx.annotation.NonNull;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashMap;
@@ -12,8 +11,10 @@ import java.util.UUID;
import java.util.regex.Matcher;
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.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.util.FileUtils;
public class TrackFilenameGenerator {
@@ -41,11 +42,11 @@ public class TrackFilenameGenerator {
public String format(@NonNull Track track, @NonNull TrackFileFormat trackFileFormat) {
Map<String, String> values = new HashMap<>();
values.put(UUID_KEY, track.getUuid().toString().substring(0, 8));
values.put(TRACKNAME_KEY, track.getName());
values.put(ACTIVITY_TYPE_KEY, track.getActivityTypeLocalized());
values.put(STARTTIME_TIME_KEY, track.getStartTime().toLocalTime().toString());
values.put(STARTTIME_DATE_KEY, track.getStartTime().toLocalDate().toString());
values.put(UUID_KEY, track.uuid().toString().substring(0, 8));
values.put(TRACKNAME_KEY, track.name());
values.put(ACTIVITY_TYPE_KEY, track.activityTypeLocalized());
values.put(STARTTIME_TIME_KEY, track.startTime().toLocalTime().toString());
values.put(STARTTIME_DATE_KEY, track.stopTime().toLocalDate().toString());
return format(format(template, values), trackFileFormat);
}
@@ -90,9 +91,16 @@ public class TrackFilenameGenerator {
}
public String getExample() {
Track track = new Track(ZoneOffset.UTC, Statistics.DEFAULT);
track.setName("Berlin");
track.setUuid(UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6"));
Track track = new Track(
null,
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);
}
@@ -111,7 +111,7 @@ public class CSVTrackExporter implements TrackExporter {
boolean headerWritten = false;
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) {
writeHeader(columns);
@@ -131,7 +131,7 @@ public class CSVTrackExporter implements TrackExporter {
}
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()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -40,6 +40,7 @@ import de.dennisguse.opentracks.AbstractActivity;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.ExportActivityBinding;
import de.dennisguse.opentracks.io.file.ErrorListDialog;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
@@ -222,9 +223,9 @@ public class ExportActivity extends AbstractActivity {
exportTasks = new ArrayList<>();
if (allInOneFile) {
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 {
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();
}
@@ -362,7 +363,7 @@ public class ExportActivity extends AbstractActivity {
if (exportTask.isMultiExport()) {
name = exportTask.getFilename();
} else {
name = contentProviderUtils.getTrack(exportTask.getTrackIds().get(0)).getName();
name = contentProviderUtils.getTrack(exportTask.getTrackIds().get(0)).name();
}
Log.e(TAG, "Error exporting " + name + ": " + errorMessage);
trackErrors.add(name);
@@ -402,7 +403,7 @@ public class ExportActivity extends AbstractActivity {
if (exportTask.isMultiExport()) {
name = exportTask.getFilename();
} 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));
setConflictVisibility(View.VISIBLE);
@@ -25,6 +25,7 @@ import java.util.List;
import de.dennisguse.opentracks.data.ContentProviderUtils;
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.TrackFilenameGenerator;
import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -17,6 +17,7 @@
package de.dennisguse.opentracks.io.file.exporter;
import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -128,7 +129,7 @@ public class GPXTrackExporter implements TrackExporter {
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()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -152,7 +153,7 @@ public class GPXTrackExporter implements TrackExporter {
writeOpenSegment();
wroteSegment = true;
if (trackPoint.hasLocation()) {
trackDistance = trackDistance.plus(writeTrackPoint(track.getZoneOffset(), trackPoint, sensorPoints, trackDistance));
trackDistance = trackDistance.plus(writeTrackPoint(track.zoneOffset(), trackPoint, sensorPoints, trackDistance));
sensorPoints.clear();
} else {
sensorPoints.add(trackPoint);
@@ -165,7 +166,7 @@ public class GPXTrackExporter implements TrackExporter {
wroteSegment = true;
}
if (trackPoint.hasLocation()) {
trackDistance = trackDistance.plus(writeTrackPoint(track.getZoneOffset(), trackPoint, sensorPoints, trackDistance));
trackDistance = trackDistance.plus(writeTrackPoint(track.zoneOffset(), trackPoint, sensorPoints, trackDistance));
sensorPoints.clear();
} else {
sensorPoints.add(trackPoint);
@@ -238,12 +239,12 @@ public class GPXTrackExporter implements TrackExporter {
}
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()) {
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) {
printWriter.println("<trk>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(track.getDescription()) + "</desc>");
printWriter.println("<type>" + StringUtils.formatCData(track.getActivityType().getId()) + "</type>");
printWriter.println("<name>" + StringUtils.formatCData(track.name()) + "</name>");
printWriter.println("<desc>" + StringUtils.formatCData(track.description()) + "</desc>");
printWriter.println("<type>" + StringUtils.formatCData(track.activityType().getId()) + "</type>");
printWriter.println("<extensions>");
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()) {
printWriter.println("<opentracks:typeTranslated>" + StringUtils.formatCData(track.getActivityTypeLocalized()) + "</opentracks:typeTranslated>");
if (!TextUtils.isEmpty(track.activityTypeLocalized())) {
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:Distance>" + trackStatistics.totalDistance().toM() + "</gpxtrkx:Distance>");
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 {
boolean hasMarkers = false;
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.getId())) {
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.id())) {
while (markerIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -145,7 +145,7 @@ public class KMLTrackExporter implements TrackExporter {
hasMarkers = true;
}
writeMarker(markerIterator.next(), track.getZoneOffset());
writeMarker(markerIterator.next(), track.zoneOffset());
}
}
if (hasMarkers) {
@@ -157,7 +157,7 @@ public class KMLTrackExporter implements TrackExporter {
boolean wroteTrack = 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()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -171,12 +171,12 @@ public class KMLTrackExporter implements TrackExporter {
case SEGMENT_START_MANUAL, SEGMENT_START_AUTOMATIC -> {
if (wroteSegment) writeCloseSegment();
writeOpenSegment();
writeTrackPoint(track.getZoneOffset(), trackPoint);
writeTrackPoint(track.zoneOffset(), trackPoint);
wroteSegment = true;
}
case SEGMENT_END_MANUAL -> {
if (!wroteSegment) writeOpenSegment();
writeTrackPoint(track.getZoneOffset(), trackPoint);
writeTrackPoint(track.zoneOffset(), trackPoint);
writeCloseSegment();
wroteSegment = false;
}
@@ -187,7 +187,7 @@ public class KMLTrackExporter implements TrackExporter {
wroteSegment = true;
}
writeTrackPoint(track.getZoneOffset(), trackPoint);
writeTrackPoint(track.zoneOffset(), trackPoint);
}
default ->
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>");
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>");
writeTrackStyle();
@@ -261,7 +261,7 @@ public class KMLTrackExporter implements TrackExporter {
private void writeBeginMarkers(Track track) {
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>");
}
@@ -291,13 +291,13 @@ public class KMLTrackExporter implements TrackExporter {
private void writeBeginTrack(Track track) {
printWriter.println("<Placemark>");
printWriter.println("<name>" + StringUtils.formatCData(track.getName()) + "</name>");
printWriter.println("<description>" + StringUtils.formatCData(track.getDescription()) + "</description>");
printWriter.println("<opentracks:trackid>" + track.getUuid() + "</opentracks:trackid>");
printWriter.println("<name>" + StringUtils.formatCData(track.name()) + "</name>");
printWriter.println("<description>" + StringUtils.formatCData(track.description()) + "</description>");
printWriter.println("<opentracks:trackid>" + track.uuid() + "</opentracks:trackid>");
printWriter.println("<styleUrl>#" + TRACK_STYLE + "</styleUrl>");
writeActivityType(track.getActivityType());
writeTypeLocalized(track.getActivityTypeLocalized());
writeActivityType(track.activityType());
writeTypeLocalized(track.activityTypeLocalized());
printWriter.println("<MultiTrack>");
printWriter.println("<altitudeMode>absolute</altitudeMode>");
printWriter.println("<interpolate>1</interpolate>");
@@ -17,7 +17,6 @@
package de.dennisguse.opentracks.io.file.exporter;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
@@ -35,6 +34,7 @@ import java.util.zip.ZipOutputStream;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.Marker;
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.util.AutoCloseableIterator;
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 {
for (Track track : tracks) {
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.getId())) {
try (AutoCloseableIterator<Marker> markerIterator = contentProviderUtils.getMarkerIterator(track.id())) {
while (markerIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
Marker marker = markerIterator.next();
if (marker.hasPhoto()) {
Uri uriPhoto = marker.getPhotoUrl();
boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, track.getId(), uriPhoto) != null;
boolean existsPhoto = MarkerUtils.buildInternalPhotoFile(context, track.id(), uriPhoto) != null;
if (existsPhoto) {
addImage(context, zipOutputStream, uriPhoto, marker);
}
@@ -22,6 +22,7 @@ import java.io.OutputStream;
import java.util.List;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
/**
* Track exporting for exporting track to an {@link OutputStream}.
@@ -17,7 +17,6 @@
package de.dennisguse.opentracks.io.file.importer;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
@@ -31,7 +30,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.zip.ZipEntry;
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.Speed;
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.stats.TrackStatisticsUpdater;
import de.dennisguse.opentracks.ui.markers.MarkerUtils;
@@ -146,12 +147,16 @@ public class TrackImporter {
adjustTrackPoints();
TrackStatisticsUpdater updater = new TrackStatisticsUpdater(trackPoints);
Track track = new Track(trackData.zoneOffset, updater.getTrackStatistics());
track.setName(trackData.name);
track.setUuid(trackData.uuid);
track.setDescription(trackData.description);
track.setActivityType(trackData.activityType);
track.setActivityTypeLocalized(trackData.activityTypeLocalized);
Track track = new Track(
null,
trackData.uuid,
trackData.name,
trackData.description,
trackData.activityTypeLocalized,
trackData.activityType,
trackData.zoneOffset,
updater.getTrackStatistics()
);
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.models.ActivityType;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.services.TrackRecordingService;
import de.dennisguse.opentracks.settings.PreferencesUtils;
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) {
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.setDescription(bundle.getString(EXTRA_TRACK_DESCRIPTION, ""));
track.setActivityType(ActivityType.findBy(bundle.getString(EXTRA_TRACK_ACTIVITY_TYPE_ID, null)));
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) {
@@ -11,7 +11,7 @@ public class StopRecording extends AbstractAPIActivity {
RecordingData recordingData = service.getRecordingDataObservable().getValue();
Track.Id trackId = null;
if (recordingData != null && recordingData.track() != null) {
trackId = recordingData.track().getId();
trackId = recordingData.track().id();
}
service.endCurrentTrack();
@@ -1,14 +1,12 @@
package de.dennisguse.opentracks.services;
import androidx.annotation.NonNull;
import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
/**
* {@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(
Track track,
@@ -19,6 +17,6 @@ public record RecordingData(
public static final RecordingData NOT_RECORDING = new RecordingData(null, null, null, null);
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.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.sensors.sensorData.SensorDataSet;
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());
trackStatisticsUpdater = new TrackStatisticsUpdater(segmentStartTrackPoint);
Track track = new Track(zoneOffset, trackStatisticsUpdater.getTrackStatistics());
TrackBuilder track = new TrackBuilder(zoneOffset, trackStatisticsUpdater.getTrackStatistics());
String activityTypeLocalized = PreferencesUtils.getDefaultActivityTypeLocalized();
track.setActivityTypeLocalized(activityTypeLocalized);
track.setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
track.setName(TrackNameUtils.getTrackName(context, trackId, track.getStartTime()));
trackId = contentProviderUtils.insertTrack(track);
trackId = contentProviderUtils.insertTrack(track.getTrack());
onNewTrackPoint(segmentStartTrackPoint);
@@ -96,7 +97,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
return false;
}
trackStatisticsUpdater = new TrackStatisticsUpdater(track.getStatistics());
trackStatisticsUpdater = new TrackStatisticsUpdater(track.statistics());
onNewTrackPoint(trackPointCreator.createSegmentStartManual());
reset();
@@ -127,9 +128,10 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
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)
@@ -149,12 +149,12 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
}
//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);
Statistics lastInterval = intervalStatistics.getLastInterval();
SensorStatistics sensorStatistics = null;
if (data.track().getId() != null) {
sensorStatistics = contentProviderUtils.getSensorStats(data.track().getId());
if (data.track().id() != null) {
sensorStatistics = contentProviderUtils.getSensorStats(data.track().id());
}
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.Statistics;
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.settings.UnitSystem;
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) {
Statistics trackStatistics = track.getStatistics();
Statistics trackStatistics = track.statistics();
SpannableStringBuilder builder = new SpannableStringBuilder();
if (shouldVoiceAnnounceTime()) {
appendTime(builder, track.getStopTime());
appendTime(builder, track.stopTime());
}
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.HeartRateZones;
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.TrackFilenameGenerator;
import de.dennisguse.opentracks.sensors.SensorType;
@@ -252,7 +253,7 @@ public class PreferencesUtils {
}
public static boolean isReportSpeed(Track track) {
return isReportSpeed(track.getActivityTypeLocalized());
return isReportSpeed(track.activityTypeLocalized());
}
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.models.Marker;
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.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.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.settings.UnitSystem;
import de.dennisguse.opentracks.util.StringUtils;
@@ -62,10 +63,10 @@ public class TrackShareSummaryGenerator {
builder.append(TEXT_LINE_BREAK);
builder.append(TEXT_LINE_BREAK);
writeString(track.getName(), builder, R.string.generic_name_line);
writeString(track.getActivityTypeLocalized(), builder, R.string.description_activity_type);
writeString(track.getDescription(), builder, R.string.generic_description_line);
builder.append(generateTrackStatisticsDescription(track.getStatistics()));
writeString(track.name(), builder, R.string.generic_name_line);
writeString(track.activityTypeLocalized(), builder, R.string.description_activity_type);
writeString(track.description(), builder, R.string.generic_description_line);
builder.append(generateTrackStatisticsDescription(track.statistics()));
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.Speed;
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;
/**
* Statistical data about a {@link Track}.
* Statistical data about a {@link TrackBuilder}.
* The data in this class should be filled out by {@link TrackStatisticsUpdater}.
*
* @author Rodrigo Damazio
@@ -18,6 +18,7 @@ import java.util.Optional;
import java.util.concurrent.Callable;
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.AltitudeGainLoss;
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.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.databinding.CustomStatsItemBinding;
import de.dennisguse.opentracks.services.RecordingData;
@@ -54,7 +56,16 @@ public class SettingsCustomLayoutEditAdapter extends RecyclerView.Adapter<Recycl
null,
null
);
Track track = new Track(ZoneOffset.UTC, statistics);
Track track = new Track(
null,
null,
"",
"",
"",
ActivityType.AIRPLANE,
ZoneOffset.UTC,
statistics);
Position position = new Position(
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.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackBuilder;
import de.dennisguse.opentracks.databinding.IntervalListViewBinding;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.settings.UnitSystem;
@@ -192,7 +192,7 @@ public class MarkerListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
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);
}