blob: 32646f16bc79396dd3e1ccafa12f90f442a81e60 [file] [log] [blame]
Sabina Leaverc5fd2772022-01-29 17:00:23 -08001package db
2
3import (
4 "database/sql"
Philipp Schrader30005e42022-03-06 13:53:58 -08005 "errors"
Sabina Leaverc5fd2772022-01-29 17:00:23 -08006 "fmt"
7
Philipp Schrader7365d322022-03-06 16:40:08 -08008 _ "github.com/jackc/pgx/stdlib"
Sabina Leaverc5fd2772022-01-29 17:00:23 -08009)
10
11type Database struct {
12 *sql.DB
13}
14
15type Match struct {
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080016 MatchNumber, Round int32
Philipp Schrader1e6c0a92022-02-27 23:30:57 -080017 CompLevel string
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080018 R1, R2, R3, B1, B2, B3 int32
Sabina Leaverc5fd2772022-01-29 17:00:23 -080019}
20
21type Stats struct {
Philipp Schraderfee07e12022-03-17 22:19:47 -070022 TeamNumber, MatchNumber int32
23 StartingQuadrant int32
24 AutoBallPickedUp [5]bool
25 // TODO(phil): Re-order auto and teleop fields so auto comes first.
Philipp Schraderfa45d742022-03-18 19:29:05 -070026 ShotsMissed, UpperGoalShots, LowerGoalShots int32
27 ShotsMissedAuto, UpperGoalAuto, LowerGoalAuto int32
28 PlayedDefense, DefenseReceivedScore int32
Philipp Schrader36df73a2022-03-17 23:27:24 -070029 // Climbing level:
30 // 0 -> "NoAttempt"
31 // 1 -> "Failed"
32 // 2 -> "FailedWithPlentyOfTime"
33 // 3 -> "Low"
34 // 4 -> "Medium"
35 // 5 -> "High"
36 // 6 -> "Transversal"
37 Climbing int32
Philipp Schraderfa45d742022-03-18 19:29:05 -070038 // Some non-numerical data that the scout felt worth noting.
39 Comment string
Philipp Schraderfae8a7e2022-03-13 22:51:54 -070040 // The username of the person who collected these statistics.
41 // "unknown" if submitted without logging in.
42 // Empty if the stats have not yet been collected.
43 CollectedBy string
Sabina Leaverc5fd2772022-01-29 17:00:23 -080044}
45
Alex Perry871eab92022-03-12 17:43:52 -080046type NotesData struct {
47 TeamNumber int32
48 Notes []string
49}
50
Yash Chainanibcd1bb32022-04-02 17:10:24 -070051type Ranking struct {
52 TeamNumber int
53 Losses, Wins, Ties int32
54 Rank, Dq int32
55}
56
Philipp Schrader7365d322022-03-06 16:40:08 -080057// Opens a database at the specified port on localhost. We currently don't
58// support connecting to databases on other hosts.
59func NewDatabase(user string, password string, port int) (*Database, error) {
Philipp Schrader83fc2722022-03-10 21:59:20 -080060 var err error
Sabina Leaverc5fd2772022-01-29 17:00:23 -080061 database := new(Database)
Philipp Schrader83fc2722022-03-10 21:59:20 -080062
Philipp Schrader7365d322022-03-06 16:40:08 -080063 psqlInfo := fmt.Sprintf("postgres://%s:%s@localhost:%d/postgres", user, password, port)
64 database.DB, err = sql.Open("pgx", psqlInfo)
65 if err != nil {
66 return nil, errors.New(fmt.Sprint("Failed to connect to postgres: ", err))
67 }
Philipp Schrader36df73a2022-03-17 23:27:24 -070068
Philipp Schrader83fc2722022-03-10 21:59:20 -080069 statement, err := database.Prepare("CREATE TABLE IF NOT EXISTS matches (" +
Philipp Schrader83fc2722022-03-10 21:59:20 -080070 "MatchNumber INTEGER, " +
71 "Round INTEGER, " +
Philipp Schrader7365d322022-03-06 16:40:08 -080072 "CompLevel VARCHAR, " +
Philipp Schrader83fc2722022-03-10 21:59:20 -080073 "R1 INTEGER, " +
74 "R2 INTEGER, " +
75 "R3 INTEGER, " +
76 "B1 INTEGER, " +
77 "B2 INTEGER, " +
Philipp Schrader45befdd2022-04-08 19:12:44 -070078 "B3 INTEGER, " +
79 "PRIMARY KEY (MatchNumber, Round, CompLevel))")
Philipp Schrader83fc2722022-03-10 21:59:20 -080080 if err != nil {
Philipp Schrader7365d322022-03-06 16:40:08 -080081 database.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -080082 return nil, errors.New(fmt.Sprint("Failed to prepare matches table creation: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -080083 }
Philipp Schrader83fc2722022-03-10 21:59:20 -080084 defer statement.Close()
85
86 _, err = statement.Exec()
87 if err != nil {
Philipp Schrader7365d322022-03-06 16:40:08 -080088 database.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -080089 return nil, errors.New(fmt.Sprint("Failed to create matches table: ", err))
90 }
91
92 statement, err = database.Prepare("CREATE TABLE IF NOT EXISTS team_match_stats (" +
Philipp Schrader7365d322022-03-06 16:40:08 -080093 "id SERIAL PRIMARY KEY, " +
Philipp Schrader83fc2722022-03-10 21:59:20 -080094 "TeamNumber INTEGER, " +
95 "MatchNumber INTEGER, " +
Philipp Schraderfee07e12022-03-17 22:19:47 -070096 "StartingQuadrant INTEGER, " +
97 "AutoBall1PickedUp BOOLEAN, " +
98 "AutoBall2PickedUp BOOLEAN, " +
99 "AutoBall3PickedUp BOOLEAN, " +
100 "AutoBall4PickedUp BOOLEAN, " +
101 "AutoBall5PickedUp BOOLEAN, " +
Philipp Schrader83fc2722022-03-10 21:59:20 -0800102 "ShotsMissed INTEGER, " +
103 "UpperGoalShots INTEGER, " +
104 "LowerGoalShots INTEGER, " +
105 "ShotsMissedAuto INTEGER, " +
106 "UpperGoalAuto INTEGER, " +
107 "LowerGoalAuto INTEGER, " +
108 "PlayedDefense INTEGER, " +
Philipp Schraderfa45d742022-03-18 19:29:05 -0700109 "DefenseReceivedScore INTEGER, " +
Philipp Schraderfae8a7e2022-03-13 22:51:54 -0700110 "Climbing INTEGER, " +
Philipp Schraderfa45d742022-03-18 19:29:05 -0700111 "Comment VARCHAR, " +
Philipp Schraderfae8a7e2022-03-13 22:51:54 -0700112 "CollectedBy VARCHAR)")
Philipp Schrader83fc2722022-03-10 21:59:20 -0800113 if err != nil {
Philipp Schrader7365d322022-03-06 16:40:08 -0800114 database.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800115 return nil, errors.New(fmt.Sprint("Failed to prepare stats table creation: ", err))
116 }
117 defer statement.Close()
118
119 _, err = statement.Exec()
120 if err != nil {
Philipp Schrader7365d322022-03-06 16:40:08 -0800121 database.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800122 return nil, errors.New(fmt.Sprint("Failed to create team_match_stats table: ", err))
123 }
124
Alex Perry871eab92022-03-12 17:43:52 -0800125 statement, err = database.Prepare("CREATE TABLE IF NOT EXISTS team_notes (" +
Philipp Schrader7365d322022-03-06 16:40:08 -0800126 "id SERIAL PRIMARY KEY, " +
Alex Perry871eab92022-03-12 17:43:52 -0800127 "TeamNumber INTEGER, " +
128 "Notes TEXT)")
129 if err != nil {
130 return nil, errors.New(fmt.Sprint("Failed to prepare notes table creation: ", err))
131 }
132 defer statement.Close()
133
134 _, err = statement.Exec()
135 if err != nil {
136 return nil, errors.New(fmt.Sprint("Failed to create notes table: ", err))
137 }
138
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700139 statement, err = database.Prepare("CREATE TABLE IF NOT EXISTS rankings (" +
140 "id SERIAL PRIMARY KEY, " +
141 "Losses INTEGER, " +
142 "Wins INTEGER, " +
143 "Ties INTEGER, " +
144 "Rank INTEGER, " +
145 "Dq INTEGER, " +
146 "TeamNumber INTEGER)")
147 if err != nil {
148 return nil, errors.New(fmt.Sprint("Failed to prepare rankings table creation: ", err))
149 }
150 defer statement.Close()
151
152 _, err = statement.Exec()
153 if err != nil {
154 return nil, errors.New(fmt.Sprint("Failed to create rankings table: ", err))
155 }
156
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800157 return database, nil
158}
159
160func (database *Database) Delete() error {
Philipp Schrader83fc2722022-03-10 21:59:20 -0800161 statement, err := database.Prepare("DROP TABLE IF EXISTS matches")
162 if err != nil {
163 return errors.New(fmt.Sprint("Failed to prepare dropping matches table: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800164 }
Philipp Schrader83fc2722022-03-10 21:59:20 -0800165 _, err = statement.Exec()
166 if err != nil {
167 return errors.New(fmt.Sprint("Failed to drop matches table: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800168 }
Philipp Schrader83fc2722022-03-10 21:59:20 -0800169
170 statement, err = database.Prepare("DROP TABLE IF EXISTS team_match_stats")
171 if err != nil {
172 return errors.New(fmt.Sprint("Failed to prepare dropping stats table: ", err))
173 }
174 _, err = statement.Exec()
175 if err != nil {
176 return errors.New(fmt.Sprint("Failed to drop stats table: ", err))
177 }
Alex Perry871eab92022-03-12 17:43:52 -0800178
179 statement, err = database.Prepare("DROP TABLE IF EXISTS team_notes")
180 if err != nil {
181 return errors.New(fmt.Sprint("Failed to prepare dropping notes table: ", err))
182 }
183 _, err = statement.Exec()
184 if err != nil {
185 return errors.New(fmt.Sprint("Failed to drop notes table: ", err))
186 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800187 return nil
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700188
189 statement, err = database.Prepare("DROP TABLE IF EXISTS rankings")
190 if err != nil {
191 return errors.New(fmt.Sprint("Failed to prepare dropping rankings table: ", err))
192 }
193 _, err = statement.Exec()
194 if err != nil {
195 return errors.New(fmt.Sprint("Failed to drop rankings table: ", err))
196 }
197 return nil
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800198}
199
200// This function will also populate the Stats table with six empty rows every time a match is added
201func (database *Database) AddToMatch(m Match) error {
Philipp Schradercd12c952022-04-08 18:58:49 -0700202 statement, err := database.Prepare("INSERT INTO matches(" +
203 "MatchNumber, Round, CompLevel, " +
204 "R1, R2, R3, B1, B2, B3) " +
205 "VALUES (" +
206 "$1, $2, $3, " +
Philipp Schraderfe583842022-04-08 19:47:07 -0700207 "$4, $5, $6, $7, $8, $9) " +
208 "ON CONFLICT (MatchNumber, Round, CompLevel) DO UPDATE SET " +
209 "R1 = EXCLUDED.R1, R2 = EXCLUDED.R2, R3 = EXCLUDED.R3, " +
210 "B1 = EXCLUDED.B1, B2 = EXCLUDED.B2, B3 = EXCLUDED.B3")
Philipp Schradercd12c952022-04-08 18:58:49 -0700211 if err != nil {
212 return errors.New(fmt.Sprint("Failed to prepare insertion into match database: ", err))
213 }
214 defer statement.Close()
215
216 _, err = statement.Exec(m.MatchNumber, m.Round, m.CompLevel,
217 m.R1, m.R2, m.R3, m.B1, m.B2, m.B3)
218 if err != nil {
219 return errors.New(fmt.Sprint("Failed to insert into match database: ", err))
220 }
221 return nil
222}
223
224func (database *Database) AddToStats(s Stats) error {
225 matches, err := database.QueryMatches(s.TeamNumber)
226 if err != nil {
227 return err
228 }
229 foundMatch := false
230 for _, match := range matches {
231 if match.MatchNumber == s.MatchNumber {
232 foundMatch = true
233 break
234 }
235 }
236 if !foundMatch {
237 return errors.New(fmt.Sprint(
238 "Failed to find team ", s.TeamNumber,
239 " in match ", s.MatchNumber, " in the schedule."))
240 }
241
Philipp Schrader83fc2722022-03-10 21:59:20 -0800242 statement, err := database.Prepare("INSERT INTO team_match_stats(" +
243 "TeamNumber, MatchNumber, " +
Philipp Schraderfee07e12022-03-17 22:19:47 -0700244 "StartingQuadrant, " +
245 "AutoBall1PickedUp, AutoBall2PickedUp, AutoBall3PickedUp, " +
246 "AutoBall4PickedUp, AutoBall5PickedUp, " +
Philipp Schrader83fc2722022-03-10 21:59:20 -0800247 "ShotsMissed, UpperGoalShots, LowerGoalShots, " +
248 "ShotsMissedAuto, UpperGoalAuto, LowerGoalAuto, " +
Philipp Schraderfa45d742022-03-18 19:29:05 -0700249 "PlayedDefense, DefenseReceivedScore, Climbing, " +
250 "Comment, CollectedBy) " +
Philipp Schrader83fc2722022-03-10 21:59:20 -0800251 "VALUES (" +
Philipp Schrader7365d322022-03-06 16:40:08 -0800252 "$1, $2, " +
Philipp Schraderfee07e12022-03-17 22:19:47 -0700253 "$3, " +
254 "$4, $5, $6, " +
255 "$7, $8, " +
256 "$9, $10, $11, " +
257 "$12, $13, $14, " +
Philipp Schraderfa45d742022-03-18 19:29:05 -0700258 "$15, $16, $17, " +
Philipp Schradercd12c952022-04-08 18:58:49 -0700259 "$18, $19)")
Philipp Schrader83fc2722022-03-10 21:59:20 -0800260 if err != nil {
261 return errors.New(fmt.Sprint("Failed to prepare stats update statement: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800262 }
Philipp Schrader83fc2722022-03-10 21:59:20 -0800263 defer statement.Close()
264
Philipp Schradercd12c952022-04-08 18:58:49 -0700265 _, err = statement.Exec(
Philipp Schraderfee07e12022-03-17 22:19:47 -0700266 s.TeamNumber, s.MatchNumber,
267 s.StartingQuadrant,
268 s.AutoBallPickedUp[0], s.AutoBallPickedUp[1], s.AutoBallPickedUp[2],
269 s.AutoBallPickedUp[3], s.AutoBallPickedUp[4],
Philipp Schrader83fc2722022-03-10 21:59:20 -0800270 s.ShotsMissed, s.UpperGoalShots, s.LowerGoalShots,
271 s.ShotsMissedAuto, s.UpperGoalAuto, s.LowerGoalAuto,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700272 s.PlayedDefense, s.DefenseReceivedScore, s.Climbing,
Philipp Schradercd12c952022-04-08 18:58:49 -0700273 s.Comment, s.CollectedBy)
Philipp Schrader83fc2722022-03-10 21:59:20 -0800274 if err != nil {
275 return errors.New(fmt.Sprint("Failed to update stats database: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800276 }
Philipp Schrader83fc2722022-03-10 21:59:20 -0800277
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800278 return nil
279}
280
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700281func (database *Database) AddOrUpdateRankings(r Ranking) error {
282 statement, err := database.Prepare("UPDATE rankings SET " +
283 "Losses = $1, Wins = $2, Ties = $3, " +
284 "Rank = $4, Dq = $5, TeamNumber = $6 " +
285 "WHERE TeamNumber = $6")
286 if err != nil {
287 return errors.New(fmt.Sprint("Failed to prepare rankings database update: ", err))
288 }
289 defer statement.Close()
290
291 result, err := statement.Exec(r.Losses, r.Wins, r.Ties,
292 r.Rank, r.Dq, r.TeamNumber)
293 if err != nil {
294 return errors.New(fmt.Sprint("Failed to update rankings database: ", err))
295 }
296
297 numRowsAffected, err := result.RowsAffected()
298 if err != nil {
299 return errors.New(fmt.Sprint("Failed to query rows affected: ", err))
300 }
301 if numRowsAffected == 0 {
302 statement, err := database.Prepare("INSERT INTO rankings(" +
303 "Losses, Wins, Ties, " +
304 "Rank, Dq, TeamNumber) " +
305 "VALUES (" +
306 "$1, $2, $3, " +
307 "$4, $5, $6)")
308 if err != nil {
309 return errors.New(fmt.Sprint("Failed to prepare insertion into rankings database: ", err))
310 }
311 defer statement.Close()
312
313 _, err = statement.Exec(r.Losses, r.Wins, r.Ties,
314 r.Rank, r.Dq, r.TeamNumber)
315 if err != nil {
316 return errors.New(fmt.Sprint("Failed to insert into rankings database: ", err))
317 }
318 }
319
320 return nil
321}
322
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800323func (database *Database) ReturnMatches() ([]Match, error) {
Philipp Schrader83fc2722022-03-10 21:59:20 -0800324 rows, err := database.Query("SELECT * FROM matches")
325 if err != nil {
326 return nil, errors.New(fmt.Sprint("Failed to select from matches: ", err))
327 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800328 defer rows.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800329
330 matches := make([]Match, 0)
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800331 for rows.Next() {
332 var match Match
Philipp Schrader45befdd2022-04-08 19:12:44 -0700333 err := rows.Scan(&match.MatchNumber, &match.Round, &match.CompLevel,
Philipp Schradercd12c952022-04-08 18:58:49 -0700334 &match.R1, &match.R2, &match.R3, &match.B1, &match.B2, &match.B3)
Philipp Schrader83fc2722022-03-10 21:59:20 -0800335 if err != nil {
336 return nil, errors.New(fmt.Sprint("Failed to scan from matches: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800337 }
338 matches = append(matches, match)
339 }
340 return matches, nil
341}
342
343func (database *Database) ReturnStats() ([]Stats, error) {
Philipp Schrader83fc2722022-03-10 21:59:20 -0800344 rows, err := database.Query("SELECT * FROM team_match_stats")
345 if err != nil {
346 return nil, errors.New(fmt.Sprint("Failed to SELECT * FROM team_match_stats: ", err))
Philipp Schrader30005e42022-03-06 13:53:58 -0800347 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800348 defer rows.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800349
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800350 teams := make([]Stats, 0)
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800351 for rows.Next() {
352 var team Stats
Philipp Schrader83fc2722022-03-10 21:59:20 -0800353 var id int
Philipp Schraderfee07e12022-03-17 22:19:47 -0700354 err = rows.Scan(&id,
355 &team.TeamNumber, &team.MatchNumber,
356 &team.StartingQuadrant,
357 &team.AutoBallPickedUp[0], &team.AutoBallPickedUp[1], &team.AutoBallPickedUp[2],
358 &team.AutoBallPickedUp[3], &team.AutoBallPickedUp[4],
Philipp Schrader83fc2722022-03-10 21:59:20 -0800359 &team.ShotsMissed, &team.UpperGoalShots, &team.LowerGoalShots,
360 &team.ShotsMissedAuto, &team.UpperGoalAuto, &team.LowerGoalAuto,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700361 &team.PlayedDefense, &team.DefenseReceivedScore, &team.Climbing,
362 &team.Comment, &team.CollectedBy)
Philipp Schrader83fc2722022-03-10 21:59:20 -0800363 if err != nil {
364 return nil, errors.New(fmt.Sprint("Failed to scan from stats: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800365 }
366 teams = append(teams, team)
367 }
368 return teams, nil
369}
370
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700371func (database *Database) ReturnRankings() ([]Ranking, error) {
372 rows, err := database.Query("SELECT * FROM rankings")
373 if err != nil {
374 return nil, errors.New(fmt.Sprint("Failed to SELECT * FROM rankings: ", err))
375 }
376 defer rows.Close()
377
378 all_rankings := make([]Ranking, 0)
379 for rows.Next() {
380 var ranking Ranking
381 var id int
382 err = rows.Scan(&id,
383 &ranking.Losses, &ranking.Wins, &ranking.Ties,
384 &ranking.Rank, &ranking.Dq, &ranking.TeamNumber)
385 if err != nil {
386 return nil, errors.New(fmt.Sprint("Failed to scan from rankings: ", err))
387 }
388 all_rankings = append(all_rankings, ranking)
389 }
390 return all_rankings, nil
391}
392
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800393func (database *Database) QueryMatches(teamNumber_ int32) ([]Match, error) {
Philipp Schrader83fc2722022-03-10 21:59:20 -0800394 rows, err := database.Query("SELECT * FROM matches WHERE "+
Philipp Schrader7365d322022-03-06 16:40:08 -0800395 "R1 = $1 OR R2 = $2 OR R3 = $3 OR B1 = $4 OR B2 = $5 OR B3 = $6",
Philipp Schrader83fc2722022-03-10 21:59:20 -0800396 teamNumber_, teamNumber_, teamNumber_, teamNumber_, teamNumber_, teamNumber_)
397 if err != nil {
398 return nil, errors.New(fmt.Sprint("Failed to select from matches for team: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800399 }
400 defer rows.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800401
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800402 var matches []Match
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800403 for rows.Next() {
404 var match Match
Philipp Schrader45befdd2022-04-08 19:12:44 -0700405 err = rows.Scan(&match.MatchNumber, &match.Round, &match.CompLevel,
Philipp Schradercd12c952022-04-08 18:58:49 -0700406 &match.R1, &match.R2, &match.R3, &match.B1, &match.B2, &match.B3)
Philipp Schrader83fc2722022-03-10 21:59:20 -0800407 if err != nil {
408 return nil, errors.New(fmt.Sprint("Failed to scan from matches: ", err))
409 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800410 matches = append(matches, match)
411 }
412 return matches, nil
413}
414
415func (database *Database) QueryStats(teamNumber_ int) ([]Stats, error) {
Philipp Schrader7365d322022-03-06 16:40:08 -0800416 rows, err := database.Query("SELECT * FROM team_match_stats WHERE TeamNumber = $1", teamNumber_)
Philipp Schrader83fc2722022-03-10 21:59:20 -0800417 if err != nil {
418 return nil, errors.New(fmt.Sprint("Failed to select from stats: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800419 }
420 defer rows.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800421
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800422 var teams []Stats
423 for rows.Next() {
424 var team Stats
425 var id int
Philipp Schraderfee07e12022-03-17 22:19:47 -0700426 err = rows.Scan(&id,
427 &team.TeamNumber, &team.MatchNumber,
428 &team.StartingQuadrant,
429 &team.AutoBallPickedUp[0], &team.AutoBallPickedUp[1], &team.AutoBallPickedUp[2],
430 &team.AutoBallPickedUp[3], &team.AutoBallPickedUp[4],
Philipp Schrader83fc2722022-03-10 21:59:20 -0800431 &team.ShotsMissed, &team.UpperGoalShots, &team.LowerGoalShots,
432 &team.ShotsMissedAuto, &team.UpperGoalAuto, &team.LowerGoalAuto,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700433 &team.PlayedDefense, &team.DefenseReceivedScore, &team.Climbing,
434 &team.Comment, &team.CollectedBy)
Philipp Schrader83fc2722022-03-10 21:59:20 -0800435 if err != nil {
436 return nil, errors.New(fmt.Sprint("Failed to scan from stats: ", err))
437 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800438 teams = append(teams, team)
439 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800440 return teams, nil
441}
Alex Perry871eab92022-03-12 17:43:52 -0800442
443func (database *Database) QueryNotes(TeamNumber int32) (NotesData, error) {
Philipp Schrader7365d322022-03-06 16:40:08 -0800444 rows, err := database.Query("SELECT * FROM team_notes WHERE TeamNumber = $1", TeamNumber)
Alex Perry871eab92022-03-12 17:43:52 -0800445 if err != nil {
446 return NotesData{}, errors.New(fmt.Sprint("Failed to select from notes: ", err))
447 }
448 defer rows.Close()
449
450 var notes []string
451 for rows.Next() {
452 var id int32
453 var data string
454 err = rows.Scan(&id, &TeamNumber, &data)
455 if err != nil {
456 return NotesData{}, errors.New(fmt.Sprint("Failed to scan from notes: ", err))
457 }
458 notes = append(notes, data)
459 }
460 return NotesData{TeamNumber, notes}, nil
461}
462
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700463func (database *Database) QueryRankings(TeamNumber int) ([]Ranking, error) {
464 rows, err := database.Query("SELECT * FROM rankings WHERE TeamNumber = $1", TeamNumber)
465 if err != nil {
466 return nil, errors.New(fmt.Sprint("Failed to select from rankings: ", err))
467 }
468 defer rows.Close()
469
470 all_rankings := make([]Ranking, 0)
471 for rows.Next() {
472 var ranking Ranking
473 var id int
474 err = rows.Scan(&id,
475 &ranking.Losses, &ranking.Wins, &ranking.Ties,
476 &ranking.Rank, &ranking.Dq, &ranking.TeamNumber)
477 if err != nil {
478 return nil, errors.New(fmt.Sprint("Failed to scan from rankings: ", err))
479 }
480 all_rankings = append(all_rankings, ranking)
481 }
482 return all_rankings, nil
483}
484
Alex Perry871eab92022-03-12 17:43:52 -0800485func (database *Database) AddNotes(data NotesData) error {
486 if len(data.Notes) > 1 {
487 return errors.New("Can only insert one row of notes at a time")
488 }
489 statement, err := database.Prepare("INSERT INTO " +
490 "team_notes(TeamNumber, Notes)" +
Philipp Schrader7365d322022-03-06 16:40:08 -0800491 "VALUES ($1, $2)")
Alex Perry871eab92022-03-12 17:43:52 -0800492 if err != nil {
493 return errors.New(fmt.Sprint("Failed to prepare insertion into notes table: ", err))
494 }
495 defer statement.Close()
496
497 _, err = statement.Exec(data.TeamNumber, data.Notes[0])
498 if err != nil {
499 return errors.New(fmt.Sprint("Failed to insert into Notes database: ", err))
500 }
501 return nil
502}