trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(track.getId(), null)) {
while (trackPointIterator.hasNext()) {
if (Thread.interrupted()) throw new InterruptedException();
@@ -384,9 +384,13 @@ public class KMLTrackExporter implements TrackExporter {
heartRateList.add(trackPoint.hasHeartRate() ? trackPoint.getHeartRate().getBPM() : null);
cadenceList.add(trackPoint.hasCadence() ? trackPoint.getCadence().getRPM() : null);
powerList.add(trackPoint.hasPower() ? trackPoint.getPower().getW() : null);
-
- altitudeGainList.add(trackPoint.hasAltitudeGain() ? trackPoint.getAltitudeGain() : null);
- altitudeLossList.add(trackPoint.hasAltitudeLoss() ? trackPoint.getAltitudeLoss() : null);
+ if (trackPoint.hasAltitudeGainLoss()) {
+ altitudeGainList.add(trackPoint.getAltitudeGainLoss().loss_m());
+ altitudeLossList.add(trackPoint.getAltitudeGainLoss().loss_m());
+ } else {
+ altitudeGainList.add(null);
+ altitudeLossList.add(null);
+ }
accuracyHorizontal.add(trackPoint.hasHorizontalAccuracy() ? (float) trackPoint.getHorizontalAccuracy().toM() : null);
accuracyVertical.add(trackPoint.hasVerticalAccuracy() ? (float) trackPoint.getVerticalAccuracy().toM() : null);
}
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/GPXTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/GPXTrackImporter.java
index 452231dfe..9abac901d 100644
--- a/src/main/java/de/dennisguse/opentracks/io/file/importer/GPXTrackImporter.java
+++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/GPXTrackImporter.java
@@ -38,6 +38,7 @@ import de.dennisguse.opentracks.data.models.Position;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
+import de.dennisguse.opentracks.stats.SegmentStatisticUpdater;
import de.dennisguse.opentracks.util.StringUtils;
/**
@@ -48,7 +49,7 @@ import de.dennisguse.opentracks.util.StringUtils;
*
* {@link de.dennisguse.opentracks.io.file.exporter.GPXTrackExporter} does not export information if a segment was started automatic or manually.
* Therefore, all segments starts are marked as SEGMENT_START_AUTOMATIC.
- * Thus, the {@link de.dennisguse.opentracks.stats.TrackStatistics} cannot be restored correctly.
+ * Thus, the {@link SegmentStatisticUpdater} cannot be restored correctly.
*
* @author Jimmy Shih
*/
@@ -368,18 +369,11 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
}
}
- if (gain != null) {
+ if (gain != null && loss != null) {
try {
- trackPoint.setAltitudeGain(Float.parseFloat(gain));
+ trackPoint.setAltitudeGainLoss(Float.parseFloat(gain), Float.parseFloat(loss));
} catch (NumberFormatException e) {
- throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse altitude gain: %s", gain)), e);
- }
- }
- if (loss != null) {
- try {
- trackPoint.setAltitudeLoss(Float.parseFloat(loss));
- } catch (NumberFormatException e) {
- throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse altitude loss: %s", loss)), e);
+ throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse altitude gain: %s or los: %s", gain, loss)), e);
}
}
if (sensorDistance != null) {
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/KMLTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/KMLTrackImporter.java
index 370f9ea50..3e77dac96 100644
--- a/src/main/java/de/dennisguse/opentracks/io/file/importer/KMLTrackImporter.java
+++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/KMLTrackImporter.java
@@ -342,11 +342,10 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
if (i < sensorPowerList.size() && sensorPowerList.get(i) != null) {
trackPoint.setPower(sensorPowerList.get(i));
}
- if (i < altitudeGainList.size()) {
- trackPoint.setAltitudeGain(altitudeGainList.get(i));
- }
- if (i < altitudeLossList.size()) {
- trackPoint.setAltitudeLoss(altitudeLossList.get(i));
+ if (i < altitudeGainList.size() && i < altitudeLossList.size()) {
+ if (altitudeGainList.get(i) != null && altitudeLossList.get(i) != null) {
+ trackPoint.setAltitudeGainLoss(altitudeGainList.get(i), altitudeLossList.get(i));
+ }
}
if (i < accuracyHorizontal.size() && accuracyHorizontal.get(i) != null) {
trackPoint.setHorizontalAccuracy(Distance.of(accuracyHorizontal.get(i)));
diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java
index fc9ee0616..433aafa1f 100644
--- a/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java
+++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/TrackImporter.java
@@ -147,7 +147,7 @@ public class TrackImporter {
TrackStatisticsUpdater updater = new TrackStatisticsUpdater();
updater.addTrackPoints(trackPoints);
- track.setTrackStatistics(updater.getTrackStatistics());
+ track.setStatistics(updater.getTrackStatistics());
Track.Id trackId = contentProviderUtils.insertTrack(track);
diff --git a/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java b/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java
index cc0c9b29a..b28bedfdd 100644
--- a/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java
+++ b/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java
@@ -3,6 +3,7 @@ package de.dennisguse.opentracks.sensors;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
+import android.os.PowerManager;
import android.util.Log;
import androidx.annotation.Nullable;
@@ -15,6 +16,7 @@ import de.dennisguse.opentracks.sensors.sensorData.Aggregator;
import de.dennisguse.opentracks.sensors.sensorData.Raw;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
+import de.dennisguse.opentracks.util.SystemUtils;
public class SensorManager implements SharedPreferences.OnSharedPreferenceChangeListener {
@@ -24,6 +26,8 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
@VisibleForTesting
public SensorDataSet sensorDataSet;
+ private PowerManager.WakeLock wakeLock;
+
private final TrackPointCreator observer;
private final SensorDataChangedObserver listener = new SensorDataChangedObserver() {
@@ -71,6 +75,8 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
throw new RuntimeException("SensorManager cannot be started twice; stop first.");
}
+ wakeLock = SystemUtils.acquireWakeLock(context, wakeLock);
+
gpsManager = new GpsManager(observer, listener);
altitudeSumManager = new GainManager(listener);
bluetoothSensorManager = new BluetoothRemoteSensorManager(context, handler, listener);
@@ -83,6 +89,8 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
}
public void stop(Context context) {
+ wakeLock = SystemUtils.releaseWakeLock(wakeLock);
+
bluetoothSensorManager.stop(context);
bluetoothSensorManager = null;
diff --git a/src/main/java/de/dennisguse/opentracks/sensors/sensorData/SensorDataSet.java b/src/main/java/de/dennisguse/opentracks/sensors/sensorData/SensorDataSet.java
index 2d1e6aeb5..eacfc9e49 100644
--- a/src/main/java/de/dennisguse/opentracks/sensors/sensorData/SensorDataSet.java
+++ b/src/main/java/de/dennisguse/opentracks/sensors/sensorData/SensorDataSet.java
@@ -185,8 +185,7 @@ public class SensorDataSet {
}
if (barometer != null && barometer.hasReceivedData()) {
- trackPoint.setAltitudeGain(barometer.getAggregatedValue(trackPointCreator.createNow()).gain_m());
- trackPoint.setAltitudeLoss(barometer.getAggregatedValue(trackPointCreator.createNow()).loss_m());
+ trackPoint.setAltitudeGainLoss(barometer.getAggregatedValue(trackPointCreator.createNow()).gain_m(), barometer.getAggregatedValue(trackPointCreator.createNow()).loss_m());
}
}
diff --git a/src/main/java/de/dennisguse/opentracks/services/RecordingData.java b/src/main/java/de/dennisguse/opentracks/services/RecordingData.java
index 92d9734a3..2d4a57512 100644
--- a/src/main/java/de/dennisguse/opentracks/services/RecordingData.java
+++ b/src/main/java/de/dennisguse/opentracks/services/RecordingData.java
@@ -2,15 +2,16 @@ package de.dennisguse.opentracks.services;
import androidx.annotation.NonNull;
+import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
-import de.dennisguse.opentracks.stats.TrackStatistics;
+import de.dennisguse.opentracks.stats.SegmentStatisticUpdater;
/**
* {@link Track} and {@link TrackPoint} must be immutable (i.e., their content does not change).
*/
-public record RecordingData(Track track, TrackPoint latestTrackPoint, SensorDataSet sensorDataSet, TrackStatistics currentSegment) {
+public record RecordingData(Track track, TrackPoint latestTrackPoint, SensorDataSet sensorDataSet, Statistics currentSegment) {
public String getTrackCategory() {
if (track == null) {
return "";
@@ -18,22 +19,13 @@ public record RecordingData(Track track, TrackPoint latestTrackPoint, SensorData
return track.getActivityTypeLocalized();
}
+ @Deprecated
@NonNull
- public TrackStatistics getStatisticsTrack() {
+ public Statistics getStatisticsTrack() {
if (track == null) {
- return new TrackStatistics();
+ return new SegmentStatisticUpdater().getStatistics();
}
- return track.getTrackStatistics();
+ return track.getStatistics();
}
-
- @NonNull
- public TrackStatistics getStatisticsCurrentSegment() {
- if (currentSegment == null) {
- return new TrackStatistics();
- }
-
- return currentSegment;
- }
-
}
diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingManager.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingManager.java
index a30bb330a..e674c610d 100644
--- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingManager.java
+++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingManager.java
@@ -17,13 +17,13 @@ import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.ActivityType;
import de.dennisguse.opentracks.data.models.Distance;
+import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.services.handlers.AltitudeCorrectionManager;
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
import de.dennisguse.opentracks.settings.PreferencesUtils;
-import de.dennisguse.opentracks.stats.TrackStatistics;
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
import de.dennisguse.opentracks.util.TrackNameUtils;
@@ -80,7 +80,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
String activityTypeLocalized = PreferencesUtils.getDefaultActivityTypeLocalized();
track.setActivityTypeLocalized(activityTypeLocalized);
track.setActivityType(ActivityType.findByLocalizedString(context, activityTypeLocalized));
- track.setTrackStatistics(trackStatisticsUpdater.getTrackStatistics());
+ track.setStatistics(trackStatisticsUpdater.getTrackStatistics());
track.setName(TrackNameUtils.getTrackName(context, trackId, track.getStartTime()));
contentProviderUtils.updateTrack(track);
@@ -98,7 +98,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
return false;
}
- trackStatisticsUpdater = new TrackStatisticsUpdater(track.getTrackStatistics());
+ trackStatisticsUpdater = new TrackStatisticsUpdater(track.getStatistics());
onNewTrackPoint(trackPointCreator.createSegmentStartManual());
reset();
@@ -124,16 +124,15 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
ALTITUDE_CORRECTION_MANAGER.correctAltitude(context, current.first);
- Track track = contentProviderUtils.getTrack(trackId); //Get copy
+ Track track = contentProviderUtils.getTrack(trackId); //Get copy TODO: Avoid re-loading data from DB
if (track == null) {
Log.w(TAG, "Requesting data if not recording is taking place, should not be done.");
return null;
}
- track.setTrackStatistics(tmpTrackStatisticsUpdater.getTrackStatistics());
- TrackStatistics currentSegment = tmpTrackStatisticsUpdater.getCurrentSegment();
+ track.setStatistics(tmpTrackStatisticsUpdater.getTrackStatistics());
- return new RecordingData(track, current.first, current.second, currentSegment);
+ return new RecordingData(track, current.first, current.second, tmpTrackStatisticsUpdater.getCurrentSegment());
}
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
@@ -225,7 +224,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
handler.postDelayed(ON_IDLE, idleDuration.toMillis());
}
- TrackStatistics getTrackStatistics() {
+ Statistics getTrackStatistics() {
return trackStatisticsUpdater == null ? null : trackStatisticsUpdater.getTrackStatistics();
}
diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java
index 3a04ae1aa..e16668b4c 100644
--- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java
+++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingService.java
@@ -22,7 +22,6 @@ import android.content.SharedPreferences;
import android.content.pm.ServiceInfo;
import android.os.Handler;
import android.os.Looper;
-import android.os.PowerManager.WakeLock;
import android.util.Log;
import androidx.annotation.Nullable;
@@ -44,7 +43,6 @@ import de.dennisguse.opentracks.sensors.GpsStatusValue;
import de.dennisguse.opentracks.services.announcement.VoiceAnnouncementManager;
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
import de.dennisguse.opentracks.settings.PreferencesUtils;
-import de.dennisguse.opentracks.util.SystemUtils;
public class TrackRecordingService extends Service implements TrackPointCreator.Callback, SharedPreferences.OnSharedPreferenceChangeListener, TrackRecordingManager.IdleObserver {
@@ -89,7 +87,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
private MutableLiveData recordingDataObservable;
// The following variables are set when recording:
- private WakeLock wakeLock; //TODO Move to SensorManager
private Handler handler;
private TrackPointCreator trackPointCreator;
@@ -125,7 +122,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
if (isRecording()) {
endCurrentTrack();
}
- if (isSensorStarted()) {
+ if (trackPointCreator != null && trackPointCreator.isStarted()) {
stopSensors();
}
@@ -200,7 +197,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
}
public void tryStartSensors() {
- if (isSensorStarted()) return;
+ if (trackPointCreator.isStarted()) return;
Log.i(TAG, "tryStartSensors");
@@ -208,12 +205,11 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
}
private synchronized void startSensors() {
- if (isSensorStarted()) {
+ if (trackPointCreator.isStarted()) {
Log.i(TAG, "sensors already started; skipping");
return;
}
Log.i(TAG, "startSensors");
- wakeLock = SystemUtils.acquireWakeLock(this, wakeLock);
trackPointCreator.start(this, handler);
ServiceCompat.startForeground(this, TrackRecordingServiceNotificationManager.NOTIFICATION_ID, notificationManager.onSensorsStarted(this), ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION + ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE);
@@ -241,7 +237,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
trackPointCreator.stop();
stopForeground(true);
notificationManager.stop();
- wakeLock = SystemUtils.releaseWakeLock(wakeLock);
gpsStatusObservable.postValue(STATUS_GPS_DEFAULT);
}
@@ -318,7 +313,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
// Compute temporary track statistics using sensorData and update time.
RecordingData data = trackRecordingManager.getDataForUI();
- voiceAnnouncementManager.announceStatisticsIfNeeded(data.track(), data.sensorDataSet());
+ voiceAnnouncementManager.announceStatisticsIfNeeded(data);
recordingDataObservable.postValue(data);
}
@@ -347,9 +342,6 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
return recordingStatus.isRecording();
}
- private boolean isSensorStarted() {
- return wakeLock != null;
- }
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, @Nullable String key) {
diff --git a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceNotificationManager.java b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceNotificationManager.java
index 37bc03217..7e085a70a 100644
--- a/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceNotificationManager.java
+++ b/src/main/java/de/dennisguse/opentracks/services/TrackRecordingServiceNotificationManager.java
@@ -118,7 +118,7 @@ class TrackRecordingServiceNotificationManager implements SharedPreferences.OnSh
previousLocationWasAccurate = currentLocationWasAccurate;
}
- notificationBuilder.setContentTitle(context.getString(R.string.track_distance_notification, formatter.formatDistance(recordingData.getStatisticsTrack().getTotalDistance())));
+ notificationBuilder.setContentTitle(context.getString(R.string.track_distance_notification, formatter.formatDistance(recordingData.getStatisticsTrack().totalDistance())));
String formattedSpeed = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(true).build(context).formatSpeed(recordingData.latestTrackPoint().getSpeed());
notificationBuilder.setContentText(context.getString(R.string.track_speed_notification, formattedSpeed));
notificationBuilder.setSubText(context.getString(R.string.track_recording_notification_accuracy, formattedAccuracy));
diff --git a/src/main/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementManager.java b/src/main/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementManager.java
index 322a1c611..917339e90 100644
--- a/src/main/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementManager.java
+++ b/src/main/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementManager.java
@@ -30,15 +30,14 @@ import java.util.List;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.ContentProviderUtils;
-import de.dennisguse.opentracks.data.TrackPointIterator;
import de.dennisguse.opentracks.data.models.Distance;
-import de.dennisguse.opentracks.data.models.Track;
+import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.TrackPoint;
-import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
+import de.dennisguse.opentracks.services.RecordingData;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.stats.SensorStatistics;
-import de.dennisguse.opentracks.stats.TrackStatistics;
-import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
+import de.dennisguse.opentracks.ui.intervals.IntervalStatisticsUpdater;
+import de.dennisguse.opentracks.util.AutoCloseableIterator;
/**
* Execute a periodic task on a time or distance schedule.
@@ -53,7 +52,7 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
private TTSManager voiceAnnouncement;
- private TrackStatistics trackStatistics;
+ private Statistics trackStatistics;
private static final Distance DISTANCE_OFF = Distance.of(Double.MAX_VALUE);
private Distance distanceFrequency = DISTANCE_OFF;
@@ -69,23 +68,23 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
private final ContentProviderUtils contentProviderUtils;
private TrackPoint.Id startTrackPointId = null;
- private IntervalStatistics intervalStatistics;
+ private IntervalStatisticsUpdater intervalStatistics;
private Distance intervalDistance;
public VoiceAnnouncementManager(@NonNull Context context) {
this.context = context;
contentProviderUtils = new ContentProviderUtils(context);
intervalDistance = PreferencesUtils.getVoiceAnnouncementDistance();
- intervalStatistics = new IntervalStatistics(intervalDistance);
+ intervalStatistics = new IntervalStatisticsUpdater(intervalDistance);
}
- public void start(@Nullable TrackStatistics trackStatistics) {
+ public void start(@Nullable Statistics trackStatistics) {
voiceAnnouncement = new TTSManager(context);
voiceAnnouncement.start();
update(trackStatistics);
}
- void update(@Nullable TrackStatistics trackStatistics) {
+ void update(@Nullable Statistics trackStatistics) {
this.trackStatistics = trackStatistics;
updateNextDuration();
updateNextTaskDistance();
@@ -120,44 +119,46 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
voiceAnnouncement.speak(VoiceAnnouncementUtils.createIdle(context));
}
- public void announceStatisticsIfNeeded(@NonNull Track track, @NonNull SensorDataSet sensorDataSet) {
+ public void announceStatisticsIfNeeded(@NonNull RecordingData data) {
if (shouldNotAnnounce()) {
return;
}
boolean announce = false;
- this.trackStatistics = track.getTrackStatistics();
- if (trackStatistics.getTotalDistance().greaterThan(nextTotalDistance)) {
+ this.trackStatistics = data.track().getStatistics();
+ if (trackStatistics.totalDistance().greaterThan(nextTotalDistance)) {
updateNextTaskDistance();
announce = true;
}
- if (!trackStatistics.getTotalTime().minus(nextTotalTime).isNegative()) {
+ if (!trackStatistics.totalTime().minus(nextTotalTime).isNegative()) {
updateNextDuration();
announce = true;
}
if (announce) {
- voiceAnnouncement.speak(createAnnouncement(track, sensorDataSet));
+ voiceAnnouncement.speak(createAnnouncement(data));
}
}
- private Spannable createAnnouncement(Track track, SensorDataSet sensorDataSet) {
+ private Spannable createAnnouncement(RecordingData data) {
Distance currentIntervalDistance = PreferencesUtils.getVoiceAnnouncementDistance();
if (currentIntervalDistance != intervalDistance) {
- intervalStatistics = new IntervalStatistics(currentIntervalDistance);
+ intervalStatistics = new IntervalStatisticsUpdater(currentIntervalDistance);
intervalDistance = currentIntervalDistance;
startTrackPointId = null;
}
- TrackPointIterator trackPointIterator = new TrackPointIterator(contentProviderUtils, track.getId(), startTrackPointId);
- startTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator);
- IntervalStatistics.Interval lastInterval = intervalStatistics.getLastInterval();
- SensorStatistics sensorStatistics = null;
- if (track.getId() != null) {
- sensorStatistics = contentProviderUtils.getSensorStats(track.getId());
- }
+ //TODO Avoid reloading (some) TrackPoints just to announce the last interval.
+ try (AutoCloseableIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(data.track().getId(), startTrackPointId)) {
+ startTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator);
+ Statistics lastInterval = intervalStatistics.getLastInterval();
+ SensorStatistics sensorStatistics = null;
+ if (data.track().getId() != null) {
+ sensorStatistics = contentProviderUtils.getSensorStats(data.track().getId());
+ }
- return VoiceAnnouncementUtils.createStatistics(context, track, sensorDataSet, PreferencesUtils.getUnitSystem(), PreferencesUtils.isReportSpeed(track), lastInterval, sensorStatistics);
+ return VoiceAnnouncementUtils.createStatistics(context, data.track(), data.sensorDataSet(), PreferencesUtils.getUnitSystem(), PreferencesUtils.isReportSpeed(data.track()), lastInterval, sensorStatistics);
+ }
}
public void stop() {
@@ -182,7 +183,7 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
nextTotalDistance = DISTANCE_OFF;
} else {
- Distance distance = trackStatistics.getTotalDistance();
+ Distance distance = trackStatistics.totalDistance();
int index = (int) (distance.dividedBy(distanceFrequency));
nextTotalDistance = distanceFrequency.multipliedBy(index + 1);
@@ -195,10 +196,9 @@ public class VoiceAnnouncementManager implements SharedPreferences.OnSharedPrefe
nextTotalTime = TOTALTIME_OFF;
} else {
- Duration totalTime = trackStatistics.getTotalTime();
- Duration intervalMod = Duration.ofMillis(trackStatistics.getTotalTime().toMillis() % totalTimeFrequency.toMillis());
+ Duration intervalMod = Duration.ofMillis(trackStatistics.totalTime().toMillis() % totalTimeFrequency.toMillis());
- nextTotalTime = totalTime.plus(totalTimeFrequency.minus(intervalMod));
+ nextTotalTime = trackStatistics.totalTime().plus(totalTimeFrequency.minus(intervalMod));
}
}
diff --git a/src/main/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementUtils.java b/src/main/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementUtils.java
index ab3be8785..86a626ec2 100644
--- a/src/main/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementUtils.java
+++ b/src/main/java/de/dennisguse/opentracks/services/announcement/VoiceAnnouncementUtils.java
@@ -33,12 +33,11 @@ import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.Speed;
+import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
import de.dennisguse.opentracks.settings.UnitSystem;
import de.dennisguse.opentracks.stats.SensorStatistics;
-import de.dennisguse.opentracks.stats.TrackStatistics;
-import de.dennisguse.opentracks.ui.intervals.IntervalStatistics;
import de.dennisguse.opentracks.util.StringUtils;
class VoiceAnnouncementUtils {
@@ -51,8 +50,8 @@ class VoiceAnnouncementUtils {
.append(context.getString(R.string.voiceIdle));
}
- static Spannable createStatistics(Context context, Track track, SensorDataSet sensorDataSet, UnitSystem unitSystem, boolean isReportSpeed, @Nullable IntervalStatistics.Interval currentInterval, @Nullable SensorStatistics sensorStatistics) {
- TrackStatistics trackStatistics = track.getTrackStatistics();
+ static Spannable createStatistics(Context context, Track track, SensorDataSet sensorDataSet, UnitSystem unitSystem, boolean isReportSpeed, @Nullable Statistics currentInterval, @Nullable SensorStatistics sensorStatistics) {
+ Statistics trackStatistics = track.getStatistics();
SpannableStringBuilder builder = new SpannableStringBuilder();
@@ -60,9 +59,9 @@ class VoiceAnnouncementUtils {
appendTime(builder, track.getStopTime());
}
- Distance totalDistance = trackStatistics.getTotalDistance();
+ Distance totalDistance = trackStatistics.totalDistance();
Speed averageMovingSpeed = trackStatistics.getAverageMovingSpeed();
- Speed currentDistancePerTime = currentInterval != null ? currentInterval.getSpeed() : null;
+ Speed currentDistancePerTime = currentInterval != null ? currentInterval.getAverageSpeed() : null;
int perUnitStringId = R.string.empty;
int distanceId = R.string.voiceDistance;
@@ -112,7 +111,7 @@ class VoiceAnnouncementUtils {
boolean hasTravelledDistance = !totalDistance.isZero();
// Announce time
- Duration movingTime = trackStatistics.getMovingTime();
+ Duration movingTime = trackStatistics.movingTime();
if (shouldVoiceAnnounceMovingTime() && hasTravelledDistance && !movingTime.isZero()) {
appendDuration(context, builder, movingTime);
builder.append(".");
@@ -179,8 +178,8 @@ class VoiceAnnouncementUtils {
appendCardinal(builder, context.getString(R.string.sensor_state_heart_rate_value, averageHeartRate), averageHeartRate);
builder.append(".");
}
- if (shouldVoiceAnnounceLapHeartRate() && currentInterval != null && currentInterval.hasAverageHeartRate()) {
- int currentHeartRate = Math.round(currentInterval.getAverageHeartRate().getBPM());
+ if (shouldVoiceAnnounceLapHeartRate() && currentInterval != null && currentInterval.avgHeartRate() != null) {
+ int currentHeartRate = Math.round(currentInterval.avgHeartRate().getBPM());
builder.append(" ")
.append(context.getString(R.string.lap_heart_rate));
@@ -188,8 +187,8 @@ class VoiceAnnouncementUtils {
builder.append(".");
}
- if (shouldVoiceAnnounceLapPower() && currentInterval != null && currentInterval.hasAveragePower()) {
- int currentPower = Math.round(currentInterval.getAveragePower().getW());
+ if (shouldVoiceAnnounceLapPower() && currentInterval != null && currentInterval.avgPower() != null) {
+ int currentPower = Math.round(currentInterval.avgPower().getW());
if (shouldVoiceAnnounceUnit()) {
String template = context.getResources().getString(R.string.power_x_watt);
builder.append(" ")
diff --git a/src/main/java/de/dennisguse/opentracks/services/handlers/TrackPointCreator.java b/src/main/java/de/dennisguse/opentracks/services/handlers/TrackPointCreator.java
index 74b839a16..cce45bf80 100644
--- a/src/main/java/de/dennisguse/opentracks/services/handlers/TrackPointCreator.java
+++ b/src/main/java/de/dennisguse/opentracks/services/handlers/TrackPointCreator.java
@@ -47,7 +47,7 @@ public class TrackPointCreator implements SharedPreferences.OnSharedPreferenceCh
sensorManager.start(context, handler);
}
- private boolean isStarted() {
+ public boolean isStarted() {
return context != null;
}
diff --git a/src/main/java/de/dennisguse/opentracks/share/TrackShareSummaryGenerator.java b/src/main/java/de/dennisguse/opentracks/share/TrackShareSummaryGenerator.java
index 1a1039162..355d28956 100644
--- a/src/main/java/de/dennisguse/opentracks/share/TrackShareSummaryGenerator.java
+++ b/src/main/java/de/dennisguse/opentracks/share/TrackShareSummaryGenerator.java
@@ -29,9 +29,9 @@ import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Speed;
import de.dennisguse.opentracks.data.models.SpeedFormatter;
+import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.settings.UnitSystem;
-import de.dennisguse.opentracks.stats.TrackStatistics;
import de.dennisguse.opentracks.util.StringUtils;
/**
@@ -65,7 +65,7 @@ public class TrackShareSummaryGenerator {
writeString(track.getName(), builder, R.string.generic_name_line);
writeString(track.getActivityTypeLocalized(), builder, R.string.description_activity_type);
writeString(track.getDescription(), builder, R.string.generic_description_line);
- builder.append(generateTrackStatisticsDescription(track.getTrackStatistics()));
+ builder.append(generateTrackStatisticsDescription(track.getStatistics()));
return builder.toString();
}
@@ -78,17 +78,17 @@ public class TrackShareSummaryGenerator {
builder.append(TrackShareSummaryGenerator.TEXT_LINE_BREAK);
}
- private String generateTrackStatisticsDescription(TrackStatistics stats) {
+ private String generateTrackStatisticsDescription(Statistics stats) {
StringBuilder builder = new StringBuilder();
// Total distance
- writeDistance(stats.getTotalDistance(), builder, R.string.description_total_distance);
+ writeDistance(stats.totalDistance(), builder, R.string.description_total_distance);
// Total time
- writeTime(stats.getTotalTime(), builder, R.string.description_total_time);
+ writeTime(stats.totalTime(), builder, R.string.description_total_time);
// Moving time
- writeTime(stats.getMovingTime(), builder, R.string.description_moving_time);
+ writeTime(stats.movingTime(), builder, R.string.description_moving_time);
// Average speed
writeSpeed(stats.getAverageSpeed(), builder, R.string.description_average_speed);
@@ -97,7 +97,7 @@ public class TrackShareSummaryGenerator {
writeSpeed(stats.getAverageMovingSpeed(), builder, R.string.description_average_moving_speed);
// Max speed
- writeSpeed(stats.getMaxSpeed(), builder, R.string.description_max_speed);
+ writeSpeed(stats.maxSpeed(), builder, R.string.description_max_speed);
// Average pace
writePace(stats.getAverageSpeed(), builder, R.string.description_average_pace_in_minute);
@@ -106,26 +106,22 @@ public class TrackShareSummaryGenerator {
writePace(stats.getAverageMovingSpeed(), builder, R.string.description_average_moving_pace_in_minute);
// Fastest pace
- writePace(stats.getMaxSpeed(), builder, R.string.description_fastest_pace_in_minute);
+ writePace(stats.maxSpeed(), builder, R.string.description_fastest_pace_in_minute);
// Min and Max altitude
- if (stats.hasAltitudeExtremities()) {
- writeAltitude(stats.getMaxAltitude(), builder, R.string.description_max_altitude);
- writeAltitude(stats.getMinAltitude(), builder, R.string.description_min_altitude);
+ if (stats.altitudeExtremities() != null) {
+ writeAltitude(stats.altitudeExtremities().max_m(), builder, R.string.description_max_altitude);
+ writeAltitude(stats.altitudeExtremities().min_m(), builder, R.string.description_min_altitude);
}
- // Altitude gain
- if (stats.hasTotalAltitudeGain()) {
- writeAltitude(stats.getTotalAltitudeGain(), builder, R.string.description_altitude_gain);
- }
-
- // Altitude loss
- if (stats.hasTotalAltitudeLoss()) {
- writeAltitude(stats.getTotalAltitudeLoss(), builder, R.string.description_altitude_loss);
+ // Altitude gain & loss
+ if (stats.altitudeGainLoss() != null) {
+ writeAltitude(stats.altitudeGainLoss().gain_m(), builder, R.string.description_altitude_gain);
+ writeAltitude(stats.altitudeGainLoss().loss_m(), builder, R.string.description_altitude_loss);
}
// Recorded time
- builder.append(context.getString(R.string.description_recorded_time, StringUtils.formatDateTimeWithOffset(OffsetDateTime.ofInstant(stats.getStartTime(), ZoneId.systemDefault()))));
+ builder.append(context.getString(R.string.description_recorded_time, StringUtils.formatDateTimeWithOffset(OffsetDateTime.ofInstant(stats.startTime(), ZoneId.systemDefault()))));
builder.append(TEXT_LINE_BREAK);
return builder.toString();
diff --git a/src/main/java/de/dennisguse/opentracks/stats/ExtremityMonitor.java b/src/main/java/de/dennisguse/opentracks/stats/ExtremityMonitor.java
index eda982ce9..e26c5fd37 100644
--- a/src/main/java/de/dennisguse/opentracks/stats/ExtremityMonitor.java
+++ b/src/main/java/de/dennisguse/opentracks/stats/ExtremityMonitor.java
@@ -100,14 +100,15 @@ public class ExtremityMonitor {
* @param min the minimum value
* @param max the maximum value
*/
- public void set(double min, double max) {
+ public void set(Double min, Double max) {
+ if (min == null || max == null) {
+ reset();
+ return;
+ }
this.min = min;
this.max = max;
}
- /**
- * Returns true if has data.
- */
public boolean hasData() {
return min != Double.POSITIVE_INFINITY && max != Double.NEGATIVE_INFINITY;
}
diff --git a/src/main/java/de/dennisguse/opentracks/stats/TrackStatistics.java b/src/main/java/de/dennisguse/opentracks/stats/SegmentStatisticUpdater.java
similarity index 74%
rename from src/main/java/de/dennisguse/opentracks/stats/TrackStatistics.java
rename to src/main/java/de/dennisguse/opentracks/stats/SegmentStatisticUpdater.java
index 203219d39..1044810b2 100644
--- a/src/main/java/de/dennisguse/opentracks/stats/TrackStatistics.java
+++ b/src/main/java/de/dennisguse/opentracks/stats/SegmentStatisticUpdater.java
@@ -24,10 +24,13 @@ import java.time.Duration;
import java.time.Instant;
import de.dennisguse.opentracks.data.models.Altitude;
+import de.dennisguse.opentracks.data.models.AltitudeExtremities;
+import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.Power;
import de.dennisguse.opentracks.data.models.Speed;
+import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
@@ -38,8 +41,7 @@ import de.dennisguse.opentracks.data.models.TrackPoint;
* @author Rodrigo Damazio
*/
//TODO Check that data ranges are valid (not less than zero etc.)
-//TODO Should be a Java record
-public class TrackStatistics {
+public class SegmentStatisticUpdater {
// The min and max altitude (meters) seen on this track.
private final ExtremityMonitor altitudeExtremities = new ExtremityMonitor();
@@ -50,7 +52,11 @@ public class TrackStatistics {
private Instant stopTime; //TODO Should never be null!
private Distance totalDistance;
- // Updated when new points are received, may be stale.
+ /**
+ * Updated when new points are received, may be stale.
+ * This statistic is only updated when a new point is added to the statistics, so it may be off.
+ * If you need to calculate the proper totalTime, use startTime with the current time.
+ */
private Duration totalTime;
// Based on when we believe the user is traveling.
private Duration movingTime;
@@ -64,7 +70,7 @@ public class TrackStatistics {
private boolean isIdle;
- public TrackStatistics() {
+ public SegmentStatisticUpdater() {
reset();
}
@@ -73,31 +79,27 @@ public class TrackStatistics {
*
* @param other another statistics data object to copy from
*/
- public TrackStatistics(TrackStatistics other) {
- startTime = other.startTime;
- stopTime = other.stopTime;
- totalDistance = other.totalDistance;
- totalTime = other.totalTime;
- movingTime = other.movingTime;
- maxSpeed = other.maxSpeed;
- altitudeExtremities.set(other.altitudeExtremities.getMin(), other.altitudeExtremities.getMax());
- totalAltitudeGain_m = other.totalAltitudeGain_m;
- totalAltitudeLoss_m = other.totalAltitudeLoss_m;
- avgHeartRate = other.avgHeartRate;
- avgPower = other.avgPower;
- isIdle = other.isIdle;
+ public SegmentStatisticUpdater(SegmentStatisticUpdater other) {
+ this(other.getStatistics());
+ this.isIdle = other.isIdle();
}
- @VisibleForTesting
- public TrackStatistics(String startTime, String stopTime, double totalDistance_m, int totalTime_s, int movingTime_s, float maxSpeed_mps, Float totalAltitudeGain_m, Float totalAltitudeLoss_m) {
- this.startTime = Instant.parse(startTime);
- this.stopTime = Instant.parse(stopTime);
- this.totalDistance = Distance.of(totalDistance_m);
- this.totalTime = Duration.ofSeconds(totalTime_s);
- this.movingTime = Duration.ofSeconds(movingTime_s);
- this.maxSpeed = Speed.of(maxSpeed_mps);
- this.totalAltitudeGain_m = totalAltitudeGain_m;
- this.totalAltitudeLoss_m = totalAltitudeLoss_m;
+ public SegmentStatisticUpdater(Statistics statistics) {
+ startTime = statistics.startTime();
+ stopTime = statistics.stopTime();
+ totalDistance = statistics.totalDistance();
+ totalTime = statistics.totalTime();
+ movingTime = statistics.movingTime();
+ maxSpeed = statistics.maxSpeed();
+ if (statistics.altitudeExtremities() != null) {
+ altitudeExtremities.set(statistics.altitudeExtremities().min_m(), statistics.altitudeExtremities().max_m());
+ }
+ if (statistics.altitudeGainLoss() != null) {
+ totalAltitudeGain_m = statistics.altitudeGainLoss().gain_m();
+ totalAltitudeLoss_m = statistics.altitudeGainLoss().loss_m();
+ }
+ avgHeartRate = statistics.avgHeartRate();
+ avgPower = statistics.avgPower();
}
/**
@@ -107,7 +109,7 @@ public class TrackStatistics {
* @param other another statistics data object
*/
//TODO Should be refactored to append only [mainly due to isIdle] (NOTE: This requires to use a custom value object for AggregatedStatistics; this is anyhow recommended).
- public void merge(TrackStatistics other) {
+ public void merge(SegmentStatisticUpdater other) {
if (startTime == null) {
startTime = other.startTime;
} else {
@@ -183,12 +185,12 @@ public class TrackStatistics {
startTime = null;
stopTime = null;
- setTotalDistance(Distance.of(0));
- setTotalTime(Duration.ofSeconds(0));
- setMovingTime(Duration.ofSeconds(0));
- setMaxSpeed(Speed.zero());
- setTotalAltitudeGain(null);
- setTotalAltitudeLoss(null);
+ totalTime = Duration.ofSeconds(0);
+ movingTime = Duration.ofSeconds(0);
+ totalDistance = Distance.of(0);
+ maxSpeed = Speed.zero();
+ totalAltitudeGain_m = null;
+ totalAltitudeLoss_m = null;
isIdle = false;
}
@@ -198,6 +200,22 @@ public class TrackStatistics {
setStartTime(startTime);
}
+ public Statistics getStatistics() {
+ return new Statistics(
+ startTime,
+ stopTime,
+ totalTime,
+ movingTime,
+
+ totalDistance,
+ getMaxSpeed(),
+ altitudeExtremities.hasData() ? new AltitudeExtremities(altitudeExtremities.getMin(), altitudeExtremities.getMax()) : null,
+ totalAltitudeGain_m != null && totalAltitudeLoss_m != null ? new AltitudeGainLoss(totalAltitudeGain_m, totalAltitudeLoss_m) : null,
+ avgHeartRate,
+ avgPower
+ );
+ }
+
public Instant getStartTime() {
return startTime;
}
@@ -226,6 +244,7 @@ public class TrackStatistics {
return totalDistance;
}
+ @VisibleForTesting
public void setTotalDistance(Distance totalDistance_m) {
this.totalDistance = totalDistance_m;
}
@@ -234,11 +253,6 @@ public class TrackStatistics {
totalDistance = totalDistance.plus(distance_m);
}
- /**
- * Gets the total time in milliseconds that this track has been active.
- * This statistic is only updated when a new point is added to the statistics, so it may be off.
- * If you need to calculate the proper total time, use {@link #getStartTime} with the current time.
- */
public Duration getTotalTime() {
return totalTime;
}
@@ -267,10 +281,6 @@ public class TrackStatistics {
movingTime = movingTime.plus(time);
}
- public Duration getStoppedTime() {
- return totalTime.minus(movingTime);
- }
-
public boolean isIdle() {
return isIdle;
}
@@ -279,19 +289,11 @@ public class TrackStatistics {
isIdle = idle;
}
- public boolean hasAverageHeartRate() {
- return avgHeartRate != null;
- }
-
@Nullable
public HeartRate getAverageHeartRate() {
return avgHeartRate;
}
- public boolean hasPower() {
- return avgPower != null;
- }
-
@Nullable
public Power getAveragePower() {
return avgPower;
@@ -320,10 +322,6 @@ public class TrackStatistics {
this.maxSpeed = maxSpeed;
}
- public boolean hasAltitudeExtremities() {
- return altitudeExtremities.hasData();
- }
-
public double getMinAltitude() {
return altitudeExtremities.getMin();
}
@@ -362,64 +360,42 @@ public class TrackStatistics {
}
}
- public boolean hasTotalAltitudeGain() {
- return totalAltitudeGain_m != null;
- }
-
+ @VisibleForTesting
+ @Deprecated
@Nullable
public Float getTotalAltitudeGain() {
return totalAltitudeGain_m;
}
+ @VisibleForTesting
+ @Deprecated
public void setTotalAltitudeGain(Float totalAltitudeGain_m) {
this.totalAltitudeGain_m = totalAltitudeGain_m;
}
- @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
- public void addTotalAltitudeGain(float gain_m) {
- if (totalAltitudeGain_m == null) {
- totalAltitudeGain_m = 0f;
- }
- totalAltitudeGain_m += gain_m;
- }
-
- public boolean hasTotalAltitudeLoss() {
- return totalAltitudeLoss_m != null;
- }
-
+ @VisibleForTesting
+ @Deprecated
@Nullable
public Float getTotalAltitudeLoss() {
return totalAltitudeLoss_m;
}
- public void setTotalAltitudeLoss(Float totalAltitudeLoss_m) {
- this.totalAltitudeLoss_m = totalAltitudeLoss_m;
- }
-
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
- public void addTotalAltitudeLoss(float loss_m) {
+ public void addTotalAltitudeGainLoss(AltitudeGainLoss altitudeGainLoss) {
+ if (totalAltitudeGain_m == null) {
+ totalAltitudeGain_m = 0f;
+ }
+ totalAltitudeGain_m += altitudeGainLoss.gain_m();
+
if (totalAltitudeLoss_m == null) {
totalAltitudeLoss_m = 0f;
}
- totalAltitudeLoss_m += loss_m;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof TrackStatistics)) return false;
-
- return toString().equals(o.toString());
+ totalAltitudeLoss_m += altitudeGainLoss.loss_m();
}
@NonNull
@Override
public String toString() {
- return "TrackStatistics { Start Time: " + getStartTime() + "; Stop Time: " + getStopTime()
- + "; Total Distance: " + getTotalDistance() + "; Total Time: " + getTotalTime()
- + "; Moving Time: " + getMovingTime() + "; Max Speed: " + getMaxSpeed()
- + "; Min Altitude: " + getMinAltitude() + "; Max Altitude: " + getMaxAltitude()
- + "; Altitude Gain: " + getTotalAltitudeGain()
- + "; Altitude Loss: " + getTotalAltitudeLoss() + "}";
+ return "SegmentStatisticUpdater{" + getStatistics() + "}";
}
}
\ No newline at end of file
diff --git a/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java b/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java
index 9e84fbfca..b0d1bed61 100644
--- a/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java
+++ b/src/main/java/de/dennisguse/opentracks/stats/TrackStatisticsUpdater.java
@@ -17,6 +17,7 @@
package de.dennisguse.opentracks.stats;
import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
import java.time.Duration;
import java.util.List;
@@ -25,12 +26,13 @@ import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.Power;
import de.dennisguse.opentracks.data.models.Speed;
+import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.settings.PreferencesUtils;
/**
- * Updater for {@link TrackStatistics}.
- * For updating track {@link TrackStatistics} as new {@link TrackPoint}s are added.
+ * Updater for {@link SegmentStatisticUpdater}.
+ * For updating track {@link SegmentStatisticUpdater} as new {@link TrackPoint}s are added.
* NOTE: Some of the locations represent pause/resume separator.
* NOTE: Has still support for segments (at the moment unused).
*
@@ -41,7 +43,7 @@ public class TrackStatisticsUpdater {
private static final String TAG = TrackStatisticsUpdater.class.getSimpleName();
- private final TrackStatistics trackStatistics;
+ private final SegmentStatisticUpdater segmentStatisticUpdater;
private float averageHeartRateBPM;
private Duration totalHeartRateDuration = Duration.ZERO;
@@ -49,38 +51,49 @@ public class TrackStatisticsUpdater {
private Duration totalPowerDuration = Duration.ZERO;
// The current segment's statistics
- private final TrackStatistics currentSegment;
+ private final SegmentStatisticUpdater currentSegment;
// Current segment's last trackPoint
private TrackPoint lastTrackPoint;
public TrackStatisticsUpdater() {
- this(new TrackStatistics());
+ this(new SegmentStatisticUpdater());
}
- public TrackStatisticsUpdater(TrackStatistics trackStatistics) {
- this.trackStatistics = trackStatistics;
- this.currentSegment = new TrackStatistics();
+ public TrackStatisticsUpdater(Statistics statistics) {
+ this(new SegmentStatisticUpdater(statistics));
+ }
+
+ @Deprecated
+ private TrackStatisticsUpdater(SegmentStatisticUpdater segmentStatisticUpdater) {
+ this.segmentStatisticUpdater = segmentStatisticUpdater;
+ this.currentSegment = new SegmentStatisticUpdater();
resetAverageHeartRate();
}
public TrackStatisticsUpdater(TrackStatisticsUpdater toCopy) {
- this.currentSegment = new TrackStatistics(toCopy.currentSegment);
- this.trackStatistics = new TrackStatistics(toCopy.trackStatistics);
+ this.currentSegment = new SegmentStatisticUpdater(toCopy.currentSegment);
+ this.segmentStatisticUpdater = new SegmentStatisticUpdater(toCopy.segmentStatisticUpdater);
this.lastTrackPoint = toCopy.lastTrackPoint;
resetAverageHeartRate();
}
- public TrackStatistics getTrackStatistics() {
+ @Deprecated //TODO Remove
+ @VisibleForTesting
+ public SegmentStatisticUpdater getSegmentStatisticUpdater() {
// Take a snapshot - we don't want anyone messing with our trackStatistics
- TrackStatistics stats = new TrackStatistics(trackStatistics);
+ SegmentStatisticUpdater stats = new SegmentStatisticUpdater(segmentStatisticUpdater);
stats.merge(currentSegment);
return stats;
}
- public TrackStatistics getCurrentSegment() {
- // Take a snapshot - we don't want anyone messing with our currentSegment
- return new TrackStatistics(currentSegment);
+
+ public Statistics getTrackStatistics() {
+ return getSegmentStatisticUpdater().getStatistics();
+ }
+
+ public Statistics getCurrentSegment() {
+ return currentSegment.getStatistics();
}
public void addTrackPoints(List trackPoints) {
@@ -101,12 +114,8 @@ public class TrackStatisticsUpdater {
currentSegment.setTotalTime(Duration.between(currentSegment.getStartTime(), trackPoint.getTime()));
// Process sensor data: barometer
- if (trackPoint.hasAltitudeGain()) {
- currentSegment.addTotalAltitudeGain(trackPoint.getAltitudeGain());
- }
-
- if (trackPoint.hasAltitudeLoss()) {
- currentSegment.addTotalAltitudeLoss(trackPoint.getAltitudeLoss());
+ if (trackPoint.hasAltitudeGainLoss()) {
+ currentSegment.addTotalAltitudeGainLoss(trackPoint.getAltitudeGainLoss());
}
//Update absolute (GPS-based) altitude
@@ -182,7 +191,7 @@ public class TrackStatisticsUpdater {
private void reset(TrackPoint trackPoint) {
if (currentSegment.isInitialized()) {
- trackStatistics.merge(currentSegment);
+ segmentStatisticUpdater.merge(currentSegment);
}
currentSegment.reset(trackPoint.getTime());
@@ -209,7 +218,7 @@ public class TrackStatisticsUpdater {
@Override
public String toString() {
return "TrackStatisticsUpdater{" +
- "trackStatistics=" + trackStatistics +
+ "trackStatistics=" + segmentStatisticUpdater +
'}';
}
}
diff --git a/src/main/java/de/dennisguse/opentracks/ui/TrackListAdapter.java b/src/main/java/de/dennisguse/opentracks/ui/TrackListAdapter.java
index 671b39022..63f1406cc 100644
--- a/src/main/java/de/dennisguse/opentracks/ui/TrackListAdapter.java
+++ b/src/main/java/de/dennisguse/opentracks/ui/TrackListAdapter.java
@@ -1,9 +1,7 @@
package de.dennisguse.opentracks.ui;
-import android.app.ActivityOptions;
import android.content.Intent;
import android.database.Cursor;
-import android.util.Pair;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -269,10 +267,7 @@ public class TrackListAdapter extends RecyclerView.Adapter open detail activity.
Intent newIntent = IntentUtils.newIntent(context, TrackRecordedActivity.class)
.putExtra(TrackRecordedActivity.EXTRA_TRACK_ID, trackId);
- ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(
- context,
- new Pair<>(viewBinding.getRoot().findViewById(R.id.track_list_item_icon), TrackRecordedActivity.VIEW_TRACK_ICON));
- context.startActivity(newIntent, activityOptions.toBundle());
+ context.startActivity(newIntent);
}
}
diff --git a/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/AggregatedStatistics.java b/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/AggregatedStatistics.java
index 8de17659d..5a6faa17d 100644
--- a/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/AggregatedStatistics.java
+++ b/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/AggregatedStatistics.java
@@ -8,8 +8,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
-import de.dennisguse.opentracks.stats.TrackStatistics;
+import de.dennisguse.opentracks.stats.SegmentStatisticUpdater;
public class AggregatedStatistics {
@@ -35,9 +36,9 @@ public class AggregatedStatistics {
public void aggregate(@NonNull Track track) {
String activityTypeLocalized = track.getActivityTypeLocalized();
if (dataMap.containsKey(activityTypeLocalized)) {
- dataMap.get(activityTypeLocalized).add(track.getTrackStatistics());
+ dataMap.get(activityTypeLocalized).add(track.getStatistics());
} else {
- dataMap.put(activityTypeLocalized, new AggregatedStatistic(activityTypeLocalized, track.getTrackStatistics()));
+ dataMap.put(activityTypeLocalized, new AggregatedStatistic(activityTypeLocalized, track.getStatistics()));
}
}
@@ -55,19 +56,19 @@ public class AggregatedStatistics {
public static class AggregatedStatistic {
private final String activityTypeLocalized;
- private final TrackStatistics trackStatistics;
+ private final SegmentStatisticUpdater trackStatistics;
private int countTracks = 1;
- public AggregatedStatistic(String activityTypeLocalized, TrackStatistics trackStatistics) {
+ public AggregatedStatistic(String activityTypeLocalized, Statistics trackStatistics) {
this.activityTypeLocalized = activityTypeLocalized;
- this.trackStatistics = trackStatistics;
+ this.trackStatistics = new SegmentStatisticUpdater(trackStatistics);
}
public String getActivityTypeLocalized() {
return activityTypeLocalized;
}
- public TrackStatistics getTrackStatistics() {
+ public SegmentStatisticUpdater getTrackStatistics() {
return trackStatistics;
}
@@ -75,8 +76,8 @@ public class AggregatedStatistics {
return countTracks;
}
- void add(TrackStatistics statistics) {
- trackStatistics.merge(statistics);
+ void add(Statistics statistics) {
+ trackStatistics.merge(new SegmentStatisticUpdater(statistics));
countTracks++;
}
}
diff --git a/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/RecordingLayoutIO.java b/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/RecordingLayoutIO.java
index fd30e6610..0c7752af1 100644
--- a/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/RecordingLayoutIO.java
+++ b/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/RecordingLayoutIO.java
@@ -11,6 +11,7 @@ import java.util.stream.Collectors;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.settings.PreferencesUtils;
+//TODO Migrate to DataStore.
public class RecordingLayoutIO {
private static final String TAG = RecordingLayout.class.getSimpleName();
diff --git a/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/SettingsCustomLayoutEditAdapter.java b/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/SettingsCustomLayoutEditAdapter.java
index 45d19a368..5f8dab3ca 100644
--- a/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/SettingsCustomLayoutEditAdapter.java
+++ b/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/SettingsCustomLayoutEditAdapter.java
@@ -19,15 +19,16 @@ import java.util.concurrent.Callable;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.models.Altitude;
+import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.Position;
import de.dennisguse.opentracks.data.models.Speed;
+import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.databinding.CustomStatsItemBinding;
import de.dennisguse.opentracks.services.RecordingData;
import de.dennisguse.opentracks.settings.UnitSystem;
-import de.dennisguse.opentracks.stats.TrackStatistics;
import de.dennisguse.opentracks.viewmodels.Mapping;
import de.dennisguse.opentracks.viewmodels.StatisticViewHolder;
@@ -38,17 +39,22 @@ public class SettingsCustomLayoutEditAdapter extends RecyclerView.Adapter {
- private List intervalList;
+ private List intervalList = new ArrayList<>();
private final Context context;
private final StackMode stackMode;
private UnitSystem unitSystem;
@@ -43,46 +45,39 @@ public class IntervalStatisticsAdapter extends RecyclerView.Adapter 0) {
- sumDistance = intervalList.get(actualPosition - 1).getDistance()
+ sumDistance = intervalList.get(actualPosition - 1).totalDistance()
.multipliedBy(actualPosition)
- .plus(interval.getDistance());
+ .plus(interval.totalDistance());
} else {
- sumDistance = interval.getDistance().multipliedBy(nextPosition);
+ sumDistance = interval.totalDistance().multipliedBy(nextPosition);
}
viewHolder.viewBinding.intervalItemDistance.setText(DistanceFormatter.Builder()
.setUnit(unitSystem)
.build(context).formatDistance(sumDistance));
SpeedFormatter formatter = SpeedFormatter.Builder().setUnit(unitSystem).setReportSpeedOrPace(isReportSpeed).build(context);
- viewHolder.viewBinding.intervalItemRate.setText(formatter.formatSpeed(interval.getSpeed()));
+ viewHolder.viewBinding.intervalItemRate.setText(formatter.formatSpeed(interval.getAverageSpeed()));
- viewHolder.viewBinding.intervalItemGain.setText(StringUtils.formatAltitude(context, interval.getGain_m(), unitSystem));
- viewHolder.viewBinding.intervalItemLoss.setText(StringUtils.formatAltitude(context, interval.getLoss_m(), unitSystem));
+ viewHolder.viewBinding.intervalItemGain.setText(StringUtils.formatAltitude(context, interval.altitudeGainLoss() != null ? interval.altitudeGainLoss().gain_m() : null, unitSystem));
+ viewHolder.viewBinding.intervalItemLoss.setText(StringUtils.formatAltitude(context, interval.altitudeGainLoss() != null ? interval.altitudeGainLoss().loss_m() : null, unitSystem));
}
@Override
public int getItemCount() {
- if (intervalList == null) {
- return 0;
- }
return intervalList.size();
}
- public List swapData(List data, UnitSystem unitSystem, boolean isReportSpeed) {
+ public void swapData(@NonNull List data, UnitSystem unitSystem, boolean isReportSpeed) {
this.unitSystem = unitSystem;
this.isReportSpeed = isReportSpeed;
intervalList = data;
- if (data != null) {
- this.notifyDataSetChanged();
- }
-
- return data;
+ this.notifyDataSetChanged();
}
/**
diff --git a/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsModel.java b/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsModel.java
index 2bd1c892e..13ebf67f4 100644
--- a/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsModel.java
+++ b/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsModel.java
@@ -17,12 +17,13 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import de.dennisguse.opentracks.data.ContentProviderUtils;
-import de.dennisguse.opentracks.data.TrackPointIterator;
import de.dennisguse.opentracks.data.models.Distance;
+import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
import de.dennisguse.opentracks.settings.UnitSystem;
+import de.dennisguse.opentracks.util.AutoCloseableIterator;
/**
* This model is used to load intervals for a track.
@@ -32,8 +33,8 @@ public class IntervalStatisticsModel extends AndroidViewModel {
private static final String TAG = IntervalStatisticsModel.class.getSimpleName();
- private MutableLiveData> intervalsLiveData;
- private IntervalStatistics intervalStatistics;
+ private MutableLiveData> intervalsLiveData;
+ private IntervalStatisticsUpdater intervalStatistics;
private Distance distanceInterval;
private final ContentResolver contentResolver;
private ContentObserver trackPointsTableObserver;
@@ -65,7 +66,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
handler = null;
}
- public MutableLiveData> getIntervalStats(Track.Id trackId, UnitSystem unitSystem, @Nullable IntervalOption interval) {
+ public MutableLiveData> getIntervalStats(Track.Id trackId, UnitSystem unitSystem, @Nullable IntervalOption interval) {
if (intervalsLiveData == null) {
if (interval == null) {
interval = IntervalOption.OPTION_1;
@@ -73,7 +74,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
intervalsLiveData = new MutableLiveData<>();
distanceInterval = interval.getDistance(unitSystem);
- intervalStatistics = new IntervalStatistics(distanceInterval);
+ intervalStatistics = new IntervalStatisticsUpdater(distanceInterval);
loadIntervalStatistics(trackId);
}
@@ -92,7 +93,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
private void loadIntervalStatistics(Track.Id trackId) {
executor.execute(() -> {
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(getApplication());
- try (TrackPointIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, lastTrackPointId)) {
+ try (AutoCloseableIterator trackPointIterator = contentProviderUtils.getTrackPointLocationIterator(trackId, lastTrackPointId)) {
lastTrackPointId = intervalStatistics.addTrackPoints(trackPointIterator);
intervalsLiveData.postValue(intervalStatistics.getIntervalList());
}
@@ -112,7 +113,7 @@ public class IntervalStatisticsModel extends AndroidViewModel {
lastTrackPointId = null;
distanceInterval = interval.getDistance(unitSystem);
- intervalStatistics = new IntervalStatistics(distanceInterval);
+ intervalStatistics = new IntervalStatisticsUpdater(distanceInterval);
loadIntervalStatistics(trackId);
}
diff --git a/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatistics.java b/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsUpdater.java
similarity index 66%
rename from src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatistics.java
rename to src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsUpdater.java
index 8ce364f71..f96621af9 100644
--- a/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatistics.java
+++ b/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalStatisticsUpdater.java
@@ -4,18 +4,19 @@ import androidx.annotation.Nullable;
import java.time.Duration;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
-import de.dennisguse.opentracks.data.TrackPointIterator;
+import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.data.models.HeartRate;
import de.dennisguse.opentracks.data.models.Power;
import de.dennisguse.opentracks.data.models.Speed;
+import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.TrackPoint;
-import de.dennisguse.opentracks.stats.TrackStatistics;
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
-public class IntervalStatistics {
+public class IntervalStatisticsUpdater {
private TrackStatisticsUpdater trackStatisticsUpdater = new TrackStatisticsUpdater();
private final List intervalList;
private final Distance distanceInterval;
@@ -24,7 +25,7 @@ public class IntervalStatistics {
/**
* @param distanceInterval distance of every interval.
*/
- public IntervalStatistics(Distance distanceInterval) {
+ public IntervalStatisticsUpdater(Distance distanceInterval) {
this.distanceInterval = distanceInterval;
interval = new Interval();
@@ -38,7 +39,7 @@ public class IntervalStatistics {
*
* @return the last track point's id used to compute the intervals.
*/
- public TrackPoint.Id addTrackPoints(TrackPointIterator trackPointIterator) {
+ public TrackPoint.Id addTrackPoints(Iterator trackPointIterator) {
boolean newIntervalAdded = false;
TrackPoint trackPoint = null;
@@ -46,7 +47,7 @@ public class IntervalStatistics {
trackPoint = trackPointIterator.next();
trackStatisticsUpdater.addTrackPoint(trackPoint);
- if (trackStatisticsUpdater.getTrackStatistics().getTotalDistance().plus(interval.distance).greaterOrEqualThan(distanceInterval)) {
+ if (trackStatisticsUpdater.getTrackStatistics().totalDistance().plus(interval.distance).greaterOrEqualThan(distanceInterval)) {
interval.add(trackStatisticsUpdater.getTrackStatistics(), trackPoint);
double adjustFactor = distanceInterval.dividedBy(interval.distance);
@@ -74,8 +75,8 @@ public class IntervalStatistics {
return trackPoint != null ? trackPoint.getId() : null;
}
- public List getIntervalList() {
- return intervalList;
+ public List getIntervalList() {
+ return intervalList.stream().map(Interval::toStatistics).toList();
}
/**
@@ -84,21 +85,24 @@ public class IntervalStatistics {
*
* @return the interval object or null if any interval is completed.
*/
- public Interval getLastInterval() {
+ @Nullable
+ public Statistics getLastInterval() {
if (intervalList.size() == 1 && intervalList.get(0).getDistance().lessThan(distanceInterval)) {
return null;
}
for (int i = intervalList.size() - 1; i >= 0; i--) {
if (intervalList.get(i).getDistance().greaterOrEqualThan(distanceInterval)) {
- return this.intervalList.get(i);
+ return this.intervalList.get(i).toStatistics();
}
}
return null;
}
- public static class Interval {
+ //TODO Could be replaced with Statistics?
+ @Deprecated
+ private static class Interval {
private Distance distance = Distance.of(0);
private Duration time = Duration.ofSeconds(0);
private Float gain_m;
@@ -144,18 +148,6 @@ public class IntervalStatistics {
return gain_m != null;
}
- public Float getGain_m() {
- return gain_m;
- }
-
- public boolean hasLoss() {
- return loss_m != null;
- }
-
- public Float getLoss_m() {
- return loss_m;
- }
-
public boolean hasAverageHeartRate() {
return avgHeartRate != null;
}
@@ -172,31 +164,48 @@ public class IntervalStatistics {
return avgPower;
}
- private void add(TrackStatistics trackStatistics, @Nullable TrackPoint lastTrackPoint) {
- distance = distance.plus(trackStatistics.getTotalDistance());
- time = time.plus(trackStatistics.getTotalTime());
- gain_m = trackStatistics.hasTotalAltitudeGain() ? trackStatistics.getTotalAltitudeGain() : gain_m;
- loss_m = trackStatistics.hasTotalAltitudeLoss() ? trackStatistics.getTotalAltitudeLoss() : loss_m;
- avgHeartRate = trackStatistics.getAverageHeartRate();
- avgPower = trackStatistics.getAveragePower();
+ private void add(Statistics trackStatistics, @Nullable TrackPoint lastTrackPoint) {
+ distance = distance.plus(trackStatistics.totalDistance());
+ time = time.plus(trackStatistics.totalTime());
+ if (trackStatistics.altitudeGainLoss() != null) {
+ gain_m = trackStatistics.altitudeGainLoss().gain_m();
+ loss_m = trackStatistics.altitudeGainLoss().loss_m();
+ }
+ avgHeartRate = trackStatistics.avgHeartRate();
+ avgPower = trackStatistics.avgPower();
if (lastTrackPoint == null) {
return;
}
- if (hasGain() && lastTrackPoint.hasAltitudeGain()) {
- gain_m = gain_m - lastTrackPoint.getAltitudeGain();
- }
- if (hasLoss() && lastTrackPoint.hasAltitudeLoss()) {
- loss_m = loss_m - lastTrackPoint.getAltitudeLoss();
+ if (hasGain() && lastTrackPoint.hasAltitudeGainLoss()) {
+ gain_m = gain_m - lastTrackPoint.getAltitudeGainLoss().gain_m();
+ loss_m = loss_m - lastTrackPoint.getAltitudeGainLoss().loss_m();
}
}
- private void set(TrackStatistics trackStatistics) {
- distance = trackStatistics.getTotalDistance();
- time = trackStatistics.getTotalTime();
- gain_m = trackStatistics.hasTotalAltitudeGain() ? trackStatistics.getTotalAltitudeGain() : gain_m;
- loss_m = trackStatistics.hasTotalAltitudeLoss() ? trackStatistics.getTotalAltitudeLoss() : loss_m;
- avgHeartRate = trackStatistics.getAverageHeartRate();
- avgPower = trackStatistics.getAveragePower();
+ private void set(Statistics trackStatistics) {
+ distance = trackStatistics.totalDistance();
+ time = trackStatistics.totalTime();
+ if (trackStatistics.altitudeGainLoss() != null) {
+ gain_m = trackStatistics.altitudeGainLoss().gain_m();
+ loss_m = trackStatistics.altitudeGainLoss().loss_m();
+ }
+ avgHeartRate = trackStatistics.avgHeartRate();
+ avgPower = trackStatistics.avgPower();
+ }
+
+ private Statistics toStatistics() {
+ return new Statistics(
+ null,
+ null,
+ time,
+ null,
+ distance,
+ null,
+ null,
+ gain_m != null ? new AltitudeGainLoss(gain_m, loss_m) : null,
+ avgHeartRate,
+ avgPower
+ );
}
}
}
diff --git a/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalsFragment.java b/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalsFragment.java
index 7c814210e..801d2afcb 100644
--- a/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalsFragment.java
+++ b/src/main/java/de/dennisguse/opentracks/ui/intervals/IntervalsFragment.java
@@ -21,6 +21,7 @@ import java.util.Objects;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.data.ContentProviderUtils;
import de.dennisguse.opentracks.data.models.DistanceFormatter;
+import de.dennisguse.opentracks.data.models.Statistics;
import de.dennisguse.opentracks.data.models.Track;
import de.dennisguse.opentracks.databinding.IntervalListViewBinding;
import de.dennisguse.opentracks.settings.PreferencesUtils;
@@ -192,7 +193,7 @@ public class IntervalsFragment extends Fragment {
}
viewBinding.intervalRate.setText(isReportSpeed ? getString(R.string.stats_speed) : getString(R.string.stats_pace));
- LiveData> liveData = viewModel.getIntervalStats(trackId, unitSystem, selectedInterval);
+ LiveData> liveData = viewModel.getIntervalStats(trackId, unitSystem, selectedInterval);
liveData.observe(getActivity(), intervalList -> adapter.swapData(intervalList, unitSystem, isReportSpeed));
setIntervalsDropdownText();
diff --git a/src/main/java/de/dennisguse/opentracks/util/AutoCloseableIterator.java b/src/main/java/de/dennisguse/opentracks/util/AutoCloseableIterator.java
new file mode 100644
index 000000000..ab145f9f5
--- /dev/null
+++ b/src/main/java/de/dennisguse/opentracks/util/AutoCloseableIterator.java
@@ -0,0 +1,11 @@
+package de.dennisguse.opentracks.util;
+
+import java.util.Iterator;
+
+public abstract class AutoCloseableIterator implements Iterator, AutoCloseable {
+
+ /**
+ * Override: AutoClosable.close() throws Exception.
+ */
+ public abstract void close();
+}
diff --git a/src/main/java/de/dennisguse/opentracks/viewmodels/GenericStatisticsViewHolder.java b/src/main/java/de/dennisguse/opentracks/viewmodels/GenericStatisticsViewHolder.java
index 32f592687..ffea4bbf7 100644
--- a/src/main/java/de/dennisguse/opentracks/viewmodels/GenericStatisticsViewHolder.java
+++ b/src/main/java/de/dennisguse/opentracks/viewmodels/GenericStatisticsViewHolder.java
@@ -34,7 +34,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = DistanceFormatter.Builder()
.setUnit(unitSystem)
- .build(getContext()).getDistanceParts(data.getStatisticsTrack().getTotalDistance());
+ .build(getContext()).getDistanceParts(data.getStatisticsTrack().totalDistance());
getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second);
@@ -46,7 +46,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = new Pair<>(StringUtils.formatElapsedTime(data.getStatisticsTrack().getTotalTime()), null);
+ Pair valueAndUnit = new Pair<>(StringUtils.formatElapsedTime(data.getStatisticsTrack().totalTime()), null);
getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second);
@@ -58,7 +58,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getMaxSpeed());
+ Pair valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().maxSpeed());
getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second);
@@ -208,7 +208,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsCurrentSegment().getAverageMovingSpeed());
+ Pair valueAndUnit = speedFormatterSpeed.getSpeedParts(data.currentSegment().getAverageMovingSpeed());
getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second);
@@ -220,7 +220,7 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().getMaxSpeed());
+ Pair valueAndUnit = speedFormatterSpeed.getSpeedParts(data.getStatisticsTrack().maxSpeed());
getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second);
@@ -264,8 +264,9 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = StringUtils.getAltitudeParts(getContext(), data.getStatisticsTrack().getTotalAltitudeGain(), unitSystem);
+ Pair valueAndUnit = StringUtils.getAltitudeParts(getContext(), gain, unitSystem);
getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second);
@@ -277,8 +278,9 @@ public abstract class GenericStatisticsViewHolder extends StatisticViewHolder valueAndUnit = StringUtils.getAltitudeParts(getContext(), data.getStatisticsTrack().getTotalAltitudeLoss(), unitSystem);
+ Pair valueAndUnit = StringUtils.getAltitudeParts(getContext(), loss, unitSystem);
getBinding().statsValue.setText(valueAndUnit.first);
getBinding().statsUnit.setText(valueAndUnit.second);