aboutsummaryrefslogtreecommitdiff
path: root/rideanalysis
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-08-23 12:12:59 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-08-23 12:12:59 +0200
commite5e7870eafbfc80f4668d2c0d0995149ddc2f60a (patch)
tree48d93921782aa41d5bc6fc699e1d3d01ec384131 /rideanalysis
parentd0875a51b2f07766b339b34a580d4e6e9fab348d (diff)
Match official climbs once per lap on looping rides
Official climb matching now returns all non-overlapping occurrences per ride instead of only the globally nearest pair. Each lap is detected by clustering contiguous points within the endpoint radius and pairing each start cluster with the first end cluster inside its window, preserving direction. The ride analysis aggregates all matches and sorts claimed ranges before excluding them from auto-detection. Fixes the case where a looping ride only showed one instance of a saved climb while the user expected one per repetition.
Diffstat (limited to 'rideanalysis')
-rw-r--r--rideanalysis/analysis.go9
1 files changed, 4 insertions, 5 deletions
diff --git a/rideanalysis/analysis.go b/rideanalysis/analysis.go
index fae64b8..90be629 100644
--- a/rideanalysis/analysis.go
+++ b/rideanalysis/analysis.go
@@ -39,13 +39,12 @@ func Analyze(parsed ride.Ride, passes []mountain_pass.MountainPass, officialClim
claimedClimbs := make([]AnalyzedClimb, 0)
claimedRanges := make([]ride.Range, 0)
for _, official := range officialClimbs {
- matched, found := official_climb.MatchClimb(parsed.Coords, official, matchPolicy.EndpointRadiusM)
- if !found {
- continue
+ for _, matched := range official_climb.MatchClimbs(parsed.Coords, official, matchPolicy.EndpointRadiusM) {
+ claimedRanges = append(claimedRanges, ride.Range{Start: matched.StartIndex, End: matched.EndIndex})
+ claimedClimbs = append(claimedClimbs, analyzedClimb(parsed, parsed.ClimbFromIndexes(matched.StartIndex, matched.EndIndex), official.Name, official.ID))
}
- claimedRanges = append(claimedRanges, ride.Range{Start: matched.StartIndex, End: matched.EndIndex})
- claimedClimbs = append(claimedClimbs, analyzedClimb(parsed, parsed.ClimbFromIndexes(matched.StartIndex, matched.EndIndex), official.Name, official.ID))
}
+ slices.SortFunc(claimedRanges, func(a, b ride.Range) int { return a.Start - b.Start })
for _, detectedClimb := range parsed.DetectClimbs(claimedRanges, ride.ClimbSlopeMinimum) {
displayClimb := detectedClimb
if matchedPass, ok := mountain_pass.MatchClimb(displayClimb, passes, passMatchRadiusM, passMatchElevationToleranceM); ok {