-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscore.go
More file actions
120 lines (100 loc) · 2.21 KB
/
Copy pathscore.go
File metadata and controls
120 lines (100 loc) · 2.21 KB
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package rvglutils
import (
"sort"
"strings"
)
type ScoreSessionOpts struct {
IncludeAI bool
Interval int
ExtraPointsPerRace int
ExcludeRaces int
Handicap map[string]int
Multipliers map[string]float64
}
func (o *ScoreSessionOpts) Apply(opts *ScoreSessionOpts) {
if o != nil {
if opts != nil {
opts.IncludeAI = o.IncludeAI
if o.ExcludeRaces > 0 {
opts.ExcludeRaces = o.ExcludeRaces
}
if o.Interval > 0 {
opts.Interval = o.Interval
}
if o.Handicap != nil {
opts.Handicap = o.Handicap
}
if o.Multipliers != nil {
opts.Multipliers = o.Multipliers
}
}
}
}
type ScoreSessionOpt interface {
Apply(*ScoreSessionOpts)
}
type Score struct {
Player string
Points float64
}
func newScoreSessionOpts(opts ...ScoreSessionOpt) *ScoreSessionOpts {
o := &ScoreSessionOpts{}
for _, opt := range opts {
opt.Apply(o)
}
return o
}
func ScoreSession(session *Session, opts ...ScoreSessionOpt) []Score {
if session == nil || len(session.Races) == 0 {
return []Score{}
}
var (
o = newScoreSessionOpts(opts...)
tmp = make(map[string]float64)
lenRaces = len(session.Races)
)
if o.ExcludeRaces > lenRaces {
o.ExcludeRaces = lenRaces
} else if o.ExcludeRaces < 0 {
o.ExcludeRaces = 0
}
for k, v := range o.Handicap {
tmp[k] = float64(v)
}
for _, race := range session.Races[o.ExcludeRaces:] {
players := len(race.Results)
for _, result := range race.Results {
if !o.IncludeAI && (result.Car == result.Player || strings.ToUpper(result.Player) != result.Player) {
continue
}
points := float64(1 + o.ExtraPointsPerRace + players - result.Position)
if points < 0 {
points = 0
}
if o.Multipliers != nil {
if multiplier, ok := o.Multipliers[result.Car]; ok {
points *= multiplier
}
}
tmp[result.Player] += points
if tmp[result.Player] >= float64(o.Interval) && o.Interval > 0 {
tmp[result.Player] = 0
}
}
}
var (
score = make([]Score, len(tmp))
i = 0
)
for player, points := range tmp {
score[i] = Score{
Player: player,
Points: points,
}
i++
}
sort.Slice(score, func(i, j int) bool {
return score[i].Points > score[j].Points
})
return score
}