Added support for average pace of the current segment

This commit is contained in:
Jeff Shelley
2025-10-08 21:56:06 -05:00
parent 1fa76301e2
commit 94595f2a1f
10 changed files with 67 additions and 27 deletions
@@ -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). * {@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() { public String getTrackCategory() {
if (track == null) { if (track == null) {
return ""; return "";
@@ -20,11 +19,21 @@ public record RecordingData(Track track, TrackPoint latestTrackPoint, SensorData
} }
@NonNull @NonNull
public TrackStatistics getTrackStatistics() { public TrackStatistics getStatisticsTrack() {
if (track == null) { if (track == null) {
return new TrackStatistics(); return new TrackStatistics();
} }
return track.getTrackStatistics(); return track.getTrackStatistics();
} }
@NonNull
public TrackStatistics getStatisticsCurrentSegment() {
if (currentSegment == null) {
return new TrackStatistics();
}
return currentSegment;
}
} }
@@ -116,7 +116,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
reset(); reset();
} }
Pair<Track, Pair<TrackPoint, SensorDataSet>> getDataForUI() { RecordingData getDataForUI() {
TrackStatisticsUpdater tmpTrackStatisticsUpdater = new TrackStatisticsUpdater(trackStatisticsUpdater); TrackStatisticsUpdater tmpTrackStatisticsUpdater = new TrackStatisticsUpdater(trackStatisticsUpdater);
Pair<TrackPoint, SensorDataSet> current = trackPointCreator.createCurrentTrackPoint(lastTrackPointUIWithSpeed, lastTrackPointUIWithAltitude, lastStoredTrackPointWithLocation); Pair<TrackPoint, SensorDataSet> current = trackPointCreator.createCurrentTrackPoint(lastTrackPointUIWithSpeed, lastTrackPointUIWithAltitude, lastStoredTrackPointWithLocation);
@@ -131,8 +131,9 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
} }
track.setTrackStatistics(tmpTrackStatisticsUpdater.getTrackStatistics()); 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) @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
@@ -55,7 +55,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
private static final Duration RECORDING_DATA_UPDATE_INTERVAL = Duration.ofSeconds(1); private static final Duration RECORDING_DATA_UPDATE_INTERVAL = Duration.ofSeconds(1);
public static final RecordingStatus STATUS_DEFAULT = RecordingStatus.notRecording(); 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 static final GpsStatusValue STATUS_GPS_DEFAULT = GpsStatusValue.GPS_NONE;
public TrackPoint getLastStoredTrackPointWithLocation() { public TrackPoint getLastStoredTrackPointWithLocation() {
@@ -315,11 +315,11 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
} }
// Compute temporary track statistics using sensorData and update time. // Compute temporary track statistics using sensorData and update time.
Pair<Track, Pair<TrackPoint, SensorDataSet>> 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() { public void onIdle() {
@@ -828,7 +828,8 @@ public class PreferencesUtils {
R.array.stats_custom_layout_fields_default_value_15, 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_16,
R.array.stats_custom_layout_fields_default_value_17, 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)) ).map(id -> resources.obtainTypedArray(id))
.toList(); .toList();
} }
@@ -78,6 +78,10 @@ public class TrackStatisticsUpdater {
stats.merge(currentSegment); stats.merge(currentSegment);
return stats; 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<TrackPoint> trackPoints) { public void addTrackPoints(List<TrackPoint> trackPoints) {
trackPoints.forEach(this::addTrackPoint); trackPoints.forEach(this::addTrackPoint);
@@ -61,7 +61,7 @@ public class SettingsCustomLayoutEditAdapter extends RecyclerView.Adapter<Recycl
Speed.zero() Speed.zero()
); );
demoData = new RecordingData(track, new TrackPoint(TrackPoint.Type.TRACKPOINT, position), null); demoData = new RecordingData(track, new TrackPoint(TrackPoint.Type.TRACKPOINT, position), null, trackStatistics) ;
} }
private RecordingLayout recordingLayout; private RecordingLayout recordingLayout;
@@ -34,7 +34,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
public void onChanged(UnitSystem unitSystem, RecordingData data) { public void onChanged(UnitSystem unitSystem, RecordingData data) {
Pair<String, String> valueAndUnit = DistanceFormatter.Builder() Pair<String, String> valueAndUnit = DistanceFormatter.Builder()
.setUnit(unitSystem) .setUnit(unitSystem)
.build(getContext()).getDistanceParts(data.getTrackStatistics().getTotalDistance()); .build(getContext()).getDistanceParts(data.getStatisticsTrack().getTotalDistance());
getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second); getBinding().statsUnit.setText(valueAndUnit.second);
@@ -46,7 +46,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
@Override @Override
public void onChanged(UnitSystem unitSystem, RecordingData data) { public void onChanged(UnitSystem unitSystem, RecordingData data) {
Pair<String, String> valueAndUnit = new Pair<>(StringUtils.formatElapsedTime(data.getTrackStatistics().getTotalTime()), null); Pair<String, String> valueAndUnit = new Pair<>(StringUtils.formatElapsedTime(data.getStatisticsTrack().getTotalTime()), null);
getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second); getBinding().statsUnit.setText(valueAndUnit.second);
@@ -58,7 +58,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
@Override @Override
public void onChanged(UnitSystem unitSystem, RecordingData data) { public void onChanged(UnitSystem unitSystem, RecordingData data) {
String value = StringUtils.formatElapsedTime(data.getTrackStatistics().getMovingTime()); String value = StringUtils.formatElapsedTime(data.getStatisticsTrack().getMovingTime());
getBinding().statsValue.setText(value); getBinding().statsValue.setText(value);
getBinding().statsDescriptionMain.setText(getContext().getString(R.string.stats_moving_time)); getBinding().statsDescriptionMain.setText(getContext().getString(R.string.stats_moving_time));
@@ -123,7 +123,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
.setReportSpeedOrPace(true) .setReportSpeedOrPace(true)
.build(getContext()); .build(getContext());
Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getTrackStatistics().getAverageMovingSpeed()); Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getAverageMovingSpeed());
getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second); getBinding().statsUnit.setText(valueAndUnit.second);
@@ -140,7 +140,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
.setReportSpeedOrPace(true) .setReportSpeedOrPace(true)
.build(getContext()); .build(getContext());
Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getTrackStatistics().getAverageSpeed()); Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getAverageSpeed());
getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second); getBinding().statsUnit.setText(valueAndUnit.second);
@@ -157,7 +157,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
.setReportSpeedOrPace(true) .setReportSpeedOrPace(true)
.build(getContext()); .build(getContext());
Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getTrackStatistics().getMaxSpeed()); Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getMaxSpeed());
getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second); getBinding().statsUnit.setText(valueAndUnit.second);
@@ -174,7 +174,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
.setReportSpeedOrPace(false) .setReportSpeedOrPace(false)
.build(getContext()); .build(getContext());
Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getTrackStatistics().getAverageMovingSpeed()); Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getAverageMovingSpeed());
getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second); getBinding().statsUnit.setText(valueAndUnit.second);
@@ -191,7 +191,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
.setReportSpeedOrPace(false) .setReportSpeedOrPace(false)
.build(getContext()); .build(getContext());
Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getTrackStatistics().getAverageMovingSpeed()); Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getAverageMovingSpeed());
getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second); getBinding().statsUnit.setText(valueAndUnit.second);
@@ -199,6 +199,23 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
} }
} }
public static class AverageSegmentPace extends GenericStatisticsViewHolder {
@Override
public void onChanged(UnitSystem unitSystem, RecordingData data) {
SpeedFormatter speedFormatterSpeed = SpeedFormatter.Builder()
.setUnit(unitSystem)
.setReportSpeedOrPace(false)
.build(getContext());
Pair<String, String> 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 { public static class FastestPace extends GenericStatisticsViewHolder {
@Override @Override
@@ -208,7 +225,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
.setReportSpeedOrPace(false) .setReportSpeedOrPace(false)
.build(getContext()); .build(getContext());
Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getTrackStatistics().getMaxSpeed()); Pair<String, String> valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getMaxSpeed());
getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second); getBinding().statsUnit.setText(valueAndUnit.second);
@@ -237,7 +254,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
@Override @Override
public void onChanged(UnitSystem unitSystem, RecordingData data) { public void onChanged(UnitSystem unitSystem, RecordingData data) {
Pair<String, String> valueAndUnit = StringUtils.getAltitudeParts(getContext(), data.getTrackStatistics().getTotalAltitudeGain(), unitSystem); Pair<String, String> valueAndUnit = StringUtils.getAltitudeParts(getContext(), data.getStatisticsTrack().getTotalAltitudeGain(), unitSystem);
getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second); getBinding().statsUnit.setText(valueAndUnit.second);
@@ -250,7 +267,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder<St
@Override @Override
public void onChanged(UnitSystem unitSystem, RecordingData data) { public void onChanged(UnitSystem unitSystem, RecordingData data) {
Pair<String, String> valueAndUnit = StringUtils.getAltitudeParts(getContext(), data.getTrackStatistics().getTotalAltitudeLoss(), unitSystem); Pair<String, String> valueAndUnit = StringUtils.getAltitudeParts(getContext(), data.getStatisticsTrack().getTotalAltitudeLoss(), unitSystem);
getBinding().statsValue.setText(valueAndUnit.first); getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second); getBinding().statsUnit.setText(valueAndUnit.second);
@@ -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_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_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_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_fastest_pace_key), GenericStatisticsViewHolder.FastestPace::new);
m.put(context.getString(R.string.stats_custom_layout_altitude_key), GenericStatisticsViewHolder.Altitude::new); m.put(context.getString(R.string.stats_custom_layout_altitude_key), GenericStatisticsViewHolder.Altitude::new);
+10 -5
View File
@@ -355,6 +355,7 @@
<string name="stats_custom_layout_pace_key" translatable="false">pace</string> <string name="stats_custom_layout_pace_key" translatable="false">pace</string>
<string name="stats_custom_layout_average_moving_pace_key" translatable="false">average_moving_pace</string> <string name="stats_custom_layout_average_moving_pace_key" translatable="false">average_moving_pace</string>
<string name="stats_custom_layout_average_pace_key" translatable="false">average_pace</string> <string name="stats_custom_layout_average_pace_key" translatable="false">average_pace</string>
<string name="stats_custom_layout_average_segment_pace_key" translatable="false">average_segment_pace</string>
<string name="stats_custom_layout_fastest_pace_key" translatable="false">fastest_pace</string> <string name="stats_custom_layout_fastest_pace_key" translatable="false">fastest_pace</string>
<string name="stats_custom_layout_coordinates_key" translatable="false">coordinates</string> <string name="stats_custom_layout_coordinates_key" translatable="false">coordinates</string>
<string name="stats_custom_layout_heart_rate_key" translatable="false">heart_rate</string> <string name="stats_custom_layout_heart_rate_key" translatable="false">heart_rate</string>
@@ -422,26 +423,30 @@
<item>0,0,0</item> <item>0,0,0</item>
</string-array> </string-array>
<string-array name="stats_custom_layout_fields_default_value_13"> <string-array name="stats_custom_layout_fields_default_value_13">
<item>@string/stats_custom_layout_fastest_pace_key</item> <item>@string/stats_custom_layout_average_segment_pace_key</item>
<item>0,0,0</item> <item>0,0,0</item>
</string-array> </string-array>
<string-array name="stats_custom_layout_fields_default_value_14"> <string-array name="stats_custom_layout_fields_default_value_14">
<item>@string/stats_custom_layout_fastest_pace_key</item>
<item>0,0,0</item>
</string-array>
<string-array name="stats_custom_layout_fields_default_value_15">
<item>@string/stats_custom_layout_coordinates_key</item> <item>@string/stats_custom_layout_coordinates_key</item>
<item>0,0,1</item> <item>0,0,1</item>
</string-array> </string-array>
<string-array name="stats_custom_layout_fields_default_value_15"> <string-array name="stats_custom_layout_fields_default_value_16">
<item>@string/stats_custom_layout_heart_rate_key</item> <item>@string/stats_custom_layout_heart_rate_key</item>
<item>0,0,0</item> <item>0,0,0</item>
</string-array> </string-array>
<string-array name="stats_custom_layout_fields_default_value_16"> <string-array name="stats_custom_layout_fields_default_value_17">
<item>@string/stats_custom_layout_cadence_key</item> <item>@string/stats_custom_layout_cadence_key</item>
<item>0,0,0</item> <item>0,0,0</item>
</string-array> </string-array>
<string-array name="stats_custom_layout_fields_default_value_17"> <string-array name="stats_custom_layout_fields_default_value_18">
<item>@string/stats_custom_layout_power_key</item> <item>@string/stats_custom_layout_power_key</item>
<item>0,0,0</item> <item>0,0,0</item>
</string-array> </string-array>
<string-array name="stats_custom_layout_fields_default_value_18"> <string-array name="stats_custom_layout_fields_default_value_19">
<item>@string/stats_custom_layout_clock_key</item> <item>@string/stats_custom_layout_clock_key</item>
<item>0,0,0</item> <item>0,0,0</item>
</string-array> </string-array>
+2
View File
@@ -391,6 +391,7 @@ limitations under the License.
<string name="settings_announcements_average_heart_rate">Average heart rate</string> <string name="settings_announcements_average_heart_rate">Average heart rate</string>
<string name="settings_announcements_lap_heart_rate">Lap heart rate</string> <string name="settings_announcements_lap_heart_rate">Lap heart rate</string>
<string name="settings_announcements_average_speed_pace">Average speed/pace</string> <string name="settings_announcements_average_speed_pace">Average speed/pace</string>
<string name="settings_announcements_segment_average_speed_pace">Average speed/pace (Segment)</string>
<string name="settings_announcements_lap_speed_pace">Lap speed/pace</string> <string name="settings_announcements_lap_speed_pace">Lap speed/pace</string>
<string name="settings_announcements_unit">Distance/speed unit</string> <string name="settings_announcements_unit">Distance/speed unit</string>
<!-- Custom Layout --> <!-- Custom Layout -->
@@ -453,6 +454,7 @@ limitations under the License.
<string name="stats_average_moving_pace">Avg moving pace</string> <string name="stats_average_moving_pace">Avg moving pace</string>
<string name="stats_average_moving_speed">Avg moving speed</string> <string name="stats_average_moving_speed">Avg moving speed</string>
<string name="stats_average_pace">Avg pace</string> <string name="stats_average_pace">Avg pace</string>
<string name="stats_average_segment_pace">Avg Segment pace</string>
<string name="stats_average_speed">Avg speed</string> <string name="stats_average_speed">Avg speed</string>
<string name="stats_altitude">Elevation</string> <string name="stats_altitude">Elevation</string>
<string name="stats_fastest_pace">Fastest pace</string> <string name="stats_fastest_pace">Fastest pace</string>