aboutsummaryrefslogtreecommitdiff
path: root/ride/moving_time.go
blob: ea9ec24230b9a5e0e29970d0114db819294ce027 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

package ride

import "time"

const MovingTimeAlgorithmVersion = "v1"

// movingTimeMinSpeedMps is the minimum implied speed between two consecutive
// track points for the interval to count as moving (0.4 km/h).
const movingTimeMinSpeedMps = 0.4 / 3.6

// movingTimeMaxGap is the maximum time gap between consecutive track points
// that can count as moving. Longer gaps are pauses (stops, lost signal).
const movingTimeMaxGap = 120 * time.Second

// Bench (356 rides, `-backtest`):
// absMean 2.5%, bias -1.3, p50 0.8, p75 2.9, p90 6.0, p95 9.3, p99 26.2.
func MovingTime(r Ride) time.Duration {
	return movingTime(r, movingTimeMinSpeedMps, movingTimeMaxGap)
}

func movingTime(r Ride, minSpeedMps float64, maxGap time.Duration) time.Duration {
	var moving time.Duration
	for i := 1; i < r.Len(); i++ {
		dt := r.Timestamp(i).Sub(r.Timestamp(i - 1))
		if dt <= 0 || dt > maxGap {
			continue
		}
		dd := r.DistanceM(i) - r.DistanceM(i-1)
		if dd/dt.Seconds() > minSpeedMps {
			moving += dt
		}
	}
	return moving
}