forked from upstream-mirrors/OpenTracks
+8
-7
@@ -5,12 +5,13 @@ import org.junit.runner.Description;
|
|||||||
import org.junit.runners.model.Statement;
|
import org.junit.runners.model.Statement;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
|
|
||||||
public class PreferenceMetricUnitRule implements TestRule {
|
public class PreferenceUnitSystemRule implements TestRule {
|
||||||
private final boolean metricUnits;
|
private final UnitSystem unit;
|
||||||
|
|
||||||
public PreferenceMetricUnitRule(boolean metricUnits) {
|
public PreferenceUnitSystemRule(UnitSystem unit) {
|
||||||
this.metricUnits = metricUnits;
|
this.unit = unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -18,13 +19,13 @@ public class PreferenceMetricUnitRule implements TestRule {
|
|||||||
return new Statement() {
|
return new Statement() {
|
||||||
@Override
|
@Override
|
||||||
public void evaluate() throws Throwable {
|
public void evaluate() throws Throwable {
|
||||||
final boolean previousMetricUnits = PreferencesUtils.isMetricUnits();
|
final UnitSystem previousUnitSystem = PreferencesUtils.getUnitSystem();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PreferencesUtils.setMetricUnits(metricUnits);
|
PreferencesUtils.setUnit(unit);
|
||||||
base.evaluate();
|
base.evaluate();
|
||||||
} finally {
|
} finally {
|
||||||
PreferencesUtils.setMetricUnits(previousMetricUnits);
|
PreferencesUtils.setUnit(previousUnitSystem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -14,6 +14,7 @@ import de.dennisguse.opentracks.data.models.Altitude;
|
|||||||
import de.dennisguse.opentracks.data.models.Distance;
|
import de.dennisguse.opentracks.data.models.Distance;
|
||||||
import de.dennisguse.opentracks.data.models.Speed;
|
import de.dennisguse.opentracks.data.models.Speed;
|
||||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -26,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), Altitude.EGM2008.of(0), false, false);
|
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(0), Altitude.EGM2008.of(0), false, UnitSystem.IMPERIAL);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(1000000, (long) point.getTimeOrDistance());
|
assertEquals(1000000, (long) point.getTimeOrDistance());
|
||||||
@@ -39,7 +40,7 @@ public class ChartPointTest {
|
|||||||
statistics.setTotalDistance(Distance.of(1000));
|
statistics.setTotalDistance(Distance.of(1000));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(0), Altitude.EGM2008.of(0), true, true);
|
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(0), Altitude.EGM2008.of(0), true, UnitSystem.METRIC);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(1, (long) point.getTimeOrDistance());
|
assertEquals(1, (long) point.getTimeOrDistance());
|
||||||
@@ -51,7 +52,7 @@ public class ChartPointTest {
|
|||||||
TrackStatistics statistics = new TrackStatistics();
|
TrackStatistics statistics = new TrackStatistics();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(10), Altitude.EGM2008.of(50), false, true);
|
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(10), Altitude.EGM2008.of(50), false, UnitSystem.METRIC);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(50, point.getAltitude(), 0.01);
|
assertEquals(50, point.getAltitude(), 0.01);
|
||||||
@@ -65,7 +66,7 @@ public class ChartPointTest {
|
|||||||
TrackStatistics statistics = new TrackStatistics();
|
TrackStatistics statistics = new TrackStatistics();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(10), Altitude.EGM2008.of(50), false, true);
|
ChartPoint point = new ChartPoint(statistics, TrackStubUtils.createDefaultTrackPoint(), Speed.of(10), Altitude.EGM2008.of(50), false, UnitSystem.METRIC);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertNull(point.getHeartRate());
|
assertNull(point.getHeartRate());
|
||||||
@@ -84,7 +85,7 @@ public class ChartPointTest {
|
|||||||
TrackStatistics statistics = new TrackStatistics();
|
TrackStatistics statistics = new TrackStatistics();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
ChartPoint point = new ChartPoint(statistics, trackPoint, Speed.of(10), Altitude.EGM2008.of(50), false, true);
|
ChartPoint point = new ChartPoint(statistics, trackPoint, Speed.of(10), Altitude.EGM2008.of(50), false, UnitSystem.METRIC);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(100.0, point.getHeartRate(), 0.01);
|
assertEquals(100.0, point.getHeartRate(), 0.01);
|
||||||
|
|||||||
+4
-2
@@ -10,6 +10,8 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class DistanceFormatterTest {
|
public class DistanceFormatterTest {
|
||||||
|
|
||||||
@@ -19,7 +21,7 @@ public class DistanceFormatterTest {
|
|||||||
public void testFormatDistance_metric() {
|
public void testFormatDistance_metric() {
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setDecimalCount(2)
|
.setDecimalCount(2)
|
||||||
.setMetricUnits(true)
|
.setUnit(UnitSystem.METRIC)
|
||||||
.build(context);
|
.build(context);
|
||||||
|
|
||||||
// A large number in metric
|
// A large number in metric
|
||||||
@@ -32,7 +34,7 @@ public class DistanceFormatterTest {
|
|||||||
public void testFormatDistance_imperial() {
|
public void testFormatDistance_imperial() {
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setDecimalCount(2)
|
.setDecimalCount(2)
|
||||||
.setMetricUnits(false)
|
.setUnit(UnitSystem.IMPERIAL)
|
||||||
.build(context);
|
.build(context);
|
||||||
|
|
||||||
// A large number in imperial
|
// A large number in imperial
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class SpeedFormatterTest {
|
public class SpeedFormatterTest {
|
||||||
|
|
||||||
@@ -19,7 +21,7 @@ public class SpeedFormatterTest {
|
|||||||
public void testGetSpeedParts_pace_metric() {
|
public void testGetSpeedParts_pace_metric() {
|
||||||
SpeedFormatter formatter = SpeedFormatter.Builder()
|
SpeedFormatter formatter = SpeedFormatter.Builder()
|
||||||
.setDecimalCount(2)
|
.setDecimalCount(2)
|
||||||
.setMetricUnits(true)
|
.setUnit(UnitSystem.METRIC)
|
||||||
.setReportSpeedOrPace(false)
|
.setReportSpeedOrPace(false)
|
||||||
.build(context);
|
.build(context);
|
||||||
|
|
||||||
@@ -33,7 +35,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)
|
||||||
.setMetricUnits(false)
|
.setUnit(UnitSystem.IMPERIAL)
|
||||||
.setReportSpeedOrPace(false)
|
.setReportSpeedOrPace(false)
|
||||||
.build(context);
|
.build(context);
|
||||||
|
|
||||||
@@ -47,7 +49,7 @@ public class SpeedFormatterTest {
|
|||||||
public void testGetSpeedParts_speed_metric() {
|
public void testGetSpeedParts_speed_metric() {
|
||||||
SpeedFormatter formatter = SpeedFormatter.Builder()
|
SpeedFormatter formatter = SpeedFormatter.Builder()
|
||||||
.setDecimalCount(2)
|
.setDecimalCount(2)
|
||||||
.setMetricUnits(true)
|
.setUnit(UnitSystem.METRIC)
|
||||||
.setReportSpeedOrPace(true)
|
.setReportSpeedOrPace(true)
|
||||||
.build(context);
|
.build(context);
|
||||||
|
|
||||||
@@ -59,7 +61,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)
|
||||||
.setMetricUnits(false)
|
.setUnit(UnitSystem.IMPERIAL)
|
||||||
.setReportSpeedOrPace(true)
|
.setReportSpeedOrPace(true)
|
||||||
.build(context);
|
.build(context);
|
||||||
|
|
||||||
@@ -71,7 +73,7 @@ public class SpeedFormatterTest {
|
|||||||
public void testFormatSpeed() {
|
public void testFormatSpeed() {
|
||||||
SpeedFormatter formatter = SpeedFormatter.Builder()
|
SpeedFormatter formatter = SpeedFormatter.Builder()
|
||||||
.setDecimalCount(2)
|
.setDecimalCount(2)
|
||||||
.setMetricUnits(true)
|
.setUnit(UnitSystem.METRIC)
|
||||||
.setReportSpeedOrPace(false)
|
.setReportSpeedOrPace(false)
|
||||||
.build(context);
|
.build(context);
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -19,6 +19,7 @@ import org.mockito.junit.MockitoJUnitRunner;
|
|||||||
import de.dennisguse.opentracks.data.models.Distance;
|
import de.dennisguse.opentracks.data.models.Distance;
|
||||||
import de.dennisguse.opentracks.data.models.Speed;
|
import de.dennisguse.opentracks.data.models.Speed;
|
||||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
@@ -48,7 +49,7 @@ public class TrackRecordingServiceNotificationManagerTest {
|
|||||||
.thenReturn(notificationCompatBuilder);
|
.thenReturn(notificationCompatBuilder);
|
||||||
|
|
||||||
TrackRecordingServiceNotificationManager subject = new TrackRecordingServiceNotificationManager(notificationManager, notificationCompatBuilder);
|
TrackRecordingServiceNotificationManager subject = new TrackRecordingServiceNotificationManager(notificationManager, notificationCompatBuilder);
|
||||||
subject.setMetricUnits(true);
|
subject.setUnitSystem(UnitSystem.METRIC);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
subject.updateTrackPoint(context, trackStatisticsMock, trackPointMock, Distance.of(100));
|
subject.updateTrackPoint(context, trackStatisticsMock, trackPointMock, Distance.of(100));
|
||||||
|
|||||||
+10
-9
@@ -25,6 +25,7 @@ import de.dennisguse.opentracks.data.models.HeartRate;
|
|||||||
import de.dennisguse.opentracks.data.models.Speed;
|
import de.dennisguse.opentracks.data.models.Speed;
|
||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
|
import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
|
||||||
@@ -54,7 +55,7 @@ public class VoiceAnnouncementUtilsTest {
|
|||||||
stats.setTotalAltitudeGain(6000f);
|
stats.setTotalAltitudeGain(6000f);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, true, true, null, null).toString();
|
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.METRIC, true, null, null).toString();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals("Total distance 20.00 kilometers. 1 hour 5 minutes 10 seconds. Speed 18.4 kilometers per hour.", announcement);
|
assertEquals("Total distance 20.00 kilometers. 1 hour 5 minutes 10 seconds. Speed 18.4 kilometers per hour.", announcement);
|
||||||
@@ -76,7 +77,7 @@ public class VoiceAnnouncementUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, true, true, lastInterval, null).toString();
|
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.METRIC, true, lastInterval, null).toString();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals("Total distance 14.21 kilometers. 16 minutes 39 seconds. Speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour.", announcement);
|
assertEquals("Total distance 14.21 kilometers. 16 minutes 39 seconds. Speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour.", announcement);
|
||||||
@@ -92,7 +93,7 @@ public class VoiceAnnouncementUtilsTest {
|
|||||||
stats.setTotalAltitudeGain(6000f);
|
stats.setTotalAltitudeGain(6000f);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, true, false, null, null).toString();
|
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.METRIC, false, null, null).toString();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals("Total distance 20.00 kilometers. 1 hour 5 minutes 10 seconds. Pace 3 minutes 15 seconds per kilometer.", announcement);
|
assertEquals("Total distance 20.00 kilometers. 1 hour 5 minutes 10 seconds. Pace 3 minutes 15 seconds per kilometer.", announcement);
|
||||||
@@ -114,7 +115,7 @@ public class VoiceAnnouncementUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, true, false, lastInterval, null).toString();
|
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.METRIC, false, lastInterval, null).toString();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals("Total distance 14.21 kilometers. 16 minutes 39 seconds. Pace 1 minute 10 seconds per kilometer. Lap time 1 minute 10 seconds per kilometer.", announcement);
|
assertEquals("Total distance 14.21 kilometers. 16 minutes 39 seconds. Pace 1 minute 10 seconds per kilometer. Lap time 1 minute 10 seconds per kilometer.", announcement);
|
||||||
@@ -130,7 +131,7 @@ public class VoiceAnnouncementUtilsTest {
|
|||||||
stats.setTotalAltitudeGain(6000f);
|
stats.setTotalAltitudeGain(6000f);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, false, true, null, null).toString();
|
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL, true, null, null).toString();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals("Total distance 12.43 miles. 1 hour 5 minutes 10 seconds. Speed 11.4 miles per hour.", announcement);
|
assertEquals("Total distance 12.43 miles. 1 hour 5 minutes 10 seconds. Speed 11.4 miles per hour.", announcement);
|
||||||
@@ -152,7 +153,7 @@ public class VoiceAnnouncementUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, false, true, lastInterval, null).toString();
|
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL, true, lastInterval, null).toString();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals("Total distance 8.83 miles. 16 minutes 39 seconds. Speed 31.8 miles per hour. Lap speed 31.8 miles per hour.", announcement);
|
assertEquals("Total distance 8.83 miles. 16 minutes 39 seconds. Speed 31.8 miles per hour. Lap speed 31.8 miles per hour.", announcement);
|
||||||
@@ -168,7 +169,7 @@ public class VoiceAnnouncementUtilsTest {
|
|||||||
stats.setTotalAltitudeGain(6000f);
|
stats.setTotalAltitudeGain(6000f);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, false, false, null, null).toString();
|
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL, false, null, null).toString();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals("Total distance 12.43 miles. 1 hour 5 minutes 10 seconds. Pace 5 minutes 15 seconds per mile.", announcement);
|
assertEquals("Total distance 12.43 miles. 1 hour 5 minutes 10 seconds. Pace 5 minutes 15 seconds per mile.", announcement);
|
||||||
@@ -190,7 +191,7 @@ public class VoiceAnnouncementUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, false, false, lastInterval, null).toString();
|
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.IMPERIAL, false, lastInterval, null).toString();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals("Total distance 8.83 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.83 miles. 16 minutes 39 seconds. Pace 1 minute 53 seconds per mile. Lap time 1 minute 53 seconds per mile.", announcement);
|
||||||
@@ -215,7 +216,7 @@ public class VoiceAnnouncementUtilsTest {
|
|||||||
SensorStatistics sensorStatistics = new SensorStatistics(HeartRate.of(180f), HeartRate.of(180f), null, null, null);
|
SensorStatistics sensorStatistics = new SensorStatistics(HeartRate.of(180f), HeartRate.of(180f), null, null, null);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, true, true, lastInterval, sensorStatistics).toString();
|
String announcement = VoiceAnnouncementUtils.getAnnouncement(context, stats, UnitSystem.METRIC, true, lastInterval, sensorStatistics).toString();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals("Total distance 14.21 kilometers. 16 minutes 39 seconds. Speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour. Average heart rate 180 bpm. Current heart rate 133 bpm.", announcement);
|
assertEquals("Total distance 14.21 kilometers. 16 minutes 39 seconds. Speed 51.2 kilometers per hour. Lap speed 51.2 kilometers per hour. Average heart rate 180 bpm. Current heart rate 133 bpm.", announcement);
|
||||||
|
|||||||
+3
-2
@@ -23,6 +23,7 @@ import de.dennisguse.opentracks.data.models.HeartRate;
|
|||||||
import de.dennisguse.opentracks.data.models.Power;
|
import de.dennisguse.opentracks.data.models.Power;
|
||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
import de.dennisguse.opentracks.services.RecordingData;
|
import de.dennisguse.opentracks.services.RecordingData;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.ui.customRecordingLayout.Layout;
|
import de.dennisguse.opentracks.ui.customRecordingLayout.Layout;
|
||||||
@@ -61,7 +62,7 @@ public class StatisticDataBuilderTest extends TestCase {
|
|||||||
layout.addField(context.getString(R.string.stats_custom_layout_max_speed_key), context.getString(R.string.stats_max_speed), false, true, false);
|
layout.addField(context.getString(R.string.stats_custom_layout_max_speed_key), context.getString(R.string.stats_max_speed), false, true, false);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
List<StatisticData> statisticDataList = StatisticDataBuilder.fromRecordingData(context, recordingDataMock, layout, true);
|
List<StatisticData> statisticDataList = StatisticDataBuilder.fromRecordingData(context, recordingDataMock, layout, UnitSystem.METRIC);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(statisticDataList.size(), 3);
|
assertEquals(statisticDataList.size(), 3);
|
||||||
@@ -100,7 +101,7 @@ public class StatisticDataBuilderTest extends TestCase {
|
|||||||
layout.addField(context.getString(R.string.stats_custom_layout_power_key), context.getString(R.string.stats_sensors_power), true, true, false);
|
layout.addField(context.getString(R.string.stats_custom_layout_power_key), context.getString(R.string.stats_sensors_power), true, true, false);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
List<StatisticData> statisticDataList = StatisticDataBuilder.fromRecordingData(context, recordingDataMock, layout, true);
|
List<StatisticData> statisticDataList = StatisticDataBuilder.fromRecordingData(context, recordingDataMock, layout, UnitSystem.METRIC);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(statisticDataList.size(), 18);
|
assertEquals(statisticDataList.size(), 18);
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import android.app.Application;
|
|||||||
import android.os.StrictMode;
|
import android.os.StrictMode;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,9 +26,7 @@ public class Startup extends Application {
|
|||||||
PreferencesUtils.initPreferences(this, getResources());
|
PreferencesUtils.initPreferences(this, getResources());
|
||||||
// Set default values of preferences on first start.
|
// Set default values of preferences on first start.
|
||||||
PreferencesUtils.resetPreferences(this, false);
|
PreferencesUtils.resetPreferences(this, false);
|
||||||
if (PreferencesUtils.getString( R.string.stats_units_key, "").equals("")) {
|
PreferencesUtils.applyDefaultUnit();
|
||||||
PreferencesUtils.setMetricUnits(!Locale.US.equals(Locale.getDefault()));
|
|
||||||
}
|
|
||||||
PreferencesUtils.applyNightMode();
|
PreferencesUtils.applyNightMode();
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
|||||||
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
|
import de.dennisguse.opentracks.services.handlers.GpsStatusValue;
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
import de.dennisguse.opentracks.settings.SettingsActivity;
|
import de.dennisguse.opentracks.settings.SettingsActivity;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.share.ShareUtils;
|
import de.dennisguse.opentracks.share.ShareUtils;
|
||||||
import de.dennisguse.opentracks.ui.aggregatedStatistics.AggregatedStatisticsActivity;
|
import de.dennisguse.opentracks.ui.aggregatedStatistics.AggregatedStatisticsActivity;
|
||||||
import de.dennisguse.opentracks.ui.aggregatedStatistics.ConfirmDeleteDialogFragment;
|
import de.dennisguse.opentracks.ui.aggregatedStatistics.ConfirmDeleteDialogFragment;
|
||||||
@@ -88,7 +89,7 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
|
|||||||
private final TrackLoaderCallBack loaderCallbacks = new TrackLoaderCallBack();
|
private final TrackLoaderCallBack loaderCallbacks = new TrackLoaderCallBack();
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
private boolean metricUnits = true;
|
private UnitSystem unitSystem = UnitSystem.defaultUnitSystem();
|
||||||
|
|
||||||
private GpsStatusValue gpsStatusValue = TrackRecordingService.STATUS_GPS_DEFAULT;
|
private GpsStatusValue gpsStatusValue = TrackRecordingService.STATUS_GPS_DEFAULT;
|
||||||
private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
private RecordingStatus recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||||
@@ -112,7 +113,7 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
|
|||||||
|
|
||||||
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> {
|
private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> {
|
||||||
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
||||||
metricUnits = PreferencesUtils.isMetricUnits();
|
unitSystem = PreferencesUtils.getUnitSystem();
|
||||||
}
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
@@ -192,7 +193,7 @@ public class TrackListActivity extends AbstractTrackDeleteActivity implements Co
|
|||||||
String name = cursor.getString(nameIndex);
|
String name = cursor.getString(nameIndex);
|
||||||
String totalTime = StringUtils.formatElapsedTime(Duration.ofMillis(cursor.getLong(totalTimeIndex)));
|
String totalTime = StringUtils.formatElapsedTime(Duration.ofMillis(cursor.getLong(totalTimeIndex)));
|
||||||
String totalDistance = DistanceFormatter.Builder()
|
String totalDistance = DistanceFormatter.Builder()
|
||||||
.setMetricUnits(metricUnits)
|
.setUnit(unitSystem)
|
||||||
.build(TrackListActivity.this).formatDistance(Distance.of(cursor.getDouble(totalDistanceIndex)));
|
.build(TrackListActivity.this).formatDistance(Distance.of(cursor.getDouble(totalDistanceIndex)));
|
||||||
int markerCount = cursor.getInt(markerCountIndex);
|
int markerCount = cursor.getInt(markerCountIndex);
|
||||||
long startTime = cursor.getLong(startTimeIndex);
|
long startTime = cursor.getLong(startTimeIndex);
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import de.dennisguse.opentracks.data.models.Track;
|
|||||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||||
import de.dennisguse.opentracks.databinding.ChartBinding;
|
import de.dennisguse.opentracks.databinding.ChartBinding;
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
||||||
|
|
||||||
@@ -77,9 +78,9 @@ public class ChartFragment extends Fragment implements TrackDataHub.Listener {
|
|||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
||||||
boolean metricUnits = PreferencesUtils.isMetricUnits();
|
UnitSystem unitSystem = PreferencesUtils.getUnitSystem();
|
||||||
if (metricUnits != viewBinding.chartView.getMetricUnits()) {
|
if (unitSystem != viewBinding.chartView.getUnitSystem()) {
|
||||||
viewBinding.chartView.setMetricUnits(metricUnits);
|
viewBinding.chartView.setUnitSystem(unitSystem);
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
if (isResumed()) {
|
if (isResumed()) {
|
||||||
viewBinding.chartView.requestLayout();
|
viewBinding.chartView.requestLayout();
|
||||||
@@ -189,7 +190,7 @@ public class ChartFragment extends Fragment implements TrackDataHub.Listener {
|
|||||||
|
|
||||||
public void onSampledInTrackPoint(@NonNull TrackPoint trackPoint, @NonNull TrackStatistics trackStatistics, Speed smoothedSpeed, Altitude smoothedAltitude) {
|
public void onSampledInTrackPoint(@NonNull TrackPoint trackPoint, @NonNull TrackStatistics trackStatistics, Speed smoothedSpeed, Altitude smoothedAltitude) {
|
||||||
if (isResumed()) {
|
if (isResumed()) {
|
||||||
ChartPoint point = new ChartPoint(trackStatistics, trackPoint, smoothedSpeed, smoothedAltitude, chartByDistance, viewBinding.chartView.getMetricUnits());
|
ChartPoint point = new ChartPoint(trackStatistics, trackPoint, smoothedSpeed, smoothedAltitude, chartByDistance, viewBinding.chartView.getUnitSystem());
|
||||||
pendingPoints.add(point);
|
pendingPoints.add(point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import de.dennisguse.opentracks.data.models.Distance;
|
|||||||
import de.dennisguse.opentracks.data.models.Speed;
|
import de.dennisguse.opentracks.data.models.Speed;
|
||||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||||
import de.dennisguse.opentracks.data.models.UnitConversions;
|
import de.dennisguse.opentracks.data.models.UnitConversions;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
|
|
||||||
public class ChartPoint {
|
public class ChartPoint {
|
||||||
@@ -28,20 +29,20 @@ public class ChartPoint {
|
|||||||
this.altitude = altitude;
|
this.altitude = altitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChartPoint(@NonNull TrackStatistics trackStatistics, @NonNull TrackPoint trackPoint, Speed smoothedSpeed, Altitude smoothedAltitude, boolean chartByDistance, boolean metricUnits) {
|
public ChartPoint(@NonNull TrackStatistics trackStatistics, @NonNull TrackPoint trackPoint, Speed smoothedSpeed, Altitude smoothedAltitude, boolean chartByDistance, UnitSystem unitSystem) {
|
||||||
if (chartByDistance) {
|
if (chartByDistance) {
|
||||||
timeOrDistance = trackStatistics.getTotalDistance().toKM_Miles(metricUnits);
|
timeOrDistance = trackStatistics.getTotalDistance().toKM_Miles(unitSystem);
|
||||||
} else {
|
} else {
|
||||||
timeOrDistance = trackStatistics.getTotalTime().toMillis();
|
timeOrDistance = trackStatistics.getTotalTime().toMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smoothedAltitude != null) {
|
if (smoothedAltitude != null) {
|
||||||
altitude = Distance.of(smoothedAltitude.toM()).toM_FT(metricUnits);
|
altitude = Distance.of(smoothedAltitude.toM()).toM_FT(unitSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smoothedSpeed != null) {
|
if (smoothedSpeed != null) {
|
||||||
speed = smoothedSpeed.to(metricUnits);
|
speed = smoothedSpeed.to(unitSystem);
|
||||||
pace = smoothedSpeed.toPace(metricUnits).toMillis() * UnitConversions.MS_TO_S * UnitConversions.S_TO_MIN;
|
pace = smoothedSpeed.toPace(unitSystem).toMillis() * UnitConversions.MS_TO_S * UnitConversions.S_TO_MIN;
|
||||||
}
|
}
|
||||||
if (trackPoint.hasHeartRate()) {
|
if (trackPoint.hasHeartRate()) {
|
||||||
heartRate = (double) trackPoint.getHeartRate().getBPM();
|
heartRate = (double) trackPoint.getHeartRate().getBPM();
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import androidx.annotation.NonNull;
|
|||||||
|
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.ExtremityMonitor;
|
import de.dennisguse.opentracks.stats.ExtremityMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -217,11 +218,15 @@ abstract class ChartValueSeries {
|
|||||||
return maxMarkerValue;
|
return maxMarkerValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int getTitleId(UnitSystem unitSystem) {
|
||||||
* Gets the title id.
|
switch (unitSystem) {
|
||||||
*/
|
case METRIC:
|
||||||
int getTitleId(boolean metricUnits) {
|
return metricTitleId;
|
||||||
return metricUnits ? metricTitleId : imperialTitleId;
|
case IMPERIAL:
|
||||||
|
return imperialTitleId;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.data.models.Marker;
|
import de.dennisguse.opentracks.data.models.Marker;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.ExtremityMonitor;
|
import de.dennisguse.opentracks.stats.ExtremityMonitor;
|
||||||
import de.dennisguse.opentracks.ui.markers.MarkerDetailActivity;
|
import de.dennisguse.opentracks.ui.markers.MarkerDetailActivity;
|
||||||
import de.dennisguse.opentracks.ui.markers.MarkerUtils;
|
import de.dennisguse.opentracks.ui.markers.MarkerUtils;
|
||||||
@@ -116,7 +117,7 @@ public class ChartView extends View {
|
|||||||
private int effectiveHeight = 0;
|
private int effectiveHeight = 0;
|
||||||
|
|
||||||
private boolean chartByDistance = false;
|
private boolean chartByDistance = false;
|
||||||
private boolean metricUnits = true;
|
private UnitSystem unitSystem = UnitSystem.defaultUnitSystem();
|
||||||
private boolean reportSpeed = true;
|
private boolean reportSpeed = true;
|
||||||
private boolean showPointer = false;
|
private boolean showPointer = false;
|
||||||
|
|
||||||
@@ -371,17 +372,12 @@ public class ChartView extends View {
|
|||||||
this.chartByDistance = chartByDistance;
|
this.chartByDistance = chartByDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getMetricUnits() {
|
public UnitSystem getUnitSystem() {
|
||||||
return metricUnits;
|
return unitSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void setUnitSystem(UnitSystem value) {
|
||||||
* Sets metric units.
|
unitSystem = value;
|
||||||
*
|
|
||||||
* @param value true to use metric units
|
|
||||||
*/
|
|
||||||
public void setMetricUnits(boolean value) {
|
|
||||||
metricUnits = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getReportSpeed() {
|
public boolean getReportSpeed() {
|
||||||
@@ -677,7 +673,7 @@ public class ChartView extends View {
|
|||||||
for (ChartValueSeries chartValueSeries : seriesList) {
|
for (ChartValueSeries chartValueSeries : seriesList) {
|
||||||
if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(chartValueSeries)) {
|
if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(chartValueSeries)) {
|
||||||
count++;
|
count++;
|
||||||
String title = getContext().getString(chartValueSeries.getTitleId(metricUnits));
|
String title = getContext().getString(chartValueSeries.getTitleId(unitSystem));
|
||||||
Paint paint = chartValueSeries.getTitlePaint();
|
Paint paint = chartValueSeries.getTitlePaint();
|
||||||
int x = (int) (0.5 * width) + getScrollX();
|
int x = (int) (0.5 * width) + getScrollX();
|
||||||
int y = topBorder - spacer - (lines - count) * (lineHeight + spacer);
|
int y = topBorder - spacer - (lines - count) * (lineHeight + spacer);
|
||||||
@@ -696,7 +692,7 @@ public class ChartView extends View {
|
|||||||
for (ChartValueSeries chartValueSeries : seriesList) {
|
for (ChartValueSeries chartValueSeries : seriesList) {
|
||||||
if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(chartValueSeries)) {
|
if (chartValueSeries.isEnabled() && chartValueSeries.hasData() || allowIfEmpty(chartValueSeries)) {
|
||||||
lines++;
|
lines++;
|
||||||
String title = getContext().getString(chartValueSeries.getTitleId(metricUnits));
|
String title = getContext().getString(chartValueSeries.getTitleId(unitSystem));
|
||||||
Rect rect = getRect(chartValueSeries.getTitlePaint(), title);
|
Rect rect = getRect(chartValueSeries.getTitlePaint(), title);
|
||||||
if (rect.height() > lineHeight) {
|
if (rect.height() > lineHeight) {
|
||||||
lineHeight = rect.height();
|
lineHeight = rect.height();
|
||||||
@@ -731,7 +727,14 @@ public class ChartView extends View {
|
|||||||
private String getXAxisLabel() {
|
private String getXAxisLabel() {
|
||||||
Context context = getContext();
|
Context context = getContext();
|
||||||
if (chartByDistance) {
|
if (chartByDistance) {
|
||||||
return metricUnits ? context.getString(R.string.unit_kilometer) : context.getString(R.string.unit_mile);
|
switch (unitSystem) {
|
||||||
|
case METRIC:
|
||||||
|
return context.getString(R.string.unit_kilometer);
|
||||||
|
case IMPERIAL:
|
||||||
|
return context.getString(R.string.unit_mile);
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return context.getString(R.string.description_time);
|
return context.getString(R.string.description_time);
|
||||||
}
|
}
|
||||||
@@ -986,7 +989,7 @@ public class ChartView extends View {
|
|||||||
|
|
||||||
private double getMarkerXValue(Marker marker) {
|
private double getMarkerXValue(Marker marker) {
|
||||||
if (chartByDistance) {
|
if (chartByDistance) {
|
||||||
return marker.getLength().toKM_Miles(metricUnits);
|
return marker.getLength().toKM_Miles(unitSystem);
|
||||||
} else {
|
} else {
|
||||||
return marker.getDuration().toMillis();
|
return marker.getDuration().toMillis();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import androidx.annotation.Nullable;
|
|||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
|
|
||||||
public class Distance {
|
public class Distance {
|
||||||
|
|
||||||
public static Distance of(double distance_m) {
|
public static Distance of(double distance_m) {
|
||||||
@@ -43,11 +45,14 @@ public class Distance {
|
|||||||
return of(0.1 * distance_dm);
|
return of(0.1 * distance_dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Distance one(boolean metricUnit) {
|
public static Distance one(UnitSystem unitSystem) {
|
||||||
if (metricUnit) {
|
switch (unitSystem) {
|
||||||
return Distance.ofKilometer(1);
|
case METRIC:
|
||||||
} else {
|
return Distance.ofKilometer(1);
|
||||||
return Distance.ofMile(1);
|
case IMPERIAL:
|
||||||
|
return Distance.ofMile(1);
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,12 +114,26 @@ public class Distance {
|
|||||||
return toKM() * UnitConversions.KM_TO_MI;
|
return toKM() * UnitConversions.KM_TO_MI;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double toKM_Miles(boolean metricUnit) {
|
public double toKM_Miles(UnitSystem unitSystem) {
|
||||||
return metricUnit ? toKM() : toMI();
|
switch (unitSystem) {
|
||||||
|
case METRIC:
|
||||||
|
return toKM();
|
||||||
|
case IMPERIAL:
|
||||||
|
return toMI();
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double toM_FT(boolean metricUnit) {
|
public double toM_FT(UnitSystem unitSystem) {
|
||||||
return metricUnit ? toM() : toFT();
|
switch (unitSystem) {
|
||||||
|
case METRIC:
|
||||||
|
return toM();
|
||||||
|
case IMPERIAL:
|
||||||
|
return toFT();
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import android.content.Context;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
|
|
||||||
public class DistanceFormatter {
|
public class DistanceFormatter {
|
||||||
@@ -13,12 +16,13 @@ public class DistanceFormatter {
|
|||||||
|
|
||||||
private final int decimalCount;
|
private final int decimalCount;
|
||||||
|
|
||||||
private final boolean metricUnits;
|
private final UnitSystem unitSystem;
|
||||||
|
|
||||||
private DistanceFormatter(Resources resources, int decimalCount, boolean metricUnits) {
|
private DistanceFormatter(Resources resources, int decimalCount, UnitSystem unitSystem) {
|
||||||
this.resources = resources;
|
this.resources = resources;
|
||||||
this.decimalCount = decimalCount;
|
this.decimalCount = decimalCount;
|
||||||
this.metricUnits = metricUnits;
|
this.unitSystem = unitSystem;
|
||||||
|
assert unitSystem != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String formatDistance(Distance distance) {
|
public String formatDistance(Distance distance) {
|
||||||
@@ -34,26 +38,35 @@ public class DistanceFormatter {
|
|||||||
/**
|
/**
|
||||||
* Get the formatted distance with unit.
|
* Get the formatted distance with unit.
|
||||||
*
|
*
|
||||||
* @param metricUnits true to use metric unit
|
|
||||||
* @return the formatted distance (or null) and it's unit as {@link Pair}
|
* @return the formatted distance (or null) and it's unit as {@link Pair}
|
||||||
*/
|
*/
|
||||||
public Pair<String, String> getDistanceParts(Distance distance) {
|
public Pair<String, String> getDistanceParts(Distance distance) {
|
||||||
if (distance.isInvalid()) {
|
if (distance.isInvalid()) {
|
||||||
return new Pair<>(null, resources.getString(metricUnits ? R.string.unit_meter : R.string.unit_feet));
|
switch (unitSystem) {
|
||||||
|
case METRIC:
|
||||||
|
return new Pair<>(null, resources.getString(R.string.unit_meter));
|
||||||
|
case IMPERIAL:
|
||||||
|
return new Pair<>(null, resources.getString(R.string.unit_feet));
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metricUnits) {
|
switch (unitSystem) {
|
||||||
if (distance.greaterThan(Distance.of(500))) {
|
case METRIC:
|
||||||
return new Pair<>(StringUtils.formatDecimal(distance.toKM(), decimalCount), resources.getString(R.string.unit_kilometer));
|
if (distance.greaterThan(Distance.of(500))) {
|
||||||
} else {
|
return new Pair<>(StringUtils.formatDecimal(distance.toKM(), decimalCount), resources.getString(R.string.unit_kilometer));
|
||||||
return new Pair<>(StringUtils.formatDecimal(distance.toM(), decimalCount), resources.getString(R.string.unit_meter));
|
} else {
|
||||||
}
|
return new Pair<>(StringUtils.formatDecimal(distance.toM(), decimalCount), resources.getString(R.string.unit_meter));
|
||||||
} else {
|
}
|
||||||
if (distance.greaterThan(Distance.ofMile(0.5))) {
|
case IMPERIAL:
|
||||||
return new Pair<>(StringUtils.formatDecimal(distance.toMI(), decimalCount), resources.getString(R.string.unit_mile));
|
if (distance.greaterThan(Distance.ofMile(0.5))) {
|
||||||
} else {
|
return new Pair<>(StringUtils.formatDecimal(distance.toMI(), decimalCount), resources.getString(R.string.unit_mile));
|
||||||
return new Pair<>(StringUtils.formatDecimal(distance.toFT(), decimalCount), resources.getString(R.string.unit_feet));
|
} else {
|
||||||
}
|
return new Pair<>(StringUtils.formatDecimal(distance.toFT(), decimalCount), resources.getString(R.string.unit_feet));
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,11 +78,10 @@ public class DistanceFormatter {
|
|||||||
|
|
||||||
private int decimalCount;
|
private int decimalCount;
|
||||||
|
|
||||||
private boolean metricUnits;
|
private UnitSystem unitSystem;
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
decimalCount = 2;
|
decimalCount = 2;
|
||||||
metricUnits = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setDecimalCount(int decimalCount) {
|
public Builder setDecimalCount(int decimalCount) {
|
||||||
@@ -77,13 +89,13 @@ public class DistanceFormatter {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setMetricUnits(boolean metricUnits) {
|
public Builder setUnit(@Nullable UnitSystem unitSystem) {
|
||||||
this.metricUnits = metricUnits;
|
this.unitSystem = unitSystem;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DistanceFormatter build(Resources resource) {
|
public DistanceFormatter build(Resources resource) {
|
||||||
return new DistanceFormatter(resource, decimalCount, metricUnits);
|
return new DistanceFormatter(resource, decimalCount, unitSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DistanceFormatter build(Context context) {
|
public DistanceFormatter build(Context context) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.time.Duration;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
|
|
||||||
public class Speed {
|
public class Speed {
|
||||||
|
|
||||||
@@ -92,35 +93,37 @@ public class Speed {
|
|||||||
return toKMH() * UnitConversions.KM_TO_MI;
|
return toKMH() * UnitConversions.KM_TO_MI;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Duration toPace(boolean metricUnit) {
|
public Duration toPace(UnitSystem unitSystem) {
|
||||||
if (isZero()) {
|
if (isZero()) {
|
||||||
return Duration.ofSeconds(0);
|
return Duration.ofSeconds(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
double distance = speed_mps * (metricUnit ? UnitConversions.M_TO_KM : UnitConversions.M_TO_MI);
|
double distance = speed_mps;
|
||||||
|
switch (unitSystem) { //TODO Can we use to(UnitSystem)?
|
||||||
|
case METRIC:
|
||||||
|
distance *= UnitConversions.M_TO_KM;
|
||||||
|
break;
|
||||||
|
case IMPERIAL:
|
||||||
|
distance *= UnitConversions.M_TO_MI;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
return Duration.ofSeconds(Math.round(1 / distance));
|
return Duration.ofSeconds(Math.round(1 / distance));
|
||||||
}
|
}
|
||||||
|
|
||||||
public double to(boolean metricUnit) {
|
public double to(UnitSystem unitSystem) {
|
||||||
return to(metricUnit ? Unit.KMH : Unit.MPH);
|
switch (unitSystem) {
|
||||||
}
|
case METRIC:
|
||||||
|
|
||||||
public double to(Unit unit) {
|
|
||||||
switch (unit) {
|
|
||||||
case KMH:
|
|
||||||
return toKMH();
|
return toKMH();
|
||||||
case MPH:
|
case IMPERIAL:
|
||||||
return toMPH();
|
return toMPH();
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("Not implemented");
|
throw new RuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Unit {
|
|
||||||
KMH,
|
|
||||||
MPH,
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import android.content.Context;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
|
|
||||||
public class SpeedFormatter {
|
public class SpeedFormatter {
|
||||||
@@ -13,14 +16,14 @@ public class SpeedFormatter {
|
|||||||
|
|
||||||
private final int decimalCount;
|
private final int decimalCount;
|
||||||
|
|
||||||
private final boolean metricUnits;
|
private final UnitSystem unitSystem;
|
||||||
|
|
||||||
private final boolean reportSpeedOrPace;
|
private final boolean reportSpeedOrPace;
|
||||||
|
|
||||||
private SpeedFormatter(Resources resources, int decimalCount, boolean metricUnits, boolean reportSpeedOrPace) {
|
private SpeedFormatter(Resources resources, int decimalCount, UnitSystem unitSystem, boolean reportSpeedOrPace) {
|
||||||
this.resources = resources;
|
this.resources = resources;
|
||||||
this.decimalCount = decimalCount;
|
this.decimalCount = decimalCount;
|
||||||
this.metricUnits = metricUnits;
|
this.unitSystem = unitSystem;
|
||||||
this.reportSpeedOrPace = reportSpeedOrPace;
|
this.reportSpeedOrPace = reportSpeedOrPace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,11 +40,17 @@ public class SpeedFormatter {
|
|||||||
*/
|
*/
|
||||||
public Pair<String, String> getSpeedParts(Speed speed) {
|
public Pair<String, String> getSpeedParts(Speed speed) {
|
||||||
int unitId;
|
int unitId;
|
||||||
if (metricUnits) {
|
switch (unitSystem) {
|
||||||
unitId = reportSpeedOrPace ? R.string.unit_kilometer_per_hour : R.string.unit_minute_per_kilometer;
|
case METRIC:
|
||||||
} else {
|
unitId = reportSpeedOrPace ? R.string.unit_kilometer_per_hour : R.string.unit_minute_per_kilometer;
|
||||||
unitId = reportSpeedOrPace ? R.string.unit_mile_per_hour : R.string.unit_minute_per_mile;
|
break;
|
||||||
|
case IMPERIAL:
|
||||||
|
unitId = reportSpeedOrPace ? R.string.unit_mile_per_hour : R.string.unit_minute_per_mile;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
String unitString = resources.getString(unitId);
|
String unitString = resources.getString(unitId);
|
||||||
|
|
||||||
if (speed == null) {
|
if (speed == null) {
|
||||||
@@ -49,10 +58,10 @@ public class SpeedFormatter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (reportSpeedOrPace) {
|
if (reportSpeedOrPace) {
|
||||||
return new Pair<>(StringUtils.formatDecimal(speed.to(metricUnits), 1), unitString);
|
return new Pair<>(StringUtils.formatDecimal(speed.to(unitSystem), 1), unitString);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pace = (int) speed.toPace(metricUnits).getSeconds();
|
int pace = (int) speed.toPace(unitSystem).getSeconds();
|
||||||
|
|
||||||
int minutes = pace / 60;
|
int minutes = pace / 60;
|
||||||
int seconds = pace % 60;
|
int seconds = pace % 60;
|
||||||
@@ -67,13 +76,12 @@ public class SpeedFormatter {
|
|||||||
|
|
||||||
private int decimalCount;
|
private int decimalCount;
|
||||||
|
|
||||||
private boolean metricUnits;
|
private UnitSystem unitSystem;
|
||||||
|
|
||||||
private boolean reportSpeedOrPace;
|
private boolean reportSpeedOrPace;
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
decimalCount = 2;
|
decimalCount = 2;
|
||||||
metricUnits = true;
|
|
||||||
reportSpeedOrPace = true;
|
reportSpeedOrPace = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,8 +90,8 @@ public class SpeedFormatter {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setMetricUnits(boolean metricUnits) {
|
public Builder setUnit(@NonNull UnitSystem unitSystem) {
|
||||||
this.metricUnits = metricUnits;
|
this.unitSystem = unitSystem;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +101,7 @@ public class SpeedFormatter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public SpeedFormatter build(Resources resource) {
|
public SpeedFormatter build(Resources resource) {
|
||||||
return new SpeedFormatter(resource, decimalCount, metricUnits, reportSpeedOrPace);
|
return new SpeedFormatter(resource, decimalCount, unitSystem, reportSpeedOrPace);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpeedFormatter build(Context context) {
|
public SpeedFormatter build(Context context) {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
|||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
import de.dennisguse.opentracks.databinding.StatisticsRecordedBinding;
|
import de.dennisguse.opentracks.databinding.StatisticsRecordedBinding;
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
@@ -81,7 +82,7 @@ public class StatisticsRecordedFragment extends Fragment {
|
|||||||
|
|
||||||
private StatisticsRecordedBinding viewBinding;
|
private StatisticsRecordedBinding viewBinding;
|
||||||
|
|
||||||
private boolean preferenceMetricUnits;
|
private UnitSystem unitSystem = UnitSystem.defaultUnitSystem();
|
||||||
private boolean preferenceReportSpeed;
|
private boolean preferenceReportSpeed;
|
||||||
|
|
||||||
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> {
|
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> {
|
||||||
@@ -89,7 +90,7 @@ public class StatisticsRecordedFragment extends Fragment {
|
|||||||
|
|
||||||
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
||||||
updateUInecessary = true;
|
updateUInecessary = true;
|
||||||
preferenceMetricUnits = PreferencesUtils.isMetricUnits();
|
unitSystem = PreferencesUtils.getUnitSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PreferencesUtils.isKey(R.string.stats_rate_key, key) && track != null) {
|
if (PreferencesUtils.isKey(R.string.stats_rate_key, key) && track != null) {
|
||||||
@@ -189,7 +190,7 @@ public class StatisticsRecordedFragment extends Fragment {
|
|||||||
// Set total distance
|
// Set total distance
|
||||||
{
|
{
|
||||||
Pair<String, String> parts = DistanceFormatter.Builder()
|
Pair<String, String> parts = DistanceFormatter.Builder()
|
||||||
.setMetricUnits(preferenceMetricUnits)
|
.setUnit(unitSystem)
|
||||||
.build(getContext()).getDistanceParts(trackStatistics.getTotalDistance());
|
.build(getContext()).getDistanceParts(trackStatistics.getTotalDistance());
|
||||||
|
|
||||||
viewBinding.statsDistanceValue.setText(parts.first);
|
viewBinding.statsDistanceValue.setText(parts.first);
|
||||||
@@ -208,7 +209,7 @@ public class StatisticsRecordedFragment extends Fragment {
|
|||||||
viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(trackStatistics.getTotalTime()));
|
viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(trackStatistics.getTotalTime()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SpeedFormatter formatter = SpeedFormatter.Builder().setMetricUnits(preferenceMetricUnits).setReportSpeedOrPace(preferenceReportSpeed).build(getContext());
|
SpeedFormatter formatter = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(preferenceReportSpeed).build(getContext());
|
||||||
// Set average speed/pace
|
// Set average speed/pace
|
||||||
{
|
{
|
||||||
viewBinding.statsAverageSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace);
|
viewBinding.statsAverageSpeedLabel.setText(preferenceReportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace);
|
||||||
@@ -243,11 +244,11 @@ public class StatisticsRecordedFragment extends Fragment {
|
|||||||
|
|
||||||
Pair<String, String> parts;
|
Pair<String, String> parts;
|
||||||
|
|
||||||
parts = StringUtils.getAltitudeChangeParts(getContext(), altitudeGain_m, preferenceMetricUnits);
|
parts = StringUtils.getAltitudeParts(getContext(), altitudeGain_m, unitSystem);
|
||||||
viewBinding.statsAltitudeGainValue.setText(parts.first);
|
viewBinding.statsAltitudeGainValue.setText(parts.first);
|
||||||
viewBinding.statsAltitudeGainUnit.setText(parts.second);
|
viewBinding.statsAltitudeGainUnit.setText(parts.second);
|
||||||
|
|
||||||
parts = StringUtils.getAltitudeChangeParts(getContext(), altitudeLoss_m, preferenceMetricUnits);
|
parts = StringUtils.getAltitudeParts(getContext(), altitudeLoss_m, unitSystem);
|
||||||
viewBinding.statsAltitudeLossValue.setText(parts.first);
|
viewBinding.statsAltitudeLossValue.setText(parts.first);
|
||||||
viewBinding.statsAltitudeLossUnit.setText(parts.second);
|
viewBinding.statsAltitudeLossUnit.setText(parts.second);
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import de.dennisguse.opentracks.services.RecordingData;
|
|||||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.ui.customRecordingLayout.Layout;
|
import de.dennisguse.opentracks.ui.customRecordingLayout.Layout;
|
||||||
import de.dennisguse.opentracks.viewmodels.StatisticData;
|
import de.dennisguse.opentracks.viewmodels.StatisticData;
|
||||||
import de.dennisguse.opentracks.viewmodels.StatisticsDataModel;
|
import de.dennisguse.opentracks.viewmodels.StatisticsDataModel;
|
||||||
@@ -55,14 +56,14 @@ public class StatisticsRecordingFragment extends Fragment {
|
|||||||
private StatisticsDataModel viewModel;
|
private StatisticsDataModel viewModel;
|
||||||
private LiveData<List<StatisticData>> statisticsLiveData;
|
private LiveData<List<StatisticData>> statisticsLiveData;
|
||||||
|
|
||||||
private boolean preferenceMetricUnits;
|
private UnitSystem unitSystem = UnitSystem.defaultUnitSystem();
|
||||||
|
|
||||||
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> {
|
private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> {
|
||||||
boolean updateUInecessary = false;
|
boolean updateUInecessary = false;
|
||||||
|
|
||||||
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
||||||
updateUInecessary = true;
|
updateUInecessary = true;
|
||||||
preferenceMetricUnits = PreferencesUtils.isMetricUnits();
|
unitSystem = PreferencesUtils.getUnitSystem();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PreferencesUtils.isKey(R.string.stats_custom_layouts_key, key) || PreferencesUtils.isKey(R.string.stats_custom_layout_selected_layout_key, key)) {
|
if (PreferencesUtils.isKey(R.string.stats_custom_layouts_key, key) || PreferencesUtils.isKey(R.string.stats_custom_layout_selected_layout_key, key)) {
|
||||||
@@ -157,7 +158,7 @@ public class StatisticsRecordingFragment extends Fragment {
|
|||||||
|
|
||||||
private void updateUI() {
|
private void updateUI() {
|
||||||
if (isResumed()) {
|
if (isResumed()) {
|
||||||
viewModel.update(recordingData, layout, preferenceMetricUnits);
|
viewModel.update(recordingData, layout, unitSystem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-6
@@ -24,6 +24,7 @@ import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
|||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.util.IntentUtils;
|
import de.dennisguse.opentracks.util.IntentUtils;
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
|
|||||||
|
|
||||||
private boolean previousLocationWasAccurate = true;
|
private boolean previousLocationWasAccurate = true;
|
||||||
|
|
||||||
private Boolean metricUnits = null;
|
private UnitSystem unitSystem = null;
|
||||||
|
|
||||||
TrackRecordingServiceNotificationManager(Context context) {
|
TrackRecordingServiceNotificationManager(Context context) {
|
||||||
PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
|
PreferencesUtils.registerOnSharedPreferenceChangeListener(this);
|
||||||
@@ -85,7 +86,7 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
|
|||||||
String formattedAccuracy = context.getString(R.string.value_none);
|
String formattedAccuracy = context.getString(R.string.value_none);
|
||||||
|
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setMetricUnits(metricUnits)
|
.setUnit(unitSystem)
|
||||||
.build(context);
|
.build(context);
|
||||||
if (trackPoint.hasHorizontalAccuracy()) {
|
if (trackPoint.hasHorizontalAccuracy()) {
|
||||||
formattedAccuracy = formatter.formatDistance(trackPoint.getHorizontalAccuracy());
|
formattedAccuracy = formatter.formatDistance(trackPoint.getHorizontalAccuracy());
|
||||||
@@ -97,7 +98,7 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
|
|||||||
}
|
}
|
||||||
|
|
||||||
notificationBuilder.setContentTitle(context.getString(R.string.track_distance_notification, formatter.formatDistance(trackStatistics.getTotalDistance())));
|
notificationBuilder.setContentTitle(context.getString(R.string.track_distance_notification, formatter.formatDistance(trackStatistics.getTotalDistance())));
|
||||||
String formattedSpeed = SpeedFormatter.Builder().setMetricUnits(metricUnits).setReportSpeedOrPace(true).build(context).formatSpeed(trackPoint.getSpeed());
|
String formattedSpeed = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(true).build(context).formatSpeed(trackPoint.getSpeed());
|
||||||
notificationBuilder.setContentText(context.getString(R.string.track_speed_notification, formattedSpeed));
|
notificationBuilder.setContentText(context.getString(R.string.track_speed_notification, formattedSpeed));
|
||||||
notificationBuilder.setSubText(context.getString(R.string.track_recording_notification_accuracy, formattedAccuracy));
|
notificationBuilder.setSubText(context.getString(R.string.track_recording_notification_accuracy, formattedAccuracy));
|
||||||
updateNotification();
|
updateNotification();
|
||||||
@@ -149,8 +150,8 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
|
|||||||
notificationManager.cancel(NOTIFICATION_ID);
|
notificationManager.cancel(NOTIFICATION_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMetricUnits(boolean metricUnits) {
|
void setUnitSystem(UnitSystem unitSystem) {
|
||||||
this.metricUnits = metricUnits;
|
this.unitSystem = unitSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateNotification() {
|
private void updateNotification() {
|
||||||
@@ -164,7 +165,7 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
|
|||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
if (PreferencesUtils.isKey(R.string.stats_units_key, key)) {
|
||||||
setMetricUnits(PreferencesUtils.isMetricUnits());
|
setUnitSystem(PreferencesUtils.getUnitSystem());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import de.dennisguse.opentracks.data.TrackPointIterator;
|
|||||||
import de.dennisguse.opentracks.data.models.Distance;
|
import de.dennisguse.opentracks.data.models.Distance;
|
||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
|
import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
|
||||||
@@ -165,12 +166,12 @@ public class VoiceAnnouncement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boolean isMetricUnits = PreferencesUtils.isMetricUnits();
|
UnitSystem unitSystem = PreferencesUtils.getUnitSystem();
|
||||||
boolean isReportSpeed = PreferencesUtils.isReportSpeed(track.getCategory());
|
boolean isReportSpeed = PreferencesUtils.isReportSpeed(track.getCategory());
|
||||||
|
|
||||||
//TODO Do not load all trackpoints for every announcement
|
//TODO Do not load all trackpoints for every announcement
|
||||||
TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null);
|
TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null);
|
||||||
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.one(isMetricUnits));
|
IntervalStatistics intervalStatistics = new IntervalStatistics(Distance.one(unitSystem));
|
||||||
intervalStatistics.addTrackPoints(trackPointIterator);
|
intervalStatistics.addTrackPoints(trackPointIterator);
|
||||||
IntervalStatistics.Interval lastInterval = intervalStatistics.getLastInterval();
|
IntervalStatistics.Interval lastInterval = intervalStatistics.getLastInterval();
|
||||||
SensorStatistics sensorStatistics = null;
|
SensorStatistics sensorStatistics = null;
|
||||||
@@ -178,7 +179,7 @@ public class VoiceAnnouncement {
|
|||||||
sensorStatistics = contentProviderUtils.getSensorStats(track.getId());
|
sensorStatistics = contentProviderUtils.getSensorStats(track.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
Spannable announcement = VoiceAnnouncementUtils.getAnnouncement(context, track.getTrackStatistics(), isMetricUnits, isReportSpeed, lastInterval, sensorStatistics);
|
Spannable announcement = VoiceAnnouncementUtils.getAnnouncement(context, track.getTrackStatistics(), unitSystem, isReportSpeed, lastInterval, sensorStatistics);
|
||||||
|
|
||||||
// We don't care about the utterance id. It is supplied here to force onUtteranceCompleted to be called.
|
// We don't care about the utterance id. It is supplied here to force onUtteranceCompleted to be called.
|
||||||
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null, "not used");
|
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null, "not used");
|
||||||
|
|||||||
+34
-12
@@ -16,6 +16,7 @@ import java.time.Duration;
|
|||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.data.models.Distance;
|
import de.dennisguse.opentracks.data.models.Distance;
|
||||||
import de.dennisguse.opentracks.data.models.Speed;
|
import de.dennisguse.opentracks.data.models.Speed;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
|
import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
|
||||||
@@ -25,15 +26,37 @@ class VoiceAnnouncementUtils {
|
|||||||
private VoiceAnnouncementUtils() {
|
private VoiceAnnouncementUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Spannable getAnnouncement(Context context, TrackStatistics trackStatistics, boolean isMetricUnits, boolean isReportSpeed, @Nullable IntervalStatistics.Interval currentInterval, @Nullable SensorStatistics sensorStatistics) {
|
static Spannable getAnnouncement(Context context, TrackStatistics trackStatistics, UnitSystem unitSystem, boolean isReportSpeed, @Nullable IntervalStatistics.Interval currentInterval, @Nullable SensorStatistics sensorStatistics) {
|
||||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||||
Distance distance = trackStatistics.getTotalDistance();
|
Distance distance = trackStatistics.getTotalDistance();
|
||||||
Speed distancePerTime = trackStatistics.getAverageMovingSpeed();
|
Speed distancePerTime = trackStatistics.getAverageMovingSpeed();
|
||||||
Speed currentDistancePerTime = currentInterval != null ? currentInterval.getSpeed() : null;
|
Speed currentDistancePerTime = currentInterval != null ? currentInterval.getSpeed() : null;
|
||||||
int perUnitStringId = isMetricUnits ? R.string.voice_per_kilometer : R.string.voice_per_mile;
|
|
||||||
|
|
||||||
double distanceInUnit = distance.toKM_Miles(isMetricUnits);
|
int perUnitStringId;
|
||||||
int distanceId = isMetricUnits ? R.plurals.voiceDistanceKilometers : R.plurals.voiceDistanceMiles;
|
int distanceId;
|
||||||
|
int speedId;
|
||||||
|
String unitDistanceTTS;
|
||||||
|
String unitSpeedTTS;
|
||||||
|
switch (unitSystem) {
|
||||||
|
case METRIC:
|
||||||
|
perUnitStringId = R.string.voice_per_kilometer;
|
||||||
|
distanceId = R.plurals.voiceDistanceKilometers;
|
||||||
|
speedId = R.plurals.voiceSpeedKilometersPerHour;
|
||||||
|
unitDistanceTTS = "kilometer";
|
||||||
|
unitSpeedTTS = "kilometer per hour";
|
||||||
|
break;
|
||||||
|
case IMPERIAL:
|
||||||
|
perUnitStringId = R.string.voice_per_mile;
|
||||||
|
distanceId = R.plurals.voiceDistanceMiles;
|
||||||
|
speedId = R.plurals.voiceSpeedMilesPerHour;
|
||||||
|
unitDistanceTTS = "mile";
|
||||||
|
unitSpeedTTS = "mile per hour";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
double distanceInUnit = distance.toKM_Miles(unitSystem);
|
||||||
|
|
||||||
builder.append(context.getString(R.string.total_distance));
|
builder.append(context.getString(R.string.total_distance));
|
||||||
long distanceIntegerPart = (long) distanceInUnit;
|
long distanceIntegerPart = (long) distanceInUnit;
|
||||||
@@ -41,7 +64,7 @@ class VoiceAnnouncementUtils {
|
|||||||
String distanceFractionalPart = String.format("%.2f", (distanceInUnit - distanceIntegerPart)).substring(2);
|
String distanceFractionalPart = String.format("%.2f", (distanceInUnit - distanceIntegerPart)).substring(2);
|
||||||
// Units should always be english singular for TTS.
|
// Units should always be english singular for TTS.
|
||||||
// See https://developer.android.com/reference/android/text/style/TtsSpan?hl=en#TYPE_MEASURE
|
// See https://developer.android.com/reference/android/text/style/TtsSpan?hl=en#TYPE_MEASURE
|
||||||
appendDecimalUnit(builder, context.getResources().getQuantityString(distanceId, getQuantityCount(distanceInUnit), distanceInUnit), distanceIntegerPart, distanceFractionalPart, isMetricUnits ? "kilometer" : "mile");
|
appendDecimalUnit(builder, context.getResources().getQuantityString(distanceId, getQuantityCount(distanceInUnit), distanceInUnit), distanceIntegerPart, distanceFractionalPart, unitDistanceTTS);
|
||||||
// Punctuation helps introduce natural pauses in TTS
|
// Punctuation helps introduce natural pauses in TTS
|
||||||
builder.append(".");
|
builder.append(".");
|
||||||
if (distance.isZero()) {
|
if (distance.isZero()) {
|
||||||
@@ -56,19 +79,18 @@ class VoiceAnnouncementUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isReportSpeed) {
|
if (isReportSpeed) {
|
||||||
int speedId = isMetricUnits ? R.plurals.voiceSpeedKilometersPerHour : R.plurals.voiceSpeedMilesPerHour;
|
double speedInUnit = distancePerTime.to(unitSystem);
|
||||||
double speedInUnit = distancePerTime.to(isMetricUnits);
|
|
||||||
|
|
||||||
builder.append(" ")
|
builder.append(" ")
|
||||||
.append(context.getString(R.string.speed));
|
.append(context.getString(R.string.speed));
|
||||||
long speedIntegerPart = (long) speedInUnit;
|
long speedIntegerPart = (long) speedInUnit;
|
||||||
// Extract the decimal part
|
// Extract the decimal part
|
||||||
String speedFractionalPart = String.format("%.1f", (speedInUnit - speedIntegerPart)).substring(2);
|
String speedFractionalPart = String.format("%.1f", (speedInUnit - speedIntegerPart)).substring(2);
|
||||||
appendDecimalUnit(builder, context.getResources().getQuantityString(speedId, getQuantityCount(speedInUnit), speedInUnit), speedIntegerPart, speedFractionalPart, isMetricUnits ? "kilometer per hour" : "mile per hour");
|
appendDecimalUnit(builder, context.getResources().getQuantityString(speedId, getQuantityCount(speedInUnit), speedInUnit), speedIntegerPart, speedFractionalPart, unitSpeedTTS);
|
||||||
builder.append(".");
|
builder.append(".");
|
||||||
|
|
||||||
if (currentDistancePerTime != null) {
|
if (currentDistancePerTime != null) {
|
||||||
double currentDistancePerTimeInUnit = currentDistancePerTime.to(isMetricUnits);
|
double currentDistancePerTimeInUnit = currentDistancePerTime.to(unitSystem);
|
||||||
|
|
||||||
if (currentDistancePerTimeInUnit > 0) {
|
if (currentDistancePerTimeInUnit > 0) {
|
||||||
|
|
||||||
@@ -77,12 +99,12 @@ class VoiceAnnouncementUtils {
|
|||||||
long currentDistanceIntegerPart = (long) currentDistancePerTimeInUnit;
|
long currentDistanceIntegerPart = (long) currentDistancePerTimeInUnit;
|
||||||
// Extract the decimal part
|
// Extract the decimal part
|
||||||
String currentDistanceFractionalPart = String.format("%.1f", (currentDistancePerTimeInUnit - currentDistanceIntegerPart)).substring(2);
|
String currentDistanceFractionalPart = String.format("%.1f", (currentDistancePerTimeInUnit - currentDistanceIntegerPart)).substring(2);
|
||||||
appendDecimalUnit(builder, context.getResources().getQuantityString(speedId, getQuantityCount(currentDistancePerTimeInUnit), currentDistancePerTimeInUnit), currentDistanceIntegerPart, currentDistanceFractionalPart, isMetricUnits ? "kilometer per hour" : "mile per hour");
|
appendDecimalUnit(builder, context.getResources().getQuantityString(speedId, getQuantityCount(currentDistancePerTimeInUnit), currentDistancePerTimeInUnit), currentDistanceIntegerPart, currentDistanceFractionalPart, unitSpeedTTS);
|
||||||
builder.append(".");
|
builder.append(".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Duration time = distancePerTime.toPace(isMetricUnits);
|
Duration time = distancePerTime.toPace(unitSystem);
|
||||||
builder.append(" ")
|
builder.append(" ")
|
||||||
.append(context.getString(R.string.pace));
|
.append(context.getString(R.string.pace));
|
||||||
appendDuration(context, builder, time);
|
appendDuration(context, builder, time);
|
||||||
@@ -90,7 +112,7 @@ class VoiceAnnouncementUtils {
|
|||||||
.append(context.getString(perUnitStringId))
|
.append(context.getString(perUnitStringId))
|
||||||
.append(".");
|
.append(".");
|
||||||
|
|
||||||
Duration currentTime = currentDistancePerTime != null ? currentDistancePerTime.toPace(isMetricUnits) : Duration.ofMillis(0);
|
Duration currentTime = currentDistancePerTime != null ? currentDistancePerTime.toPace(unitSystem) : Duration.ofMillis(0);
|
||||||
if (!currentTime.isZero()) {
|
if (!currentTime.isZero()) {
|
||||||
builder.append(" ")
|
builder.append(" ")
|
||||||
.append(context.getString(R.string.lap_time));
|
.append(context.getString(R.string.lap_time));
|
||||||
|
|||||||
@@ -64,10 +64,23 @@ public class DefaultsSettingsFragment extends PreferenceFragmentCompat implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateUnits() {
|
private void updateUnits() {
|
||||||
boolean metricUnits = PreferencesUtils.isMetricUnits();
|
UnitSystem unitSystem = PreferencesUtils.getUnitSystem();
|
||||||
|
|
||||||
ListPreference statsRatePreferences = findPreference(getString(R.string.stats_rate_key));
|
ListPreference statsRatePreferences = findPreference(getString(R.string.stats_rate_key));
|
||||||
String[] entries = getResources().getStringArray(metricUnits ? R.array.stats_rate_metric_options : R.array.stats_rate_imperial_options);
|
|
||||||
|
int entriesId;
|
||||||
|
switch (unitSystem) {
|
||||||
|
case METRIC:
|
||||||
|
entriesId = R.array.stats_rate_metric_options;
|
||||||
|
break;
|
||||||
|
case IMPERIAL:
|
||||||
|
entriesId = R.array.stats_rate_imperial_options;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] entries = getResources().getStringArray(entriesId);
|
||||||
statsRatePreferences.setEntries(entries);
|
statsRatePreferences.setEntries(entries);
|
||||||
|
|
||||||
HackUtils.invalidatePreference(statsRatePreferences);
|
HackUtils.invalidatePreference(statsRatePreferences);
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ public class GpsSettingsFragment extends PreferenceFragmentCompat {
|
|||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
addPreferencesFromResource(R.xml.settings_gps);
|
addPreferencesFromResource(R.xml.settings_gps);
|
||||||
|
|
||||||
boolean metricUnits = PreferencesUtils.isMetricUnits();
|
UnitSystem unitSystem = PreferencesUtils.getUnitSystem();
|
||||||
|
|
||||||
final DistanceFormatter formatter = DistanceFormatter.Builder()
|
final DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setDecimalCount(0)
|
.setDecimalCount(0)
|
||||||
.setMetricUnits(metricUnits)
|
.setUnit(unitSystem)
|
||||||
.build(getContext());
|
.build(getContext());
|
||||||
|
|
||||||
findPreference(getString(R.string.recording_distance_interval_key))
|
findPreference(getString(R.string.recording_distance_interval_key))
|
||||||
|
|||||||
@@ -32,7 +32,9 @@ import androidx.preference.PreferenceManager;
|
|||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -193,19 +195,30 @@ public class PreferencesUtils {
|
|||||||
return getBoolean(R.string.publicapi_dashboard_enabled_key, resources.getBoolean(R.bool.publicapi_dashboard_enabled_default));
|
return getBoolean(R.string.publicapi_dashboard_enabled_key, resources.getBoolean(R.bool.publicapi_dashboard_enabled_default));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isMetricUnits() {
|
public static UnitSystem getUnitSystem() {
|
||||||
final String STATS_UNIT = resources.getString(R.string.stats_units_default);
|
final String STATS_UNIT_DEFAULT = resources.getString(R.string.stats_units_default);
|
||||||
return STATS_UNIT.equals(getString(R.string.stats_units_key, STATS_UNIT));
|
|
||||||
|
final String VALUE = getString(R.string.stats_units_key, STATS_UNIT_DEFAULT);
|
||||||
|
return Arrays.stream(UnitSystem.values())
|
||||||
|
.filter(d -> VALUE.equals(getString(d.getPreferenceId(), STATS_UNIT_DEFAULT)))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(UnitSystem.defaultUnitSystem()); //TODO This AGAIN defines the default
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setMetricUnits(boolean metricUnits) {
|
public static void setUnit(UnitSystem unitSystem) {
|
||||||
String unit;
|
setString(R.string.stats_units_key, unitSystem.getPreferenceId());
|
||||||
if (metricUnits) {
|
}
|
||||||
unit = resources.getString(R.string.stats_units_metric);
|
|
||||||
} else {
|
//TODO Check if actually needed or can be superseeded by a flexible default in getUnit()
|
||||||
unit = resources.getString(R.string.stats_units_imperial);
|
public static void applyDefaultUnit() {
|
||||||
|
if (getString(R.string.stats_units_key, "").equals("")) {
|
||||||
|
|
||||||
|
if (!Locale.US.equals(Locale.getDefault())) {
|
||||||
|
setUnit(UnitSystem.METRIC);
|
||||||
|
} else {
|
||||||
|
setUnit(UnitSystem.IMPERIAL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setString(R.string.stats_units_key, unit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isReportSpeed(String category) {
|
public static boolean isReportSpeed(String category) {
|
||||||
@@ -292,31 +305,31 @@ public class PreferencesUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Result depends on isMetricUnits
|
* @return Result depends on getUnitSystem
|
||||||
*/
|
*/
|
||||||
public static Distance getVoiceAnnouncementDistance() {
|
public static Distance getVoiceAnnouncementDistance() {
|
||||||
final float DEFAULT = Integer.parseInt(resources.getString(R.string.voice_announcement_distance_default));
|
final float DEFAULT = Integer.parseInt(resources.getString(R.string.voice_announcement_distance_default));
|
||||||
float value = getFloat(R.string.voice_announcement_distance_key, DEFAULT);
|
float value = getFloat(R.string.voice_announcement_distance_key, DEFAULT);
|
||||||
return Distance.one(isMetricUnits()).multipliedBy(value);
|
return Distance.one(getUnitSystem()).multipliedBy(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Result depends on isMetricUnits
|
* @return Result depends on getUnitSystem
|
||||||
*/
|
*/
|
||||||
static String[] getVoiceAnnouncementDistanceEntries() {
|
static String[] getVoiceAnnouncementDistanceEntries() {
|
||||||
String[] values = resources.getStringArray(R.array.voice_announcement_distance_values);
|
String[] values = resources.getStringArray(R.array.voice_announcement_distance_values);
|
||||||
String[] options = new String[values.length];
|
String[] options = new String[values.length];
|
||||||
boolean metricUnits = isMetricUnits();
|
UnitSystem unitSystem = getUnitSystem();
|
||||||
|
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setDecimalCount(0)
|
.setDecimalCount(0)
|
||||||
.setMetricUnits(metricUnits)
|
.setUnit(unitSystem)
|
||||||
.build(resources);
|
.build(resources);
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < values.length; i++) {
|
||||||
if (resources.getString(R.string.announcement_off).equals(values[i])) {
|
if (resources.getString(R.string.announcement_off).equals(values[i])) {
|
||||||
options[i] = resources.getString(R.string.value_off);
|
options[i] = resources.getString(R.string.value_off);
|
||||||
} else {
|
} else {
|
||||||
Distance distance = Distance.one(metricUnits).multipliedBy(Double.parseDouble(values[i]));
|
Distance distance = Distance.one(unitSystem).multipliedBy(Double.parseDouble(values[i]));
|
||||||
options[i] = formatter.formatDistance(distance);
|
options[i] = formatter.formatDistance(distance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,10 +367,10 @@ public class PreferencesUtils {
|
|||||||
String[] entries = new String[entryValues.length];
|
String[] entries = new String[entryValues.length];
|
||||||
|
|
||||||
final int recordingDistanceIntervalDefault = (int) getRecordingDistanceIntervalDefault().toM();
|
final int recordingDistanceIntervalDefault = (int) getRecordingDistanceIntervalDefault().toM();
|
||||||
boolean metricUnits = isMetricUnits();
|
UnitSystem unitSystem = getUnitSystem();
|
||||||
|
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setMetricUnits(metricUnits)
|
.setUnit(unitSystem)
|
||||||
.setDecimalCount(0)
|
.setDecimalCount(0)
|
||||||
.build(resources);
|
.build(resources);
|
||||||
for (int i = 0; i < entryValues.length; i++) {
|
for (int i = 0; i < entryValues.length; i++) {
|
||||||
@@ -365,18 +378,23 @@ public class PreferencesUtils {
|
|||||||
Distance distance = Distance.of(1).multipliedBy(value);
|
Distance distance = Distance.of(1).multipliedBy(value);
|
||||||
|
|
||||||
String displayValue = formatter.formatDistance(distance);
|
String displayValue = formatter.formatDistance(distance);
|
||||||
if (metricUnits) {
|
switch (unitSystem) {
|
||||||
if (value == recordingDistanceIntervalDefault) {
|
case METRIC:
|
||||||
entries[i] = resources.getString(R.string.value_integer_meter_recommended, value);
|
if (value == recordingDistanceIntervalDefault) {
|
||||||
} else {
|
entries[i] = resources.getString(R.string.value_integer_meter_recommended, value);
|
||||||
entries[i] = displayValue;
|
} else {
|
||||||
}
|
entries[i] = displayValue;
|
||||||
} else {
|
}
|
||||||
if (value == recordingDistanceIntervalDefault) {
|
break;
|
||||||
entries[i] = resources.getString(R.string.value_integer_feet_recommended, (int) distance.toFT());
|
case IMPERIAL:
|
||||||
} else {
|
if (value == recordingDistanceIntervalDefault) {
|
||||||
entries[i] = displayValue;
|
entries[i] = resources.getString(R.string.value_integer_feet_recommended, (int) distance.toFT());
|
||||||
}
|
} else {
|
||||||
|
entries[i] = displayValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,29 +411,34 @@ public class PreferencesUtils {
|
|||||||
String[] entries = new String[entryValues.length];
|
String[] entries = new String[entryValues.length];
|
||||||
|
|
||||||
final int maxRecordingDistanceDefault = Integer.parseInt(resources.getString(R.string.max_recording_distance_default));
|
final int maxRecordingDistanceDefault = Integer.parseInt(resources.getString(R.string.max_recording_distance_default));
|
||||||
boolean metricUnits = isMetricUnits();
|
UnitSystem unitSystem = getUnitSystem();
|
||||||
|
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setDecimalCount(0)
|
.setDecimalCount(0)
|
||||||
.setMetricUnits(metricUnits)
|
.setUnit(unitSystem)
|
||||||
.build(resources);
|
.build(resources);
|
||||||
for (int i = 0; i < entryValues.length; i++) {
|
for (int i = 0; i < entryValues.length; i++) {
|
||||||
int value = Integer.parseInt(entryValues[i]);
|
int value = Integer.parseInt(entryValues[i]);
|
||||||
Distance distance = Distance.of(1).multipliedBy(value);
|
Distance distance = Distance.of(1).multipliedBy(value);
|
||||||
|
|
||||||
String displayValue = formatter.formatDistance(distance);
|
String displayValue = formatter.formatDistance(distance);
|
||||||
if (metricUnits) {
|
switch (unitSystem) {
|
||||||
if (value == maxRecordingDistanceDefault) {
|
case METRIC:
|
||||||
entries[i] = resources.getString(R.string.value_integer_meter_recommended, value);
|
if (value == maxRecordingDistanceDefault) {
|
||||||
} else {
|
entries[i] = resources.getString(R.string.value_integer_meter_recommended, value);
|
||||||
entries[i] = displayValue;
|
} else {
|
||||||
}
|
entries[i] = displayValue;
|
||||||
} else {
|
}
|
||||||
if (value == maxRecordingDistanceDefault) {
|
break;
|
||||||
entries[i] = resources.getString(R.string.value_integer_feet_recommended, (int) distance.toFT());
|
case IMPERIAL:
|
||||||
} else {
|
if (value == maxRecordingDistanceDefault) {
|
||||||
entries[i] = displayValue;
|
entries[i] = resources.getString(R.string.value_integer_feet_recommended, (int) distance.toFT());
|
||||||
}
|
} else {
|
||||||
|
entries[i] = displayValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,11 +483,11 @@ public class PreferencesUtils {
|
|||||||
final int recordingGPSAccuracyExcellent = Integer.parseInt(resources.getString(R.string.recording_gps_accuracy_excellent));
|
final int recordingGPSAccuracyExcellent = Integer.parseInt(resources.getString(R.string.recording_gps_accuracy_excellent));
|
||||||
final int recordingGPSAccuracyPoor = Integer.parseInt(resources.getString(R.string.recording_gps_accuracy_poor));
|
final int recordingGPSAccuracyPoor = Integer.parseInt(resources.getString(R.string.recording_gps_accuracy_poor));
|
||||||
|
|
||||||
boolean metricUnits = isMetricUnits();
|
UnitSystem unitSystem = getUnitSystem();
|
||||||
|
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setDecimalCount(0)
|
.setDecimalCount(0)
|
||||||
.setMetricUnits(metricUnits)
|
.setUnit(unitSystem)
|
||||||
.build(resources);
|
.build(resources);
|
||||||
|
|
||||||
for (int i = 0; i < entryValues.length; i++) {
|
for (int i = 0; i < entryValues.length; i++) {
|
||||||
@@ -472,24 +495,29 @@ public class PreferencesUtils {
|
|||||||
Distance distance = Distance.of(1).multipliedBy(value);
|
Distance distance = Distance.of(1).multipliedBy(value);
|
||||||
|
|
||||||
String displayValue = formatter.formatDistance(distance);
|
String displayValue = formatter.formatDistance(distance);
|
||||||
if (metricUnits) {
|
switch (unitSystem) {
|
||||||
if (value == recordingGPSAccuracyDefault) {
|
case METRIC:
|
||||||
entries[i] = resources.getString(R.string.value_integer_meter_recommended, value);
|
if (value == recordingGPSAccuracyDefault) {
|
||||||
} else if (value == recordingGPSAccuracyExcellent) {
|
entries[i] = resources.getString(R.string.value_integer_meter_recommended, value);
|
||||||
entries[i] = resources.getString(R.string.value_integer_meter_excellent_gps, value);
|
} else if (value == recordingGPSAccuracyExcellent) {
|
||||||
} else if (value == recordingGPSAccuracyPoor) {
|
entries[i] = resources.getString(R.string.value_integer_meter_excellent_gps, value);
|
||||||
entries[i] = resources.getString(R.string.value_integer_meter_poor_gps, value);
|
} else if (value == recordingGPSAccuracyPoor) {
|
||||||
} else {
|
entries[i] = resources.getString(R.string.value_integer_meter_poor_gps, value);
|
||||||
entries[i] = displayValue;
|
} else {
|
||||||
}
|
entries[i] = displayValue;
|
||||||
} else {
|
}
|
||||||
if (value == recordingGPSAccuracyDefault) {
|
break;
|
||||||
entries[i] = resources.getString(R.string.value_integer_feet_recommended, (int) distance.toFT());
|
case IMPERIAL:
|
||||||
} else if (value == recordingGPSAccuracyExcellent) {
|
if (value == recordingGPSAccuracyDefault) {
|
||||||
entries[i] = resources.getString(R.string.value_integer_feet_excellent_gps, (int) distance.toFT());
|
entries[i] = resources.getString(R.string.value_integer_feet_recommended, (int) distance.toFT());
|
||||||
} else {
|
} else if (value == recordingGPSAccuracyExcellent) {
|
||||||
entries[i] = displayValue;
|
entries[i] = resources.getString(R.string.value_integer_feet_excellent_gps, (int) distance.toFT());
|
||||||
}
|
} else {
|
||||||
|
entries[i] = displayValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,24 +537,30 @@ public class PreferencesUtils {
|
|||||||
|
|
||||||
final float idleSpeedDefault = Float.parseFloat(resources.getString(R.string.idle_speed_default));
|
final float idleSpeedDefault = Float.parseFloat(resources.getString(R.string.idle_speed_default));
|
||||||
|
|
||||||
boolean metricUnits = isMetricUnits();
|
UnitSystem unitSystem = getUnitSystem();
|
||||||
|
|
||||||
for (int i = 0; i < entryValues.length; i++) {
|
for (int i = 0; i < entryValues.length; i++) {
|
||||||
float value = Float.parseFloat(entryValues[i]);
|
float value = Float.parseFloat(entryValues[i]);
|
||||||
if (metricUnits) {
|
|
||||||
if (value == idleSpeedDefault) {
|
|
||||||
entries[i] = resources.getString(R.string.value_float_kilometer_hour_recommended, value);
|
|
||||||
} else {
|
|
||||||
entries[i] = resources.getString(R.string.value_float_kilometer_hour, value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
double valueMPH = Speed.ofKMH(value).toMPH();
|
|
||||||
|
|
||||||
if (value == idleSpeedDefault) {
|
switch (unitSystem) {
|
||||||
entries[i] = resources.getString(R.string.value_float_mile_hour_recommended, valueMPH);
|
case METRIC:
|
||||||
} else {
|
if (value == idleSpeedDefault) {
|
||||||
entries[i] = resources.getString(R.string.value_float_mile_hour, valueMPH);
|
entries[i] = resources.getString(R.string.value_float_kilometer_hour_recommended, value);
|
||||||
}
|
} else {
|
||||||
|
entries[i] = resources.getString(R.string.value_float_kilometer_hour, value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IMPERIAL:
|
||||||
|
double valueMPH = Speed.ofKMH(value).toMPH();
|
||||||
|
|
||||||
|
if (value == idleSpeedDefault) {
|
||||||
|
entries[i] = resources.getString(R.string.value_float_mile_hour_recommended, valueMPH);
|
||||||
|
} else {
|
||||||
|
entries[i] = resources.getString(R.string.value_float_mile_hour, valueMPH);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package de.dennisguse.opentracks.settings;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.R;
|
||||||
|
|
||||||
|
public enum UnitSystem {
|
||||||
|
METRIC(R.string.stats_units_metric),
|
||||||
|
IMPERIAL(R.string.stats_units_imperial);
|
||||||
|
|
||||||
|
private final int preferenceIdentifier;
|
||||||
|
|
||||||
|
UnitSystem(int preferenceIdentifier) {
|
||||||
|
this.preferenceIdentifier = preferenceIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPreferenceId() {
|
||||||
|
return preferenceIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated //TODO used to initialize before loading from preferences; should be loaded first
|
||||||
|
public static UnitSystem defaultUnitSystem() {
|
||||||
|
return METRIC;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@ import de.dennisguse.opentracks.data.models.Speed;
|
|||||||
import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
import de.dennisguse.opentracks.data.models.UnitConversions;
|
import de.dennisguse.opentracks.data.models.UnitConversions;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
|
|
||||||
@@ -210,8 +211,8 @@ 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().setMetricUnits(true).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().setMetricUnits(false).setReportSpeedOrPace(false).build(context).getSpeedParts(speed);
|
Pair<String, String> paceInImperial = SpeedFormatter.Builder().setUnit(UnitSystem.IMPERIAL).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);
|
||||||
|
|||||||
+6
-5
@@ -16,6 +16,7 @@ import de.dennisguse.opentracks.R;
|
|||||||
import de.dennisguse.opentracks.data.models.DistanceFormatter;
|
import de.dennisguse.opentracks.data.models.DistanceFormatter;
|
||||||
import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
import de.dennisguse.opentracks.util.TrackIconUtils;
|
import de.dennisguse.opentracks.util.TrackIconUtils;
|
||||||
|
|
||||||
@@ -99,7 +100,7 @@ public class AggregatedStatisticsAdapter extends BaseAdapter {
|
|||||||
private final TextView maxSpeedUnit;
|
private final TextView maxSpeedUnit;
|
||||||
private final TextView maxSpeedLabel;
|
private final TextView maxSpeedLabel;
|
||||||
|
|
||||||
private boolean metricsUnits;
|
private UnitSystem unitSystem = UnitSystem.defaultUnitSystem();
|
||||||
private boolean reportSpeed;
|
private boolean reportSpeed;
|
||||||
|
|
||||||
public ViewHolder(View view) {
|
public ViewHolder(View view) {
|
||||||
@@ -121,7 +122,7 @@ public class AggregatedStatisticsAdapter extends BaseAdapter {
|
|||||||
public void setSpeed(AggregatedStatistics.AggregatedStatistic aggregatedStatistic) {
|
public void setSpeed(AggregatedStatistics.AggregatedStatistic aggregatedStatistic) {
|
||||||
setCommonValues(aggregatedStatistic);
|
setCommonValues(aggregatedStatistic);
|
||||||
|
|
||||||
SpeedFormatter formatter = SpeedFormatter.Builder().setMetricUnits(metricsUnits).setReportSpeedOrPace(reportSpeed).build(context);
|
SpeedFormatter formatter = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(reportSpeed).build(context);
|
||||||
{
|
{
|
||||||
Pair<String, String> parts = formatter.getSpeedParts(aggregatedStatistic.getTrackStatistics().getAverageMovingSpeed());
|
Pair<String, String> parts = formatter.getSpeedParts(aggregatedStatistic.getTrackStatistics().getAverageMovingSpeed());
|
||||||
avgSpeed.setText(parts.first);
|
avgSpeed.setText(parts.first);
|
||||||
@@ -138,7 +139,7 @@ public class AggregatedStatisticsAdapter extends BaseAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setPace(AggregatedStatistics.AggregatedStatistic aggregatedStatistic) {
|
public void setPace(AggregatedStatistics.AggregatedStatistic aggregatedStatistic) {
|
||||||
SpeedFormatter formatter = SpeedFormatter.Builder().setMetricUnits(metricsUnits).setReportSpeedOrPace(reportSpeed).build(context);
|
SpeedFormatter formatter = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(reportSpeed).build(context);
|
||||||
|
|
||||||
setCommonValues(aggregatedStatistic);
|
setCommonValues(aggregatedStatistic);
|
||||||
{
|
{
|
||||||
@@ -161,14 +162,14 @@ public class AggregatedStatisticsAdapter extends BaseAdapter {
|
|||||||
String category = aggregatedStatistic.getCategory();
|
String category = aggregatedStatistic.getCategory();
|
||||||
|
|
||||||
reportSpeed = PreferencesUtils.isReportSpeed(category);
|
reportSpeed = PreferencesUtils.isReportSpeed(category);
|
||||||
metricsUnits = PreferencesUtils.isMetricUnits();
|
unitSystem = PreferencesUtils.getUnitSystem();
|
||||||
|
|
||||||
sportIcon.setImageResource(getIcon(aggregatedStatistic));
|
sportIcon.setImageResource(getIcon(aggregatedStatistic));
|
||||||
typeLabel.setText(category);
|
typeLabel.setText(category);
|
||||||
numTracks.setText(StringUtils.valueInParentheses(String.valueOf(aggregatedStatistic.getCountTracks())));
|
numTracks.setText(StringUtils.valueInParentheses(String.valueOf(aggregatedStatistic.getCountTracks())));
|
||||||
|
|
||||||
Pair<String, String> parts = DistanceFormatter.Builder()
|
Pair<String, String> parts = DistanceFormatter.Builder()
|
||||||
.setMetricUnits(metricsUnits)
|
.setUnit(unitSystem)
|
||||||
.build(context).getDistanceParts(aggregatedStatistic.getTrackStatistics().getTotalDistance());
|
.build(context).getDistanceParts(aggregatedStatistic.getTrackStatistics().getTotalDistance());
|
||||||
distance.setText(parts.first);
|
distance.setText(parts.first);
|
||||||
distanceUnit.setText(parts.second);
|
distanceUnit.setText(parts.second);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import de.dennisguse.opentracks.R;
|
|||||||
import de.dennisguse.opentracks.data.models.Distance;
|
import de.dennisguse.opentracks.data.models.Distance;
|
||||||
import de.dennisguse.opentracks.data.models.DistanceFormatter;
|
import de.dennisguse.opentracks.data.models.DistanceFormatter;
|
||||||
import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
|
|
||||||
public class IntervalStatisticsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
public class IntervalStatisticsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
@@ -22,11 +23,11 @@ public class IntervalStatisticsAdapter extends RecyclerView.Adapter<RecyclerView
|
|||||||
private List<IntervalStatistics.Interval> intervalList;
|
private List<IntervalStatistics.Interval> intervalList;
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final StackMode stackMode;
|
private final StackMode stackMode;
|
||||||
private boolean metricUnits;
|
private UnitSystem unitSystem = UnitSystem.defaultUnitSystem();
|
||||||
private boolean isReportSpeed;
|
private boolean isReportSpeed;
|
||||||
|
|
||||||
public IntervalStatisticsAdapter(Context context, StackMode stackMode, boolean metricUnits, boolean isReportSpeed) {
|
public IntervalStatisticsAdapter(Context context, StackMode stackMode, UnitSystem unitSystem, boolean isReportSpeed) {
|
||||||
this.metricUnits = metricUnits;
|
this.unitSystem = unitSystem;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.stackMode = stackMode;
|
this.stackMode = stackMode;
|
||||||
this.isReportSpeed = isReportSpeed;
|
this.isReportSpeed = isReportSpeed;
|
||||||
@@ -57,14 +58,14 @@ public class IntervalStatisticsAdapter extends RecyclerView.Adapter<RecyclerView
|
|||||||
sumDistance = interval.getDistance().multipliedBy(nextPosition);
|
sumDistance = interval.getDistance().multipliedBy(nextPosition);
|
||||||
}
|
}
|
||||||
viewHolder.distance.setText(DistanceFormatter.Builder()
|
viewHolder.distance.setText(DistanceFormatter.Builder()
|
||||||
.setMetricUnits(metricUnits)
|
.setUnit(unitSystem)
|
||||||
.build(context).formatDistance(sumDistance));
|
.build(context).formatDistance(sumDistance));
|
||||||
|
|
||||||
SpeedFormatter formatter = SpeedFormatter.Builder().setMetricUnits(metricUnits).setReportSpeedOrPace(isReportSpeed).build(context);
|
SpeedFormatter formatter = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(isReportSpeed).build(context);
|
||||||
viewHolder.rate.setText(formatter.formatSpeed(interval.getSpeed()));
|
viewHolder.rate.setText(formatter.formatSpeed(interval.getSpeed()));
|
||||||
|
|
||||||
viewHolder.gain.setText(StringUtils.formatAltitudeChange(context, interval.getGain_m(), metricUnits));
|
viewHolder.gain.setText(StringUtils.formatAltitude(context, interval.getGain_m(), unitSystem));
|
||||||
viewHolder.loss.setText(StringUtils.formatAltitudeChange(context, interval.getLoss_m(), metricUnits));
|
viewHolder.loss.setText(StringUtils.formatAltitude(context, interval.getLoss_m(), unitSystem));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,8 +77,8 @@ public class IntervalStatisticsAdapter extends RecyclerView.Adapter<RecyclerView
|
|||||||
return intervalList.size();
|
return intervalList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<IntervalStatistics.Interval> swapData(List<IntervalStatistics.Interval> data, boolean metricUnits, boolean isReportSpeed) {
|
public List<IntervalStatistics.Interval> swapData(List<IntervalStatistics.Interval> data, UnitSystem unitSystem, boolean isReportSpeed) {
|
||||||
this.metricUnits = metricUnits;
|
this.unitSystem = unitSystem;
|
||||||
this.isReportSpeed = isReportSpeed;
|
this.isReportSpeed = isReportSpeed;
|
||||||
intervalList = data;
|
intervalList = data;
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import de.dennisguse.opentracks.data.models.Distance;
|
|||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||||
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
|
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This model is used to load intervals for a track.
|
* This model is used to load intervals for a track.
|
||||||
@@ -64,14 +65,14 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
|||||||
handler = null;
|
handler = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableLiveData<List<IntervalStatistics.Interval>> getIntervalStats(Track.Id trackId, boolean metricUnits, @Nullable IntervalOption interval) {
|
public MutableLiveData<List<IntervalStatistics.Interval>> getIntervalStats(Track.Id trackId, UnitSystem unitSystem, @Nullable IntervalOption interval) {
|
||||||
if (intervalsLiveData == null) {
|
if (intervalsLiveData == null) {
|
||||||
if (interval == null) {
|
if (interval == null) {
|
||||||
interval = IntervalOption.OPTION_1;
|
interval = IntervalOption.OPTION_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
intervalsLiveData = new MutableLiveData<>();
|
intervalsLiveData = new MutableLiveData<>();
|
||||||
distanceInterval = interval.getDistance(metricUnits);
|
distanceInterval = interval.getDistance(unitSystem);
|
||||||
intervalStatistics = new IntervalStatistics(distanceInterval);
|
intervalStatistics = new IntervalStatistics(distanceInterval);
|
||||||
|
|
||||||
loadIntervalStatistics(trackId);
|
loadIntervalStatistics(trackId);
|
||||||
@@ -104,13 +105,13 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(Track.Id trackId, boolean metricUnits, @Nullable IntervalOption interval) {
|
public void update(Track.Id trackId, UnitSystem unitSystem, @Nullable IntervalOption interval) {
|
||||||
if (interval == null) {
|
if (interval == null) {
|
||||||
interval = IntervalOption.DEFAULT;
|
interval = IntervalOption.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastTrackPointId = null;
|
lastTrackPointId = null;
|
||||||
distanceInterval = interval.getDistance(metricUnits);
|
distanceInterval = interval.getDistance(unitSystem);
|
||||||
intervalStatistics = new IntervalStatistics(distanceInterval);
|
intervalStatistics = new IntervalStatistics(distanceInterval);
|
||||||
loadIntervalStatistics(trackId);
|
loadIntervalStatistics(trackId);
|
||||||
}
|
}
|
||||||
@@ -138,9 +139,9 @@ public class IntervalStatisticsModel extends AndroidViewModel {
|
|||||||
this.multiplier = multiplier;
|
this.multiplier = multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Distance getDistance(boolean metricUnits) {
|
public Distance getDistance(UnitSystem unitSystem) {
|
||||||
return Distance
|
return Distance
|
||||||
.one(metricUnits)
|
.one(unitSystem)
|
||||||
.multipliedBy(multiplier);
|
.multipliedBy(multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import de.dennisguse.opentracks.data.models.DistanceFormatter;
|
|||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
import de.dennisguse.opentracks.databinding.IntervalListViewBinding;
|
import de.dennisguse.opentracks.databinding.IntervalListViewBinding;
|
||||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fragment to display the intervals from recorded track.
|
* A fragment to display the intervals from recorded track.
|
||||||
@@ -41,7 +42,7 @@ public class IntervalsFragment extends Fragment {
|
|||||||
private IntervalStatisticsModel.IntervalOption selectedInterval;
|
private IntervalStatisticsModel.IntervalOption selectedInterval;
|
||||||
|
|
||||||
private Track.Id trackId;
|
private Track.Id trackId;
|
||||||
private boolean metricUnits;
|
private UnitSystem unitSystem = UnitSystem.defaultUnitSystem();
|
||||||
private IntervalStatisticsAdapter adapter;
|
private IntervalStatisticsAdapter adapter;
|
||||||
private ArrayAdapter<IntervalStatisticsModel.IntervalOption> intervalsAdapter;
|
private ArrayAdapter<IntervalStatisticsModel.IntervalOption> intervalsAdapter;
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ public class IntervalsFragment extends Fragment {
|
|||||||
|
|
||||||
protected final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> {
|
protected final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> {
|
||||||
if (PreferencesUtils.isKey(R.string.stats_units_key, key) || PreferencesUtils.isKey(R.string.stats_rate_key, key)) {
|
if (PreferencesUtils.isKey(R.string.stats_units_key, key) || PreferencesUtils.isKey(R.string.stats_rate_key, key)) {
|
||||||
updateIntervals(PreferencesUtils.isMetricUnits(), selectedInterval);
|
updateIntervals(PreferencesUtils.getUnitSystem(), selectedInterval);
|
||||||
if (intervalsAdapter != null) {
|
if (intervalsAdapter != null) {
|
||||||
intervalsAdapter.notifyDataSetChanged();
|
intervalsAdapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
@@ -101,14 +102,14 @@ public class IntervalsFragment extends Fragment {
|
|||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
adapter = new IntervalStatisticsAdapter(getContext(), stackModeListView, metricUnits, isReportSpeed);
|
adapter = new IntervalStatisticsAdapter(getContext(), stackModeListView, unitSystem, isReportSpeed);
|
||||||
viewBinding.intervalList.setLayoutManager(new LinearLayoutManager(getContext()));
|
viewBinding.intervalList.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
// TODO handle empty view: before we did viewBinding.intervalList.setEmptyView(viewBinding.intervalListEmptyView);
|
// TODO handle empty view: before we did viewBinding.intervalList.setEmptyView(viewBinding.intervalListEmptyView);
|
||||||
viewBinding.intervalList.setAdapter(adapter);
|
viewBinding.intervalList.setAdapter(adapter);
|
||||||
|
|
||||||
final DistanceFormatter formatter = DistanceFormatter.Builder()
|
final DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setDecimalCount(0)
|
.setDecimalCount(0)
|
||||||
.setMetricUnits(metricUnits)
|
.setUnit(unitSystem)
|
||||||
.build(getContext());
|
.build(getContext());
|
||||||
|
|
||||||
intervalsAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item, IntervalStatisticsModel.IntervalOption.values()) {
|
intervalsAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item, IntervalStatisticsModel.IntervalOption.values()) {
|
||||||
@@ -118,7 +119,7 @@ public class IntervalsFragment extends Fragment {
|
|||||||
TextView v = (TextView) super.getView(position, convertView, parent);
|
TextView v = (TextView) super.getView(position, convertView, parent);
|
||||||
|
|
||||||
IntervalStatisticsModel.IntervalOption option = getItem(position);
|
IntervalStatisticsModel.IntervalOption option = getItem(position);
|
||||||
String stringValue = formatter.formatDistance(option.getDistance(metricUnits));
|
String stringValue = formatter.formatDistance(option.getDistance(unitSystem));
|
||||||
v.setText(stringValue);
|
v.setText(stringValue);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@@ -131,7 +132,7 @@ public class IntervalsFragment extends Fragment {
|
|||||||
|
|
||||||
viewBinding.intervalsDropdown.setAdapter(intervalsAdapter);
|
viewBinding.intervalsDropdown.setAdapter(intervalsAdapter);
|
||||||
viewBinding.intervalsDropdown.setOnItemClickListener((parent, view1, position, id) -> {
|
viewBinding.intervalsDropdown.setOnItemClickListener((parent, view1, position, id) -> {
|
||||||
updateIntervals(metricUnits, IntervalStatisticsModel.IntervalOption.values()[position]);
|
updateIntervals(unitSystem, IntervalStatisticsModel.IntervalOption.values()[position]);
|
||||||
|
|
||||||
//TODO This duplicates the intervalAdapter code
|
//TODO This duplicates the intervalAdapter code
|
||||||
setIntervalsDropdownText();
|
setIntervalsDropdownText();
|
||||||
@@ -191,8 +192,8 @@ public class IntervalsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewBinding.intervalRate.setText(isReportSpeed ? getString(R.string.stats_speed) : getString(R.string.stats_pace));
|
viewBinding.intervalRate.setText(isReportSpeed ? getString(R.string.stats_speed) : getString(R.string.stats_pace));
|
||||||
LiveData<List<IntervalStatistics.Interval>> liveData = viewModel.getIntervalStats(trackId, metricUnits, selectedInterval);
|
LiveData<List<IntervalStatistics.Interval>> liveData = viewModel.getIntervalStats(trackId, unitSystem, selectedInterval);
|
||||||
liveData.observe(getActivity(), intervalList -> adapter.swapData(intervalList, metricUnits, isReportSpeed));
|
liveData.observe(getActivity(), intervalList -> adapter.swapData(intervalList, unitSystem, isReportSpeed));
|
||||||
|
|
||||||
setIntervalsDropdownText();
|
setIntervalsDropdownText();
|
||||||
}
|
}
|
||||||
@@ -200,23 +201,23 @@ public class IntervalsFragment extends Fragment {
|
|||||||
private void setIntervalsDropdownText() {
|
private void setIntervalsDropdownText() {
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setDecimalCount(0)
|
.setDecimalCount(0)
|
||||||
.setMetricUnits(metricUnits)
|
.setUnit(unitSystem)
|
||||||
.build(getContext());
|
.build(getContext());
|
||||||
|
|
||||||
IntervalStatisticsModel.IntervalOption option = selectedInterval != null ? selectedInterval : IntervalStatisticsModel.IntervalOption.DEFAULT;
|
IntervalStatisticsModel.IntervalOption option = selectedInterval != null ? selectedInterval : IntervalStatisticsModel.IntervalOption.DEFAULT;
|
||||||
String stringValue = formatter.formatDistance(option.getDistance(metricUnits));
|
String stringValue = formatter.formatDistance(option.getDistance(unitSystem));
|
||||||
viewBinding.intervalsDropdown.setText(stringValue, false);
|
viewBinding.intervalsDropdown.setText(stringValue, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void updateIntervals(boolean metricUnits, IntervalStatisticsModel.IntervalOption selectedInterval) {
|
private synchronized void updateIntervals(UnitSystem unitSystem, IntervalStatisticsModel.IntervalOption selectedInterval) {
|
||||||
boolean update = metricUnits != this.metricUnits
|
boolean update = unitSystem != this.unitSystem
|
||||||
|| selectedInterval == null
|
|| selectedInterval == null
|
||||||
|| !selectedInterval.sameMultiplier(this.selectedInterval);
|
|| !selectedInterval.sameMultiplier(this.selectedInterval);
|
||||||
this.metricUnits = metricUnits;
|
this.unitSystem = unitSystem;
|
||||||
this.selectedInterval = selectedInterval;
|
this.selectedInterval = selectedInterval;
|
||||||
|
|
||||||
if (update && viewModel != null) {
|
if (update && viewModel != null) {
|
||||||
viewModel.update(trackId, this.metricUnits, this.selectedInterval);
|
viewModel.update(trackId, this.unitSystem, this.selectedInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,8 +43,10 @@ import java.time.temporal.TemporalAccessor;
|
|||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.data.models.Cadence;
|
import de.dennisguse.opentracks.data.models.Cadence;
|
||||||
import de.dennisguse.opentracks.data.models.Distance;
|
import de.dennisguse.opentracks.data.models.Distance;
|
||||||
|
import de.dennisguse.opentracks.data.models.DistanceFormatter;
|
||||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||||
import de.dennisguse.opentracks.data.models.Power;
|
import de.dennisguse.opentracks.data.models.Power;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Various string manipulation methods.
|
* Various string manipulation methods.
|
||||||
@@ -252,35 +254,18 @@ public class StringUtils {
|
|||||||
/**
|
/**
|
||||||
* @return the formatted altitude_m (or null) and it's unit as {@link Pair}
|
* @return the formatted altitude_m (or null) and it's unit as {@link Pair}
|
||||||
*/
|
*/
|
||||||
public static Pair<String, String> getAltitudeParts(Context context, Float altitude_m, boolean metricUnits) {
|
public static Pair<String, String> getAltitudeParts(Context context, Float altitude_m, UnitSystem unitSystem) {
|
||||||
String formattedValue = context.getString(R.string.value_unknown);
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
String unit = context.getString(metricUnits ? R.string.unit_meter : R.string.unit_feet);
|
.setDecimalCount(1)
|
||||||
|
.setUnit(unitSystem)
|
||||||
|
.build(context);
|
||||||
|
|
||||||
if (altitude_m != null) {
|
Distance distance = altitude_m != null ? Distance.of(altitude_m) : Distance.of(Double.NaN); //TODO Refactor Double.NaN
|
||||||
double value = Distance.of(altitude_m).toM_FT(metricUnits);
|
return formatter.getDistanceParts(distance);
|
||||||
formattedValue = StringUtils.formatDecimal(value, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Pair<>(formattedValue, unit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String formatAltitude(Context context, Float altitude_m, boolean metricUnits) {
|
public static String formatAltitude(Context context, Float altitude_m, UnitSystem unitSystem) {
|
||||||
Pair<String, String> altitudeParts = getAltitudeParts(context, altitude_m, metricUnits);
|
Pair<String, String> altitudeParts = getAltitudeParts(context, altitude_m, unitSystem);
|
||||||
|
|
||||||
return context.getString(R.string.altitude_with_unit, altitudeParts.first, altitudeParts.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the formatted altitudeDifference_m (or null) and it's unit as {@link Pair}
|
|
||||||
*/
|
|
||||||
public static Pair<String, String> getAltitudeChangeParts(Context context, Float altitudeDifference_m, boolean metricUnits) {
|
|
||||||
String formattedValue = altitudeDifference_m != null ? String.valueOf((int) Distance.of(altitudeDifference_m).toM_FT(metricUnits)) : context.getString(R.string.value_unknown);
|
|
||||||
String unit = context.getString(metricUnits ? R.string.unit_meter : R.string.unit_feet);
|
|
||||||
return new Pair<>(formattedValue, unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String formatAltitudeChange(Context context, Float altitude_m, boolean metricUnits) {
|
|
||||||
Pair<String, String> altitudeParts = getAltitudeChangeParts(context, altitude_m, metricUnits);
|
|
||||||
|
|
||||||
return context.getString(R.string.altitude_with_unit, altitudeParts.first, altitudeParts.second);
|
return context.getString(R.string.altitude_with_unit, altitudeParts.first, altitudeParts.second);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import de.dennisguse.opentracks.data.models.SpeedFormatter;
|
|||||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||||
import de.dennisguse.opentracks.services.RecordingData;
|
import de.dennisguse.opentracks.services.RecordingData;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.ui.customRecordingLayout.DataField;
|
import de.dennisguse.opentracks.ui.customRecordingLayout.DataField;
|
||||||
@@ -26,17 +27,17 @@ import de.dennisguse.opentracks.util.StringUtils;
|
|||||||
|
|
||||||
public class StatisticDataBuilder {
|
public class StatisticDataBuilder {
|
||||||
|
|
||||||
public static List<StatisticData> fromRecordingData(@NonNull Context context, @NonNull RecordingData recordingData, @NonNull Layout layout, boolean metricUnits) {
|
public static List<StatisticData> fromRecordingData(@NonNull Context context, @NonNull RecordingData recordingData, @NonNull Layout layout, UnitSystem unitSystem) {
|
||||||
List<StatisticData> statisticDataList = layout.getFields().stream()
|
List<StatisticData> statisticDataList = layout.getFields().stream()
|
||||||
.filter(DataField::isVisible)
|
.filter(DataField::isVisible)
|
||||||
.map(field -> build(context, recordingData, field.getKey(), field.isPrimary(), metricUnits))
|
.map(field -> build(context, recordingData, field.getKey(), field.isPrimary(), unitSystem))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
statisticDataList.addAll(getSensorStatsDataIfNeeded(context, recordingData, statisticDataList, metricUnits));
|
statisticDataList.addAll(getSensorStatsDataIfNeeded(context, recordingData, statisticDataList, unitSystem));
|
||||||
return statisticDataList;
|
return statisticDataList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StatisticData build(@NonNull Context context, @NonNull RecordingData recordingData, @NonNull String fieldKey, boolean isPrimary, boolean metricUnits) {
|
private static StatisticData build(@NonNull Context context, @NonNull RecordingData recordingData, @NonNull String fieldKey, boolean isPrimary, UnitSystem unitSystem) {
|
||||||
final TrackPoint latestTrackPoint = recordingData.getLatestTrackPoint();
|
final TrackPoint latestTrackPoint = recordingData.getLatestTrackPoint();
|
||||||
final SensorDataSet sensorDataSet = recordingData.getSensorDataSet();
|
final SensorDataSet sensorDataSet = recordingData.getSensorDataSet();
|
||||||
final TrackStatistics trackStatistics = recordingData.getTrackStatistics();
|
final TrackStatistics trackStatistics = recordingData.getTrackStatistics();
|
||||||
@@ -48,8 +49,8 @@ public class StatisticDataBuilder {
|
|||||||
|
|
||||||
final String sensorUnknown = context.getString(R.string.value_unknown);
|
final String sensorUnknown = context.getString(R.string.value_unknown);
|
||||||
|
|
||||||
SpeedFormatter speedFormatterPace = SpeedFormatter.Builder().setMetricUnits(metricUnits).setReportSpeedOrPace(false).build(context);
|
SpeedFormatter speedFormatterPace = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(false).build(context);
|
||||||
SpeedFormatter speedFormatterSpeed = SpeedFormatter.Builder().setMetricUnits(metricUnits).setReportSpeedOrPace(true).build(context);
|
SpeedFormatter speedFormatterSpeed = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(true).build(context);
|
||||||
|
|
||||||
|
|
||||||
if (fieldKey.equals(context.getString(R.string.stats_custom_layout_total_time_key))) {
|
if (fieldKey.equals(context.getString(R.string.stats_custom_layout_total_time_key))) {
|
||||||
@@ -60,14 +61,14 @@ public class StatisticDataBuilder {
|
|||||||
title = context.getString(R.string.stats_moving_time);
|
title = context.getString(R.string.stats_moving_time);
|
||||||
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_distance_key))) {
|
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_distance_key))) {
|
||||||
valueAndUnit = DistanceFormatter.Builder()
|
valueAndUnit = DistanceFormatter.Builder()
|
||||||
.setMetricUnits(metricUnits)
|
.setUnit(unitSystem)
|
||||||
.build(context).getDistanceParts(trackStatistics.getTotalDistance());
|
.build(context).getDistanceParts(trackStatistics.getTotalDistance());
|
||||||
title = context.getString(R.string.stats_distance);
|
title = context.getString(R.string.stats_distance);
|
||||||
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_speed_key)) || fieldKey.equals(context.getString(R.string.stats_custom_layout_pace_key))) {
|
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_speed_key)) || fieldKey.equals(context.getString(R.string.stats_custom_layout_pace_key))) {
|
||||||
boolean reportSpeed = fieldKey.equals("speed");
|
boolean reportSpeed = fieldKey.equals("speed");
|
||||||
title = reportSpeed ? context.getString(R.string.stats_speed) : context.getString(R.string.stats_pace);
|
title = reportSpeed ? context.getString(R.string.stats_speed) : context.getString(R.string.stats_pace);
|
||||||
|
|
||||||
SpeedFormatter localSpeedFormatter = SpeedFormatter.Builder().setMetricUnits(metricUnits).setReportSpeedOrPace(reportSpeed).build(context);
|
SpeedFormatter localSpeedFormatter = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(reportSpeed).build(context);
|
||||||
if (sensorDataSet != null && sensorDataSet.getSpeed() != null) {
|
if (sensorDataSet != null && sensorDataSet.getSpeed() != null) {
|
||||||
valueAndUnit = localSpeedFormatter.getSpeedParts(sensorDataSet.getSpeed().first);
|
valueAndUnit = localSpeedFormatter.getSpeedParts(sensorDataSet.getSpeed().first);
|
||||||
description = sensorDataSet.getSpeed().second;
|
description = sensorDataSet.getSpeed().second;
|
||||||
@@ -98,12 +99,12 @@ public class StatisticDataBuilder {
|
|||||||
Float altitude = latestTrackPoint != null && latestTrackPoint.hasAltitude() ? (float) latestTrackPoint.getAltitude().toM() : null;
|
Float altitude = latestTrackPoint != null && latestTrackPoint.hasAltitude() ? (float) latestTrackPoint.getAltitude().toM() : null;
|
||||||
title = context.getString(R.string.stats_altitude);
|
title = context.getString(R.string.stats_altitude);
|
||||||
description = latestTrackPoint != null && latestTrackPoint.hasAltitude() ? context.getString(latestTrackPoint.getAltitude().getLabelId()) : null;
|
description = latestTrackPoint != null && latestTrackPoint.hasAltitude() ? context.getString(latestTrackPoint.getAltitude().getLabelId()) : null;
|
||||||
valueAndUnit = StringUtils.getAltitudeParts(context, altitude, metricUnits);
|
valueAndUnit = StringUtils.getAltitudeParts(context, altitude, unitSystem);
|
||||||
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_gain_key))) {
|
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_gain_key))) {
|
||||||
valueAndUnit = StringUtils.getAltitudeChangeParts(context, trackStatistics.getTotalAltitudeGain(), metricUnits);
|
valueAndUnit = StringUtils.getAltitudeParts(context, trackStatistics.getTotalAltitudeGain(), unitSystem);
|
||||||
title = context.getString(R.string.stats_gain);
|
title = context.getString(R.string.stats_gain);
|
||||||
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_loss_key))) {
|
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_loss_key))) {
|
||||||
valueAndUnit = StringUtils.getAltitudeChangeParts(context, trackStatistics.getTotalAltitudeLoss(), metricUnits);
|
valueAndUnit = StringUtils.getAltitudeParts(context, trackStatistics.getTotalAltitudeLoss(), unitSystem);
|
||||||
title = context.getString(R.string.stats_loss);
|
title = context.getString(R.string.stats_loss);
|
||||||
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_coordinates_key))) {
|
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_coordinates_key))) {
|
||||||
title = context.getString(R.string.stats_coordinates);
|
title = context.getString(R.string.stats_coordinates);
|
||||||
@@ -162,20 +163,20 @@ public class StatisticDataBuilder {
|
|||||||
/**
|
/**
|
||||||
* Builds a list of StatisticData with sensors configured but not in statisticDataList.
|
* Builds a list of StatisticData with sensors configured but not in statisticDataList.
|
||||||
*/
|
*/
|
||||||
private static List<StatisticData> getSensorStatsDataIfNeeded(Context context, RecordingData recordingData, List<StatisticData> statisticDataList, boolean metricUnits) {
|
private static List<StatisticData> getSensorStatsDataIfNeeded(Context context, RecordingData recordingData, List<StatisticData> statisticDataList, UnitSystem unitSystem) {
|
||||||
List<StatisticData> sensorDataList = new ArrayList<>();
|
List<StatisticData> sensorDataList = new ArrayList<>();
|
||||||
SensorDataSet sensorDataSet = recordingData.getSensorDataSet();
|
SensorDataSet sensorDataSet = recordingData.getSensorDataSet();
|
||||||
if (sensorDataSet == null) {
|
if (sensorDataSet == null) {
|
||||||
return sensorDataList;
|
return sensorDataList;
|
||||||
}
|
}
|
||||||
if (statisticDataList.stream().noneMatch(i -> i.getField().getTitle().equals(context.getString(R.string.stats_sensors_heart_rate))) && sensorDataSet.getHeartRate() != null) {
|
if (statisticDataList.stream().noneMatch(i -> i.getField().getTitle().equals(context.getString(R.string.stats_sensors_heart_rate))) && sensorDataSet.getHeartRate() != null) {
|
||||||
sensorDataList.add(build(context, recordingData, "heart_rate", true, metricUnits));
|
sensorDataList.add(build(context, recordingData, "heart_rate", true, unitSystem));
|
||||||
}
|
}
|
||||||
if (statisticDataList.stream().noneMatch(i -> i.getField().getTitle().equals(context.getString(R.string.stats_sensors_cadence))) && sensorDataSet.getCadence() != null) {
|
if (statisticDataList.stream().noneMatch(i -> i.getField().getTitle().equals(context.getString(R.string.stats_sensors_cadence))) && sensorDataSet.getCadence() != null) {
|
||||||
sensorDataList.add(build(context, recordingData, "cadence", true, metricUnits));
|
sensorDataList.add(build(context, recordingData, "cadence", true, unitSystem));
|
||||||
}
|
}
|
||||||
if (statisticDataList.stream().noneMatch(i -> i.getField().getTitle().equals(context.getString(R.string.stats_sensors_power))) && sensorDataSet.getCyclingPower() != null && sensorDataSet.getCyclingPower().hasValue()) {
|
if (statisticDataList.stream().noneMatch(i -> i.getField().getTitle().equals(context.getString(R.string.stats_sensors_power))) && sensorDataSet.getCyclingPower() != null && sensorDataSet.getCyclingPower().hasValue()) {
|
||||||
sensorDataList.add(build(context, recordingData, "power", true, metricUnits));
|
sensorDataList.add(build(context, recordingData, "power", true, unitSystem));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sensorDataList;
|
return sensorDataList;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import androidx.lifecycle.MutableLiveData;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.services.RecordingData;
|
import de.dennisguse.opentracks.services.RecordingData;
|
||||||
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.ui.customRecordingLayout.Layout;
|
import de.dennisguse.opentracks.ui.customRecordingLayout.Layout;
|
||||||
|
|
||||||
public class StatisticsDataModel extends AndroidViewModel {
|
public class StatisticsDataModel extends AndroidViewModel {
|
||||||
@@ -26,9 +27,9 @@ public class StatisticsDataModel extends AndroidViewModel {
|
|||||||
return statsData;
|
return statsData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(RecordingData recordingData, Layout layout, boolean metricUnit) {
|
public void update(RecordingData recordingData, Layout layout, UnitSystem unitSystem) {
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
List<StatisticData> statisticDataList = StatisticDataBuilder.fromRecordingData(getApplication(), recordingData, layout, metricUnit);
|
List<StatisticData> statisticDataList = StatisticDataBuilder.fromRecordingData(getApplication(), recordingData, layout, unitSystem);
|
||||||
statsData.postValue(statisticDataList);
|
statsData.postValue(statisticDataList);
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user