From 8d015fee6c7bfaf63ad30af460ca72a434fecdd8 Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Tue, 11 Nov 2025 21:14:02 +0100 Subject: [PATCH] Cleanup: SegmentStatisticUpdater. --- .../stats/TrackStatisticsUpdaterTest.java | 150 ++++++++++-------- .../stats/SegmentStatisticUpdater.java | 75 +-------- .../stats/TrackStatisticsUpdater.java | 1 + 3 files changed, 87 insertions(+), 139 deletions(-) diff --git a/src/androidTest/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdaterTest.java b/src/androidTest/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdaterTest.java index e897c2819..a4969ffab 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdaterTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdaterTest.java @@ -2,7 +2,6 @@ package de.dennisguse.opentracks.stats; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -16,34 +15,42 @@ import java.util.List; import de.dennisguse.opentracks.content.data.TestDataUtil; 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.Position; +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.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 - SegmentStatisticUpdater statistics = subject.getSegmentStatisticUpdater(); - assertNull(statistics.getStartTime()); - assertNull(statistics.getStopTime()); - assertEquals(Duration.ZERO, statistics.getTotalTime()); - assertEquals(Duration.ZERO, statistics.getMovingTime()); - - assertEquals(Speed.ZERO, statistics.getAverageSpeed()); - assertEquals(Speed.ZERO, statistics.getAverageMovingSpeed()); - assertEquals(Speed.ZERO, statistics.getMaxSpeed()); - - assertNull(statistics.getTotalAltitudeGain()); - assertNull(statistics.getTotalAltitudeLoss()); - assertNull(statistics.getAverageHeartRate()); + assertEquals( + new Statistics( + null, + null, + Duration.ZERO, + Duration.ZERO, + Distance.ZERO, + Speed.ZERO, + null, + null, + null, + null + ), + subject.getSegmentStatisticUpdater().getStatistics() + ); } @Test @@ -58,19 +65,22 @@ public class TrackStatisticsUpdaterTest { subject.addTrackPoint(tp); // then - SegmentStatisticUpdater statistics = subject.getSegmentStatisticUpdater(); - assertEquals(startTime, statistics.getStartTime()); - assertEquals(startTime, statistics.getStopTime()); - assertEquals(Duration.ZERO, statistics.getTotalTime()); - assertEquals(Duration.ZERO, statistics.getMovingTime()); - - assertEquals(Speed.ZERO, statistics.getAverageSpeed()); - assertEquals(Speed.ZERO, statistics.getAverageMovingSpeed()); - assertEquals(Speed.ZERO, statistics.getMaxSpeed()); - - assertNull(statistics.getTotalAltitudeGain()); - assertNull(statistics.getTotalAltitudeLoss()); - assertNull(statistics.getAverageHeartRate()); + // then + assertEquals( + new Statistics( + startTime, + startTime, + Duration.ZERO, + Duration.ZERO, + Distance.ZERO, + Speed.ZERO, + null, + null, + null, + null + ), + subject.getSegmentStatisticUpdater().getStatistics() + ); } @Test @@ -83,20 +93,22 @@ public class TrackStatisticsUpdaterTest { data.trackPoints().forEach(subject::addTrackPoint); // then - SegmentStatisticUpdater statistics = subject.getSegmentStatisticUpdater(); - assertEquals(142.26, statistics.getTotalDistance().toM(), 0.01); - assertEquals(Duration.ofSeconds(12), statistics.getTotalTime()); - assertEquals(Duration.ofSeconds(12), statistics.getMovingTime()); - - assertEquals(2.5, statistics.getMinAltitude(), 0.01); - assertEquals(32.5, statistics.getMaxAltitude(), 0.01); - assertEquals(36, statistics.getTotalAltitudeGain(), 0.01); - assertEquals(36, statistics.getTotalAltitudeLoss(), 0.01); - - assertEquals(11.85, statistics.getMaxSpeed().toMPS(), 0.01); - assertEquals(11.85, statistics.getAverageMovingSpeed().toMPS(), 0.01); - assertEquals(11.85, statistics.getAverageSpeed().toMPS(), 0.01); - assertEquals(106.834f, statistics.getAverageHeartRate().getBPM(), 0.01); + Statistics result = subject.getSegmentStatisticUpdater().getStatistics(); + assertEquals( + new Statistics( + Instant.EPOCH, + Instant.EPOCH.plusSeconds(13), + Duration.ofSeconds(12), + Duration.ofSeconds(12), + Distance.of(142.2637701034546), + Speed.of(11.855314175287882), + new AltitudeExtremities(2.5, 32.5), + new AltitudeGainLoss(36, 36), + HeartRate.of(106.833336f), + Power.of(405.2778f) + ), + result + ); } @Test @@ -115,7 +127,7 @@ public class TrackStatisticsUpdaterTest { subject.addTrackPoint(tp3); // then - assertEquals(1.10, subject.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01); + assertEquals(Distance.of(1.1057428121566772), subject.getSegmentStatisticUpdater().getStatistics().totalDistance()); } @Test @@ -140,14 +152,14 @@ public class TrackStatisticsUpdaterTest { subject.addTrackPoint(tp3); // then - assertEquals(110.57, subject.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01); + assertEquals(Distance.of(110.57427215576172), subject.getSegmentStatisticUpdater().getStatistics().totalDistance()); // when subject.addTrackPoint(tp4); subject.addTrackPoint(tp5); // then - assertEquals(125.57, subject.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01); + assertEquals(Distance.of(125.57427215576172), subject.getSegmentStatisticUpdater().getStatistics().totalDistance()); } @Test @@ -171,20 +183,20 @@ public class TrackStatisticsUpdaterTest { subject.addTrackPoint(tp3); // then - assertEquals(5, subject.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01); + assertEquals(Distance.of(5), subject.getSegmentStatisticUpdater().getStatistics().totalDistance()); // when subject.addTrackPoint(tp4); subject.addTrackPoint(tp5); // then - assertEquals(59.18, subject.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01); + assertEquals(Distance.of(59.181396484375), subject.getSegmentStatisticUpdater().getStatistics().totalDistance()); } @Test public void addTrackPoint_maxSpeed_multiple_segments() { TrackStatisticsUpdater subject = new TrackStatisticsUpdater(); - assertEquals(Speed.of(0f), subject.getSegmentStatisticUpdater().getMaxSpeed()); + assertEquals(Speed.of(0), subject.getSegmentStatisticUpdater().getStatistics().maxSpeed()); subject.addTrackPoints(List.of( new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.ofEpochSecond(0)), @@ -194,7 +206,7 @@ public class TrackStatisticsUpdaterTest { .setSpeed(Speed.of(2f)), new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.ofEpochSecond(4)) )); - assertEquals(Speed.of(2f), subject.getSegmentStatisticUpdater().getMaxSpeed()); + assertEquals(Speed.of(2), subject.getSegmentStatisticUpdater().getStatistics().maxSpeed()); // when subject.addTrackPoints(List.of( @@ -207,7 +219,7 @@ public class TrackStatisticsUpdaterTest { )); // then - assertEquals(Speed.of(2f), subject.getSegmentStatisticUpdater().getMaxSpeed()); + assertEquals(Speed.of(2f), subject.getSegmentStatisticUpdater().getStatistics().maxSpeed()); } @Test @@ -234,7 +246,7 @@ public class TrackStatisticsUpdaterTest { )); // then - assertEquals(Duration.ofSeconds(35), subject.getSegmentStatisticUpdater().getMovingTime()); + assertEquals(Duration.ofSeconds(35), subject.getSegmentStatisticUpdater().getStatistics().movingTime()); } @Test @@ -264,8 +276,9 @@ public class TrackStatisticsUpdaterTest { )); // then - assertEquals(Duration.ofSeconds(40), subject.getSegmentStatisticUpdater().getMovingTime()); - assertEquals(Distance.of(1040), subject.getSegmentStatisticUpdater().getTotalDistance()); + assertEquals(Duration.ofSeconds(40), subject.getSegmentStatisticUpdater().getStatistics().movingTime()); + + assertEquals(Distance.of(1040), subject.getSegmentStatisticUpdater().getStatistics().totalDistance()); } @Test @@ -281,9 +294,9 @@ public class TrackStatisticsUpdaterTest { subject.addTrackPoint(new TrackPoint(TrackPoint.Type.IDLE, Instant.ofEpochSecond(30))); // then assertTrue(subject.getSegmentStatisticUpdater().isIdle()); - assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getMovingTime()); - assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getTotalTime()); - assertEquals(Distance.of(10), subject.getSegmentStatisticUpdater().getTotalDistance()); + assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getStatistics().movingTime()); + assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getStatistics().totalTime()); + assertEquals(Distance.of(10), subject.getSegmentStatisticUpdater().getStatistics().totalDistance()); // when subject.addTrackPoint( @@ -291,9 +304,9 @@ public class TrackStatisticsUpdaterTest { .setSensorDistance(Distance.ZERO)); // then assertTrue(subject.getSegmentStatisticUpdater().isIdle()); - assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getMovingTime()); - assertEquals(Duration.ofSeconds(40), subject.getSegmentStatisticUpdater().getTotalTime()); - assertEquals(Distance.of(10), subject.getSegmentStatisticUpdater().getTotalDistance()); + assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getStatistics().movingTime()); + assertEquals(Duration.ofSeconds(40), subject.getSegmentStatisticUpdater().getStatistics().totalTime()); + assertEquals(Distance.of(10), subject.getSegmentStatisticUpdater().getStatistics().totalDistance()); // when subject.addTrackPoint( @@ -301,9 +314,9 @@ public class TrackStatisticsUpdaterTest { .setSensorDistance(Distance.of(1))); // then assertTrue(subject.getSegmentStatisticUpdater().isIdle()); - assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getMovingTime()); - assertEquals(Duration.ofSeconds(45), subject.getSegmentStatisticUpdater().getTotalTime()); - assertEquals(Distance.of(11), subject.getSegmentStatisticUpdater().getTotalDistance()); + assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getStatistics().movingTime()); + assertEquals(Duration.ofSeconds(45), subject.getSegmentStatisticUpdater().getStatistics().totalTime()); + assertEquals(Distance.of(11), subject.getSegmentStatisticUpdater().getStatistics().totalDistance()); // when subject.addTrackPoint( @@ -311,18 +324,18 @@ public class TrackStatisticsUpdaterTest { .setSensorDistance(Distance.of(10))); // then assertFalse(subject.getSegmentStatisticUpdater().isIdle()); - assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getMovingTime()); - assertEquals(Duration.ofSeconds(50), subject.getSegmentStatisticUpdater().getTotalTime()); - assertEquals(Distance.of(21), subject.getSegmentStatisticUpdater().getTotalDistance()); + assertEquals(Duration.ofSeconds(30), subject.getSegmentStatisticUpdater().getStatistics().movingTime()); + assertEquals(Duration.ofSeconds(50), subject.getSegmentStatisticUpdater().getStatistics().totalTime()); + assertEquals(Distance.of(21), subject.getSegmentStatisticUpdater().getStatistics().totalDistance()); // when subject.addTrackPoint(new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.ofEpochSecond(60))); // then assertFalse(subject.getSegmentStatisticUpdater().isIdle()); - assertEquals(Duration.ofSeconds(40), subject.getSegmentStatisticUpdater().getMovingTime()); - assertEquals(Duration.ofSeconds(60), subject.getSegmentStatisticUpdater().getTotalTime()); - assertEquals(Distance.of(21), subject.getSegmentStatisticUpdater().getTotalDistance()); + assertEquals(Duration.ofSeconds(40), subject.getSegmentStatisticUpdater().getStatistics().movingTime()); + assertEquals(Duration.ofSeconds(60), subject.getSegmentStatisticUpdater().getStatistics().totalTime()); + assertEquals(Distance.of(21), subject.getSegmentStatisticUpdater().getStatistics().totalDistance()); } @Test @@ -350,8 +363,7 @@ public class TrackStatisticsUpdaterTest { copy.addTrackPoint(tp5); // then - assertEquals(55.287, subject.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01); - assertEquals(55.287, copy.getSegmentStatisticUpdater().getTotalDistance().toM(), 0.01); + assertEquals(Distance.of(55.28713929653168), subject.getSegmentStatisticUpdater().getStatistics().totalDistance()); } public TrackPoint createTrackPoint(double latitude, double longitude, Altitude altitude, Instant time) { diff --git a/src/main/java/de/dennisguse/opentracks/stats/SegmentStatisticUpdater.java b/src/main/java/de/dennisguse/opentracks/stats/SegmentStatisticUpdater.java index 2b5b3174a..b7c9ebfcb 100644 --- a/src/main/java/de/dennisguse/opentracks/stats/SegmentStatisticUpdater.java +++ b/src/main/java/de/dennisguse/opentracks/stats/SegmentStatisticUpdater.java @@ -17,7 +17,6 @@ package de.dennisguse.opentracks.stats; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import java.time.Duration; @@ -201,6 +200,7 @@ public class SegmentStatisticUpdater { } public Statistics getStatistics() { + // Times may not be live (i.e., updated automatically). return new Statistics( startTime, stopTime, @@ -209,6 +209,8 @@ public class SegmentStatisticUpdater { totalDistance, getMaxSpeed(), + + // This is calculated from the smoothed altitude, so this can actually be less than the current altitude. altitudeExtremities.hasData() ? new AltitudeExtremities(altitudeExtremities.getMin(), altitudeExtremities.getMax()) : null, totalAltitudeGain_m != null && totalAltitudeLoss_m != null ? new AltitudeGainLoss(totalAltitudeGain_m, totalAltitudeLoss_m) : null, avgHeartRate, @@ -228,10 +230,6 @@ public class SegmentStatisticUpdater { setStopTime(startTime); } - public Instant getStopTime() { - return stopTime; - } - public void setStopTime(Instant stopTime) { if (stopTime.isBefore(startTime)) { // Time must be monotonically increasing, but we might have events at the same point in time (BLE and GPS) @@ -240,10 +238,6 @@ public class SegmentStatisticUpdater { this.stopTime = stopTime; } - public Distance getTotalDistance() { - return totalDistance; - } - @VisibleForTesting public void setTotalDistance(Distance totalDistance_m) { this.totalDistance = totalDistance_m; @@ -253,23 +247,11 @@ public class SegmentStatisticUpdater { totalDistance = totalDistance.plus(distance_m); } - public Duration getTotalTime() { - return totalTime; - } - + @VisibleForTesting public void setTotalTime(Duration totalTime) { this.totalTime = totalTime; } - public Duration getMovingTime() { - return movingTime; - } - - @VisibleForTesting - public void setMovingTime(Duration movingTime) { - this.movingTime = movingTime; - } - public void addMovingTime(TrackPoint trackPoint, TrackPoint lastTrackPoint) { Duration movingDuration = Duration.between(lastTrackPoint.getTime(), trackPoint.getTime()); @@ -287,24 +269,7 @@ public class SegmentStatisticUpdater { isIdle = idle; } - @VisibleForTesting - @Nullable - public HeartRate getAverageHeartRate() { - return avgHeartRate; - } - - /** - * Gets the average speed. - * This calculation only takes into account the displacement until the last point that was accounted for in statistics. - */ - public Speed getAverageSpeed() { - if (totalTime.isZero()) { - return Speed.ZERO; - } - return Speed.of(totalDistance.toM() / totalTime.getSeconds()); - } - - public Speed getAverageMovingSpeed() { + private Speed getAverageMovingSpeed() { return Speed.of(totalDistance, movingTime); } @@ -316,22 +281,6 @@ public class SegmentStatisticUpdater { this.maxSpeed = maxSpeed; } - @VisibleForTesting - @Deprecated - public double getMinAltitude() { - return altitudeExtremities.getMin(); - } - - /** - * Gets the maximum altitude. - * This is calculated from the smoothed altitude, so this can actually be less than the current altitude. - */ - @VisibleForTesting - @Deprecated - public double getMaxAltitude() { - return altitudeExtremities.getMax(); - } - public void updateAltitudeExtremities(Altitude altitude) { if (altitude != null) { altitudeExtremities.update(altitude.toM()); @@ -350,26 +299,12 @@ public class SegmentStatisticUpdater { } } - @VisibleForTesting - @Deprecated - @Nullable - public Float getTotalAltitudeGain() { - return totalAltitudeGain_m; - } - @VisibleForTesting @Deprecated public void setTotalAltitudeGain(Float totalAltitudeGain_m) { this.totalAltitudeGain_m = totalAltitudeGain_m; } - @VisibleForTesting - @Deprecated - @Nullable - public Float getTotalAltitudeLoss() { - return totalAltitudeLoss_m; - } - @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) public void addTotalAltitudeGainLoss(AltitudeGainLoss altitudeGainLoss) { if (totalAltitudeGain_m == null) { diff --git a/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java b/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java index c119f5b2c..73fad9b9b 100644 --- a/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java +++ b/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java @@ -214,6 +214,7 @@ public class TrackStatisticsUpdater { } } + @NonNull @Override public String toString() { return "TrackStatisticsUpdater{" +