-
Notifications
You must be signed in to change notification settings - Fork 0
/
models.go
226 lines (200 loc) · 5.72 KB
/
models.go
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
package main
import (
"container/list"
"database/sql"
"errors"
"fmt"
"log"
)
const (
DEFAULT_PLAYER_RATING = 5.0
PLAYER_ALREADY_EXISTS_ERROR = "column identifier is not unique"
)
type RootError struct {
Error JsonError `json:"error"`
}
type JsonError struct {
UserMessage string `json:"msg"`
TechMessage string `json:"tech_msg"`
}
type Club struct {
Identifier int `json:"identifier"`
Name string `json:"name"`
League string `json:"league"`
Country string `json:"country"`
Stars float64 `json:"stars"`
}
func (g Club) FetchAll() ([]Club, error) {
rows, err := DB.Query("select id, name, league, country, stars from clubs")
if err != nil {
return []Club{}, err
}
result := list.New()
for rows.Next() {
var club Club
if err := rows.Scan(&club.Identifier, &club.Name, &club.League, &club.Country, &club.Stars); err != nil {
log.Println(err)
return []Club{}, err
} else {
result.PushBack(club)
}
}
if err := rows.Err(); err != nil {
log.Println(err)
return []Club{}, err
}
clubs := make([]Club, result.Len())
for e, i := result.Front(), 0; e != nil; e, i = e.Next(), i+1 {
clubs[i] = e.Value.(Club)
}
return clubs, nil
}
type Player struct {
Identifier string `json:"identifier"`
Name string `json:"name"`
Rating float64 `json:"rating"`
Played int `json:"player"`
Wins int `json:"wins"`
Losses int `json:"losses"`
Ties int `json:"ties"`
}
func (p Player) Save() error {
_, err := DB.Exec(`insert into players (identifier, name, rating, played, wins, losses, ties) values (?, ?, ?, ?, ?, ?, ?);`,
p.Identifier, p.Name, p.Rating, p.Played, p.Wins, p.Losses, p.Ties)
return err
}
func (p Player) UpdateRating() error {
_, err := DB.Exec(`update players set rating = ? where identifier = ?;`, p.Rating, p.Identifier)
return err
}
func (p Player) FetchAll() ([]Player, error) {
rows, err := DB.Query(`select identifier, name, rating from players order by rating desc;`)
if err != nil {
return []Player{}, err
}
result := list.New()
for rows.Next() {
var p Player
if err := rows.Scan(&p.Identifier, &p.Name, &p.Rating); err != nil {
log.Println(err)
return []Player{}, err
} else {
result.PushBack(p)
}
}
if err := rows.Err(); err != nil {
log.Println(err)
return []Player{}, err
}
players := make([]Player, result.Len())
for e, i := result.Front(), 0; e != nil; e, i = e.Next(), i+1 {
players[i] = e.Value.(Player)
}
return players, nil
}
func (p Player) FetchByIdentifier(id string) (Player, error) {
row := DB.QueryRow(`select identifier, name, rating from players where identifier=?;`, id)
err := row.Scan(&p.Identifier, &p.Name, &p.Rating)
// sorry, being lazy and not handling empty result and DB
// failure differently (assuming empty result)
if err != nil {
return p, err
}
return p, nil
}
type Match struct {
HomeTeam []Player `json:"homeTeam"`
AwayTeam []Player `json:"awayTeam"`
HomeClub Club `json:"homeClub"`
AwayClub Club `json:"awayClub"`
HomeScore int `json:"homeScore"`
AwayScore int `json:"awayScore"`
Timestamp string `json:"timestamp"`
}
func (m Match) Save() (int64, error) {
homeTeamId, err := m.determineTeamId(m.HomeTeam)
if err != nil {
return -1, err
}
awayTeamId, err := m.determineTeamId(m.AwayTeam)
if err != nil {
return -1, err
}
res, err := DB.Exec(`insert into matches (home_team_id, away_team_id, home_club_id, away_club_id, home_score, away_score, timestamp) values (?, ?, ?, ?, ?, ?, ?);`,
homeTeamId, awayTeamId, m.HomeClub.Identifier, m.AwayClub.Identifier, m.HomeScore, m.AwayScore, m.Timestamp)
if err != nil {
return -1, err
}
switch {
case m.HomeScore > m.AwayScore:
m.HomeTeam[0].Rating += 0.2
m.AwayTeam[0].Rating -= 0.2
case m.HomeScore < m.AwayScore:
m.HomeTeam[0].Rating -= 0.2
m.AwayTeam[0].Rating += 0.2
}
m.HomeTeam[0].UpdateRating()
m.AwayTeam[0].UpdateRating()
return res.LastInsertId()
}
// Finds the team id for the given set of player or creates a team if
// they haven't played together before
func (m Match) determineTeamId(players []Player) (int64, error) {
teamSize := len(players)
// this is somewhat hackish but unfortunately I haven't
// figured out a more elegant way of doing this in the
// database yet
switch {
case teamSize == 0:
return -1, errors.New("No team members defined.")
case teamSize == 1:
return m.determineTeamOfOne(players[0])
case teamSize == 2:
return m.determineTeamOfTwo(players)
case teamSize == 3:
return m.determineTeamOfThree(players)
}
return -1, errors.New(fmt.Sprintf("Too many players in team (%d). Max supported is 3.", teamSize))
}
func (m Match) determineTeamOfOne(player Player) (int64, error) {
var teamId int64
row := DB.QueryRow(`select t.team_id from teams_1 t join players p where t.player_id = p.id and p.identifier = ?;`, player.Identifier)
err := row.Scan(&teamId)
switch {
case err == sql.ErrNoRows:
return m.createTeamOfOne(player)
case err != nil:
return -1, err
default:
return teamId, nil
}
}
func (m Match) createTeamOfOne(player Player) (int64, error) {
tx, err := DB.Begin()
if err != nil {
return -1, err
}
res, err := tx.Exec(`insert into teams (type) values ("ONE");`)
if err != nil {
tx.Rollback()
return -1, err
}
teamId, err := res.LastInsertId()
if err != nil {
tx.Rollback()
return teamId, err
}
_, err = tx.Exec(`insert into teams_1 (team_id, player_id) values (?, (select id from players where identifier = ?));`, teamId, player.Identifier)
if err != nil {
tx.Rollback()
return teamId, err
}
err = tx.Commit()
return teamId, err
}
func (m Match) determineTeamOfTwo(players []Player) (int64, error) {
return -1, nil
}
func (m Match) determineTeamOfThree(players []Player) (int64, error) {
return -1, nil
}