From 825cf388b55a6c8441e02149749bb6e2968477c0 Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Thu, 27 Aug 2026 11:21:17 +0200 Subject: Extract climb detection into a dedicated climb package Move climb detection, slope, and Cotacol scoring out of ride into a new climb package that operates on a geometry-only Route (distances, elevations, coords). Ride embeds climb.Route and keeps its timing and telemetry columns. - climb.Detect returns []DetectedClimb (Climb + ride-absolute Start). - Climb owns its sliced geometry; indices are local, with Start reported at the detection boundary for absolute position. - Detected bounds use core.Interval; freeRegions claim suppression fixed. - ride no longer builds slices: ClimbFromDist/ClimbFromIndexes/climbFrom and ride.Climb/Interval/Range are removed; rideanalysis, mountain_pass MatchClimb, and web views are rewired to climb types. - New internal/routetest builds climb.Route from the ride DSL; ridetest reuses it and adds timestamps and telemetry. - Tests moved to climb (synthetic detection and difficulty) and kept in ride for GPX-example integration; ride.comparison detection coverage retained. - mountain_pass.nearestCrossing now reuses geo.Nearest. --- internal/ridetest/ride_test.go | 48 +++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'internal/ridetest/ride_test.go') diff --git a/internal/ridetest/ride_test.go b/internal/ridetest/ride_test.go index 65483f2..46bd632 100644 --- a/internal/ridetest/ride_test.go +++ b/internal/ridetest/ride_test.go @@ -12,30 +12,30 @@ func TestRideSingleSection(t *testing.T) { r, err := Ride("1km at 10%") require.NoError(t, err) - assert.Len(t, r.Distances(), 11) - assert.Equal(t, 0.0, r.Distances()[0]) - assert.Equal(t, 1000.0, r.Distances()[10]) - assert.Equal(t, 0.0, r.Elevations()[0]) - assert.Equal(t, 100.0, r.Elevations()[10]) + assert.Len(t, r.Distances, 11) + assert.Equal(t, 0.0, r.Distances[0]) + assert.Equal(t, 1000.0, r.Distances[10]) + assert.Equal(t, 0.0, r.Elevations[0]) + assert.Equal(t, 100.0, r.Elevations[10]) } func TestRideSectionsWithDescentAndFlat(t *testing.T) { r, err := Ride("0.5km at 10% | 0.5km at -10%") require.NoError(t, err) - assert.Len(t, r.Distances(), 11) - assert.Equal(t, 1000.0, r.Distances()[10]) - assert.Equal(t, 50.0, r.Elevations()[5]) // top of the first section - assert.Equal(t, 0.0, r.Elevations()[10]) // back to start elevation + assert.Len(t, r.Distances, 11) + assert.Equal(t, 1000.0, r.Distances[10]) + assert.Equal(t, 50.0, r.Elevations[5]) // top of the first section + assert.Equal(t, 0.0, r.Elevations[10]) // back to start elevation } func TestRideSamplingOption(t *testing.T) { r, err := Ride("1km at 10%", Sampling(50)) require.NoError(t, err) - assert.Len(t, r.Distances(), 21) - assert.Equal(t, 1000.0, r.Distances()[20]) - assert.Equal(t, 5.0, r.Elevations()[1]) + assert.Len(t, r.Distances, 21) + assert.Equal(t, 1000.0, r.Distances[20]) + assert.Equal(t, 5.0, r.Elevations[1]) } func TestRideStartCoordHeading(t *testing.T) { @@ -44,13 +44,13 @@ func TestRideStartCoordHeading(t *testing.T) { // Coordinates advance northeast by 0.01° per km; float64 literals like // 43.11 drift in the last bits, so compare with a small tolerance. - require.Len(t, r.Coords(), 3) - assert.InDelta(t, 43.10, r.Coords()[0].Lat, 1e-9) - assert.InDelta(t, 5.10, r.Coords()[0].Lon, 1e-9) - assert.InDelta(t, 43.11, r.Coords()[1].Lat, 1e-9) - assert.InDelta(t, 5.11, r.Coords()[1].Lon, 1e-9) - assert.InDelta(t, 43.12, r.Coords()[2].Lat, 1e-9) - assert.InDelta(t, 5.12, r.Coords()[2].Lon, 1e-9) + require.Len(t, r.Coords, 3) + assert.InDelta(t, 43.10, r.Coords[0].Lat, 1e-9) + assert.InDelta(t, 5.10, r.Coords[0].Lon, 1e-9) + assert.InDelta(t, 43.11, r.Coords[1].Lat, 1e-9) + assert.InDelta(t, 5.11, r.Coords[1].Lon, 1e-9) + assert.InDelta(t, 43.12, r.Coords[2].Lat, 1e-9) + assert.InDelta(t, 5.12, r.Coords[2].Lon, 1e-9) } func TestRideHeadingOption(t *testing.T) { @@ -59,9 +59,9 @@ func TestRideHeadingOption(t *testing.T) { // A single kilometer at 0.1°/km ends at (43.1, 5.1), matching rides whose // points are spaced 0.1° apart over a kilometer. - require.Len(t, r.Coords(), 2) - assert.InDelta(t, 43.1, r.Coords()[1].Lat, 1e-9) - assert.InDelta(t, 5.1, r.Coords()[1].Lon, 1e-9) + require.Len(t, r.Coords, 2) + assert.InDelta(t, 43.1, r.Coords[1].Lat, 1e-9) + assert.InDelta(t, 5.1, r.Coords[1].Lon, 1e-9) } func TestRideStartTime(t *testing.T) { @@ -79,8 +79,8 @@ func TestRideStartElevation(t *testing.T) { r, err := Ride("1km at 0%", StartElevation(100)) require.NoError(t, err) - assert.Equal(t, 100.0, r.Elevations()[0]) - assert.Equal(t, 100.0, r.Elevations()[10]) + assert.Equal(t, 100.0, r.Elevations[0]) + assert.Equal(t, 100.0, r.Elevations[10]) } func TestRideMetricsCompleteColumns(t *testing.T) { -- cgit v1.3