diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementManagerTest.java b/src/androidTest/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementManagerTest.java index 59e0de1a5..3d8690caa 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementManagerTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementManagerTest.java @@ -55,13 +55,32 @@ public class VoiceAnnouncementManagerTest { voiceAnnouncementManager.setFrequency(Distance.ofKilometer(5)); // when - SegmentStatisticUpdater statistics = new SegmentStatisticUpdater(); - statistics.setTotalDistance(Distance.ofKilometer(13)); - voiceAnnouncementManager.start(statistics.getStatistics()); + voiceAnnouncementManager.start(new Statistics( + null, + null, + Duration.ofSeconds(91), + Duration.ZERO, + Distance.ofKilometer(13), + null, + null, + null, + null, + null + )); assertEquals(Distance.of(15000), voiceAnnouncementManager.getNextTotalDistance()); - statistics.setTotalDistance(Distance.of(15100)); - voiceAnnouncementManager.start(statistics.getStatistics()); + voiceAnnouncementManager.start(new Statistics( + null, + null, + Duration.ofSeconds(91), + Duration.ZERO, + Distance.of(15000), + null, + null, + null, + null, + null + )); assertEquals(Distance.of(20000), voiceAnnouncementManager.getNextTotalDistance()); } diff --git a/src/androidTest/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdaterTest.java b/src/androidTest/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdaterTest.java index 2d07bb4df..e74b68255 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdaterTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdaterTest.java @@ -29,30 +29,6 @@ import de.dennisguse.opentracks.data.models.TrackPoint; @RunWith(AndroidJUnit4.class) public class TrackStatisticsUpdaterTest { - @Deprecated //TODO SegmentStatisticsUpdater should always have data, right? - @Test - public void empty() { - // when - TrackStatisticsUpdater subject = new TrackStatisticsUpdater(); - - // then - assertEquals( - new Statistics( - null, - null, - Duration.ZERO, - Duration.ZERO, - Distance.ZERO, - Speed.ZERO, - null, - null, - null, - null - ), - subject.getTrackStatistics() - ); - } - @Test public void startTime() { // given @@ -60,11 +36,8 @@ public class TrackStatisticsUpdaterTest { TrackPoint tp = new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, startTime); // when - TrackStatisticsUpdater subject = new TrackStatisticsUpdater(); + TrackStatisticsUpdater subject = new TrackStatisticsUpdater(tp); - subject.addTrackPoint(tp); - - // then // then assertEquals( new Statistics( @@ -89,8 +62,7 @@ public class TrackStatisticsUpdaterTest { TestDataUtil.TrackData data = TestDataUtil.createTestingTrack(new Track.Id(1)); // when - TrackStatisticsUpdater subject = new TrackStatisticsUpdater(); - data.trackPoints().forEach(subject::addTrackPoint); + TrackStatisticsUpdater subject = new TrackStatisticsUpdater(data.trackPoints()); // then Statistics result = subject.getTrackStatistics(); @@ -114,17 +86,13 @@ public class TrackStatisticsUpdaterTest { @Test public void addTrackPoint_distance_from_GPS_moving() { // given - TrackStatisticsUpdater subject = new TrackStatisticsUpdater(); - TrackPoint tp1 = new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.ofEpochMilli(1000)); TrackPoint tp2 = createTrackPoint(0, 0, Altitude.WGS84.of(5.0), Instant.ofEpochMilli(2000)); TrackPoint tp3 = createTrackPoint(0.00001, 0, Altitude.WGS84.of(5.0), Instant.ofEpochMilli(3000)); tp3.setSpeed(Speed.of(5f)); // when - subject.addTrackPoint(tp1); - subject.addTrackPoint(tp2); - subject.addTrackPoint(tp3); + TrackStatisticsUpdater subject = new TrackStatisticsUpdater(List.of(tp1, tp2, tp3)); // then assertEquals(Distance.of(1.1057428121566772), subject.getTrackStatistics().totalDistance()); @@ -133,8 +101,6 @@ public class TrackStatisticsUpdaterTest { @Test public void addTrackPoint_distance_from_GPS_moving_and_sensor_moving() { // given - TrackStatisticsUpdater subject = new TrackStatisticsUpdater(); - TrackPoint tp1 = new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.ofEpochMilli(1000)); TrackPoint tp2 = createTrackPoint(0, 0, Altitude.WGS84.of(5.0), Instant.ofEpochMilli(2000)); tp2.setSpeed(Speed.of(5f)); @@ -147,9 +113,7 @@ public class TrackStatisticsUpdaterTest { tp5.setSensorDistance(Distance.of(10f)); // when - subject.addTrackPoint(tp1); - subject.addTrackPoint(tp2); - subject.addTrackPoint(tp3); + TrackStatisticsUpdater subject = new TrackStatisticsUpdater(List.of(tp1, tp2, tp3)); // then assertEquals(Distance.of(110.57427215576172), subject.getTrackStatistics().totalDistance()); @@ -165,8 +129,6 @@ public class TrackStatisticsUpdaterTest { @Test public void addTrackPoint_distance_from_GPS_moving_and_sensor_disconnecting() { // given - TrackStatisticsUpdater subject = new TrackStatisticsUpdater(); - TrackPoint tp1 = new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.ofEpochMilli(1000)); TrackPoint tp2 = createTrackPoint(0, 0, Altitude.WGS84.of(5.0), Instant.ofEpochMilli(2000)); tp2.setSpeed(Speed.of(5f)); @@ -178,9 +140,7 @@ public class TrackStatisticsUpdaterTest { TrackPoint tp5 = new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.ofEpochMilli(5000)); // when - subject.addTrackPoint(tp1); - subject.addTrackPoint(tp2); - subject.addTrackPoint(tp3); + TrackStatisticsUpdater subject = new TrackStatisticsUpdater(List.of(tp1, tp2, tp3)); // then assertEquals(Distance.of(5), subject.getTrackStatistics().totalDistance()); @@ -195,10 +155,7 @@ public class TrackStatisticsUpdaterTest { @Test public void addTrackPoint_maxSpeed_multiple_segments() { - TrackStatisticsUpdater subject = new TrackStatisticsUpdater(); - assertEquals(Speed.of(0), subject.getTrackStatistics().maxSpeed()); - - subject.addTrackPoints(List.of( + TrackStatisticsUpdater subject = new TrackStatisticsUpdater(List.of( new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.ofEpochSecond(0)), createTrackPoint(0, 0, Altitude.WGS84.of(0), Instant.ofEpochSecond(1)) .setSpeed(Speed.of(2f)), @@ -224,10 +181,8 @@ public class TrackStatisticsUpdaterTest { @Test public void addTrackPoint_idle_withoutDistance() { - TrackStatisticsUpdater subject = new TrackStatisticsUpdater(); - // when - subject.addTrackPoints(List.of( + TrackStatisticsUpdater subject = new TrackStatisticsUpdater(List.of( new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.ofEpochSecond(0)), createTrackPoint(0, 0, Altitude.WGS84.of(0), Instant.ofEpochSecond(1)) .setSpeed(Speed.of(2f)), @@ -251,10 +206,8 @@ public class TrackStatisticsUpdaterTest { @Test public void addTrackPoint_idle_withDistance() { - TrackStatisticsUpdater subject = new TrackStatisticsUpdater(); - // when - subject.addTrackPoints(List.of( + TrackStatisticsUpdater subject = new TrackStatisticsUpdater(List.of( new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.ofEpochSecond(0)), createTrackPoint(0, 0, Altitude.WGS84.of(0), Instant.ofEpochSecond(1)) .setSensorDistance(Distance.of(10)), @@ -283,10 +236,8 @@ public class TrackStatisticsUpdaterTest { @Test public void addTrackPoint_idle_remain_idle() { - TrackStatisticsUpdater subject = new TrackStatisticsUpdater(); - // when - subject.addTrackPoint(new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.ofEpochSecond(0))); + TrackStatisticsUpdater subject = new TrackStatisticsUpdater(new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.ofEpochSecond(0))); subject.addTrackPoint( createTrackPoint(0, 0, Altitude.WGS84.of(0), Instant.ofEpochSecond(10)) .setSensorDistance(Distance.of(10))); @@ -341,8 +292,6 @@ public class TrackStatisticsUpdaterTest { @Test public void copy_constructor() { // given - TrackStatisticsUpdater subject = new TrackStatisticsUpdater(); - TrackPoint tp1 = new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.ofEpochMilli(1000)); TrackPoint tp2 = createTrackPoint(0, 0, Altitude.WGS84.of(5.0), Instant.ofEpochMilli(2000)); tp2.setSpeed(Speed.of(5f)); @@ -352,10 +301,7 @@ public class TrackStatisticsUpdaterTest { tp4.setSpeed(Speed.of(5f)); TrackPoint tp5 = new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.ofEpochMilli(5000)); - subject.addTrackPoint(tp1); - subject.addTrackPoint(tp2); - subject.addTrackPoint(tp3); - subject.addTrackPoint(tp4); + TrackStatisticsUpdater subject = new TrackStatisticsUpdater(List.of(tp1, tp2,tp3, tp4)); // when TrackStatisticsUpdater copy = new TrackStatisticsUpdater(subject); diff --git a/src/androidTest/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsUpdaterTest.java b/src/androidTest/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsUpdaterTest.java index 4e4d527d2..77b75eaf1 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsUpdaterTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsUpdaterTest.java @@ -99,13 +99,12 @@ public class IntervalStatisticsUpdaterTest { // given float distanceInterval = 1000f; int numberOfPoints = 10000; - TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(); ArrayList trackPoints = new ArrayList<>(); for (int i = 0; i < numberOfPoints; i++) { trackPoints.add(TestDataUtil.createTrackPoint(i).setAltitudeGainLoss(null)); } - trackStatisticsUpdater.addTrackPoints(trackPoints); + TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoints); Track dummyTrack = new Track(trackStatisticsUpdater.getTrackStatistics()); dummyTrack.setId(new Track.Id(System.currentTimeMillis())); @@ -169,13 +168,11 @@ public class IntervalStatisticsUpdaterTest { } private static Pair> buildTrackWithTrackPoints(int numberOfPoints) { - TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(); - ArrayList trackPoints = new ArrayList<>(); for (int i = 0; i < numberOfPoints; i++) { trackPoints.add(TestDataUtil.createTrackPoint(i)); } - trackStatisticsUpdater.addTrackPoints(trackPoints); + TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoints); return new Pair<>(new Track(trackStatisticsUpdater.getTrackStatistics()), trackPoints); } diff --git a/src/main/java/de/dennisguse/opentracks/data/TrackDataHub.java b/src/main/java/de/dennisguse/opentracks/data/TrackDataHub.java index db169f62b..59716488c 100644 --- a/src/main/java/de/dennisguse/opentracks/data/TrackDataHub.java +++ b/src/main/java/de/dennisguse/opentracks/data/TrackDataHub.java @@ -334,8 +334,6 @@ public class TrackDataHub { try (AutoCloseableIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(selectedTrackId, next)) { while (trackPointIterator.hasNext()) { - //Prevents a NPE if stop() is happening while notifyTrackPointsTableUpdate() - TrackStatisticsUpdater currentUpdater = trackStatisticsUpdater; if (!isStarted()) { return; @@ -360,7 +358,14 @@ public class TrackDataHub { samplingFrequency = 1 + (int) (numTotalPoints / targetNumPoints); } - currentUpdater.addTrackPoint(trackPoint); + //Prevents a NPE if stop() is happening while notifyTrackPointsTableUpdate() + //TODO Check if this NPE is still happening (and if so, fix it properly. Not with currentUpdater. + if (trackStatisticsUpdater == null) { + trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoint); + } else { + trackStatisticsUpdater.addTrackPoint(trackPoint); + } + TrackStatisticsUpdater currentUpdater = trackStatisticsUpdater; // Also include the last point if the selected track is not recording. if ((localNumLoadedTrackPoints % samplingFrequency == 0) || (trackPointId == lastTrackPointId && !isSelectedTrackRecording())) { @@ -391,7 +396,6 @@ public class TrackDataHub { } - /** * Resets the track points sampling states. */ @@ -399,7 +403,7 @@ public class TrackDataHub { numLoadedPoints = 0; firstSeenTrackPointId = null; lastSeenTrackPointId = null; - trackStatisticsUpdater = new TrackStatisticsUpdater(); + trackStatisticsUpdater = null; } private boolean isStarted() { diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java index 433aafa1f..6f4b005e7 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java @@ -145,8 +145,7 @@ public class TrackImporter { adjustTrackPoints(); - TrackStatisticsUpdater updater = new TrackStatisticsUpdater(); - updater.addTrackPoints(trackPoints); + TrackStatisticsUpdater updater = new TrackStatisticsUpdater(trackPoints); track.setStatistics(updater.getTrackStatistics()); Track.Id trackId = contentProviderUtils.insertTrack(track); diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingManager.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingManager.java index bb76fb8b6..9975ed9cc 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingManager.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingManager.java @@ -69,20 +69,19 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen TrackPoint segmentStartTrackPoint = trackPointCreator.createSegmentStartManual(); ZoneOffset zoneOffset = ZoneOffset.systemDefault().getRules().getOffset(segmentStartTrackPoint.getTime()); - trackStatisticsUpdater = new TrackStatisticsUpdater(); + trackStatisticsUpdater = new TrackStatisticsUpdater(segmentStartTrackPoint); Track track = new Track(zoneOffset, trackStatisticsUpdater.getTrackStatistics()); - trackId = contentProviderUtils.insertTrack(track); - track.setId(trackId); - - onNewTrackPoint(segmentStartTrackPoint); String activityTypeLocalized = PreferencesUtils.getDefaultActivityTypeLocalized(); track.setActivityTypeLocalized(activityTypeLocalized); track.setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized)); track.setStatistics(trackStatisticsUpdater.getTrackStatistics()); track.setName(TrackNameUtils.getTrackName(context, trackId, track.getStartTime())); - contentProviderUtils.updateTrack(track); + + trackId = contentProviderUtils.insertTrack(track); + + onNewTrackPoint(segmentStartTrackPoint); return trackId; } diff --git a/src/main/java/de/dennisguse/opentracks/stats/SegmentStatisticUpdater.java b/src/main/java/de/dennisguse/opentracks/stats/SegmentStatisticUpdater.java index 18ade3d4e..097f4ef43 100644 --- a/src/main/java/de/dennisguse/opentracks/stats/SegmentStatisticUpdater.java +++ b/src/main/java/de/dennisguse/opentracks/stats/SegmentStatisticUpdater.java @@ -98,11 +98,15 @@ public class SegmentStatisticUpdater { avgPower = statistics.avgPower(); } + public Statistics aggregate(Statistics statistics) { + SegmentStatisticUpdater intermediate = new SegmentStatisticUpdater(statistics); + intermediate.merge(this); + return intermediate.getStatistics(); + } + /** * Combines these statistics with those from another object. * This assumes that the time periods covered by each do not intersect. - * - * @param other another statistics data object */ //TODO Should be refactored to append only [mainly due to isIdle] public void merge(SegmentStatisticUpdater other) { diff --git a/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java b/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java index 51555732b..b85ca896a 100644 --- a/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java +++ b/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java @@ -62,6 +62,18 @@ public class TrackStatisticsUpdater { this(new SegmentStatisticUpdater().getStatistics()); } + public TrackStatisticsUpdater(@NonNull TrackPoint trackPoint) { + this(); + addTrackPoint(trackPoint); + } + + public TrackStatisticsUpdater(List trackPoints) { + this(); + assert !trackPoints.isEmpty(); //TODO Enforce that this is always true (e.g., import) + + addTrackPoints(trackPoints); + } + public TrackStatisticsUpdater(@NonNull Statistics statistics) { this.statisticsWithoutCurrentSegment = statistics; this.currentSegment = new SegmentStatisticUpdater(); @@ -82,9 +94,7 @@ public class TrackStatisticsUpdater { * Compute TrackStatistics. */ public Statistics getTrackStatistics() { - SegmentStatisticUpdater stats = new SegmentStatisticUpdater(statisticsWithoutCurrentSegment); //TODO Should not be necessary. - stats.merge(currentSegment); - return stats.getStatistics(); + return currentSegment.aggregate(statisticsWithoutCurrentSegment); } public boolean isIdle() { @@ -190,10 +200,7 @@ public class TrackStatisticsUpdater { private void reset(TrackPoint trackPoint) { if (currentSegment.isInitialized()) { - //TODO Simplify - SegmentStatisticUpdater intermediate = new SegmentStatisticUpdater(statisticsWithoutCurrentSegment); - intermediate.merge(currentSegment); - statisticsWithoutCurrentSegment = intermediate.getStatistics(); + statisticsWithoutCurrentSegment = currentSegment.aggregate(statisticsWithoutCurrentSegment); } currentSegment.reset(trackPoint.getTime()); diff --git a/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsUpdater.java b/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsUpdater.java index 24d5855c9..267dac5f3 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsUpdater.java +++ b/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsUpdater.java @@ -17,7 +17,7 @@ import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.stats.TrackStatisticsUpdater; public class IntervalStatisticsUpdater { - private TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater(); + private TrackStatisticsUpdater trackStatisticsUpdater; private final List intervalList; private final Distance distanceInterval; private Interval interval, lastInterval; @@ -45,7 +45,11 @@ public class IntervalStatisticsUpdater { while (trackPointIterator.hasNext()) { trackPoint = trackPointIterator.next(); - trackStatisticsUpdater.addTrackPoint(trackPoint); + if (trackStatisticsUpdater == null) { + trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoint); + } else { + trackStatisticsUpdater.addTrackPoint(trackPoint); + } if (trackStatisticsUpdater.getTrackStatistics().totalDistance().plus(interval.distance).greaterOrEqualThan(distanceInterval)) { interval.add(trackStatisticsUpdater.getTrackStatistics(), trackPoint); @@ -56,8 +60,7 @@ public class IntervalStatisticsUpdater { intervalList.set(intervalList.size() - 1, adjustedInterval); interval = new Interval(interval.distance.minus(adjustedInterval.distance), interval.time.minus(adjustedInterval.time)); - trackStatisticsUpdater = new TrackStatisticsUpdater(); - trackStatisticsUpdater.addTrackPoint(trackPoint); + trackStatisticsUpdater = new TrackStatisticsUpdater(trackPoint); lastInterval = new Interval(interval); intervalList.add(lastInterval); @@ -66,10 +69,12 @@ public class IntervalStatisticsUpdater { } } - if (newIntervalAdded) { - lastInterval.add(trackStatisticsUpdater.getTrackStatistics(), null); - } else { - lastInterval.set(trackStatisticsUpdater.getTrackStatistics()); + if (trackStatisticsUpdater != null) { + if (newIntervalAdded) { + lastInterval.add(trackStatisticsUpdater.getTrackStatistics(), null); + } else { + lastInterval.set(trackStatisticsUpdater.getTrackStatistics()); + } } return trackPoint != null ? trackPoint.getId() : null;