Track is now a record.

Create Track directly.
This commit is contained in:
Dennis Guse
2025-11-27 20:34:51 +01:00
parent 21404fed50
commit 12d1a50995
6 changed files with 65 additions and 101 deletions
@@ -7,10 +7,13 @@ import android.util.Pair;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneOffset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Altitude; import de.dennisguse.opentracks.data.models.Altitude;
import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Marker; import de.dennisguse.opentracks.data.models.Marker;
@@ -36,11 +39,15 @@ public class TestDataUtil {
* Create a track without any trackPoints. * Create a track without any trackPoints.
*/ */
public static Track createTrack(Track.Id trackId) { public static Track createTrack(Track.Id trackId) {
TrackBuilder track = new TrackBuilder(Statistics.DEFAULT); return new Track(
track.setId(trackId); trackId,
track.setName("Test: " + trackId.id()); UUID.randomUUID(),
"Test: " + trackId.id(),
return track.getTrack(); "",
"",
ActivityType.UNKNOWN,
ZoneOffset.UTC,
Statistics.DEFAULT);
} }
/** /**
@@ -42,6 +42,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -50,6 +51,7 @@ import java.util.UUID;
import de.dennisguse.opentracks.content.data.TestDataUtil; import de.dennisguse.opentracks.content.data.TestDataUtil;
import de.dennisguse.opentracks.content.data.TestSensorDataUtil; import de.dennisguse.opentracks.content.data.TestSensorDataUtil;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Altitude; import de.dennisguse.opentracks.data.models.Altitude;
import de.dennisguse.opentracks.data.models.AltitudeExtremities; import de.dennisguse.opentracks.data.models.AltitudeExtremities;
import de.dennisguse.opentracks.data.models.AltitudeGainLoss; import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
@@ -130,10 +132,17 @@ public class CustomContentProviderUtilsTest {
} }
private TrackPoint.Id initializeTrack(Track.Id id, int numPoints) { private TrackPoint.Id initializeTrack(Track.Id id, int numPoints) {
TrackBuilder trackbuilder = new TrackBuilder(Statistics.DEFAULT); Track createdTrack = new Track(
trackbuilder.setId(id); id,
trackbuilder.setName("Test: " + id.id()); UUID.randomUUID(),
contentProviderUtils.insertTrack(trackbuilder.getTrack()); "Test: " + id,
"",
"",
ActivityType.UNKNOWN,
ZoneOffset.UTC,
Statistics.DEFAULT);
contentProviderUtils.insertTrack(createdTrack);
Track track = contentProviderUtils.getTrack(id); Track track = contentProviderUtils.getTrack(id);
assertNotNull(track); assertNotNull(track);
@@ -9,10 +9,12 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.JUnit4; import org.junit.runners.JUnit4;
import java.time.ZoneOffset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import de.dennisguse.opentracks.content.data.TestDataUtil; import de.dennisguse.opentracks.content.data.TestDataUtil;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Statistics; import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.Track;
@@ -103,26 +105,34 @@ public class IntervalStatisticsUpdaterTest {
ArrayList<TrackPoint> trackPoints = new ArrayList<>(); ArrayList<TrackPoint> trackPoints = new ArrayList<>();
for (int i = 0; i < numberOfPoints; i++) { for (int i = 0; i < numberOfPoints; i++) {
trackPoints.add(TestDataUtil.createTrackPoint(i).setAltitudeGainLoss(null)); trackPoints.add(TestDataUtil.createTrackPoint(i)
.setAltitudeGainLoss(null));
} }
TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoints); TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoints);
TrackBuilder dummyTrack = new TrackBuilder(trackStatisticsUpdater.getTrackStatistics()); Track dummyTrack = new Track(
dummyTrack.setId(new Track.Id(System.currentTimeMillis())); new Track.Id(System.currentTimeMillis()),
dummyTrack.setName("Dummy Track Without Elevation Loss"); null,
"Dummy Track Without Elevation Loss",
null,
"",
null,
ZoneOffset.UTC,
trackStatisticsUpdater.getTrackStatistics()
);
Pair<TrackBuilder, List<TrackPoint>> trackWithStats = new Pair<>(dummyTrack, trackPoints); Pair<Track, List<TrackPoint>> trackWithStats = new Pair<>(dummyTrack, trackPoints);
// when and then // when and then
whenAndThen(trackWithStats.first, trackWithStats.second, numberOfPoints, distanceInterval); whenAndThen(trackWithStats.first, trackWithStats.second, numberOfPoints, distanceInterval);
} }
private void whenAndThen(int numberOfPoints, float distanceInterval) { private void whenAndThen(int numberOfPoints, float distanceInterval) {
Pair<TrackBuilder, List<TrackPoint>> trackWithStats = buildTrackWithTrackPoints(numberOfPoints); Pair<Track, List<TrackPoint>> trackWithStats = buildTrackWithTrackPoints(numberOfPoints);
whenAndThen(trackWithStats.first, trackWithStats.second, numberOfPoints, distanceInterval); whenAndThen(trackWithStats.first, trackWithStats.second, numberOfPoints, distanceInterval);
} }
private void whenAndThen(TrackBuilder track, List<TrackPoint> trackPoints, int numberOfPoints, float distanceInterval) { private void whenAndThen(Track track, List<TrackPoint> trackPoints, int numberOfPoints, float distanceInterval) {
IntervalStatisticsUpdater intervalStatistics = new IntervalStatisticsUpdater(Distance.of(distanceInterval)); IntervalStatisticsUpdater intervalStatistics = new IntervalStatisticsUpdater(Distance.of(distanceInterval));
intervalStatistics.addTrackPoints(trackPoints.iterator()); intervalStatistics.addTrackPoints(trackPoints.iterator());
@@ -150,9 +160,9 @@ public class IntervalStatisticsUpdaterTest {
} }
// then // then
assertEquals(track.getStatistics().totalDuration().toSeconds(), totalTime, 0.01); assertEquals(track.statistics().totalDuration().toSeconds(), totalTime, 0.01);
assertEquals(track.getStatistics().totalDistance().toM(), totalDistance.toM(), 0.01); assertEquals(track.statistics().totalDistance().toM(), totalDistance.toM(), 0.01);
assertEquals(intervalList.size(), (int) Math.ceil(track.getStatistics().totalDistance().toM() / distanceInterval)); assertEquals(intervalList.size(), (int) Math.ceil(track.statistics().totalDistance().toM() / distanceInterval));
if (totalGain != null && totalLoss != null) { if (totalGain != null && totalLoss != null) {
assertEquals(totalGain, numberOfPoints * TestDataUtil.ALTITUDE_GAIN, 0.1); assertEquals(totalGain, numberOfPoints * TestDataUtil.ALTITUDE_GAIN, 0.1);
assertEquals(totalLoss, numberOfPoints * TestDataUtil.ALTITUDE_LOSS, 0.1); assertEquals(totalLoss, numberOfPoints * TestDataUtil.ALTITUDE_LOSS, 0.1);
@@ -168,13 +178,23 @@ public class IntervalStatisticsUpdaterTest {
assertEquals(intervalList.get(intervalList.size() - 1).totalDistance().toM(), totalDistance.toM(), 0.01); assertEquals(intervalList.get(intervalList.size() - 1).totalDistance().toM(), totalDistance.toM(), 0.01);
} }
private static Pair<TrackBuilder, List<TrackPoint>> buildTrackWithTrackPoints(int numberOfPoints) { private static Pair<Track, List<TrackPoint>> buildTrackWithTrackPoints(int numberOfPoints) {
ArrayList<TrackPoint> trackPoints = new ArrayList<>(); ArrayList<TrackPoint> trackPoints = new ArrayList<>();
for (int i = 0; i < numberOfPoints; i++) { for (int i = 0; i < numberOfPoints; i++) {
trackPoints.add(TestDataUtil.createTrackPoint(i)); trackPoints.add(TestDataUtil.createTrackPoint(i));
} }
TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoints); TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoints);
return new Pair<>(new TrackBuilder(trackStatisticsUpdater.getTrackStatistics()), trackPoints); Track track = new Track(
null,
null,
"",
"",
"",
ActivityType.UNKNOWN,
ZoneOffset.UTC,
trackStatisticsUpdater.getTrackStatistics());
return new Pair<>(track, trackPoints);
} }
} }
@@ -72,9 +72,9 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
} }
trackBuilder = new TrackBuilder(track); trackBuilder = new TrackBuilder(track);
viewBinding.trackEditName.setText(trackBuilder.getName()); viewBinding.trackEditName.setText(track.name());
viewBinding.trackEditActivityTypeLocalized.setText(trackBuilder.getActivityTypeLocalized()); viewBinding.trackEditActivityTypeLocalized.setText(track.activityTypeLocalized());
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, ActivityType.getLocalizedStrings(this)); ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, ActivityType.getLocalizedStrings(this));
viewBinding.trackEditActivityTypeLocalized.setAdapter(adapter); viewBinding.trackEditActivityTypeLocalized.setAdapter(adapter);
viewBinding.trackEditActivityTypeLocalized.setOnItemClickListener((parent, view, position, id) -> { viewBinding.trackEditActivityTypeLocalized.setOnItemClickListener((parent, view, position, id) -> {
@@ -93,15 +93,15 @@ public class TrackEditActivity extends AbstractActivity implements ChooseActivit
activityType = (ActivityType) bundle.getSerializable(ICON_VALUE_KEY); activityType = (ActivityType) bundle.getSerializable(ICON_VALUE_KEY);
} }
if (activityType == null) { if (activityType == null) {
activityType = trackBuilder.getActivityType(); activityType = track.activityType();
} }
setActivityTypeIcon(activityType); setActivityTypeIcon(activityType);
viewBinding.trackEditActivityTypeIcon.setOnClickListener(v -> ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), this, viewBinding.trackEditActivityTypeLocalized.getText().toString())); viewBinding.trackEditActivityTypeIcon.setOnClickListener(v -> ChooseActivityTypeDialogFragment.showDialog(getSupportFragmentManager(), this, viewBinding.trackEditActivityTypeLocalized.getText().toString()));
viewBinding.trackEditDescription.setText(trackBuilder.getDescription()); viewBinding.trackEditDescription.setText(track.description());
final ArrayAdapter<ZoneOffset> zoneOffsetAdapter = new ZoneOffsetAdapter(this, android.R.layout.simple_dropdown_item_1line); final ArrayAdapter<ZoneOffset> zoneOffsetAdapter = new ZoneOffsetAdapter(this, android.R.layout.simple_dropdown_item_1line);
viewBinding.trackEditTimeOffset.setText(trackBuilder.getZoneOffset().toString()); viewBinding.trackEditTimeOffset.setText(track.zoneOffset().toString());
viewBinding.trackEditTimeOffset.setAdapter(zoneOffsetAdapter); viewBinding.trackEditTimeOffset.setAdapter(zoneOffsetAdapter);
viewBinding.trackEditTimeOffset.setOnItemClickListener((parent, view, position, id) -> trackBuilder.setZoneOffset(zoneOffsetAdapter.getItem(position))); viewBinding.trackEditTimeOffset.setOnItemClickListener((parent, view, position, id) -> trackBuilder.setZoneOffset(zoneOffsetAdapter.getItem(position)));
@@ -251,6 +251,7 @@ public class ContentProviderUtils {
* @return the content provider URI of the inserted track. * @return the content provider URI of the inserted track.
*/ */
public Track.Id insertTrack(Track track) { public Track.Id insertTrack(Track track) {
//TODO Unset trackId
Uri uri = contentResolver.insert(TracksColumns.CONTENT_URI, createContentValues(track)); Uri uri = contentResolver.insert(TracksColumns.CONTENT_URI, createContentValues(track));
return new Track.Id(ContentUris.parseId(uri)); return new Track.Id(ContentUris.parseId(uri));
} }
@@ -50,13 +50,6 @@ public class TrackBuilder {
@NonNull @NonNull
private Statistics trackStatistics; private Statistics trackStatistics;
@Deprecated
@VisibleForTesting
public TrackBuilder(@NonNull Statistics trackStatistics) {
this.zoneOffset = ZoneOffset.UTC;
this.trackStatistics = trackStatistics;
}
public TrackBuilder(Track track) { public TrackBuilder(Track track) {
this.id = track.id(); this.id = track.id();
this.uuid = track.uuid(); this.uuid = track.uuid();
@@ -68,60 +61,23 @@ public class TrackBuilder {
this.trackStatistics = track.statistics(); this.trackStatistics = track.statistics();
} }
/** @VisibleForTesting
* 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) { public void setId(Track.Id id) {
this.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) { public void setName(String name) {
this.name = name; this.name = name;
} }
@Deprecated
public String getDescription() {
return description;
}
public void setDescription(String description) { public void setDescription(String description) {
this.description = description; this.description = description;
} }
@Deprecated
public String getActivityTypeLocalized() {
return activityTypeLocalized;
}
public void setActivityTypeLocalized(String activityTypeLocalized) { public void setActivityTypeLocalized(String activityTypeLocalized) {
this.activityTypeLocalized = activityTypeLocalized; this.activityTypeLocalized = activityTypeLocalized;
} }
@Deprecated
public ActivityType getActivityType() {
return activityType;
}
public void setActivityType(ActivityType activityType) { public void setActivityType(ActivityType activityType) {
this.activityType = activityType; this.activityType = activityType;
} }
@@ -131,27 +87,10 @@ public class TrackBuilder {
setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized)); setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
} }
@Deprecated
public ZoneOffset getZoneOffset() {
return zoneOffset;
}
public void setZoneOffset(@NonNull ZoneOffset zoneOffset) { public void setZoneOffset(@NonNull ZoneOffset zoneOffset) {
this.zoneOffset = zoneOffset; this.zoneOffset = zoneOffset;
} }
@Deprecated
public OffsetDateTime getStartTime() {
return trackStatistics
.startTime().atOffset(zoneOffset);
}
@Deprecated
public OffsetDateTime getStopTime() {
return trackStatistics
.stopTime().atOffset(zoneOffset);
}
@Deprecated @Deprecated
public Statistics getStatistics() { public Statistics getStatistics() {
return trackStatistics; return trackStatistics;
@@ -173,16 +112,4 @@ public class TrackBuilder {
trackStatistics trackStatistics
); );
} }
@NonNull
@Override
public String toString() {
return "Track{" +
"name='" + name + '\'' +
", description='" + description + '\'' +
", activityTypeLocalized='" + activityTypeLocalized + '\'' +
", activityType=" + activityType +
'}';
}
} }