aboutsummaryrefslogtreecommitdiff
path: root/ride/difficulty_test.go
blob: bd316b499c88715affe743b245c334fc41e434d1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

package ride_test

import (
	"math"
	"testing"

	"github.com/martinlehoux/biking_home/internal/ridetest"
	"github.com/martinlehoux/biking_home/ride"
	"github.com/stretchr/testify/assert"
)

func TestCotacolConstantClimb(t *testing.T) {
	r := ridetest.MustRide("2km at 7%")
	assert.InDelta(t, 98.0, ride.Cotacol(r), 1e-9)
}

func TestCotacolIgnoresDescent(t *testing.T) {
	r := ridetest.MustRide("2km at 7% | 2km at -7%")
	assert.InDelta(t, 98.0, ride.Cotacol(r), 1e-9)
}

func TestCotacolFlatIsZero(t *testing.T) {
	r := ridetest.MustRide("5km at 0%")
	assert.Zero(t, ride.Cotacol(r))
}

func TestCotacolSteepShortCountsMore(t *testing.T) {
	steep := ridetest.MustRide("0.5km at 14%")
	long := ridetest.MustRide("1km at 7%")
	assert.InDelta(t, 98.0, ride.Cotacol(steep), 1e-9)
	assert.InDelta(t, 49.0, ride.Cotacol(long), 1e-9)
}

func TestCotacolPrecisionInvariant(t *testing.T) {
	coarse := ridetest.MustRide("3km at 5%")
	fine := ridetest.MustRide("3km at 5%", ridetest.Sampling(50))
	assert.InDelta(t, ride.Cotacol(coarse), ride.Cotacol(fine), 1e-9)
}

func TestCotacolExampleRide(t *testing.T) {
	r, err := ride.ParseFile(parser, "../examples/2022-07-21.Pogacar.gpx")
	assert.NoError(t, err)
	assert.InDelta(t, 3049.0, ride.Cotacol(r), 1)
}

func TestCotacolClimbNotAtStart(t *testing.T) {
	r := ridetest.MustRide("1km at 0% | 2km at 7%")
	climbs := r.DetectClimbs(nil, ride.ClimbSlopeMinimum)
	assert.Len(t, climbs, 1)
	assert.InDelta(t, 98.0, climbs[0].DifficultyScore(), 1e-9)
}

func TestCategoryOfBoundaries(t *testing.T) {
	cases := []struct {
		score float64
		want  ride.Category
	}{
		{-5, ride.CategoryNo},
		{30, ride.CategoryNo},
		{35, ride.CategoryFour}, // 35 is the first floor, not below it
		{79, ride.CategoryFour},
		{80, ride.CategoryThree},
		{179, ride.CategoryThree},
		{180, ride.CategoryTwo},
		{249, ride.CategoryTwo},
		{250, ride.CategoryOne},
		{599, ride.CategoryOne},
		{600, ride.CategoryHC},
		{700, ride.CategoryHC},
		{math.NaN(), ride.CategoryHC}, // reaches no floor, like the original switch default
	}
	for _, c := range cases {
		assert.Equal(t, c.want, ride.CategoryOf(c.score), "score %v", c.score)
	}
	assert.Equal(t, "Cat 1", ride.CategoryOne.String())
	assert.Equal(t, "NO", ride.CategoryNo.String())
}

func TestCotacolHautacamClimbfinderReference(t *testing.T) {
	r, err := ride.ParseFile(parser, "../examples/2022-07-21.Pogacar.gpx")
	assert.NoError(t, err)
	climbs := r.DetectClimbs(nil, ride.ClimbSlopeMinimum)
	assert.Len(t, climbs, 6)
	hautacam := climbs[5]
	assert.InDelta(t, 128.6, hautacam.StartDistanceM()/1000, 0.1)
	assert.InDelta(t, 930.0, hautacam.DifficultyScore(), 10)
}