diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-09-01 15:32:38 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-09-01 15:32:38 +0200 |
| commit | 7b6bd3ae858c5d7877f9ef137a3ff3d6f71ce1fc (patch) | |
| tree | 28a54e79a6d3c124adca760a38844187bc84e21b /ride/elevation_outlier_test.go | |
| parent | 793d2032041335004427c10f2edb7002df20a990 (diff) | |
feat: Analyse and fix elevation issues
Diffstat (limited to 'ride/elevation_outlier_test.go')
| -rw-r--r-- | ride/elevation_outlier_test.go | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/ride/elevation_outlier_test.go b/ride/elevation_outlier_test.go new file mode 100644 index 0000000..870be08 --- /dev/null +++ b/ride/elevation_outlier_test.go @@ -0,0 +1,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) +} |
