aboutsummaryrefslogtreecommitdiff
path: root/web/views.go
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 /web/views.go
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 'web/views.go')
-rw-r--r--web/views.go24
1 files changed, 13 insertions, 11 deletions
diff --git a/web/views.go b/web/views.go
index b3cab8b..4f769cc 100644
--- a/web/views.go
+++ b/web/views.go
@@ -5,6 +5,7 @@ import (
"net/url"
"time"
+ "github.com/martinlehoux/biking_home/climb"
"github.com/martinlehoux/biking_home/mountain_pass"
"github.com/martinlehoux/biking_home/official_climb"
"github.com/martinlehoux/biking_home/ride"
@@ -47,7 +48,7 @@ func buildAnalyticsPoints(items []ride.StoredRide) []AnalyticsPoint {
points := make([]AnalyticsPoint, 0, len(items))
for _, item := range items {
cotacol, ready := item.CotacolScore()
- if !ready || item.CotacolAlgorithmVersion() != ride.CotacolAlgorithmVersion || item.DistanceM <= 0 {
+ if !ready || item.CotacolAlgorithmVersion() != climb.CotacolAlgorithmVersion || item.DistanceM <= 0 {
continue
}
points = append(points, AnalyticsPoint{
@@ -286,7 +287,7 @@ func officialClimbCreateURL(id int64) string {
}
func buildRideDetailView(item ride.StoredRide, parsed ride.Ride, passes []mountain_pass.MountainPass, officialClimbs []official_climb.OfficialClimb, matchPolicy official_climb.MatchPolicy) RideDetailView {
- coords := parsed.Coords()
+ coords := parsed.Coords
coordinates := make([][]float64, len(coords))
for i, coordinate := range coords {
coordinates[i] = []float64{coordinate.Lon, coordinate.Lat}
@@ -327,9 +328,9 @@ func buildRideMapPasses(passes []mountain_pass.MountainPass) []RideMapPass {
}
func buildRideProfile(parsed ride.Ride, passes []mountain_pass.MountainPass, officialClimbs []official_climb.OfficialClimb, matchPolicy official_climb.MatchPolicy) RideProfile {
- coords := parsed.Coords()
- distances := parsed.Distances()
- elevations := parsed.Elevations()
+ coords := parsed.Coords
+ distances := parsed.Distances
+ elevations := parsed.Elevations
profile := RideProfile{
Points: make([]RideProfilePoint, len(coords)),
Climbs: make([]RideProfileClimb, 0),
@@ -346,12 +347,13 @@ func buildRideProfile(parsed ride.Ride, passes []mountain_pass.MountainPass, off
analysis := rideanalysis.Analyze(parsed, passes, officialClimbs, matchPolicy)
for _, analyzedClimb := range analysis.Climbs {
segment := analyzedClimb.Segment
+ topIndex, topElevationM := segment.Top()
climb := RideProfileClimb{
Index: len(profile.Climbs),
- StartKm: segment.StartDistanceM() / 1000,
- EndKm: segment.EndDistanceM() / 1000,
- TopKm: segment.TopDistanceM() / 1000,
- TopElevationM: segment.TopElevationM(),
+ StartKm: segment.Distances[0] / 1000,
+ EndKm: segment.Distances[len(segment.Distances)-1] / 1000,
+ TopKm: segment.Distances[topIndex] / 1000,
+ TopElevationM: topElevationM,
Name: analyzedClimb.Name,
Category: analyzedClimb.Category,
DistanceKm: analyzedClimb.DistanceM / 1000,
@@ -359,8 +361,8 @@ func buildRideProfile(parsed ride.Ride, passes []mountain_pass.MountainPass, off
Cotacol: analyzedClimb.Cotacol,
OfficialClimbID: analyzedClimb.OfficialClimbID,
OfficialName: analyzedClimb.OfficialName,
- StartIndex: segment.StartIndex(),
- EndIndex: segment.EndIndex(),
+ StartIndex: analyzedClimb.Interval.Start,
+ EndIndex: analyzedClimb.Interval.End,
}
profile.Climbs = append(profile.Climbs, climb)
}