forked from upstream-mirrors/OpenTracks
Merge pull request #1310 from OpenTracksApp/time
Refactoring things regarding Duration, Speed, and Distance
This commit is contained in:
+4
-2
@@ -6,7 +6,7 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.2.2'
|
classpath 'com.android.tools.build:gradle:7.3.0-rc01'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,6 +81,8 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace 'de.dennisguse.opentracks'
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
applicationIdSuffix ".debug"
|
applicationIdSuffix ".debug"
|
||||||
@@ -118,7 +120,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.6'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.0'
|
||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.5.0'
|
implementation 'androidx.appcompat:appcompat:1.5.0'
|
||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.5.1'
|
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.5.1'
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import junit.framework.TestCase;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.data.models.Track;
|
import de.dennisguse.opentracks.data.models.Track;
|
||||||
@@ -105,7 +106,7 @@ public class TrackSelectionTest extends TestCase {
|
|||||||
long oneDay = 24 * 60 * 60 * 1000;
|
long oneDay = 24 * 60 * 60 * 1000;
|
||||||
TrackSelection filterWrong1 = new TrackSelection().addDateRange(instant, null);
|
TrackSelection filterWrong1 = new TrackSelection().addDateRange(instant, null);
|
||||||
TrackSelection filterWrong2 = new TrackSelection().addDateRange(null, instant);
|
TrackSelection filterWrong2 = new TrackSelection().addDateRange(null, instant);
|
||||||
TrackSelection filterOk = new TrackSelection().addDateRange(instant, instant.plusMillis(oneDay));
|
TrackSelection filterOk = new TrackSelection().addDateRange(instant, instant.plus(Duration.ofDays(1)));
|
||||||
|
|
||||||
// when
|
// when
|
||||||
SelectionData selectionWrong1 = filterWrong1.buildSelection();
|
SelectionData selectionWrong1 = filterWrong1.buildSelection();
|
||||||
|
|||||||
+1
-1
@@ -463,7 +463,7 @@ public class ExportImportTest {
|
|||||||
contentProviderUtils.deleteTrack(context, trackId);
|
contentProviderUtils.deleteTrack(context, trackId);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
InputStream expected = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.csv_export);
|
InputStream expected = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.csv_export);
|
||||||
String expectedText = new BufferedReader(new InputStreamReader(expected, StandardCharsets.UTF_8))
|
String expectedText = new BufferedReader(new InputStreamReader(expected, StandardCharsets.UTF_8))
|
||||||
.lines()
|
.lines()
|
||||||
.collect(Collectors.joining("\n"));
|
.collect(Collectors.joining("\n"));
|
||||||
|
|||||||
+5
-5
@@ -69,7 +69,7 @@ public class GPXTrackImporterTest {
|
|||||||
public void gpx_with_pause_resume() throws IOException {
|
public void gpx_with_pause_resume() throws IOException {
|
||||||
// given
|
// given
|
||||||
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
|
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
|
||||||
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.legacy_gpx_pause_resume);
|
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.legacy_gpx_pause_resume);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
// 1. import
|
// 1. import
|
||||||
@@ -123,7 +123,7 @@ public class GPXTrackImporterTest {
|
|||||||
public void gpx_without_speed() throws IOException {
|
public void gpx_without_speed() throws IOException {
|
||||||
// given
|
// given
|
||||||
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
|
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
|
||||||
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.gpx11_without_speed);
|
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.gpx11_without_speed);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
// 1. import
|
// 1. import
|
||||||
@@ -171,7 +171,7 @@ public class GPXTrackImporterTest {
|
|||||||
public void gpx_speed_no_namespace() throws IOException {
|
public void gpx_speed_no_namespace() throws IOException {
|
||||||
// given
|
// given
|
||||||
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
|
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
|
||||||
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.gpx11_with_speed_no_namespace);
|
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.gpx11_with_speed_no_namespace);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
// 1. import
|
// 1. import
|
||||||
@@ -221,8 +221,8 @@ public class GPXTrackImporterTest {
|
|||||||
public void importExportTest_timezone() throws IOException {
|
public void importExportTest_timezone() throws IOException {
|
||||||
// given
|
// given
|
||||||
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
|
XMLImporter importer = new XMLImporter(new GpxTrackImporter(context, trackImporter));
|
||||||
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.gpx_timezone);
|
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.gpx_timezone);
|
||||||
InputStream inputStreamExpected = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.gpx_timezone);
|
InputStream inputStreamExpected = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.gpx_timezone);
|
||||||
|
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -60,7 +60,7 @@ public class KMLTrackImporterTest {
|
|||||||
public void kml22_order_location_and_when() throws IOException {
|
public void kml22_order_location_and_when() throws IOException {
|
||||||
// given
|
// given
|
||||||
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
|
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
|
||||||
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.kml22_order_location_and_when);
|
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.kml22_order_location_and_when);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
// 1. import
|
// 1. import
|
||||||
@@ -109,7 +109,7 @@ public class KMLTrackImporterTest {
|
|||||||
public void kml22_time_decreases() throws IOException {
|
public void kml22_time_decreases() throws IOException {
|
||||||
// given
|
// given
|
||||||
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
|
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
|
||||||
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.kml22_time_decreases);
|
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.kml22_time_decreases);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
// 1. import
|
// 1. import
|
||||||
@@ -149,7 +149,7 @@ public class KMLTrackImporterTest {
|
|||||||
public void kml22_with_statistics_marker() throws IOException {
|
public void kml22_with_statistics_marker() throws IOException {
|
||||||
// given
|
// given
|
||||||
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
|
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
|
||||||
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.legacy_kml22_statistics_marker);
|
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.legacy_kml22_statistics_marker);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
// 1. import
|
// 1. import
|
||||||
@@ -223,7 +223,7 @@ public class KMLTrackImporterTest {
|
|||||||
public void kml_without_locations() throws IOException {
|
public void kml_without_locations() throws IOException {
|
||||||
// given
|
// given
|
||||||
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
|
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
|
||||||
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.kml22_without_locations);
|
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.kml22_without_locations);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
importTrackId = importer.importFile(inputStream).get(0);
|
importTrackId = importer.importFile(inputStream).get(0);
|
||||||
@@ -234,7 +234,7 @@ public class KMLTrackImporterTest {
|
|||||||
public void kml_when_locations_different() throws IOException {
|
public void kml_when_locations_different() throws IOException {
|
||||||
// given
|
// given
|
||||||
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
|
XMLImporter importer = new XMLImporter(new KmlTrackImporter(context, trackImporter));
|
||||||
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.debug.test.R.raw.kml22_when_locations_different);
|
InputStream inputStream = InstrumentationRegistry.getInstrumentation().getContext().getResources().openRawResource(de.dennisguse.opentracks.test.R.raw.kml22_when_locations_different);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
importTrackId = importer.importFile(inputStream).get(0);
|
importTrackId = importer.importFile(inputStream).get(0);
|
||||||
|
|||||||
+1
-2
@@ -21,7 +21,6 @@ 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.data.models.TrackPoint;
|
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||||
import de.dennisguse.opentracks.data.models.UnitConversions;
|
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
||||||
|
|
||||||
@@ -180,7 +179,7 @@ public class IntervalStatisticsTest {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(trackStatistics.getTotalDistance().toM(), totalDistance.toM(), 0.01);
|
assertEquals(trackStatistics.getTotalDistance().toM(), totalDistance.toM(), 0.01);
|
||||||
assertEquals(trackStatistics.getTotalTime().toMillis(), totalTime * UnitConversions.S_TO_MS, 1);
|
assertEquals(trackStatistics.getTotalTime().toSeconds(), totalTime, 0.01);
|
||||||
assertEquals(intervalList.size(), (int) Math.ceil(trackStatistics.getTotalDistance().toM() / distanceInterval));
|
assertEquals(intervalList.size(), (int) Math.ceil(trackStatistics.getTotalDistance().toM() / distanceInterval));
|
||||||
if (totalGain != null) {
|
if (totalGain != null) {
|
||||||
assertEquals(totalGain, numberOfPoints * TestDataUtil.ALTITUDE_GAIN, 0.1);
|
assertEquals(totalGain, numberOfPoints * TestDataUtil.ALTITUDE_GAIN, 0.1);
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ limitations under the License.
|
|||||||
-->
|
-->
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="de.dennisguse.opentracks"
|
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
|
|
||||||
<supports-screens
|
<supports-screens
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import androidx.annotation.VisibleForTesting;
|
|||||||
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.data.models.UnitConversions;
|
|
||||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||||
import de.dennisguse.opentracks.stats.TrackStatistics;
|
import de.dennisguse.opentracks.stats.TrackStatistics;
|
||||||
|
|
||||||
@@ -41,7 +40,7 @@ public class ChartPoint {
|
|||||||
|
|
||||||
if (smoothedSpeed != null) {
|
if (smoothedSpeed != null) {
|
||||||
speed = smoothedSpeed.to(unitSystem);
|
speed = smoothedSpeed.to(unitSystem);
|
||||||
pace = smoothedSpeed.toPace(unitSystem).toMillis() * UnitConversions.MS_TO_S * UnitConversions.S_TO_MIN;
|
pace = smoothedSpeed.toPace(unitSystem).toSeconds() / 60d;
|
||||||
}
|
}
|
||||||
if (trackPoint.hasHeartRate()) {
|
if (trackPoint.hasHeartRate()) {
|
||||||
heartRate = (double) trackPoint.getHeartRate().getBPM();
|
heartRate = (double) trackPoint.getHeartRate().getBPM();
|
||||||
|
|||||||
@@ -2,22 +2,35 @@ package de.dennisguse.opentracks.data.models;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Cadence {
|
public class Cadence {
|
||||||
|
|
||||||
public static Cadence of(float value) {
|
public static Cadence of(float value, Duration duration) {
|
||||||
return new Cadence(value);
|
if (duration.isZero()) {
|
||||||
|
return zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Cadence(value / (duration.toMillis() / (float) Duration.ofMinutes(1).toMillis()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final float value;
|
public static Cadence of(float value_rpm) {
|
||||||
|
return new Cadence(value_rpm);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Cadence zero() {
|
||||||
|
return of(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final float value_rpm;
|
||||||
|
|
||||||
private Cadence(float value) {
|
private Cadence(float value) {
|
||||||
this.value = value;
|
this.value_rpm = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getRPM() {
|
public float getRPM() {
|
||||||
return value;
|
return value_rpm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -25,19 +38,19 @@ public class Cadence {
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
Cadence cadence = (Cadence) o;
|
Cadence cadence = (Cadence) o;
|
||||||
return Float.compare(cadence.value, value) == 0;
|
return Float.compare(cadence.value_rpm, value_rpm) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(value);
|
return Objects.hash(value_rpm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Cadence{" +
|
return "Cadence{" +
|
||||||
"value=" + value + " rpm" +
|
"value=" + value_rpm + " rpm" +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,15 +34,15 @@ public class Distance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Distance ofMile(double distance_mile) {
|
public static Distance ofMile(double distance_mile) {
|
||||||
return of(distance_mile * UnitConversions.MI_TO_M);
|
return of(distance_mile * MI_TO_M);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Distance ofNauticalMile(double distance_mile) {
|
public static Distance ofNauticalMile(double distance_mile) {
|
||||||
return of(distance_mile * UnitConversions.NAUTICAL_MILE_TO_M);
|
return of(distance_mile * NAUTICAL_MILE_TO_M);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Distance ofKilometer(double distance_km) {
|
public static Distance ofKilometer(double distance_km) {
|
||||||
return of(distance_km * UnitConversions.KM_TO_M);
|
return of(distance_km * KM_TO_M);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Distance ofMM(double distance_mm) {
|
public static Distance ofMM(double distance_mm) {
|
||||||
@@ -117,19 +117,19 @@ public class Distance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public double toKM() {
|
public double toKM() {
|
||||||
return distance_m * UnitConversions.M_TO_KM;
|
return distance_m * M_TO_KM;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double toFT() {
|
public double toFT() {
|
||||||
return distance_m * UnitConversions.M_TO_FT;
|
return distance_m * M_TO_FT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double toMI() {
|
public double toMI() {
|
||||||
return toKM() * UnitConversions.KM_TO_MI;
|
return distance_m * M_TO_MI;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double toNauticalMiles() {
|
public double toNauticalMiles() {
|
||||||
return toKM() * UnitConversions.KM_TO_NAUTICAL_MILE;
|
return distance_m * M_TO_NAUTICAL_MILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double toKM_Miles(UnitSystem unitSystem) {
|
public double toKM_Miles(UnitSystem unitSystem) {
|
||||||
@@ -177,4 +177,17 @@ public class Distance {
|
|||||||
"distance_m=" + distance_m +
|
"distance_m=" + distance_m +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// multiplication factors for conversion
|
||||||
|
private static final double KM_TO_M = 1000.0;
|
||||||
|
private static final double M_TO_KM = 1 / KM_TO_M;
|
||||||
|
|
||||||
|
public static final double MI_TO_M = 1609.344;
|
||||||
|
public static final double M_TO_MI = 1 / MI_TO_M;
|
||||||
|
|
||||||
|
private static final double MI_TO_FT = 5280.0;
|
||||||
|
public static final double M_TO_FT = M_TO_MI * MI_TO_FT;
|
||||||
|
|
||||||
|
private static final double NAUTICAL_MILE_TO_M = 1852.0;
|
||||||
|
private static final double M_TO_NAUTICAL_MILE = 1 / NAUTICAL_MILE_TO_M;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,14 @@ public class DistanceFormatter {
|
|||||||
|
|
||||||
private final int decimalCount;
|
private final int decimalCount;
|
||||||
|
|
||||||
|
private final double threshold;
|
||||||
|
|
||||||
private final UnitSystem unitSystem;
|
private final UnitSystem unitSystem;
|
||||||
|
|
||||||
private DistanceFormatter(Resources resources, int decimalCount, UnitSystem unitSystem) {
|
private DistanceFormatter(Resources resources, int decimalCount, double threshold, UnitSystem unitSystem) {
|
||||||
this.resources = resources;
|
this.resources = resources;
|
||||||
this.decimalCount = decimalCount;
|
this.decimalCount = decimalCount;
|
||||||
|
this.threshold = threshold;
|
||||||
this.unitSystem = unitSystem;
|
this.unitSystem = unitSystem;
|
||||||
assert unitSystem != null;
|
assert unitSystem != null;
|
||||||
}
|
}
|
||||||
@@ -56,19 +59,19 @@ public class DistanceFormatter {
|
|||||||
|
|
||||||
switch (unitSystem) {
|
switch (unitSystem) {
|
||||||
case METRIC:
|
case METRIC:
|
||||||
if (distance.greaterThan(Distance.of(500))) {
|
if (distance.greaterThan(Distance.ofKilometer(threshold))) {
|
||||||
return new Pair<>(StringUtils.formatDecimal(distance.toKM(), decimalCount), resources.getString(R.string.unit_kilometer));
|
return new Pair<>(StringUtils.formatDecimal(distance.toKM(), decimalCount), resources.getString(R.string.unit_kilometer));
|
||||||
} else {
|
} else {
|
||||||
return new Pair<>(StringUtils.formatDecimal(distance.toM(), decimalCount), resources.getString(R.string.unit_meter));
|
return new Pair<>(StringUtils.formatDecimal(distance.toM(), decimalCount), resources.getString(R.string.unit_meter));
|
||||||
}
|
}
|
||||||
case IMPERIAL:
|
case IMPERIAL:
|
||||||
if (distance.greaterThan(Distance.ofMile(0.5))) {
|
if (distance.greaterThan(Distance.ofMile(threshold))) {
|
||||||
return new Pair<>(StringUtils.formatDecimal(distance.toMI(), decimalCount), resources.getString(R.string.unit_mile));
|
return new Pair<>(StringUtils.formatDecimal(distance.toMI(), decimalCount), resources.getString(R.string.unit_mile));
|
||||||
} else {
|
} else {
|
||||||
return new Pair<>(StringUtils.formatDecimal(distance.toFT(), decimalCount), resources.getString(R.string.unit_feet));
|
return new Pair<>(StringUtils.formatDecimal(distance.toFT(), decimalCount), resources.getString(R.string.unit_feet));
|
||||||
}
|
}
|
||||||
case NAUTICAL_IMPERIAL:
|
case NAUTICAL_IMPERIAL:
|
||||||
if (distance.greaterThan(Distance.ofNauticalMile(0.5))) {
|
if (distance.greaterThan(Distance.ofNauticalMile(threshold))) {
|
||||||
return new Pair<>(StringUtils.formatDecimal(distance.toNauticalMiles(), decimalCount), resources.getString(R.string.unit_nautical_mile));
|
return new Pair<>(StringUtils.formatDecimal(distance.toNauticalMiles(), decimalCount), resources.getString(R.string.unit_nautical_mile));
|
||||||
} else {
|
} else {
|
||||||
return new Pair<>(StringUtils.formatDecimal(distance.toFT(), decimalCount), resources.getString(R.string.unit_feet));
|
return new Pair<>(StringUtils.formatDecimal(distance.toFT(), decimalCount), resources.getString(R.string.unit_feet));
|
||||||
@@ -88,8 +91,11 @@ public class DistanceFormatter {
|
|||||||
|
|
||||||
private UnitSystem unitSystem;
|
private UnitSystem unitSystem;
|
||||||
|
|
||||||
|
private double threshold;
|
||||||
|
|
||||||
public Builder() {
|
public Builder() {
|
||||||
decimalCount = 2;
|
decimalCount = 2;
|
||||||
|
threshold = 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setDecimalCount(int decimalCount) {
|
public Builder setDecimalCount(int decimalCount) {
|
||||||
@@ -102,8 +108,13 @@ public class DistanceFormatter {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setThreshold(double threshold) {
|
||||||
|
this.threshold = threshold;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public DistanceFormatter build(Resources resource) {
|
public DistanceFormatter build(Resources resource) {
|
||||||
return new DistanceFormatter(resource, decimalCount, unitSystem);
|
return new DistanceFormatter(resource, decimalCount, threshold, unitSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DistanceFormatter build(Context context) {
|
public DistanceFormatter build(Context context) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class Speed {
|
|||||||
return zero();
|
return zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Speed(distance.toM() / (duration.toMillis() * UnitConversions.MS_TO_S));
|
return new Speed(distance.toM() / (duration.toMillis() / (double) Duration.ofSeconds(1).toMillis()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Speed of(double speed_mps) {
|
public static Speed of(double speed_mps) {
|
||||||
@@ -85,16 +85,23 @@ public class Speed {
|
|||||||
return speed_mps;
|
return speed_mps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We interpret {@link Speed} here as a {@link Distance} over 1h.
|
||||||
|
*/
|
||||||
|
private Distance toH() {
|
||||||
|
return Distance.of(speed_mps * Duration.ofHours(1).toSeconds());
|
||||||
|
}
|
||||||
|
|
||||||
public double toKMH() {
|
public double toKMH() {
|
||||||
return speed_mps * UnitConversions.MPS_TO_KMH;
|
return toH().toKM();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double toMPH() {
|
public double toMPH() {
|
||||||
return toKMH() * UnitConversions.KM_TO_MI;
|
return toH().toMI();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double toKnots() {
|
public double toKnots() {
|
||||||
return toKMH() * UnitConversions.KM_TO_NAUTICAL_MILE;
|
return toH().toNauticalMiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Duration toPace(UnitSystem unitSystem) {
|
public Duration toPace(UnitSystem unitSystem) {
|
||||||
@@ -102,20 +109,7 @@ public class Speed {
|
|||||||
return Duration.ofSeconds(0);
|
return Duration.ofSeconds(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
double distance = speed_mps;
|
double distance = Distance.of(speed_mps).toKM_Miles(unitSystem);
|
||||||
switch (unitSystem) { //TODO Can we use to(UnitSystem)?
|
|
||||||
case METRIC:
|
|
||||||
distance *= UnitConversions.M_TO_KM;
|
|
||||||
break;
|
|
||||||
case IMPERIAL:
|
|
||||||
distance *= UnitConversions.M_TO_MI;
|
|
||||||
break;
|
|
||||||
case NAUTICAL_IMPERIAL:
|
|
||||||
distance *= UnitConversions.M_TO_NAUTICAL_MILE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new RuntimeException("Not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Duration.ofSeconds(Math.round(1 / distance));
|
return Duration.ofSeconds(Math.round(1 / distance));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2008 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
package de.dennisguse.opentracks.data.models;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit conversion constants.
|
|
||||||
*
|
|
||||||
* @author Sandor Dornbush
|
|
||||||
*/
|
|
||||||
public class UnitConversions {
|
|
||||||
|
|
||||||
// Time //TODO Use Duration
|
|
||||||
// multiplication factor to convert seconds to milliseconds
|
|
||||||
@Deprecated
|
|
||||||
public static final long S_TO_MS = 1000;
|
|
||||||
|
|
||||||
// multiplication factor to convert milliseconds to seconds
|
|
||||||
@Deprecated
|
|
||||||
public static final double MS_TO_S = 1d / S_TO_MS;
|
|
||||||
// multiplication factor to convert minutes to seconds
|
|
||||||
@Deprecated
|
|
||||||
public static final double MIN_TO_S = 60.0;
|
|
||||||
// multiplication factor to convert seconds to minutes
|
|
||||||
@Deprecated
|
|
||||||
public static final double S_TO_MIN = 1 / MIN_TO_S;
|
|
||||||
// multiplication factor to convert minutes to hours
|
|
||||||
@Deprecated
|
|
||||||
public static final double MIN_TO_HR = 1 / 60.0;
|
|
||||||
|
|
||||||
// multiplication factor to convert kilometers to miles
|
|
||||||
public static final double KM_TO_MI = 0.621371192;
|
|
||||||
|
|
||||||
// Distance //TODO Make private to Distance class!
|
|
||||||
// multiplication factor to convert miles to feet
|
|
||||||
private static final double MI_TO_FT = 5280.0;
|
|
||||||
// multiplication factor to covert kilometers to meters
|
|
||||||
public static final double KM_TO_M = 1000.0;
|
|
||||||
// multiplication factor to convert meters to kilometers
|
|
||||||
public static final double M_TO_KM = 1 / KM_TO_M;
|
|
||||||
// multiplication factor to convert meters to miles
|
|
||||||
public static final double M_TO_MI = M_TO_KM * KM_TO_MI;
|
|
||||||
// multiplication factor to convert meters to feet
|
|
||||||
public static final double M_TO_FT = M_TO_MI * MI_TO_FT;
|
|
||||||
public static final double NAUTICAL_MILE_TO_M = 1852.0;
|
|
||||||
public static final double M_TO_NAUTICAL_MILE = 1 / NAUTICAL_MILE_TO_M;
|
|
||||||
public static final double KM_TO_NAUTICAL_MILE = 1000 * M_TO_NAUTICAL_MILE;
|
|
||||||
// multiplication factor to convert meters per second to kilometers per hour
|
|
||||||
public static final double MPS_TO_KMH = M_TO_KM / (S_TO_MIN * MIN_TO_HR);
|
|
||||||
// multiplication factor to convert miles to km
|
|
||||||
public static final double MI_TO_KM = 1 / KM_TO_MI;
|
|
||||||
// multiplication factor to convert miles to m
|
|
||||||
public static final double MI_TO_M = MI_TO_KM * KM_TO_M;
|
|
||||||
|
|
||||||
private UnitConversions() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,7 +11,6 @@ import java.time.Duration;
|
|||||||
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.Speed;
|
import de.dennisguse.opentracks.data.models.Speed;
|
||||||
import de.dennisguse.opentracks.data.models.UnitConversions;
|
|
||||||
import de.dennisguse.opentracks.sensors.UintUtils;
|
import de.dennisguse.opentracks.sensors.UintUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,8 +67,9 @@ public final class SensorDataCycling {
|
|||||||
|
|
||||||
public void compute(CyclingCadence previous) {
|
public void compute(CyclingCadence previous) {
|
||||||
if (hasData() && previous != null && previous.hasData()) {
|
if (hasData() && previous != null && previous.hasData()) {
|
||||||
float timeDiff_ms = UintUtils.diff(crankRevolutionsTime, previous.crankRevolutionsTime, UintUtils.UINT16_MAX) / 1024f * UnitConversions.S_TO_MS;
|
float timeDiff_ms = UintUtils.diff(crankRevolutionsTime, previous.crankRevolutionsTime, UintUtils.UINT16_MAX) / 1024f * 1000;
|
||||||
if (timeDiff_ms <= 0) {
|
Duration timeDiff = Duration.ofMillis((long) timeDiff_ms);
|
||||||
|
if (timeDiff.isZero() || timeDiff.isNegative()) {
|
||||||
Log.e(TAG, "Timestamps difference is invalid: cannot compute cadence.");
|
Log.e(TAG, "Timestamps difference is invalid: cannot compute cadence.");
|
||||||
value = null;
|
value = null;
|
||||||
return;
|
return;
|
||||||
@@ -82,8 +82,7 @@ public final class SensorDataCycling {
|
|||||||
}
|
}
|
||||||
|
|
||||||
long crankDiff = UintUtils.diff(crankRevolutionsCount, previous.crankRevolutionsCount, UintUtils.UINT32_MAX);
|
long crankDiff = UintUtils.diff(crankRevolutionsCount, previous.crankRevolutionsCount, UintUtils.UINT32_MAX);
|
||||||
float cadence_ms = crankDiff / timeDiff_ms;
|
value = Cadence.of(crankDiff, timeDiff);
|
||||||
value = Cadence.of((float) (cadence_ms / UnitConversions.MS_TO_S / UnitConversions.S_TO_MIN));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +146,7 @@ public final class SensorDataCycling {
|
|||||||
|
|
||||||
public void compute(DistanceSpeed previous, Distance wheelCircumference) {
|
public void compute(DistanceSpeed previous, Distance wheelCircumference) {
|
||||||
if (hasData() && previous != null && previous.hasData()) {
|
if (hasData() && previous != null && previous.hasData()) {
|
||||||
float timeDiff_ms = UintUtils.diff(wheelRevolutionsTime, previous.wheelRevolutionsTime, UintUtils.UINT16_MAX) / 1024f * UnitConversions.S_TO_MS;
|
float timeDiff_ms = UintUtils.diff(wheelRevolutionsTime, previous.wheelRevolutionsTime, UintUtils.UINT16_MAX) / 1024f * 1000;
|
||||||
Duration timeDiff = Duration.ofMillis((long) timeDiff_ms);
|
Duration timeDiff = Duration.ofMillis((long) timeDiff_ms);
|
||||||
if (timeDiff.isZero() || timeDiff.isNegative()) {
|
if (timeDiff.isZero() || timeDiff.isNegative()) {
|
||||||
Log.e(TAG, "Timestamps difference is invalid: cannot compute speed.");
|
Log.e(TAG, "Timestamps difference is invalid: cannot compute speed.");
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ public class PreferencesUtils {
|
|||||||
UnitSystem unitSystem = getUnitSystem();
|
UnitSystem unitSystem = getUnitSystem();
|
||||||
|
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setDecimalCount(1)
|
.setDecimalCount(0)
|
||||||
.setUnit(unitSystem)
|
.setUnit(unitSystem)
|
||||||
.build(resources);
|
.build(resources);
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < values.length; i++) {
|
||||||
@@ -417,7 +417,8 @@ public class PreferencesUtils {
|
|||||||
|
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setUnit(unitSystem)
|
.setUnit(unitSystem)
|
||||||
.setDecimalCount(1)
|
.setDecimalCount(0)
|
||||||
|
.setThreshold(Double.MAX_VALUE)
|
||||||
.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]);
|
||||||
@@ -461,7 +462,8 @@ public class PreferencesUtils {
|
|||||||
UnitSystem unitSystem = getUnitSystem();
|
UnitSystem unitSystem = getUnitSystem();
|
||||||
|
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setDecimalCount(1)
|
.setDecimalCount(0)
|
||||||
|
.setThreshold(Double.MAX_VALUE)
|
||||||
.setUnit(unitSystem)
|
.setUnit(unitSystem)
|
||||||
.build(resources);
|
.build(resources);
|
||||||
for (int i = 0; i < entryValues.length; i++) {
|
for (int i = 0; i < entryValues.length; i++) {
|
||||||
@@ -534,7 +536,8 @@ public class PreferencesUtils {
|
|||||||
UnitSystem unitSystem = getUnitSystem();
|
UnitSystem unitSystem = getUnitSystem();
|
||||||
|
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setDecimalCount(1)
|
.setDecimalCount(0)
|
||||||
|
.setThreshold(Double.MAX_VALUE)
|
||||||
.setUnit(unitSystem)
|
.setUnit(unitSystem)
|
||||||
.build(resources);
|
.build(resources);
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ 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.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.settings.UnitSystem;
|
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;
|
||||||
@@ -230,7 +229,7 @@ public class DescriptionGenerator {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void writeAltitude(double altitude_m, StringBuilder builder, int resId, String lineBreak) {
|
void writeAltitude(double altitude_m, StringBuilder builder, int resId, String lineBreak) {
|
||||||
long altitudeInM = Math.round(altitude_m);
|
long altitudeInM = Math.round(altitude_m);
|
||||||
long altitudeInFt = Math.round(altitude_m * UnitConversions.M_TO_FT);
|
long altitudeInFt = Math.round(Distance.of(altitude_m).toFT());
|
||||||
builder.append(context.getString(resId, altitudeInM, altitudeInFt));
|
builder.append(context.getString(resId, altitudeInM, altitudeInFt));
|
||||||
builder.append(lineBreak);
|
builder.append(lineBreak);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import de.dennisguse.opentracks.data.models.Distance;
|
|||||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
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.TrackPoint;
|
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||||
import de.dennisguse.opentracks.data.models.UnitConversions;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updater for {@link TrackStatistics}.
|
* Updater for {@link TrackStatistics}.
|
||||||
@@ -196,7 +195,7 @@ public class TrackStatisticsUpdater {
|
|||||||
// See if the speed seems physically likely. Ignore any speeds that imply acceleration greater than 2g.
|
// See if the speed seems physically likely. Ignore any speeds that imply acceleration greater than 2g.
|
||||||
Duration timeDifference = Duration.between(lastTrackPoint.getTime(), trackPoint.getTime());
|
Duration timeDifference = Duration.between(lastTrackPoint.getTime(), trackPoint.getTime());
|
||||||
Speed maxSpeedDifference = Speed.of(Distance.of(SPEED_MAX_ACCELERATION), Duration.ofMillis(1000))
|
Speed maxSpeedDifference = Speed.of(Distance.of(SPEED_MAX_ACCELERATION), Duration.ofMillis(1000))
|
||||||
.mul(timeDifference.toMillis() / UnitConversions.S_TO_MS);
|
.mul(timeDifference.toSeconds());
|
||||||
|
|
||||||
Speed speedDifference = Speed.absDiff(lastTrackPoint.getSpeed(), trackPoint.getSpeed());
|
Speed speedDifference = Speed.absDiff(lastTrackPoint.getSpeed(), trackPoint.getSpeed());
|
||||||
return speedDifference.lessThan(maxSpeedDifference);
|
return speedDifference.lessThan(maxSpeedDifference);
|
||||||
|
|||||||
@@ -257,7 +257,8 @@ public class StringUtils {
|
|||||||
//TODO altitude_m should be double or a value object
|
//TODO altitude_m should be double or a value object
|
||||||
public static Pair<String, String> getAltitudeParts(Context context, Float altitude_m, UnitSystem unitSystem) {
|
public static Pair<String, String> getAltitudeParts(Context context, Float altitude_m, UnitSystem unitSystem) {
|
||||||
DistanceFormatter formatter = DistanceFormatter.Builder()
|
DistanceFormatter formatter = DistanceFormatter.Builder()
|
||||||
.setDecimalCount(1)
|
.setDecimalCount(0)
|
||||||
|
.setThreshold(Double.MAX_VALUE)
|
||||||
.setUnit(unitSystem)
|
.setUnit(unitSystem)
|
||||||
.build(context);
|
.build(context);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user