package rideanalysis_test import ( "testing" "github.com/martinlehoux/biking_home/climb" "github.com/martinlehoux/biking_home/internal/ridetest" "github.com/martinlehoux/biking_home/official_climb" "github.com/martinlehoux/biking_home/ride" "github.com/martinlehoux/biking_home/rideanalysis" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestMergeClimbProfileMediansRecordedPassages(t *testing.T) { parsed, officialClimb := attemptRideForClimb(t) officialClimb.ID = 42 // Same trace 10 m higher: the merge must average the two passages, not pick one. shifted := ridetest.MustRide("1km at 14.7% | 1km at -6.7%", ridetest.StartCoord(43.61, 5.42), ridetest.StartElevation(310), ridetest.Sampling(1000), ridetest.StartTime(attemptRideStart)) analysis := rideanalysis.Analyze(parsed, nil, []official_climb.OfficialClimb{officialClimb}, official_climb.DefaultMatchPolicy()) aggregate := official_climb.AggregateAttempts(rideanalysis.Attempts(1, analysis, parsed)) profile := rideanalysis.MergeClimbProfile(officialClimb, []ride.Ride{parsed, shifted}, aggregate, official_climb.DefaultMatchPolicy(), climb.DefaultProfilePolicy()) assert.InDelta(t, 1000, profile.DistanceM, 0.01) require.NotEmpty(t, profile.Sections) assert.InDelta(t, 305, profile.Sections[0].StartElevationM, 1) lastSection := profile.Sections[len(profile.Sections)-1] assert.InDelta(t, 452, lastSection.EndElevationM, 2) assert.InDelta(t, 1000, lastSection.EndDistanceM, 0.01) } func TestMergeClimbProfileRouteKeepsRecordedPoints(t *testing.T) { parsed, officialClimb := attemptRideForClimb(t) officialClimb.ID = 42 analysis := rideanalysis.Analyze(parsed, nil, []official_climb.OfficialClimb{officialClimb}, official_climb.DefaultMatchPolicy()) aggregate := official_climb.AggregateAttempts(rideanalysis.Attempts(1, analysis, parsed)) profile := rideanalysis.MergeClimbProfile(officialClimb, []ride.Ride{parsed}, aggregate, official_climb.DefaultMatchPolicy(), climb.DefaultProfilePolicy()) // Full recorded precision: every matched segment point is present, not a fixed resample. require.Len(t, profile.Route, 2) assert.InDelta(t, parsed.Coords[0].Lon, profile.Route[0].Lon, 1e-9) assert.InDelta(t, parsed.Coords[0].Lat, profile.Route[0].Lat, 1e-9) assert.InDelta(t, parsed.Coords[1].Lon, profile.Route[1].Lon, 1e-9) assert.InDelta(t, parsed.Coords[1].Lat, profile.Route[1].Lat, 1e-9) } func TestMergeClimbProfileWithoutRides(t *testing.T) { _, officialClimb := attemptRideForClimb(t) profile := rideanalysis.MergeClimbProfile(officialClimb, nil, official_climb.Aggregate{DistanceM: 1000}, official_climb.DefaultMatchPolicy(), climb.DefaultProfilePolicy()) assert.Empty(t, profile.Sections) assert.Nil(t, profile.Route) }