forked from upstream-mirrors/OpenTracks
Cleanup.
This commit is contained in:
@@ -54,7 +54,7 @@ import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.data.tables.MarkerColumns;
|
||||
import de.dennisguse.opentracks.data.tables.TrackPointsColumns;
|
||||
import de.dennisguse.opentracks.data.tables.TracksColumns;
|
||||
import de.dennisguse.opentracks.stats.SensorStatistics;
|
||||
import de.dennisguse.opentracks.data.statistics.SensorStatistics;
|
||||
import de.dennisguse.opentracks.ui.markers.MarkerUtils;
|
||||
import de.dennisguse.opentracks.util.FileUtils;
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ import de.dennisguse.opentracks.data.tables.TracksColumns;
|
||||
import de.dennisguse.opentracks.services.RecordingStatus;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.handlers.AltitudeCorrectionManager;
|
||||
import de.dennisguse.opentracks.stats.TrackStatisticsUpdater;
|
||||
import de.dennisguse.opentracks.data.statistics.TrackStatisticsUpdater;
|
||||
|
||||
/**
|
||||
* Track data hub.
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2009 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.statistics;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* A helper class that tracks a minimum and a maximum of a variable.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
*/
|
||||
public class ExtremityMonitor {
|
||||
|
||||
// The smallest value seen so far.
|
||||
private double min;
|
||||
|
||||
// The largest value seen so far.
|
||||
private double max;
|
||||
|
||||
public ExtremityMonitor() {
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets this object to it's initial state where the min and max are unknown.
|
||||
*/
|
||||
public void reset() {
|
||||
min = Double.POSITIVE_INFINITY;
|
||||
max = Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimum value seen.
|
||||
*/
|
||||
public double getMin() {
|
||||
return min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum value.
|
||||
*
|
||||
* @param min the minimum value
|
||||
*/
|
||||
public void setMin(double min) {
|
||||
this.min = min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum value seen.
|
||||
*/
|
||||
public double getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum value.
|
||||
*
|
||||
* @param max the maximum value
|
||||
*/
|
||||
public void setMax(double max) {
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the min and the max with a new value.
|
||||
*
|
||||
* @param value the new value
|
||||
* @return true if an extremity was found
|
||||
*/
|
||||
public boolean update(double value) {
|
||||
boolean changed = false;
|
||||
if (value < min) {
|
||||
min = value;
|
||||
changed = true;
|
||||
}
|
||||
if (value > max) {
|
||||
max = value;
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum and maximum values.
|
||||
*
|
||||
* @param min the minimum value
|
||||
* @param max the maximum value
|
||||
*/
|
||||
public void set(Double min, Double max) {
|
||||
if (min == null || max == null) {
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public boolean hasData() {
|
||||
return min != Double.POSITIVE_INFINITY && max != Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Min: " + min + " Max: " + max;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright 2010 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.statistics;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
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.TrackBuilder;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
|
||||
/**
|
||||
* Statistical data about a {@link TrackBuilder}.
|
||||
* The data in this class should be filled out by {@link TrackStatisticsUpdater}.
|
||||
*
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
//TODO Check that data ranges are valid (not less than zero etc.)
|
||||
public class SegmentStatisticUpdater {
|
||||
|
||||
// The min and max altitude (meters) seen on this track.
|
||||
private final ExtremityMonitor altitudeExtremities = new ExtremityMonitor();
|
||||
|
||||
// The track start time.
|
||||
@NonNull
|
||||
private final Instant startTime;
|
||||
// The track stop time.
|
||||
@NonNull
|
||||
private Instant stopTime;
|
||||
|
||||
private Distance totalDistance;
|
||||
/**
|
||||
* 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 totalDuration, use startTime with the current time.
|
||||
*/
|
||||
private Duration totalDuration;
|
||||
// Based on when we believe the user is traveling.
|
||||
private Duration movingDuration;
|
||||
// The maximum speed (meters/second) that we believe is valid.
|
||||
private Speed maxSpeed;
|
||||
private Float totalAltitudeGain_m = null;
|
||||
private Float totalAltitudeLoss_m = null;
|
||||
// The average heart rate seen on this track
|
||||
private HeartRate avgHeartRate = null;
|
||||
private Power avgPower = null;
|
||||
|
||||
public SegmentStatisticUpdater(@NonNull Instant startTime) {
|
||||
this.startTime = this.stopTime = startTime;
|
||||
totalDuration = Duration.ZERO;
|
||||
movingDuration = Duration.ZERO;
|
||||
totalDistance = Distance.ZERO;
|
||||
maxSpeed = Speed.ZERO;
|
||||
totalAltitudeGain_m = null;
|
||||
totalAltitudeLoss_m = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*
|
||||
* @param other another statistics data object to copy from
|
||||
*/
|
||||
public SegmentStatisticUpdater(SegmentStatisticUpdater other) {
|
||||
this(other.getStatistics());
|
||||
}
|
||||
|
||||
public SegmentStatisticUpdater(Statistics statistics) {
|
||||
startTime = statistics.startTime();
|
||||
stopTime = statistics.stopTime();
|
||||
totalDistance = statistics.totalDistance();
|
||||
totalDuration = statistics.totalDuration();
|
||||
movingDuration = statistics.movingDuration();
|
||||
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();
|
||||
}
|
||||
|
||||
public Statistics merge(Statistics statistics) {
|
||||
return getStatistics().merge(statistics);
|
||||
}
|
||||
|
||||
public Statistics getStatistics() {
|
||||
// Times may not be live (i.e., updated automatically).
|
||||
return new Statistics(
|
||||
startTime,
|
||||
stopTime,
|
||||
totalDuration,
|
||||
movingDuration,
|
||||
|
||||
totalDistance,
|
||||
getMaxSpeed(),
|
||||
|
||||
// This is calculated from the smoothed altitude, so this can actually be less than the current altitude.
|
||||
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 void setStopTime(Instant stopTime) {
|
||||
if (stopTime.isBefore(startTime)) {
|
||||
// Time must be monotonically increasing, but we might have events at the same point in time (BLE and GPS)
|
||||
throw new RuntimeException("stopTime cannot be less than startTime: " + startTime + " " + stopTime);
|
||||
}
|
||||
this.stopTime = stopTime;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void setTotalDistance(Distance totalDistance_m) {
|
||||
this.totalDistance = totalDistance_m;
|
||||
}
|
||||
|
||||
public void addTotalDistance(Distance distance_m) {
|
||||
totalDistance = totalDistance.plus(distance_m);
|
||||
}
|
||||
|
||||
public void updateTotalTime(Instant now) {
|
||||
this.totalDuration = Duration.between(startTime, now);
|
||||
}
|
||||
|
||||
public void addMovingTime(TrackPoint trackPoint, TrackPoint lastTrackPoint) {
|
||||
Duration movingDuration = Duration.between(lastTrackPoint.getTime(), trackPoint.getTime());
|
||||
|
||||
if (movingDuration.isNegative()) {
|
||||
throw new RuntimeException("Moving time cannot be negative");
|
||||
}
|
||||
this.movingDuration = this.movingDuration.plus(movingDuration);
|
||||
}
|
||||
|
||||
private Speed getAverageMovingSpeed() {
|
||||
return Speed.of(totalDistance, movingDuration);
|
||||
}
|
||||
|
||||
public Speed getMaxSpeed() {
|
||||
return Speed.max(maxSpeed, getAverageMovingSpeed());
|
||||
}
|
||||
|
||||
public void setMaxSpeed(Speed maxSpeed) {
|
||||
this.maxSpeed = maxSpeed;
|
||||
}
|
||||
|
||||
public void updateAltitudeExtremities(Altitude altitude) {
|
||||
if (altitude != null) {
|
||||
altitudeExtremities.update(altitude.toM());
|
||||
}
|
||||
}
|
||||
|
||||
public void setAverageHeartRate(HeartRate heartRate) {
|
||||
if (heartRate != null) {
|
||||
avgHeartRate = heartRate;
|
||||
}
|
||||
}
|
||||
|
||||
public void setAveragePower(Power power) {
|
||||
if (power != null) {
|
||||
avgPower = power;
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@Deprecated
|
||||
public void setTotalAltitudeGain(Float totalAltitudeGain_m) {
|
||||
this.totalAltitudeGain_m = totalAltitudeGain_m;
|
||||
}
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
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 += altitudeGainLoss.loss_m();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SegmentStatisticUpdater{" + getStatistics() + "}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package de.dennisguse.opentracks.data.statistics;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Cadence;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
|
||||
public record SensorStatistics(
|
||||
HeartRate maxHeartRate,
|
||||
HeartRate avgHeartRate,
|
||||
Cadence maxCadence,
|
||||
Cadence avgCadence,
|
||||
Power maxPower,
|
||||
Power avgPower
|
||||
) {
|
||||
|
||||
public boolean hasHeartRate() {
|
||||
return avgHeartRate != null && maxHeartRate != null;
|
||||
}
|
||||
|
||||
public boolean hasCadence() {
|
||||
return avgCadence != null && maxCadence != null;
|
||||
}
|
||||
|
||||
public boolean hasPower() {
|
||||
return avgPower != null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright 2009 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.statistics;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
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 SegmentStatisticUpdater}.
|
||||
* For updating track {@link SegmentStatisticUpdater} as new {@link TrackPoint}s are added.
|
||||
* NOTE: {@link TrackPoint} represent pause/resume separator.
|
||||
*
|
||||
* @author Sandor Dornbush
|
||||
* @author Rodrigo Damazio
|
||||
*/
|
||||
public class TrackStatisticsUpdater {
|
||||
|
||||
private static final String TAG = TrackStatisticsUpdater.class.getSimpleName();
|
||||
|
||||
private Statistics statisticsWithoutCurrentSegment = null;
|
||||
|
||||
private float averageHeartRateBPM;
|
||||
private Duration totalHeartRateDuration = Duration.ZERO;
|
||||
private float averagePowerW;
|
||||
private Duration totalPowerDuration = Duration.ZERO;
|
||||
|
||||
// The current segment's statistics
|
||||
private SegmentStatisticUpdater currentSegment;
|
||||
// Current segment's last trackPoint
|
||||
private TrackPoint lastTrackPoint;
|
||||
|
||||
private boolean isIdle;
|
||||
|
||||
public TrackStatisticsUpdater(@NonNull TrackPoint trackPoint) {
|
||||
addTrackPoint(trackPoint);
|
||||
}
|
||||
|
||||
public TrackStatisticsUpdater(List<TrackPoint> trackPoints) {
|
||||
assert !trackPoints.isEmpty(); //TODO Enforce that this is always true (e.g., import)
|
||||
|
||||
trackPoints.forEach(this::addTrackPoint);
|
||||
}
|
||||
|
||||
public TrackStatisticsUpdater(@NonNull Statistics statistics) {
|
||||
this.statisticsWithoutCurrentSegment = statistics;
|
||||
this.currentSegment = null;
|
||||
|
||||
resetAverageHeartRate();
|
||||
}
|
||||
|
||||
public TrackStatisticsUpdater(@NonNull TrackStatisticsUpdater toCopy, TrackPoint tmp) {
|
||||
this.statisticsWithoutCurrentSegment = toCopy.statisticsWithoutCurrentSegment;
|
||||
this.currentSegment = new SegmentStatisticUpdater(toCopy.currentSegment);
|
||||
|
||||
this.lastTrackPoint = toCopy.lastTrackPoint;
|
||||
this.isIdle = toCopy.isIdle;
|
||||
resetAverageHeartRate();
|
||||
|
||||
addTrackPoint(tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute TrackStatistics.
|
||||
*/
|
||||
public Statistics getTrackStatistics() {
|
||||
return currentSegment.merge(statisticsWithoutCurrentSegment);
|
||||
}
|
||||
|
||||
public boolean isIdle() {
|
||||
return isIdle;
|
||||
}
|
||||
|
||||
public Statistics getCurrentSegment() {
|
||||
return currentSegment.getStatistics();
|
||||
}
|
||||
|
||||
public void addTrackPoint(TrackPoint trackPoint) {
|
||||
if (trackPoint.isSegmentManualStart()) {
|
||||
reset(trackPoint);
|
||||
}
|
||||
if (currentSegment == null) {
|
||||
currentSegment = new SegmentStatisticUpdater(trackPoint.getTime());
|
||||
}
|
||||
|
||||
// Always update time
|
||||
currentSegment.setStopTime(trackPoint.getTime());
|
||||
currentSegment.updateTotalTime(trackPoint.getTime());
|
||||
|
||||
// Process sensor data: barometer
|
||||
if (trackPoint.hasAltitudeGainLoss()) {
|
||||
currentSegment.addTotalAltitudeGainLoss(trackPoint.getAltitudeGainLoss());
|
||||
}
|
||||
|
||||
//Update absolute (GPS-based) altitude
|
||||
if (trackPoint.hasAltitude()) {
|
||||
currentSegment.updateAltitudeExtremities(trackPoint.getAltitude());
|
||||
}
|
||||
|
||||
// Update heart rate
|
||||
if (trackPoint.hasHeartRate() && lastTrackPoint != null) {
|
||||
Duration trackPointDuration = Duration.between(lastTrackPoint.getTime(), trackPoint.getTime());
|
||||
Duration newTotalDuration = totalHeartRateDuration.plus(trackPointDuration);
|
||||
|
||||
averageHeartRateBPM = (totalHeartRateDuration.toMillis() * averageHeartRateBPM + trackPointDuration.toMillis() * trackPoint.getHeartRate().getBPM()) / newTotalDuration.toMillis();
|
||||
totalHeartRateDuration = newTotalDuration;
|
||||
|
||||
currentSegment.setAverageHeartRate(HeartRate.of(averageHeartRateBPM));
|
||||
}
|
||||
|
||||
// Update power
|
||||
if (trackPoint.hasPower() && lastTrackPoint != null) {
|
||||
Duration trackPointDuration = Duration.between(lastTrackPoint.getTime(), trackPoint.getTime());
|
||||
Duration newTotalDuration = totalPowerDuration.plus(trackPointDuration);
|
||||
|
||||
averagePowerW = (totalPowerDuration.toMillis() * averagePowerW + trackPointDuration.toMillis() * trackPoint.getPower().getW()) / newTotalDuration.toMillis();
|
||||
totalPowerDuration = newTotalDuration;
|
||||
|
||||
currentSegment.setAveragePower(Power.of(averagePowerW));
|
||||
}
|
||||
|
||||
{
|
||||
// Update total distance
|
||||
Distance movingDistance = null;
|
||||
if (trackPoint.hasSensorDistance()) {
|
||||
movingDistance = trackPoint.getSensorDistance();
|
||||
} else if (lastTrackPoint != null
|
||||
&& lastTrackPoint.hasLocation()
|
||||
&& trackPoint.hasLocation()) {
|
||||
// GPS-based distance/speed
|
||||
movingDistance = trackPoint.distanceToPrevious(lastTrackPoint);
|
||||
}
|
||||
if (movingDistance != null) {
|
||||
currentSegment.addTotalDistance(movingDistance);
|
||||
}
|
||||
|
||||
if (!isIdle
|
||||
&& !trackPoint.isSegmentManualStart()
|
||||
&& lastTrackPoint != null) {
|
||||
currentSegment.addMovingTime(trackPoint, lastTrackPoint);
|
||||
}
|
||||
|
||||
if (trackPoint.isIdleTriggered()) {
|
||||
isIdle = true;
|
||||
} else if (isIdle) {
|
||||
// Shall we switch to non-idle?
|
||||
if (movingDistance != null
|
||||
&& movingDistance.greaterOrEqualThan(PreferencesUtils.getRecordingDistanceInterval())) {
|
||||
isIdle = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (trackPoint.hasSpeed()) {
|
||||
updateSpeed(trackPoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (trackPoint.isSegmentManualEnd()) {
|
||||
reset(trackPoint);
|
||||
return;
|
||||
}
|
||||
|
||||
lastTrackPoint = trackPoint;
|
||||
}
|
||||
|
||||
private void reset(TrackPoint trackPoint) {
|
||||
if (currentSegment != null) {
|
||||
statisticsWithoutCurrentSegment = currentSegment.merge(statisticsWithoutCurrentSegment);
|
||||
}
|
||||
currentSegment = new SegmentStatisticUpdater(trackPoint.getTime());
|
||||
|
||||
lastTrackPoint = null;
|
||||
resetAverageHeartRate();
|
||||
}
|
||||
|
||||
private void resetAverageHeartRate() {
|
||||
averageHeartRateBPM = 0.0f;
|
||||
totalHeartRateDuration = Duration.ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a speed reading while assuming the user is moving.
|
||||
*/
|
||||
private void updateSpeed(@NonNull TrackPoint trackPoint) {
|
||||
Speed currentSpeed = trackPoint.getSpeed();
|
||||
if (currentSpeed.greaterThan(currentSegment.getMaxSpeed())) {
|
||||
currentSegment.setMaxSpeed(currentSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TrackStatisticsUpdater{" +
|
||||
"segmentStatisticUpdater=" + statisticsWithoutCurrentSegment +
|
||||
", currentSegment=" + currentSegment +
|
||||
", lastTrackPoint=" + lastTrackPoint +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user