Units: add imperial with meters.

Fixes of #1609.
This commit is contained in:
Dennis Guse
2023-06-15 18:23:50 +02:00
parent 9f1ea4d745
commit eb8d28dfc1
17 changed files with 46 additions and 35 deletions
@@ -27,7 +27,7 @@ public class ChartPointTest {
statistics.setTotalTime(Duration.ofSeconds(1000)); statistics.setTotalTime(Duration.ofSeconds(1000));
// when // when
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(0), false, UnitSystem.IMPERIAL); ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(0), false, UnitSystem.IMPERIAL_FEET);
// then // then
assertEquals(1000000, (long) point.getTimeOrDistance()); assertEquals(1000000, (long) point.getTimeOrDistance());
@@ -35,7 +35,7 @@ public class DistanceFormatterTest {
public void testFormatDistance_imperial() { public void testFormatDistance_imperial() {
DistanceFormatter formatter = DistanceFormatter.Builder() DistanceFormatter formatter = DistanceFormatter.Builder()
.setDecimalCount(2) .setDecimalCount(2)
.setUnit(UnitSystem.IMPERIAL) .setUnit(UnitSystem.IMPERIAL_FEET)
.build(context); .build(context);
// A large number in imperial // A large number in imperial
@@ -36,7 +36,7 @@ public class SpeedFormatterTest {
public void testGetSpeedParts_pace_imperial() { public void testGetSpeedParts_pace_imperial() {
SpeedFormatter formatter = SpeedFormatter.Builder() SpeedFormatter formatter = SpeedFormatter.Builder()
.setDecimalCount(2) .setDecimalCount(2)
.setUnit(UnitSystem.IMPERIAL) .setUnit(UnitSystem.IMPERIAL_FEET)
.setReportSpeedOrPace(false) .setReportSpeedOrPace(false)
.build(context); .build(context);
@@ -72,7 +72,7 @@ public class SpeedFormatterTest {
public void testGetSpeedParts_speed_imperial() { public void testGetSpeedParts_speed_imperial() {
SpeedFormatter formatter = SpeedFormatter.Builder() SpeedFormatter formatter = SpeedFormatter.Builder()
.setDecimalCount(2) .setDecimalCount(2)
.setUnit(UnitSystem.IMPERIAL) .setUnit(UnitSystem.IMPERIAL_FEET)
.setReportSpeedOrPace(true) .setReportSpeedOrPace(true)
.build(context); .build(context);
@@ -185,7 +185,7 @@ public class VoiceAnnouncementUtilsTest {
stats.setTotalAltitudeGain(6000f); stats.setTotalAltitudeGain(6000f);
// when // when
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL, true, null, null).toString(); String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL_FEET, true, null, null).toString();
// then // then
assertEquals("Total distance 12.4 miles. 1 hour 5 minutes 10 seconds. Average moving speed 11.4 miles per hour.", announcement); assertEquals("Total distance 12.4 miles. 1 hour 5 minutes 10 seconds. Average moving speed 11.4 miles per hour.", announcement);
@@ -207,7 +207,7 @@ public class VoiceAnnouncementUtilsTest {
} }
// when // when
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL, true, lastInterval, null).toString(); String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL_FEET, true, lastInterval, null).toString();
// then // then
assertEquals("Total distance 8.8 miles. 16 minutes 39 seconds. Average moving speed 31.8 miles per hour. Lap speed 31.8 miles per hour.", announcement); assertEquals("Total distance 8.8 miles. 16 minutes 39 seconds. Average moving speed 31.8 miles per hour. Lap speed 31.8 miles per hour.", announcement);
@@ -223,7 +223,7 @@ public class VoiceAnnouncementUtilsTest {
stats.setTotalAltitudeGain(6000f); stats.setTotalAltitudeGain(6000f);
// when // when
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL, false, null, null).toString(); String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL_FEET, false, null, null).toString();
// then // then
assertEquals("Total distance 12.4 miles. 1 hour 5 minutes 10 seconds. Pace 5 minutes 15 seconds per mile.", announcement); assertEquals("Total distance 12.4 miles. 1 hour 5 minutes 10 seconds. Pace 5 minutes 15 seconds per mile.", announcement);
@@ -245,7 +245,7 @@ public class VoiceAnnouncementUtilsTest {
} }
// when // when
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL, false, lastInterval, null).toString(); String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL_FEET, false, lastInterval, null).toString();
// then // then
assertEquals("Total distance 8.8 miles. 16 minutes 39 seconds. Pace 1 minute 53 seconds per mile. Lap time 1 minute 53 seconds per mile.", announcement); assertEquals("Total distance 8.8 miles. 16 minutes 39 seconds. Pace 1 minute 53 seconds per mile. Lap time 1 minute 53 seconds per mile.", announcement);
@@ -212,7 +212,7 @@ abstract class ChartValueSeries {
int getTitleId(UnitSystem unitSystem) { int getTitleId(UnitSystem unitSystem) {
return switch (unitSystem) { return switch (unitSystem) {
case METRIC -> metricTitleId; case METRIC -> metricTitleId;
case IMPERIAL -> imperialTitleId; case IMPERIAL_FEET, IMPERIAL_METER -> imperialTitleId;
case NAUTICAL_IMPERIAL -> nauticalTitleId; case NAUTICAL_IMPERIAL -> nauticalTitleId;
}; };
} }
@@ -735,7 +735,7 @@ public class ChartView extends View {
if (chartByDistance) { if (chartByDistance) {
return switch (unitSystem) { return switch (unitSystem) {
case METRIC -> context.getString(R.string.unit_kilometer); case METRIC -> context.getString(R.string.unit_kilometer);
case IMPERIAL -> context.getString(R.string.unit_mile); case IMPERIAL_FEET, IMPERIAL_METER -> context.getString(R.string.unit_mile);
case NAUTICAL_IMPERIAL -> context.getString(R.string.unit_nautical_mile); case NAUTICAL_IMPERIAL -> context.getString(R.string.unit_nautical_mile);
}; };
} else { } else {
@@ -3,8 +3,6 @@ package de.dennisguse.opentracks.data.models;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import java.util.Objects;
import de.dennisguse.opentracks.settings.UnitSystem; import de.dennisguse.opentracks.settings.UnitSystem;
public record Distance(double distance_m) { public record Distance(double distance_m) {
@@ -57,7 +55,7 @@ public record Distance(double distance_m) {
public static Distance one(UnitSystem unitSystem) { public static Distance one(UnitSystem unitSystem) {
return switch (unitSystem) { return switch (unitSystem) {
case METRIC -> Distance.ofKilometer(1); case METRIC -> Distance.ofKilometer(1);
case IMPERIAL -> Distance.ofMile(1); case IMPERIAL_FEET, IMPERIAL_METER -> Distance.ofMile(1);
case NAUTICAL_IMPERIAL -> Distance.ofNauticalMile(1); case NAUTICAL_IMPERIAL -> Distance.ofNauticalMile(1);
}; };
} }
@@ -121,15 +119,15 @@ public record Distance(double distance_m) {
public double toKM_Miles(UnitSystem unitSystem) { public double toKM_Miles(UnitSystem unitSystem) {
return switch (unitSystem) { return switch (unitSystem) {
case METRIC -> toKM(); case METRIC -> toKM();
case IMPERIAL -> toMI(); case IMPERIAL_FEET, IMPERIAL_METER -> toMI();
case NAUTICAL_IMPERIAL -> toNauticalMiles(); case NAUTICAL_IMPERIAL -> toNauticalMiles();
}; };
} }
public double toM_FT(UnitSystem unitSystem) { public double toM_FT(UnitSystem unitSystem) {
return switch (unitSystem) { return switch (unitSystem) {
case METRIC -> toM(); case METRIC, IMPERIAL_METER -> toM();
case NAUTICAL_IMPERIAL, IMPERIAL -> toFT(); case NAUTICAL_IMPERIAL, IMPERIAL_FEET -> toFT();
}; };
} }
@@ -47,8 +47,9 @@ public class DistanceFormatter {
if (distance.isInvalid()) { if (distance.isInvalid()) {
String valueUnknown = resources.getString(R.string.value_unknown); String valueUnknown = resources.getString(R.string.value_unknown);
return switch (unitSystem) { return switch (unitSystem) {
case METRIC -> new Pair<>(valueUnknown, resources.getString(R.string.unit_meter)); case METRIC, IMPERIAL_METER ->
case IMPERIAL, NAUTICAL_IMPERIAL -> new Pair<>(valueUnknown, resources.getString(R.string.unit_meter));
case IMPERIAL_FEET, NAUTICAL_IMPERIAL ->
new Pair<>(valueUnknown, resources.getString(R.string.unit_feet)); new Pair<>(valueUnknown, resources.getString(R.string.unit_feet));
}; };
} }
@@ -61,13 +62,20 @@ public class DistanceFormatter {
return new Pair<>(StringUtils.formatDecimal(distance.toM(), decimalCount), resources.getString(R.string.unit_meter)); return new Pair<>(StringUtils.formatDecimal(distance.toM(), decimalCount), resources.getString(R.string.unit_meter));
} }
} }
case IMPERIAL -> { case IMPERIAL_FEET -> {
if (distance.greaterThan(Distance.ofMile(threshold))) { if (distance.greaterThan(Distance.ofMile(threshold))) {
return new Pair<>(StringUtils.formatDecimal(distance.toMI(), decimalCount), resources.getString(R.string.unit_mile)); return new Pair<>(StringUtils.formatDecimal(distance.toMI(), decimalCount), resources.getString(R.string.unit_mile));
} else { } else {
return new Pair<>(StringUtils.formatDecimal(distance.toFT(), decimalCount), resources.getString(R.string.unit_feet)); return new Pair<>(StringUtils.formatDecimal(distance.toFT(), decimalCount), resources.getString(R.string.unit_feet));
} }
} }
case IMPERIAL_METER -> {
if (distance.greaterThan(Distance.ofMile(threshold))) {
return new Pair<>(StringUtils.formatDecimal(distance.toMI(), decimalCount), resources.getString(R.string.unit_mile));
} else {
return new Pair<>(StringUtils.formatDecimal(distance.toM(), decimalCount), resources.getString(R.string.unit_meter));
}
}
case NAUTICAL_IMPERIAL -> { case NAUTICAL_IMPERIAL -> {
if (distance.greaterThan(Distance.ofNauticalMile(threshold))) { if (distance.greaterThan(Distance.ofNauticalMile(threshold))) {
return new Pair<>(StringUtils.formatDecimal(distance.toNauticalMiles(), decimalCount), resources.getString(R.string.unit_nautical_mile)); return new Pair<>(StringUtils.formatDecimal(distance.toNauticalMiles(), decimalCount), resources.getString(R.string.unit_nautical_mile));
@@ -1,9 +1,6 @@
package de.dennisguse.opentracks.data.models; package de.dennisguse.opentracks.data.models;
import androidx.annotation.NonNull;
import java.time.Duration; import java.time.Duration;
import java.util.Objects;
import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.settings.UnitSystem; import de.dennisguse.opentracks.settings.UnitSystem;
@@ -111,7 +108,7 @@ public record Speed(double speed_mps) {
public double to(UnitSystem unitSystem) { public double to(UnitSystem unitSystem) {
return switch (unitSystem) { return switch (unitSystem) {
case METRIC -> toKMH(); case METRIC -> toKMH();
case IMPERIAL -> toMPH(); case IMPERIAL_FEET, IMPERIAL_METER -> toMPH();
case NAUTICAL_IMPERIAL -> toKnots(); case NAUTICAL_IMPERIAL -> toKnots();
}; };
} }
@@ -42,7 +42,7 @@ public class SpeedFormatter {
int unitId = switch (unitSystem) { int unitId = switch (unitSystem) {
case METRIC -> case METRIC ->
reportSpeedOrPace ? R.string.unit_kilometer_per_hour : R.string.unit_minute_per_kilometer; reportSpeedOrPace ? R.string.unit_kilometer_per_hour : R.string.unit_minute_per_kilometer;
case IMPERIAL -> case IMPERIAL_FEET, IMPERIAL_METER ->
reportSpeedOrPace ? R.string.unit_mile_per_hour : R.string.unit_minute_per_mile; reportSpeedOrPace ? R.string.unit_mile_per_hour : R.string.unit_minute_per_mile;
case NAUTICAL_IMPERIAL -> case NAUTICAL_IMPERIAL ->
reportSpeedOrPace ? R.string.unit_knots : R.string.unit_minute_per_nautical_mile; reportSpeedOrPace ? R.string.unit_knots : R.string.unit_minute_per_nautical_mile;
@@ -50,7 +50,7 @@ class VoiceAnnouncementUtils {
unitDistanceTTS = "kilometer"; unitDistanceTTS = "kilometer";
unitSpeedTTS = "kilometer per hour"; unitSpeedTTS = "kilometer per hour";
} }
case IMPERIAL -> { case IMPERIAL_FEET -> {
perUnitStringId = R.string.voice_per_mile; perUnitStringId = R.string.voice_per_mile;
distanceId = R.plurals.voiceDistanceMiles; distanceId = R.plurals.voiceDistanceMiles;
speedId = R.plurals.voiceSpeedMilesPerHour; speedId = R.plurals.voiceSpeedMilesPerHour;
@@ -70,7 +70,8 @@ public class DefaultsSettingsFragment extends PreferenceFragmentCompat implement
int entriesId = switch (unitSystem) { int entriesId = switch (unitSystem) {
case METRIC -> R.array.stats_rate_metric_options; case METRIC -> R.array.stats_rate_metric_options;
case IMPERIAL, NAUTICAL_IMPERIAL -> R.array.stats_rate_imperial_options; case IMPERIAL_FEET, IMPERIAL_METER, NAUTICAL_IMPERIAL ->
R.array.stats_rate_imperial_options;
}; };
String[] entries = getResources().getStringArray(entriesId); String[] entries = getResources().getStringArray(entriesId);
@@ -228,7 +228,7 @@ public class PreferencesUtils {
if (!Locale.US.equals(Locale.getDefault())) { if (!Locale.US.equals(Locale.getDefault())) {
setUnit(UnitSystem.METRIC); setUnit(UnitSystem.METRIC);
} else { } else {
setUnit(UnitSystem.IMPERIAL); setUnit(UnitSystem.IMPERIAL_FEET);
} }
} }
} }
@@ -455,7 +455,7 @@ public class PreferencesUtils {
entries[i] = displayValue; entries[i] = displayValue;
} }
} }
case IMPERIAL, NAUTICAL_IMPERIAL -> { case IMPERIAL_FEET, NAUTICAL_IMPERIAL -> {
if (value == recordingDistanceIntervalDefault) { if (value == recordingDistanceIntervalDefault) {
entries[i] = resources.getString(R.string.value_integer_feet_recommended, (int) distance.toFT()); entries[i] = resources.getString(R.string.value_integer_feet_recommended, (int) distance.toFT());
} else { } else {
@@ -499,7 +499,7 @@ public class PreferencesUtils {
entries[i] = displayValue; entries[i] = displayValue;
} }
} }
case IMPERIAL, NAUTICAL_IMPERIAL -> { case IMPERIAL_FEET, NAUTICAL_IMPERIAL -> {
if (value == maxRecordingDistanceDefault) { if (value == maxRecordingDistanceDefault) {
entries[i] = resources.getString(R.string.value_integer_feet_recommended, (int) distance.toFT()); entries[i] = resources.getString(R.string.value_integer_feet_recommended, (int) distance.toFT());
} else { } else {
@@ -576,7 +576,7 @@ public class PreferencesUtils {
entries[i] = displayValue; entries[i] = displayValue;
} }
} }
case IMPERIAL, NAUTICAL_IMPERIAL -> { case IMPERIAL_FEET, NAUTICAL_IMPERIAL -> {
if (value == recordingGPSAccuracyDefault) { if (value == recordingGPSAccuracyDefault) {
entries[i] = resources.getString(R.string.value_integer_feet_recommended, (int) distance.toFT()); entries[i] = resources.getString(R.string.value_integer_feet_recommended, (int) distance.toFT());
} else if (value == recordingGPSAccuracyExcellent) { } else if (value == recordingGPSAccuracyExcellent) {
@@ -618,7 +618,7 @@ public class PreferencesUtils {
entries[i] = resources.getString(R.string.value_float_kilometer_hour, value); entries[i] = resources.getString(R.string.value_float_kilometer_hour, value);
} }
} }
case IMPERIAL -> { case IMPERIAL_FEET -> {
double valueMPH = Speed.ofKMH(value).toMPH(); double valueMPH = Speed.ofKMH(value).toMPH();
if (value == idleSpeedDefault) { if (value == idleSpeedDefault) {
entries[i] = resources.getString(R.string.value_float_mile_hour_recommended, valueMPH); entries[i] = resources.getString(R.string.value_float_mile_hour_recommended, valueMPH);
@@ -4,7 +4,10 @@ import de.dennisguse.opentracks.R;
public enum UnitSystem { public enum UnitSystem {
METRIC(R.string.stats_units_metric), METRIC(R.string.stats_units_metric),
IMPERIAL(R.string.stats_units_imperial),
IMPERIAL_FEET(R.string.stats_units_imperial_feet),
IMPERIAL_METER(R.string.stats_units_imperial_meter),
NAUTICAL_IMPERIAL(R.string.stats_units_nautical); // Nautical miles with feet NAUTICAL_IMPERIAL(R.string.stats_units_nautical); // Nautical miles with feet
private final int preferenceIdentifier; private final int preferenceIdentifier;
@@ -211,7 +211,7 @@ public class DescriptionGenerator {
@VisibleForTesting @VisibleForTesting
void writePace(Speed speed, StringBuilder builder, int resId, String lineBreak) { void writePace(Speed speed, StringBuilder builder, int resId, String lineBreak) {
Pair<String, String> paceInMetrics = SpeedFormatter.Builder().setUnit(UnitSystem.METRIC).setReportSpeedOrPace(false).build(context).getSpeedParts(speed); Pair<String, String> paceInMetrics = SpeedFormatter.Builder().setUnit(UnitSystem.METRIC).setReportSpeedOrPace(false).build(context).getSpeedParts(speed);
Pair<String, String> paceInImperial = SpeedFormatter.Builder().setUnit(UnitSystem.IMPERIAL).setReportSpeedOrPace(false).build(context).getSpeedParts(speed); Pair<String, String> paceInImperial = SpeedFormatter.Builder().setUnit(UnitSystem.IMPERIAL_FEET).setReportSpeedOrPace(false).build(context).getSpeedParts(speed);
String formattedPaceMetrics = paceInMetrics.first != null ? paceInMetrics.first : context.getString(R.string.value_unknown); 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); String formattedPaceImperial = paceInImperial.first != null ? paceInImperial.first : context.getString(R.string.value_unknown);
+5 -2
View File
@@ -169,15 +169,18 @@
<string name="stats_units_default" translatable="false">@string/stats_units_metric</string> <string name="stats_units_default" translatable="false">@string/stats_units_metric</string>
<string-array name="stats_units_values"> <string-array name="stats_units_values">
<item>@string/stats_units_metric</item> <item>@string/stats_units_metric</item>
<item>@string/stats_units_imperial</item> <item>@string/stats_units_imperial_feet</item>
<item>@string/stats_units_imperial_meter</item>
<item>@string/stats_units_nautical</item> <item>@string/stats_units_nautical</item>
</string-array> </string-array>
<string name="stats_units_metric" translatable="false">METRIC</string> <string name="stats_units_metric" translatable="false">METRIC</string>
<string name="stats_units_imperial" translatable="false">IMPERIAL</string> <string name="stats_units_imperial_feet" translatable="false">IMPERIAL</string>
<string name="stats_units_imperial_meter" translatable="false">IMPERIAL_METER</string>
<string name="stats_units_nautical" translatable="false">NAUTICAL</string> <string name="stats_units_nautical" translatable="false">NAUTICAL</string>
<string-array name="stats_units_options"> <string-array name="stats_units_options">
<item>@string/settings_stats_units_metric</item> <item>@string/settings_stats_units_metric</item>
<item>@string/settings_stats_units_imperial</item> <item>@string/settings_stats_units_imperial</item>
<item>@string/settings_stats_units_imperial_meter</item>
<item>@string/settings_stats_units_nautical</item> <item>@string/settings_stats_units_nautical</item>
</string-array> </string-array>
+1
View File
@@ -440,6 +440,7 @@ limitations under the License.
<!-- Settings Stats --> <!-- Settings Stats -->
<string name="settings_stats_rate_title">Preferred rate</string> <string name="settings_stats_rate_title">Preferred rate</string>
<string name="settings_stats_units_imperial">Imperial (mi, ft)</string> <string name="settings_stats_units_imperial">Imperial (mi, ft)</string>
<string name="settings_stats_units_imperial_meter">Imperial (mi, m)</string>
<string name="settings_stats_units_metric">Metric (km, m)</string> <string name="settings_stats_units_metric">Metric (km, m)</string>
<string name="settings_stats_units_nautical">Nautical (NM, ft)</string> <string name="settings_stats_units_nautical">Nautical (NM, ft)</string>
<string name="settings_stats_units_title">Preferred units</string> <string name="settings_stats_units_title">Preferred units</string>