aboutsummaryrefslogtreecommitdiff
path: root/ride/elevation_outlier_test.go
blob: 870be0874a5e2ca5e0f9ff250df10422f2bd1c1d (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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

package ride_test

import (
	"testing"

	"github.com/martinlehoux/biking_home/ride"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestDetectElevationOutliers_TunnelSpike(t *testing.T) {
	// Simulate ride 754 tunnel: steady then spike 46m over 7m (grade 657%), then normal.
	distances := []float64{0, 10, 20, 27, 34} // 7m gap at idx 3
	elevations := []float64{100, 101, 102, 148, 149}
	outliers := ride.DetectElevationOutliers(distances, elevations, 0.5)
	require.Len(t, outliers, 1)
	assert.Equal(t, 2, outliers[0].StartIdx) // expanded by 1
	assert.Equal(t, 4, outliers[0].EndIdx)
	assert.Greater(t, outliers[0].MaxGrade, 5.0)
}

func TestDetectElevationOutliers_IgnoresSmallJitter(t *testing.T) {
	distances := []float64{0, 0.5, 1.0, 1.5}
	elevations := []float64{100, 100.3, 100.6, 100.9} // 0.3m over 0.5m =60% but abs de <1.5
	outliers := ride.DetectElevationOutliers(distances, elevations, 0.5)
	assert.Empty(t, outliers)
}

func TestDetectElevationOutliers_IgnoresGentleSlope(t *testing.T) {
	distances := []float64{0, 10, 20, 30}
	elevations := []float64{100, 102, 104, 106} // 20% grade
	outliers := ride.DetectElevationOutliers(distances, elevations, 0.5)
	assert.Empty(t, outliers)
}

func TestLinearFix_Interpolates(t *testing.T) {
	distances := []float64{0, 10, 20, 30, 40}
	elevations := []float64{100, 110, 999, 130, 140}
	zones := []ride.FixZone{{StartIdx: 1, EndIdx: 3, StartKm: 0.01, EndKm: 0.03}}
	n := ride.LinearFix(distances, elevations, zones)
	assert.Equal(t, 1, n)
	assert.InDelta(t, 120, elevations[2], 0.01)
}

func TestResolveIndex_ByKm(t *testing.T) {
	distances := []float64{0, 1000, 2000, 3000}
	idx, err := ride.ResolveIndex(distances, "1.5km")
	require.NoError(t, err)
	// nearest to 1500 is idx 1 or 2 (both 500 away, picks first)
	assert.Contains(t, []int{1, 2}, idx)
}

func TestResolveIndex_ByIndex(t *testing.T) {
	distances := []float64{0, 1000, 2000}
	idx, err := ride.ResolveIndex(distances, "2")
	require.NoError(t, err)
	assert.Equal(t, 2, idx)
}