diff --git a/src/androidTest/java/de/dennisguse/opentracks/data/models/SpeedFormatterTest.java b/src/androidTest/java/de/dennisguse/opentracks/data/models/SpeedFormatterTest.java new file mode 100644 index 000000000..ac5c2acb6 --- /dev/null +++ b/src/androidTest/java/de/dennisguse/opentracks/data/models/SpeedFormatterTest.java @@ -0,0 +1,80 @@ +package de.dennisguse.opentracks.data.models; + +import static org.junit.Assert.assertEquals; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class SpeedFormatterTest { + + private final Context context = ApplicationProvider.getApplicationContext(); + + @Test + public void testGetSpeedParts_pace_metric() { + SpeedFormatter formatter = SpeedFormatter.Builder() + .setDecimalCount(2) + .setMetricUnits(true) + .setReportSpeedOrPace(false) + .build(context); + + assertEquals("4:59", formatter.getSpeedParts(Speed.of(3.34)).first); + assertEquals("5:00", formatter.getSpeedParts(Speed.of(3.33)).first); + + assertEquals("min/km", formatter.getSpeedParts(Speed.zero()).second); + } + + @Test + public void testGetSpeedParts_pace_imperial() { + SpeedFormatter formatter = SpeedFormatter.Builder() + .setDecimalCount(2) + .setMetricUnits(false) + .setReportSpeedOrPace(false) + .build(context); + +// assertEquals("TODO", formatter.getSpeedParts(Speed.of(3.34)).first); +// assertEquals("TODO", formatter.getSpeedParts(Speed.of(3.33)).first); + + assertEquals("min/mi", formatter.getSpeedParts(Speed.zero()).second); + } + + @Test + public void testGetSpeedParts_speed_metric() { + SpeedFormatter formatter = SpeedFormatter.Builder() + .setDecimalCount(2) + .setMetricUnits(true) + .setReportSpeedOrPace(true) + .build(context); + + assertEquals("11.9", formatter.getSpeedParts(Speed.of(3.31)).first); + assertEquals("km/h", formatter.getSpeedParts(Speed.zero()).second); + } + + @Test + public void testGetSpeedParts_speed_imperial() { + SpeedFormatter formatter = SpeedFormatter.Builder() + .setDecimalCount(2) + .setMetricUnits(false) + .setReportSpeedOrPace(true) + .build(context); + + assertEquals("7.5", formatter.getSpeedParts(Speed.of(3.34)).first); + assertEquals("mph", formatter.getSpeedParts(Speed.zero()).second); + } + + @Test + public void testFormatSpeed() { + SpeedFormatter formatter = SpeedFormatter.Builder() + .setDecimalCount(2) + .setMetricUnits(true) + .setReportSpeedOrPace(false) + .build(context); + + assertEquals("4:59 min/km", formatter.formatSpeed(Speed.of(3.34))); + } +} \ No newline at end of file diff --git a/src/androidTest/java/de/dennisguse/opentracks/util/StringUtilsTest.java b/src/androidTest/java/de/dennisguse/opentracks/util/StringUtilsTest.java index 85bdc6cf6..b06bf5cb5 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/util/StringUtilsTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/util/StringUtilsTest.java @@ -47,7 +47,6 @@ import java.util.TimeZone; import java.util.stream.Collectors; import de.dennisguse.opentracks.LocaleRule; -import de.dennisguse.opentracks.data.models.Speed; /** * Tests for {@link StringUtils}. @@ -167,27 +166,6 @@ public class StringUtilsTest { assertEquals("1.0", StringUtils.formatDecimal(0.99, 1)); } - @Test - public void testGetSpeedParts() { - assertEquals("4:59", StringUtils.getSpeedParts(context, Speed.of(3.34), true, false).first); - assertEquals("5:00", StringUtils.getSpeedParts(context, Speed.of(3.33), true, false).first); - - assertEquals("11.9", StringUtils.getSpeedParts(context, Speed.of(3.31), true, true).first); - assertEquals("7.5", StringUtils.getSpeedParts(context, Speed.of(3.34), false, true).first); - - assertEquals("min/km", StringUtils.getSpeedParts(context, Speed.zero(), true, false).second); - assertEquals("min/mi", StringUtils.getSpeedParts(context, Speed.zero(), false, false).second); - } - - @Test - public void testFormatSpeed() { - assertEquals("4:59 min/km", StringUtils.formatSpeed(context, Speed.of(3.34), true, false)); - assertEquals("8:02 min/mi", StringUtils.formatSpeed(context, Speed.of(3.34), false, false)); - - assertEquals("12.0 km/h", StringUtils.formatSpeed(context, Speed.of(3.34), true, true)); - assertEquals("7.5 mph", StringUtils.formatSpeed(context, Speed.of(3.34), false, true)); - } - @Test public void testFormatDateTodayRelative() { // given diff --git a/src/main/java/de/dennisguse/opentracks/data/models/SpeedFormatter.java b/src/main/java/de/dennisguse/opentracks/data/models/SpeedFormatter.java new file mode 100644 index 000000000..20556dce6 --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/data/models/SpeedFormatter.java @@ -0,0 +1,103 @@ +package de.dennisguse.opentracks.data.models; + +import android.content.Context; +import android.content.res.Resources; +import android.util.Pair; + +import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.util.StringUtils; + +public class SpeedFormatter { + + private final Resources resources; + + private final int decimalCount; + + private final boolean metricUnits; + + private final boolean reportSpeedOrPace; + + private SpeedFormatter(Resources resources, int decimalCount, boolean metricUnits, boolean reportSpeedOrPace) { + this.resources = resources; + this.decimalCount = decimalCount; + this.metricUnits = metricUnits; + this.reportSpeedOrPace = reportSpeedOrPace; + } + + public String formatSpeed(Speed speed) { + Pair distanceParts = getSpeedParts(speed); + + return resources.getString(R.string.speed_with_unit, distanceParts.first, distanceParts.second); + } + + /** + * Gets the formatted speed with unit. + * + * @return the formatted speed (or null) and it's unit as {@link Pair} + */ + public Pair getSpeedParts(Speed speed) { + int unitId; + if (metricUnits) { + unitId = reportSpeedOrPace ? R.string.unit_kilometer_per_hour : R.string.unit_minute_per_kilometer; + } else { + unitId = reportSpeedOrPace ? R.string.unit_mile_per_hour : R.string.unit_minute_per_mile; + } + String unitString = resources.getString(unitId); + + if (speed == null) { + speed = Speed.zero(); + } + + if (reportSpeedOrPace) { + return new Pair<>(StringUtils.formatDecimal(speed.to(metricUnits), 1), unitString); + } + + int pace = (int) speed.toPace(metricUnits).getSeconds(); + + int minutes = pace / 60; + int seconds = pace % 60; + return new Pair<>(resources.getString(R.string.time, minutes, seconds), unitString); + } + + public static Builder Builder() { + return new Builder(); + } + + public static class Builder { + + private int decimalCount; + + private boolean metricUnits; + + private boolean reportSpeedOrPace; + + public Builder() { + decimalCount = 2; + metricUnits = true; + reportSpeedOrPace = true; + } + + public Builder setDecimalCount(int decimalCount) { + this.decimalCount = decimalCount; + return this; + } + + public Builder setMetricUnits(boolean metricUnits) { + this.metricUnits = metricUnits; + return this; + } + + public Builder setReportSpeedOrPace(boolean reportSpeedOrPace) { + this.reportSpeedOrPace = reportSpeedOrPace; + return this; + } + + public SpeedFormatter build(Resources resource) { + return new SpeedFormatter(resource, decimalCount, metricUnits, reportSpeedOrPace); + } + + public SpeedFormatter build(Context context) { + return build(context.getResources()); + } + } +} diff --git a/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordedFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordedFragment.java index e5dc928f9..58cc36fab 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordedFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordedFragment.java @@ -38,6 +38,7 @@ import de.dennisguse.opentracks.TrackRecordedActivity; import de.dennisguse.opentracks.adapters.StatisticsAdapter; import de.dennisguse.opentracks.data.ContentProviderUtils; import de.dennisguse.opentracks.data.models.DistanceFormatter; +import de.dennisguse.opentracks.data.models.SpeedFormatter; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.databinding.StatisticsRecordedBinding; import de.dennisguse.opentracks.settings.PreferencesUtils; @@ -207,11 +208,12 @@ public class StatisticsRecordedFragment extends Fragment { viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(trackStatistics.getTotalTime())); } + SpeedFormatter formatter = SpeedFormatter.Builder().setMetricUnits(preferenceMetricUnits).setReportSpeedOrPace(preferenceReportSpeed).build(getContext()); // Set average speed/pace { viewBinding.statsAverageSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace); - Pair parts = StringUtils.getSpeedParts(getContext(), trackStatistics.getAverageSpeed(), preferenceMetricUnits, preferenceReportSpeed); + Pair parts = formatter.getSpeedParts(trackStatistics.getAverageSpeed()); viewBinding.statsAverageSpeedValue.setText(parts.first); viewBinding.statsAverageSpeedUnit.setText(parts.second); } @@ -220,7 +222,7 @@ public class StatisticsRecordedFragment extends Fragment { { viewBinding.statsMaxSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_max_speed : R.string.stats_fastest_pace); - Pair parts = StringUtils.getSpeedParts(getContext(), trackStatistics.getMaxSpeed(), preferenceMetricUnits, preferenceReportSpeed); + Pair parts = formatter.getSpeedParts(trackStatistics.getMaxSpeed()); viewBinding.statsMaxSpeedValue.setText(parts.first); viewBinding.statsMaxSpeedUnit.setText(parts.second); } @@ -229,7 +231,7 @@ public class StatisticsRecordedFragment extends Fragment { { viewBinding.statsMovingSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace); - Pair parts = StringUtils.getSpeedParts(getContext(), trackStatistics.getAverageMovingSpeed(), preferenceMetricUnits, preferenceReportSpeed); + Pair parts = formatter.getSpeedParts(trackStatistics.getAverageMovingSpeed()); viewBinding.statsMovingSpeedValue.setText(parts.first); viewBinding.statsMovingSpeedUnit.setText(parts.second); } diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceNotificationManager.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceNotificationManager.java index fcb731a1e..29a167a64 100644 --- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceNotificationManager.java +++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceNotificationManager.java @@ -20,12 +20,12 @@ import de.dennisguse.opentracks.TrackRecordedActivity; import de.dennisguse.opentracks.TrackRecordingActivity; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.DistanceFormatter; +import de.dennisguse.opentracks.data.models.SpeedFormatter; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.util.IntentUtils; -import de.dennisguse.opentracks.util.StringUtils; /** * Manages the content of the notification shown by {@link TrackRecordingService}. @@ -97,7 +97,8 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh } notificationBuilder.setContentTitle(context.getString(R.string.track_distance_notification, formatter.formatDistance(trackStatistics.getTotalDistance()))); - notificationBuilder.setContentText(context.getString(R.string.track_speed_notification, StringUtils.formatSpeed(context, trackPoint.getSpeed(), metricUnits, true))); + String formattedSpeed = SpeedFormatter.Builder().setMetricUnits(metricUnits).setReportSpeedOrPace(true).build(context).formatSpeed(trackPoint.getSpeed()); + notificationBuilder.setContentText(context.getString(R.string.track_speed_notification, formattedSpeed)); notificationBuilder.setSubText(context.getString(R.string.track_recording_notification_accuracy, formattedAccuracy)); updateNotification(); diff --git a/src/main/java/de/dennisguse/opentracks/share/DescriptionGenerator.java b/src/main/java/de/dennisguse/opentracks/share/DescriptionGenerator.java index 5f16f396b..56f1b316d 100644 --- a/src/main/java/de/dennisguse/opentracks/share/DescriptionGenerator.java +++ b/src/main/java/de/dennisguse/opentracks/share/DescriptionGenerator.java @@ -28,6 +28,7 @@ import java.time.ZoneId; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.Speed; +import de.dennisguse.opentracks.data.models.SpeedFormatter; import de.dennisguse.opentracks.data.models.Track; import de.dennisguse.opentracks.data.models.UnitConversions; import de.dennisguse.opentracks.stats.TrackStatistics; @@ -209,8 +210,8 @@ public class DescriptionGenerator { */ @VisibleForTesting void writePace(Speed speed, StringBuilder builder, int resId, String lineBreak) { - Pair paceInMetrics = StringUtils.getSpeedParts(context, speed, true, false); - Pair paceInImperial = StringUtils.getSpeedParts(context, speed, false, false); + Pair paceInMetrics = SpeedFormatter.Builder().setMetricUnits(true).setReportSpeedOrPace(false).build(context).getSpeedParts(speed); + Pair paceInImperial = SpeedFormatter.Builder().setMetricUnits(false).setReportSpeedOrPace(false).build(context).getSpeedParts(speed); String formattedPaceMetrics = paceInMetrics.first != null ? paceInMetrics.first : context.getString(R.string.value_unknown); String formattedPaceImperial = paceInImperial.first != null ? paceInImperial.first : context.getString(R.string.value_unknown); diff --git a/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/AggregatedStatisticsAdapter.java b/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/AggregatedStatisticsAdapter.java index d841bdd1d..bc493f3cd 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/AggregatedStatisticsAdapter.java +++ b/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/AggregatedStatisticsAdapter.java @@ -14,6 +14,7 @@ import java.util.List; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.models.DistanceFormatter; +import de.dennisguse.opentracks.data.models.SpeedFormatter; import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.TrackIconUtils; @@ -119,15 +120,17 @@ public class AggregatedStatisticsAdapter extends BaseAdapter { public void setSpeed(AggregatedStatistics.AggregatedStatistic aggregatedStatistic) { setCommonValues(aggregatedStatistic); + + SpeedFormatter formatter = SpeedFormatter.Builder().setMetricUnits(metricsUnits).setReportSpeedOrPace(reportSpeed).build(context); { - Pair parts = StringUtils.getSpeedParts(context, aggregatedStatistic.getTrackStatistics().getAverageMovingSpeed(), metricsUnits, reportSpeed); + Pair parts = formatter.getSpeedParts(aggregatedStatistic.getTrackStatistics().getAverageMovingSpeed()); avgSpeed.setText(parts.first); avgSpeedUnit.setText(parts.second); avgSpeedLabel.setText(context.getString(R.string.stats_average_moving_speed)); } { - Pair parts = StringUtils.getSpeedParts(context, aggregatedStatistic.getTrackStatistics().getMaxSpeed(), metricsUnits, reportSpeed); + Pair parts = formatter.getSpeedParts(aggregatedStatistic.getTrackStatistics().getMaxSpeed()); maxSpeed.setText(parts.first); maxSpeedUnit.setText(parts.second); maxSpeedLabel.setText(context.getString(R.string.stats_max_speed)); @@ -135,16 +138,18 @@ public class AggregatedStatisticsAdapter extends BaseAdapter { } public void setPace(AggregatedStatistics.AggregatedStatistic aggregatedStatistic) { + SpeedFormatter formatter = SpeedFormatter.Builder().setMetricUnits(metricsUnits).setReportSpeedOrPace(reportSpeed).build(context); + setCommonValues(aggregatedStatistic); { - Pair parts = StringUtils.getSpeedParts(context, aggregatedStatistic.getTrackStatistics().getAverageMovingSpeed(), metricsUnits, reportSpeed); + Pair parts = formatter.getSpeedParts(aggregatedStatistic.getTrackStatistics().getAverageMovingSpeed()); avgSpeed.setText(parts.first); avgSpeedUnit.setText(parts.second); avgSpeedLabel.setText(context.getString(R.string.stats_average_moving_pace)); } { - Pair parts = StringUtils.getSpeedParts(context, aggregatedStatistic.getTrackStatistics().getMaxSpeed(), metricsUnits, reportSpeed); + Pair parts = formatter.getSpeedParts(aggregatedStatistic.getTrackStatistics().getMaxSpeed()); maxSpeed.setText(parts.first); maxSpeedUnit.setText(parts.second); maxSpeedLabel.setText(R.string.stats_fastest_pace); diff --git a/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsAdapter.java b/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsAdapter.java index 16c4ef59b..615d9b52d 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsAdapter.java +++ b/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsAdapter.java @@ -14,6 +14,7 @@ import java.util.List; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.models.Distance; import de.dennisguse.opentracks.data.models.DistanceFormatter; +import de.dennisguse.opentracks.data.models.SpeedFormatter; import de.dennisguse.opentracks.util.StringUtils; public class IntervalStatisticsAdapter extends RecyclerView.Adapter { @@ -59,7 +60,8 @@ public class IntervalStatisticsAdapter extends RecyclerView.Adapter distanceParts = getSpeedParts(context, speed, metricUnits, reportSpeed); - - return context.getString(R.string.speed_with_unit, distanceParts.first, distanceParts.second); - } - - private static String formatDecimal(double value) { - return StringUtils.formatDecimal(value, 2); - } /** * Format a decimal number while removing trailing zeros of the decimal part (if present). @@ -170,39 +160,6 @@ public class StringUtils { return context.getString(R.string.location_latitude_longitude, Location.convert(latitude, Location.FORMAT_DEGREES), Location.convert(longitude, Location.FORMAT_DEGREES)); } - /** - * Gets the formatted speed with unit. - * - * @param context the context - * @param speed the speed - * @param metricUnits true to use metric unit - * @param reportSpeed true to report speed; false for pace - * @return the formatted speed (or null) and it's unit as {@link Pair} - */ - public static Pair getSpeedParts(Context context, Speed speed, boolean metricUnits, boolean reportSpeed) { - int unitId; - if (metricUnits) { - unitId = reportSpeed ? R.string.unit_kilometer_per_hour : R.string.unit_minute_per_kilometer; - } else { - unitId = reportSpeed ? R.string.unit_mile_per_hour : R.string.unit_minute_per_mile; - } - String unitString = context.getString(unitId); - - if (speed == null) { - speed = Speed.zero(); - } - - if (reportSpeed) { - return new Pair<>(StringUtils.formatDecimal(speed.to(metricUnits), 1), unitString); - } - - int pace = (int) speed.toPace(metricUnits).getSeconds(); - - int minutes = pace / 60; - int seconds = pace % 60; - return new Pair<>(context.getString(R.string.time, minutes, seconds), unitString); - } - public static Pair getHeartRateParts(Context context, HeartRate heartrate) { String value = context.getString(R.string.value_unknown); if (heartrate != null) { diff --git a/src/main/java/de/dennisguse/opentracks/viewmodels/StatisticDataBuilder.java b/src/main/java/de/dennisguse/opentracks/viewmodels/StatisticDataBuilder.java index c6ec8eb61..07455614a 100644 --- a/src/main/java/de/dennisguse/opentracks/viewmodels/StatisticDataBuilder.java +++ b/src/main/java/de/dennisguse/opentracks/viewmodels/StatisticDataBuilder.java @@ -14,6 +14,7 @@ import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.data.models.Cadence; import de.dennisguse.opentracks.data.models.DistanceFormatter; import de.dennisguse.opentracks.data.models.Speed; +import de.dennisguse.opentracks.data.models.SpeedFormatter; import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet; import de.dennisguse.opentracks.services.RecordingData; @@ -47,6 +48,10 @@ public class StatisticDataBuilder { final String sensorUnknown = context.getString(R.string.value_unknown); + SpeedFormatter speedFormatterPace = SpeedFormatter.Builder().setMetricUnits(metricUnits).setReportSpeedOrPace(false).build(context); + SpeedFormatter speedFormatterSpeed = SpeedFormatter.Builder().setMetricUnits(metricUnits).setReportSpeedOrPace(true).build(context); + + if (fieldKey.equals(context.getString(R.string.stats_custom_layout_total_time_key))) { valueAndUnit = new Pair<>(StringUtils.formatElapsedTime(trackStatistics.getTotalTime()), null); title = context.getString(R.string.stats_total_time); @@ -62,31 +67,32 @@ public class StatisticDataBuilder { boolean reportSpeed = fieldKey.equals("speed"); title = reportSpeed ? context.getString(R.string.stats_speed) : context.getString(R.string.stats_pace); + SpeedFormatter localSpeedFormatter = SpeedFormatter.Builder().setMetricUnits(metricUnits).setReportSpeedOrPace(reportSpeed).build(context); if (sensorDataSet != null && sensorDataSet.getSpeed() != null) { - valueAndUnit = StringUtils.getSpeedParts(context, sensorDataSet.getSpeed().first, metricUnits, reportSpeed); + valueAndUnit = localSpeedFormatter.getSpeedParts(sensorDataSet.getSpeed().first); description = sensorDataSet.getSpeed().second; } else { Speed speed = latestTrackPoint != null && latestTrackPoint.hasSpeed() ? latestTrackPoint.getSpeed() : null; - valueAndUnit = StringUtils.getSpeedParts(context, speed, metricUnits, reportSpeed); + valueAndUnit = localSpeedFormatter.getSpeedParts(speed); description = context.getString(R.string.description_speed_source_gps); } } else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_average_moving_speed_key))) { - valueAndUnit = StringUtils.getSpeedParts(context, trackStatistics.getAverageMovingSpeed(), metricUnits, true); + valueAndUnit = speedFormatterSpeed.getSpeedParts(trackStatistics.getAverageMovingSpeed()); title = context.getString(R.string.stats_average_moving_speed); } else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_average_speed_key))) { - valueAndUnit = StringUtils.getSpeedParts(context, trackStatistics.getAverageSpeed(), metricUnits, true); + valueAndUnit = speedFormatterSpeed.getSpeedParts(trackStatistics.getAverageSpeed()); title = context.getString(R.string.stats_average_speed); } else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_max_speed_key))) { - valueAndUnit = StringUtils.getSpeedParts(context, trackStatistics.getMaxSpeed(), metricUnits, true); + valueAndUnit = speedFormatterSpeed.getSpeedParts(trackStatistics.getMaxSpeed()); title = context.getString(R.string.stats_max_speed); } else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_average_moving_pace_key))) { - valueAndUnit = StringUtils.getSpeedParts(context, trackStatistics.getAverageMovingSpeed(), metricUnits, false); + valueAndUnit = speedFormatterPace.getSpeedParts(trackStatistics.getAverageMovingSpeed()); title = context.getString(R.string.stats_average_moving_pace); } else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_average_pace_key))) { - valueAndUnit = StringUtils.getSpeedParts(context, trackStatistics.getAverageSpeed(), metricUnits, false); + valueAndUnit = speedFormatterPace.getSpeedParts(trackStatistics.getAverageSpeed()); title = context.getString(R.string.stats_average_pace); } else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_fastest_pace_key))) { - valueAndUnit = StringUtils.getSpeedParts(context, trackStatistics.getMaxSpeed(), metricUnits, true); + valueAndUnit = speedFormatterPace.getSpeedParts(trackStatistics.getMaxSpeed()); title = context.getString(R.string.stats_fastest_pace); } else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_altitude_key))) { Float altitude = latestTrackPoint != null && latestTrackPoint.hasAltitude() ? (float) latestTrackPoint.getAltitude().toM() : null;