aboutsummaryrefslogtreecommitdiff
path: root/official_climb/list_test.go
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-09-13 21:55:59 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-09-13 21:55:59 +0200
commite3d0beee5be3dd2854b0f4fc10905a4fcdc08f47 (patch)
treeec8234d3442c498ec170b6444bd2cfae5b29a476 /official_climb/list_test.go
parentdb4d2b40895db41ce188549f49a6f277ba95c890 (diff)
Persist official climb attempts with climbs pages
Record one attempt row per (ride, climb, occurrence) when a ride detail loads, snapshotting distance, elevation gain, slope, cotacol and attempt timestamps; a climbs-backfill CLI command seeds all existing rides. New /climbs list page aggregates attempts (medians computed in Go, best time as min duration) with sortable columns, and /climbs/{id} shows the median scalar stats, a median normalized elevation profile (50 steps over each attempt's own length), the full-precision recorded route of the median-distance attempt on an OSM map, and every attempt with time at second precision.
Diffstat (limited to 'official_climb/list_test.go')
-rw-r--r--official_climb/list_test.go52
1 files changed, 52 insertions, 0 deletions
diff --git a/official_climb/list_test.go b/official_climb/list_test.go
new file mode 100644
index 0000000..6a65f80
--- /dev/null
+++ b/official_climb/list_test.go
@@ -0,0 +1,52 @@
+package official_climb_test
+
+import (
+ "testing"
+
+ "github.com/martinlehoux/biking_home/internal/dbtest"
+ "github.com/martinlehoux/biking_home/official_climb"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestListWithAggregatesMediansAndUnridden(t *testing.T) {
+ db := dbtest.New(t)
+ unridden, err := official_climb.Create(db, official_climb.OfficialClimb{Name: "Col Fantome", StartCoord: coord(43.9, 5.9), EndCoord: coord(43.92, 5.92)})
+ require.NoError(t, err)
+ climbed, err := official_climb.Create(db, official_climb.OfficialClimb{Name: "Col Fréquente", StartCoord: coord(43.6, 5.4), EndCoord: coord(43.62, 5.42)})
+ require.NoError(t, err)
+ rideID := insertRide(t, db)
+
+ attempt := attemptFixture(rideID, climbed.ID, 0)
+ attempt.DistanceM = 3000
+ attempt.Cotacol = 80
+ medianAttempt := attempt
+ medianAttempt.Occurrence = 1
+ medianAttempt.DistanceM = 3200
+ medianAttempt.Cotacol = 84
+ outlier := attempt
+ outlier.Occurrence = 2
+ outlier.DistanceM = 9000
+ outlier.Cotacol = 500
+ require.NoError(t, official_climb.ReplaceRideAttempts(db, rideID, []official_climb.Attempt{attempt, medianAttempt, outlier}))
+
+ climbs, err := official_climb.ListWithAggregates(db)
+ require.NoError(t, err)
+ require.Len(t, climbs, 2)
+
+ byID := make(map[int64]official_climb.ListedClimb)
+ for _, climb := range climbs {
+ byID[climb.ID] = climb
+ }
+ frequente := byID[climbed.ID]
+ assert.Equal(t, 3, frequente.Attempts)
+ assert.Equal(t, 3200.0, frequente.DistanceM, "median ignores the 9 km outlier")
+ assert.Equal(t, 84.0, frequente.Cotacol)
+ assert.True(t, frequente.HasBest)
+ assert.Positive(t, frequente.BestDurationS)
+
+ fantome := byID[unridden.ID]
+ assert.Equal(t, 0, fantome.Attempts)
+ assert.Equal(t, 0.0, fantome.DistanceM)
+ assert.False(t, fantome.HasBest)
+}