aboutsummaryrefslogtreecommitdiff
path: root/official_climb
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-08-27 11:21:17 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-08-27 11:21:17 +0200
commit825cf388b55a6c8441e02149749bb6e2968477c0 (patch)
treee3394cef97aa43df9775a1465d3c99f386ce3a9b /official_climb
parent366e7b0d671395c2ad32f85ee7706a592db69d15 (diff)
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.
Diffstat (limited to 'official_climb')
-rw-r--r--official_climb/official_climb_test.go28
1 files changed, 14 insertions, 14 deletions
diff --git a/official_climb/official_climb_test.go b/official_climb/official_climb_test.go
index ed121e5..6ddce5a 100644
--- a/official_climb/official_climb_test.go
+++ b/official_climb/official_climb_test.go
@@ -56,10 +56,10 @@ func TestMatchClimbMatchesWithoutDetectedClimb(t *testing.T) {
parsed := ridetest.MustRide("2km at 5% | 1km at -10%", ridetest.StartCoord(43.10, 5.10), ridetest.StartElevation(100), ridetest.Sampling(1000))
official := official_climb.OfficialClimb{
Name: "On route",
- StartCoord: parsed.Coords()[1],
- EndCoord: parsed.Coords()[2],
+ StartCoord: parsed.Coords[1],
+ EndCoord: parsed.Coords[2],
}
- matched, found := official_climb.MatchClimb(parsed.Coords(), official, official_climb.DefaultMatchRadiusM)
+ matched, found := official_climb.MatchClimb(parsed.Coords, official, official_climb.DefaultMatchRadiusM)
require.True(t, found)
assert.Equal(t, 1, matched.StartIndex)
assert.Equal(t, 2, matched.EndIndex)
@@ -72,7 +72,7 @@ func TestMatchClimbMatchesEndpointInsideRadius(t *testing.T) {
StartCoord: geodist.Coord{Lat: 43.1101, Lon: 5.1101},
EndCoord: geodist.Coord{Lat: 43.1201, Lon: 5.1201},
}
- matched, found := official_climb.MatchClimb(parsed.Coords(), official, official_climb.DefaultMatchRadiusM)
+ matched, found := official_climb.MatchClimb(parsed.Coords, official, official_climb.DefaultMatchRadiusM)
require.True(t, found)
assert.Equal(t, 1, matched.StartIndex)
assert.Equal(t, 2, matched.EndIndex)
@@ -82,10 +82,10 @@ func TestMatchClimbRejectsReversedEndpoints(t *testing.T) {
parsed := ridetest.MustRide("2km at 5% | 1km at -10%", ridetest.StartCoord(43.10, 5.10), ridetest.StartElevation(100), ridetest.Sampling(1000))
official := official_climb.OfficialClimb{
Name: "Reversed",
- StartCoord: parsed.Coords()[2],
- EndCoord: parsed.Coords()[1],
+ StartCoord: parsed.Coords[2],
+ EndCoord: parsed.Coords[1],
}
- _, found := official_climb.MatchClimb(parsed.Coords(), official, official_climb.DefaultMatchRadiusM)
+ _, found := official_climb.MatchClimb(parsed.Coords, official, official_climb.DefaultMatchRadiusM)
assert.False(t, found)
}
@@ -94,9 +94,9 @@ func TestMatchClimbRejectsEndpointOutsideRadius(t *testing.T) {
official := official_climb.OfficialClimb{
Name: "Too far",
StartCoord: geodist.Coord{Lat: 43.09, Lon: 5.09},
- EndCoord: parsed.Coords()[2],
+ EndCoord: parsed.Coords[2],
}
- _, found := official_climb.MatchClimb(parsed.Coords(), official, 10)
+ _, found := official_climb.MatchClimb(parsed.Coords, official, 10)
assert.False(t, found)
}
@@ -122,14 +122,14 @@ func TestMatchClimbsMatchesTwoLaps(t *testing.T) {
StartCoord: geodist.Coord{Lat: 43.10, Lon: 5.10},
EndCoord: geodist.Coord{Lat: 43.12, Lon: 5.12},
}
- matches := official_climb.MatchClimbs(parsed.Coords(), official, official_climb.DefaultMatchRadiusM)
+ matches := official_climb.MatchClimbs(parsed.Coords, official, official_climb.DefaultMatchRadiusM)
require.Len(t, matches, 2)
assert.Equal(t, 0, matches[0].StartIndex)
assert.Equal(t, 2, matches[0].EndIndex)
assert.Equal(t, 4, matches[1].StartIndex)
assert.Equal(t, 6, matches[1].EndIndex)
// Single-match helper still returns first occurrence for backward compatibility.
- single, found := official_climb.MatchClimb(parsed.Coords(), official, official_climb.DefaultMatchRadiusM)
+ single, found := official_climb.MatchClimb(parsed.Coords, official, official_climb.DefaultMatchRadiusM)
require.True(t, found)
assert.Equal(t, 0, single.StartIndex)
}
@@ -154,7 +154,7 @@ func TestMatchClimbsMatchesOnlyCompleteLaps(t *testing.T) {
StartCoord: geodist.Coord{Lat: 43.10, Lon: 5.10},
EndCoord: geodist.Coord{Lat: 43.12, Lon: 5.12},
}
- matches := official_climb.MatchClimbs(parsed.Coords(), official, official_climb.DefaultMatchRadiusM)
+ matches := official_climb.MatchClimbs(parsed.Coords, official, official_climb.DefaultMatchRadiusM)
require.Len(t, matches, 1)
assert.Equal(t, 3, matches[0].StartIndex)
assert.Equal(t, 5, matches[0].EndIndex)
@@ -177,7 +177,7 @@ func TestMatchClimbsPreservesDirectionAcrossLaps(t *testing.T) {
StartCoord: geodist.Coord{Lat: 43.10, Lon: 5.10},
EndCoord: geodist.Coord{Lat: 43.12, Lon: 5.12},
}
- matches := official_climb.MatchClimbs(parsed.Coords(), official, official_climb.DefaultMatchRadiusM)
+ matches := official_climb.MatchClimbs(parsed.Coords, official, official_climb.DefaultMatchRadiusM)
assert.Empty(t, matches)
}
@@ -203,7 +203,7 @@ func TestMatchClimbsClustersContiguousPoints(t *testing.T) {
StartCoord: geodist.Coord{Lat: 43.10, Lon: 5.10},
EndCoord: geodist.Coord{Lat: 43.12, Lon: 5.12},
}
- matches := official_climb.MatchClimbs(parsed.Coords(), official, official_climb.DefaultMatchRadiusM)
+ matches := official_climb.MatchClimbs(parsed.Coords, official, official_climb.DefaultMatchRadiusM)
require.Len(t, matches, 2)
assert.Equal(t, 0, matches[0].StartIndex)
assert.Equal(t, 4, matches[0].EndIndex)