From 94595f2a1f608190d42a9dd789ef6d2505ca6a8f Mon Sep 17 00:00:00 2001 From: Jeff Shelley Date: Wed, 8 Oct 2025 21:56:06 -0500 Subject: [PATCH] Added support for average pace of the current segment --- .../opentracks/services/RecordingData.java | 15 +++++-- .../services/TrackRecordingManager.java | 5 ++- .../services/TrackRecordingService.java | 8 ++-- .../opentracks/settings/PreferencesUtils.java | 3 +- .../stats/TrackStatisticsUpdater.java | 4 ++ .../SettingsCustomLayoutEditAdapter.java | 2 +- .../GenericStatisticsViewHolder.java | 39 +++++++++++++------ .../opentracks/viewmodels/Mapping.java | 1 + src/main/res/values/settings.xml | 15 ++++--- src/main/res/values/strings.xml | 2 + 10 files changed, 67 insertions(+), 27 deletions(-) diff --git a/src/main/java/de/dennisguse/opentracks/services/RecordingData.java b/src/main/java/de/dennisguse/opentracks/services/RecordingData.java index 8d95e9de0..92d9734a3 100644 --- a/src/main/java/de/dennisguse/opentracks/services/RecordingData.java +++ b/src/main/java/de/dennisguse/opentracks/services/RecordingData.java @@ -10,8 +10,7 @@ import de.dennisguse.opentracks.stats.TrackStatistics; /** * {@link Track} and {@link TrackPoint} must be immutable (i.e., their content does not change). */ -public record RecordingData(Track track, TrackPoint latestTrackPoint, SensorDataSet sensorDataSet) { - +public record RecordingData(Track track, TrackPoint latestTrackPoint, SensorDataSet sensorDataSet, TrackStatistics currentSegment) { public String getTrackCategory() { if (track == null) { return ""; @@ -20,11 +19,21 @@ public record RecordingData(Track track, TrackPoint latestTrackPoint, SensorData } @NonNull - public TrackStatistics getTrackStatistics() { + public TrackStatistics getStatisticsTrack() { if (track == null) { return new TrackStatistics(); } return track.getTrackStatistics(); } + + @NonNull + public TrackStatistics getStatisticsCurrentSegment() { + if (currentSegment == null) { + return new TrackStatistics(); + } + + return currentSegment; + } + } diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingManager.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingManager.java index 0ccc4616a..a30bb330a 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingManager.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingManager.java @@ -116,7 +116,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen reset(); } - Pair> getDataForUI() { + RecordingData getDataForUI() { TrackStatisticsUpdater tmpTrackStatisticsUpdater = new TrackStatisticsUpdater(trackStatisticsUpdater); Pair current = trackPointCreator.createCurrentTrackPoint(lastTrackPointUIWithSpeed, lastTrackPointUIWithAltitude, lastStoredTrackPointWithLocation); @@ -131,8 +131,9 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen } track.setTrackStatistics(tmpTrackStatisticsUpdater.getTrackStatistics()); + TrackStatistics currentSegment = tmpTrackStatisticsUpdater.getCurrentSegment(); - return new Pair<>(track, current); + return new RecordingData(track, current.first, current.second, currentSegment); } @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java index 984de4cc6..a16c42ed0 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java @@ -55,7 +55,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator. private static final Duration RECORDING_DATA_UPDATE_INTERVAL = Duration.ofSeconds(1); public static final RecordingStatus STATUS_DEFAULT = RecordingStatus.notRecording(); - public static final RecordingData NOT_RECORDING = new RecordingData(null, null, null); + public static final RecordingData NOT_RECORDING = new RecordingData(null, null, null, null); public static final GpsStatusValue STATUS_GPS_DEFAULT = GpsStatusValue.GPS_NONE; public TrackPoint getLastStoredTrackPointWithLocation() { @@ -315,11 +315,11 @@ public class TrackRecordingService extends Service implements TrackPointCreator. } // Compute temporary track statistics using sensorData and update time. - Pair> data = trackRecordingManager.getDataForUI(); + RecordingData data = trackRecordingManager.getDataForUI(); - voiceAnnouncementManager.announceStatisticsIfNeeded(data.first, data.second.second); + voiceAnnouncementManager.announceStatisticsIfNeeded(data.track(), data.sensorDataSet()); - recordingDataObservable.postValue(new RecordingData(data.first, data.second.first, data.second.second)); + recordingDataObservable.postValue(data); } public void onIdle() { diff --git a/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java b/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java index f6e103281..0e8ee5421 100644 --- a/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java +++ b/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java @@ -828,7 +828,8 @@ public class PreferencesUtils { R.array.stats_custom_layout_fields_default_value_15, R.array.stats_custom_layout_fields_default_value_16, R.array.stats_custom_layout_fields_default_value_17, - R.array.stats_custom_layout_fields_default_value_18 + R.array.stats_custom_layout_fields_default_value_18, + R.array.stats_custom_layout_fields_default_value_19 ).map(id -> resources.obtainTypedArray(id)) .toList(); } diff --git a/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java b/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java index 9114f9f35..9e84fbfca 100644 --- a/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java +++ b/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java @@ -78,6 +78,10 @@ public class TrackStatisticsUpdater { stats.merge(currentSegment); return stats; } + public TrackStatistics getCurrentSegment() { + // Take a snapshot - we don't want anyone messing with our currentSegment + return new TrackStatistics(currentSegment); + } public void addTrackPoints(List trackPoints) { trackPoints.forEach(this::addTrackPoint); diff --git a/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/SettingsCustomLayoutEditAdapter.java b/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/SettingsCustomLayoutEditAdapter.java index a5d1275f1..45d19a368 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/SettingsCustomLayoutEditAdapter.java +++ b/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/SettingsCustomLayoutEditAdapter.java @@ -61,7 +61,7 @@ public class SettingsCustomLayoutEditAdapter extends RecyclerView.Adapter valueAndUnit = DistanceFormatter.Builder() .setUnit(unitSystem) - .build(getContext()).getDistanceParts(data.getTrackStatistics().getTotalDistance()); + .build(getContext()).getDistanceParts(data.getStatisticsTrack().getTotalDistance()); getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsUnit.setText(valueAndUnit.second); @@ -46,7 +46,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = new Pair<>(StringUtils.formatElapsedTime(data.getTrackStatistics().getTotalTime()), null); + Pair valueAndUnit = new Pair<>(StringUtils.formatElapsedTime(data.getStatisticsTrack().getTotalTime()), null); getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsUnit.setText(valueAndUnit.second); @@ -58,7 +58,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getTrackStatistics().getAverageMovingSpeed()); + Pair valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getAverageMovingSpeed()); getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsUnit.setText(valueAndUnit.second); @@ -140,7 +140,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getTrackStatistics().getAverageSpeed()); + Pair valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getAverageSpeed()); getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsUnit.setText(valueAndUnit.second); @@ -157,7 +157,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getTrackStatistics().getMaxSpeed()); + Pair valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getMaxSpeed()); getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsUnit.setText(valueAndUnit.second); @@ -174,7 +174,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getTrackStatistics().getAverageMovingSpeed()); + Pair valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getAverageMovingSpeed()); getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsUnit.setText(valueAndUnit.second); @@ -191,7 +191,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getTrackStatistics().getAverageMovingSpeed()); + Pair valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getAverageMovingSpeed()); getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsUnit.setText(valueAndUnit.second); @@ -199,6 +199,23 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsCurrentSegment().getAverageMovingSpeed()); + + getBinding().statsValue.setText(valueAndUnit.first); + getBinding().statsUnit.setText(valueAndUnit.second); + getBinding().statsDescriptionMain.setText(getContext().getString(R.string.stats_average_segment_pace)); + } + } + public static class FastestPace extends GenericStatisticsViewHolder { @Override @@ -208,7 +225,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getTrackStatistics().getMaxSpeed()); + Pair valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getMaxSpeed()); getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsUnit.setText(valueAndUnit.second); @@ -237,7 +254,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = StringUtils.getAltitudeParts(getContext(), data.getTrackStatistics().getTotalAltitudeGain(), unitSystem); + Pair valueAndUnit = StringUtils.getAltitudeParts(getContext(), data.getStatisticsTrack().getTotalAltitudeGain(), unitSystem); getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsUnit.setText(valueAndUnit.second); @@ -250,7 +267,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = StringUtils.getAltitudeParts(getContext(), data.getTrackStatistics().getTotalAltitudeLoss(), unitSystem); + Pair valueAndUnit = StringUtils.getAltitudeParts(getContext(), data.getStatisticsTrack().getTotalAltitudeLoss(), unitSystem); getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsUnit.setText(valueAndUnit.second); diff --git a/src/main/java/de/dennisguse/opentracks/viewmodels/Mapping.java b/src/main/java/de/dennisguse/opentracks/viewmodels/Mapping.java index 8d923eb3a..46fa143e0 100644 --- a/src/main/java/de/dennisguse/opentracks/viewmodels/Mapping.java +++ b/src/main/java/de/dennisguse/opentracks/viewmodels/Mapping.java @@ -24,6 +24,7 @@ public class Mapping { m.put(context.getString(R.string.stats_custom_layout_max_speed_key), GenericStatisticsViewHolder.MaxSpeed::new); m.put(context.getString(R.string.stats_custom_layout_average_moving_pace_key), GenericStatisticsViewHolder.AverageMovingPace::new); m.put(context.getString(R.string.stats_custom_layout_average_pace_key), GenericStatisticsViewHolder.AveragePace::new); + m.put(context.getString(R.string.stats_custom_layout_average_segment_pace_key), GenericStatisticsViewHolder.AverageSegmentPace::new); m.put(context.getString(R.string.stats_custom_layout_fastest_pace_key), GenericStatisticsViewHolder.FastestPace::new); m.put(context.getString(R.string.stats_custom_layout_altitude_key), GenericStatisticsViewHolder.Altitude::new); diff --git a/src/main/res/values/settings.xml b/src/main/res/values/settings.xml index 53e37a2ae..7332ace76 100644 --- a/src/main/res/values/settings.xml +++ b/src/main/res/values/settings.xml @@ -355,6 +355,7 @@ pace average_moving_pace average_pace + average_segment_pace fastest_pace coordinates heart_rate @@ -422,26 +423,30 @@ 0,0,0 - @string/stats_custom_layout_fastest_pace_key + @string/stats_custom_layout_average_segment_pace_key 0,0,0 + @string/stats_custom_layout_fastest_pace_key + 0,0,0 + + @string/stats_custom_layout_coordinates_key 0,0,1 - + @string/stats_custom_layout_heart_rate_key 0,0,0 - + @string/stats_custom_layout_cadence_key 0,0,0 - + @string/stats_custom_layout_power_key 0,0,0 - + @string/stats_custom_layout_clock_key 0,0,0 diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 74baa205c..59c657071 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -391,6 +391,7 @@ limitations under the License. Average heart rate Lap heart rate Average speed/pace + Average speed/pace (Segment) Lap speed/pace Distance/speed unit @@ -453,6 +454,7 @@ limitations under the License. Avg moving pace Avg moving speed Avg pace + Avg Segment pace Avg speed Elevation Fastest pace