blob: d3faa58c8898713b81a2f183e3c2a51bea0e931c [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 // Each of these variables holds the matchID of the corresponding Stats row
20 r1ID, r2ID, r3ID, b1ID, b2ID, b3ID int
21}
22
23type Stats struct {
Philipp Schraderfee07e12022-03-17 22:19:47 -070024 TeamNumber, MatchNumber int32
25 StartingQuadrant int32
26 AutoBallPickedUp [5]bool
27 // TODO(phil): Re-order auto and teleop fields so auto comes first.
Philipp Schraderfa45d742022-03-18 19:29:05 -070028 ShotsMissed, UpperGoalShots, LowerGoalShots int32
29 ShotsMissedAuto, UpperGoalAuto, LowerGoalAuto int32
30 PlayedDefense, DefenseReceivedScore int32
Philipp Schrader36df73a2022-03-17 23:27:24 -070031 // Climbing level:
32 // 0 -> "NoAttempt"
33 // 1 -> "Failed"
34 // 2 -> "FailedWithPlentyOfTime"
35 // 3 -> "Low"
36 // 4 -> "Medium"
37 // 5 -> "High"
38 // 6 -> "Transversal"
39 Climbing int32
Philipp Schraderfa45d742022-03-18 19:29:05 -070040 // Some non-numerical data that the scout felt worth noting.
41 Comment string
Philipp Schraderfae8a7e2022-03-13 22:51:54 -070042 // The username of the person who collected these statistics.
43 // "unknown" if submitted without logging in.
44 // Empty if the stats have not yet been collected.
45 CollectedBy string
Sabina Leaverc5fd2772022-01-29 17:00:23 -080046}
47
Alex Perry871eab92022-03-12 17:43:52 -080048type NotesData struct {
49 TeamNumber int32
50 Notes []string
51}
52
Yash Chainanibcd1bb32022-04-02 17:10:24 -070053type Ranking struct {
54 TeamNumber int
55 Losses, Wins, Ties int32
56 Rank, Dq int32
57}
58
Philipp Schrader7365d322022-03-06 16:40:08 -080059// Opens a database at the specified port on localhost. We currently don't
60// support connecting to databases on other hosts.
61func NewDatabase(user string, password string, port int) (*Database, error) {
Philipp Schrader83fc2722022-03-10 21:59:20 -080062 var err error
Sabina Leaverc5fd2772022-01-29 17:00:23 -080063 database := new(Database)
Philipp Schrader83fc2722022-03-10 21:59:20 -080064
Philipp Schrader7365d322022-03-06 16:40:08 -080065 psqlInfo := fmt.Sprintf("postgres://%s:%s@localhost:%d/postgres", user, password, port)
66 database.DB, err = sql.Open("pgx", psqlInfo)
67 if err != nil {
68 return nil, errors.New(fmt.Sprint("Failed to connect to postgres: ", err))
69 }
Philipp Schrader36df73a2022-03-17 23:27:24 -070070
Philipp Schrader83fc2722022-03-10 21:59:20 -080071 statement, err := database.Prepare("CREATE TABLE IF NOT EXISTS matches (" +
Philipp Schrader7365d322022-03-06 16:40:08 -080072 "id SERIAL PRIMARY KEY, " +
Philipp Schrader83fc2722022-03-10 21:59:20 -080073 "MatchNumber INTEGER, " +
74 "Round INTEGER, " +
Philipp Schrader7365d322022-03-06 16:40:08 -080075 "CompLevel VARCHAR, " +
Philipp Schrader83fc2722022-03-10 21:59:20 -080076 "R1 INTEGER, " +
77 "R2 INTEGER, " +
78 "R3 INTEGER, " +
79 "B1 INTEGER, " +
80 "B2 INTEGER, " +
81 "B3 INTEGER, " +
82 "r1ID INTEGER, " +
83 "r2ID INTEGER, " +
84 "r3ID INTEGER, " +
85 "b1ID INTEGER, " +
86 "b2ID INTEGER, " +
87 "b3ID INTEGER)")
88 if err != nil {
Philipp Schrader7365d322022-03-06 16:40:08 -080089 database.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -080090 return nil, errors.New(fmt.Sprint("Failed to prepare matches table creation: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -080091 }
Philipp Schrader83fc2722022-03-10 21:59:20 -080092 defer statement.Close()
93
94 _, err = statement.Exec()
95 if err != nil {
Philipp Schrader7365d322022-03-06 16:40:08 -080096 database.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -080097 return nil, errors.New(fmt.Sprint("Failed to create matches table: ", err))
98 }
99
100 statement, err = database.Prepare("CREATE TABLE IF NOT EXISTS team_match_stats (" +
Philipp Schrader7365d322022-03-06 16:40:08 -0800101 "id SERIAL PRIMARY KEY, " +
Philipp Schrader83fc2722022-03-10 21:59:20 -0800102 "TeamNumber INTEGER, " +
103 "MatchNumber INTEGER, " +
Philipp Schraderfee07e12022-03-17 22:19:47 -0700104 "StartingQuadrant INTEGER, " +
105 "AutoBall1PickedUp BOOLEAN, " +
106 "AutoBall2PickedUp BOOLEAN, " +
107 "AutoBall3PickedUp BOOLEAN, " +
108 "AutoBall4PickedUp BOOLEAN, " +
109 "AutoBall5PickedUp BOOLEAN, " +
Philipp Schrader83fc2722022-03-10 21:59:20 -0800110 "ShotsMissed INTEGER, " +
111 "UpperGoalShots INTEGER, " +
112 "LowerGoalShots INTEGER, " +
113 "ShotsMissedAuto INTEGER, " +
114 "UpperGoalAuto INTEGER, " +
115 "LowerGoalAuto INTEGER, " +
116 "PlayedDefense INTEGER, " +
Philipp Schraderfa45d742022-03-18 19:29:05 -0700117 "DefenseReceivedScore INTEGER, " +
Philipp Schraderfae8a7e2022-03-13 22:51:54 -0700118 "Climbing INTEGER, " +
Philipp Schraderfa45d742022-03-18 19:29:05 -0700119 "Comment VARCHAR, " +
Philipp Schraderfae8a7e2022-03-13 22:51:54 -0700120 "CollectedBy VARCHAR)")
Philipp Schrader83fc2722022-03-10 21:59:20 -0800121 if err != nil {
Philipp Schrader7365d322022-03-06 16:40:08 -0800122 database.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800123 return nil, errors.New(fmt.Sprint("Failed to prepare stats table creation: ", err))
124 }
125 defer statement.Close()
126
127 _, err = statement.Exec()
128 if err != nil {
Philipp Schrader7365d322022-03-06 16:40:08 -0800129 database.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800130 return nil, errors.New(fmt.Sprint("Failed to create team_match_stats table: ", err))
131 }
132
Alex Perry871eab92022-03-12 17:43:52 -0800133 statement, err = database.Prepare("CREATE TABLE IF NOT EXISTS team_notes (" +
Philipp Schrader7365d322022-03-06 16:40:08 -0800134 "id SERIAL PRIMARY KEY, " +
Alex Perry871eab92022-03-12 17:43:52 -0800135 "TeamNumber INTEGER, " +
136 "Notes TEXT)")
137 if err != nil {
138 return nil, errors.New(fmt.Sprint("Failed to prepare notes table creation: ", err))
139 }
140 defer statement.Close()
141
142 _, err = statement.Exec()
143 if err != nil {
144 return nil, errors.New(fmt.Sprint("Failed to create notes table: ", err))
145 }
146
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700147 statement, err = database.Prepare("CREATE TABLE IF NOT EXISTS rankings (" +
148 "id SERIAL PRIMARY KEY, " +
149 "Losses INTEGER, " +
150 "Wins INTEGER, " +
151 "Ties INTEGER, " +
152 "Rank INTEGER, " +
153 "Dq INTEGER, " +
154 "TeamNumber INTEGER)")
155 if err != nil {
156 return nil, errors.New(fmt.Sprint("Failed to prepare rankings table creation: ", err))
157 }
158 defer statement.Close()
159
160 _, err = statement.Exec()
161 if err != nil {
162 return nil, errors.New(fmt.Sprint("Failed to create rankings table: ", err))
163 }
164
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800165 return database, nil
166}
167
168func (database *Database) Delete() error {
Philipp Schrader83fc2722022-03-10 21:59:20 -0800169 statement, err := database.Prepare("DROP TABLE IF EXISTS matches")
170 if err != nil {
171 return errors.New(fmt.Sprint("Failed to prepare dropping matches table: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800172 }
Philipp Schrader83fc2722022-03-10 21:59:20 -0800173 _, err = statement.Exec()
174 if err != nil {
175 return errors.New(fmt.Sprint("Failed to drop matches table: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800176 }
Philipp Schrader83fc2722022-03-10 21:59:20 -0800177
178 statement, err = database.Prepare("DROP TABLE IF EXISTS team_match_stats")
179 if err != nil {
180 return errors.New(fmt.Sprint("Failed to prepare dropping stats table: ", err))
181 }
182 _, err = statement.Exec()
183 if err != nil {
184 return errors.New(fmt.Sprint("Failed to drop stats table: ", err))
185 }
Alex Perry871eab92022-03-12 17:43:52 -0800186
187 statement, err = database.Prepare("DROP TABLE IF EXISTS team_notes")
188 if err != nil {
189 return errors.New(fmt.Sprint("Failed to prepare dropping notes table: ", err))
190 }
191 _, err = statement.Exec()
192 if err != nil {
193 return errors.New(fmt.Sprint("Failed to drop notes table: ", err))
194 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800195 return nil
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700196
197 statement, err = database.Prepare("DROP TABLE IF EXISTS rankings")
198 if err != nil {
199 return errors.New(fmt.Sprint("Failed to prepare dropping rankings table: ", err))
200 }
201 _, err = statement.Exec()
202 if err != nil {
203 return errors.New(fmt.Sprint("Failed to drop rankings table: ", err))
204 }
205 return nil
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800206}
207
208// This function will also populate the Stats table with six empty rows every time a match is added
209func (database *Database) AddToMatch(m Match) error {
Philipp Schrader83fc2722022-03-10 21:59:20 -0800210 statement, err := database.Prepare("INSERT INTO team_match_stats(" +
211 "TeamNumber, MatchNumber, " +
Philipp Schraderfee07e12022-03-17 22:19:47 -0700212 "StartingQuadrant, " +
213 "AutoBall1PickedUp, AutoBall2PickedUp, AutoBall3PickedUp, " +
214 "AutoBall4PickedUp, AutoBall5PickedUp, " +
Philipp Schrader83fc2722022-03-10 21:59:20 -0800215 "ShotsMissed, UpperGoalShots, LowerGoalShots, " +
216 "ShotsMissedAuto, UpperGoalAuto, LowerGoalAuto, " +
Philipp Schraderfa45d742022-03-18 19:29:05 -0700217 "PlayedDefense, DefenseReceivedScore, Climbing, " +
218 "Comment, CollectedBy) " +
Philipp Schrader83fc2722022-03-10 21:59:20 -0800219 "VALUES (" +
Philipp Schrader7365d322022-03-06 16:40:08 -0800220 "$1, $2, " +
Philipp Schraderfee07e12022-03-17 22:19:47 -0700221 "$3, " +
222 "$4, $5, $6, " +
223 "$7, $8, " +
224 "$9, $10, $11, " +
225 "$12, $13, $14, " +
Philipp Schraderfa45d742022-03-18 19:29:05 -0700226 "$15, $16, $17, " +
227 "$18, $19) " +
Philipp Schrader7365d322022-03-06 16:40:08 -0800228 "RETURNING id")
Philipp Schrader83fc2722022-03-10 21:59:20 -0800229 if err != nil {
230 return errors.New(fmt.Sprint("Failed to prepare insertion into stats database: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800231 }
Philipp Schrader83fc2722022-03-10 21:59:20 -0800232 defer statement.Close()
233
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800234 var rowIds [6]int64
Philipp Schrader80ccb662022-03-01 21:47:30 -0800235 for i, TeamNumber := range []int32{m.R1, m.R2, m.R3, m.B1, m.B2, m.B3} {
Philipp Schraderfee07e12022-03-17 22:19:47 -0700236 row := statement.QueryRow(
237 TeamNumber, m.MatchNumber,
238 0,
239 false, false, false,
240 false, false,
241 0, 0, 0,
242 0, 0, 0,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700243 0, 0, 0,
244 "", "")
Philipp Schrader7365d322022-03-06 16:40:08 -0800245 err = row.Scan(&rowIds[i])
Philipp Schrader83fc2722022-03-10 21:59:20 -0800246 if err != nil {
247 return errors.New(fmt.Sprint("Failed to insert stats: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800248 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800249 }
Philipp Schrader83fc2722022-03-10 21:59:20 -0800250
251 statement, err = database.Prepare("INSERT INTO matches(" +
252 "MatchNumber, Round, CompLevel, " +
253 "R1, R2, R3, B1, B2, B3, " +
254 "r1ID, r2ID, r3ID, b1ID, b2ID, b3ID) " +
255 "VALUES (" +
Philipp Schrader7365d322022-03-06 16:40:08 -0800256 "$1, $2, $3, " +
257 "$4, $5, $6, $7, $8, $9, " +
258 "$10, $11, $12, $13, $14, $15)")
Philipp Schrader83fc2722022-03-10 21:59:20 -0800259 if err != nil {
260 return errors.New(fmt.Sprint("Failed to prepare insertion into match database: ", err))
261 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800262 defer statement.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800263
264 _, err = statement.Exec(m.MatchNumber, m.Round, m.CompLevel,
265 m.R1, m.R2, m.R3, m.B1, m.B2, m.B3,
266 rowIds[0], rowIds[1], rowIds[2], rowIds[3], rowIds[4], rowIds[5])
267 if err != nil {
268 return errors.New(fmt.Sprint("Failed to insert into match database: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800269 }
270 return nil
271}
272
273func (database *Database) AddToStats(s Stats) error {
Philipp Schrader83fc2722022-03-10 21:59:20 -0800274 statement, err := database.Prepare("UPDATE team_match_stats SET " +
Philipp Schrader7365d322022-03-06 16:40:08 -0800275 "TeamNumber = $1, MatchNumber = $2, " +
Philipp Schraderfee07e12022-03-17 22:19:47 -0700276 "StartingQuadrant = $3, " +
277 "AutoBall1PickedUp = $4, AutoBall2PickedUp = $5, AutoBall3PickedUp = $6, " +
278 "AutoBall4PickedUp = $7, AutoBall5PickedUp = $8, " +
279 "ShotsMissed = $9, UpperGoalShots = $10, LowerGoalShots = $11, " +
280 "ShotsMissedAuto = $12, UpperGoalAuto = $13, LowerGoalAuto = $14, " +
Philipp Schraderfa45d742022-03-18 19:29:05 -0700281 "PlayedDefense = $15, DefenseReceivedScore = $16, Climbing = $17, " +
282 "Comment = $18, CollectedBy = $19 " +
283 "WHERE MatchNumber = $20 AND TeamNumber = $21")
Philipp Schrader83fc2722022-03-10 21:59:20 -0800284 if err != nil {
285 return errors.New(fmt.Sprint("Failed to prepare stats update statement: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800286 }
Philipp Schrader83fc2722022-03-10 21:59:20 -0800287 defer statement.Close()
288
Philipp Schraderfee07e12022-03-17 22:19:47 -0700289 result, err := statement.Exec(
290 s.TeamNumber, s.MatchNumber,
291 s.StartingQuadrant,
292 s.AutoBallPickedUp[0], s.AutoBallPickedUp[1], s.AutoBallPickedUp[2],
293 s.AutoBallPickedUp[3], s.AutoBallPickedUp[4],
Philipp Schrader83fc2722022-03-10 21:59:20 -0800294 s.ShotsMissed, s.UpperGoalShots, s.LowerGoalShots,
295 s.ShotsMissedAuto, s.UpperGoalAuto, s.LowerGoalAuto,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700296 s.PlayedDefense, s.DefenseReceivedScore, s.Climbing,
297 s.Comment, s.CollectedBy,
Philipp Schrader83fc2722022-03-10 21:59:20 -0800298 s.MatchNumber, s.TeamNumber)
299 if err != nil {
300 return errors.New(fmt.Sprint("Failed to update stats database: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800301 }
Philipp Schrader83fc2722022-03-10 21:59:20 -0800302
303 numRowsAffected, err := result.RowsAffected()
304 if err != nil {
305 return errors.New(fmt.Sprint("Failed to query rows affected: ", err))
Philipp Schrader30005e42022-03-06 13:53:58 -0800306 }
307 if numRowsAffected == 0 {
308 return errors.New(fmt.Sprint(
309 "Failed to find team ", s.TeamNumber,
310 " in match ", s.MatchNumber, " in the schedule."))
311 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800312 return nil
313}
314
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700315func (database *Database) AddOrUpdateRankings(r Ranking) error {
316 statement, err := database.Prepare("UPDATE rankings SET " +
317 "Losses = $1, Wins = $2, Ties = $3, " +
318 "Rank = $4, Dq = $5, TeamNumber = $6 " +
319 "WHERE TeamNumber = $6")
320 if err != nil {
321 return errors.New(fmt.Sprint("Failed to prepare rankings database update: ", err))
322 }
323 defer statement.Close()
324
325 result, err := statement.Exec(r.Losses, r.Wins, r.Ties,
326 r.Rank, r.Dq, r.TeamNumber)
327 if err != nil {
328 return errors.New(fmt.Sprint("Failed to update rankings database: ", err))
329 }
330
331 numRowsAffected, err := result.RowsAffected()
332 if err != nil {
333 return errors.New(fmt.Sprint("Failed to query rows affected: ", err))
334 }
335 if numRowsAffected == 0 {
336 statement, err := database.Prepare("INSERT INTO rankings(" +
337 "Losses, Wins, Ties, " +
338 "Rank, Dq, TeamNumber) " +
339 "VALUES (" +
340 "$1, $2, $3, " +
341 "$4, $5, $6)")
342 if err != nil {
343 return errors.New(fmt.Sprint("Failed to prepare insertion into rankings database: ", err))
344 }
345 defer statement.Close()
346
347 _, err = statement.Exec(r.Losses, r.Wins, r.Ties,
348 r.Rank, r.Dq, r.TeamNumber)
349 if err != nil {
350 return errors.New(fmt.Sprint("Failed to insert into rankings database: ", err))
351 }
352 }
353
354 return nil
355}
356
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800357func (database *Database) ReturnMatches() ([]Match, error) {
Philipp Schrader83fc2722022-03-10 21:59:20 -0800358 rows, err := database.Query("SELECT * FROM matches")
359 if err != nil {
360 return nil, errors.New(fmt.Sprint("Failed to select from matches: ", err))
361 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800362 defer rows.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800363
364 matches := make([]Match, 0)
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800365 for rows.Next() {
366 var match Match
367 var id int
Philipp Schrader83fc2722022-03-10 21:59:20 -0800368 err := rows.Scan(&id, &match.MatchNumber, &match.Round, &match.CompLevel,
369 &match.R1, &match.R2, &match.R3, &match.B1, &match.B2, &match.B3,
370 &match.r1ID, &match.r2ID, &match.r3ID, &match.b1ID, &match.b2ID, &match.b3ID)
371 if err != nil {
372 return nil, errors.New(fmt.Sprint("Failed to scan from matches: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800373 }
374 matches = append(matches, match)
375 }
376 return matches, nil
377}
378
379func (database *Database) ReturnStats() ([]Stats, error) {
Philipp Schrader83fc2722022-03-10 21:59:20 -0800380 rows, err := database.Query("SELECT * FROM team_match_stats")
381 if err != nil {
382 return nil, errors.New(fmt.Sprint("Failed to SELECT * FROM team_match_stats: ", err))
Philipp Schrader30005e42022-03-06 13:53:58 -0800383 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800384 defer rows.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800385
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800386 teams := make([]Stats, 0)
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800387 for rows.Next() {
388 var team Stats
Philipp Schrader83fc2722022-03-10 21:59:20 -0800389 var id int
Philipp Schraderfee07e12022-03-17 22:19:47 -0700390 err = rows.Scan(&id,
391 &team.TeamNumber, &team.MatchNumber,
392 &team.StartingQuadrant,
393 &team.AutoBallPickedUp[0], &team.AutoBallPickedUp[1], &team.AutoBallPickedUp[2],
394 &team.AutoBallPickedUp[3], &team.AutoBallPickedUp[4],
Philipp Schrader83fc2722022-03-10 21:59:20 -0800395 &team.ShotsMissed, &team.UpperGoalShots, &team.LowerGoalShots,
396 &team.ShotsMissedAuto, &team.UpperGoalAuto, &team.LowerGoalAuto,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700397 &team.PlayedDefense, &team.DefenseReceivedScore, &team.Climbing,
398 &team.Comment, &team.CollectedBy)
Philipp Schrader83fc2722022-03-10 21:59:20 -0800399 if err != nil {
400 return nil, errors.New(fmt.Sprint("Failed to scan from stats: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800401 }
402 teams = append(teams, team)
403 }
404 return teams, nil
405}
406
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700407func (database *Database) ReturnRankings() ([]Ranking, error) {
408 rows, err := database.Query("SELECT * FROM rankings")
409 if err != nil {
410 return nil, errors.New(fmt.Sprint("Failed to SELECT * FROM rankings: ", err))
411 }
412 defer rows.Close()
413
414 all_rankings := make([]Ranking, 0)
415 for rows.Next() {
416 var ranking Ranking
417 var id int
418 err = rows.Scan(&id,
419 &ranking.Losses, &ranking.Wins, &ranking.Ties,
420 &ranking.Rank, &ranking.Dq, &ranking.TeamNumber)
421 if err != nil {
422 return nil, errors.New(fmt.Sprint("Failed to scan from rankings: ", err))
423 }
424 all_rankings = append(all_rankings, ranking)
425 }
426 return all_rankings, nil
427}
428
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800429func (database *Database) QueryMatches(teamNumber_ int32) ([]Match, error) {
Philipp Schrader83fc2722022-03-10 21:59:20 -0800430 rows, err := database.Query("SELECT * FROM matches WHERE "+
Philipp Schrader7365d322022-03-06 16:40:08 -0800431 "R1 = $1 OR R2 = $2 OR R3 = $3 OR B1 = $4 OR B2 = $5 OR B3 = $6",
Philipp Schrader83fc2722022-03-10 21:59:20 -0800432 teamNumber_, teamNumber_, teamNumber_, teamNumber_, teamNumber_, teamNumber_)
433 if err != nil {
434 return nil, errors.New(fmt.Sprint("Failed to select from matches for team: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800435 }
436 defer rows.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800437
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800438 var matches []Match
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800439 for rows.Next() {
440 var match Match
Philipp Schrader83fc2722022-03-10 21:59:20 -0800441 var id int
442 err = rows.Scan(&id, &match.MatchNumber, &match.Round, &match.CompLevel,
443 &match.R1, &match.R2, &match.R3, &match.B1, &match.B2, &match.B3,
444 &match.r1ID, &match.r2ID, &match.r3ID, &match.b1ID, &match.b2ID, &match.b3ID)
445 if err != nil {
446 return nil, errors.New(fmt.Sprint("Failed to scan from matches: ", err))
447 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800448 matches = append(matches, match)
449 }
450 return matches, nil
451}
452
453func (database *Database) QueryStats(teamNumber_ int) ([]Stats, error) {
Philipp Schrader7365d322022-03-06 16:40:08 -0800454 rows, err := database.Query("SELECT * FROM team_match_stats WHERE TeamNumber = $1", teamNumber_)
Philipp Schrader83fc2722022-03-10 21:59:20 -0800455 if err != nil {
456 return nil, errors.New(fmt.Sprint("Failed to select from stats: ", err))
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800457 }
458 defer rows.Close()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800459
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800460 var teams []Stats
461 for rows.Next() {
462 var team Stats
463 var id int
Philipp Schraderfee07e12022-03-17 22:19:47 -0700464 err = rows.Scan(&id,
465 &team.TeamNumber, &team.MatchNumber,
466 &team.StartingQuadrant,
467 &team.AutoBallPickedUp[0], &team.AutoBallPickedUp[1], &team.AutoBallPickedUp[2],
468 &team.AutoBallPickedUp[3], &team.AutoBallPickedUp[4],
Philipp Schrader83fc2722022-03-10 21:59:20 -0800469 &team.ShotsMissed, &team.UpperGoalShots, &team.LowerGoalShots,
470 &team.ShotsMissedAuto, &team.UpperGoalAuto, &team.LowerGoalAuto,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700471 &team.PlayedDefense, &team.DefenseReceivedScore, &team.Climbing,
472 &team.Comment, &team.CollectedBy)
Philipp Schrader83fc2722022-03-10 21:59:20 -0800473 if err != nil {
474 return nil, errors.New(fmt.Sprint("Failed to scan from stats: ", err))
475 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800476 teams = append(teams, team)
477 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800478 return teams, nil
479}
Alex Perry871eab92022-03-12 17:43:52 -0800480
481func (database *Database) QueryNotes(TeamNumber int32) (NotesData, error) {
Philipp Schrader7365d322022-03-06 16:40:08 -0800482 rows, err := database.Query("SELECT * FROM team_notes WHERE TeamNumber = $1", TeamNumber)
Alex Perry871eab92022-03-12 17:43:52 -0800483 if err != nil {
484 return NotesData{}, errors.New(fmt.Sprint("Failed to select from notes: ", err))
485 }
486 defer rows.Close()
487
488 var notes []string
489 for rows.Next() {
490 var id int32
491 var data string
492 err = rows.Scan(&id, &TeamNumber, &data)
493 if err != nil {
494 return NotesData{}, errors.New(fmt.Sprint("Failed to scan from notes: ", err))
495 }
496 notes = append(notes, data)
497 }
498 return NotesData{TeamNumber, notes}, nil
499}
500
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700501func (database *Database) QueryRankings(TeamNumber int) ([]Ranking, error) {
502 rows, err := database.Query("SELECT * FROM rankings WHERE TeamNumber = $1", TeamNumber)
503 if err != nil {
504 return nil, errors.New(fmt.Sprint("Failed to select from rankings: ", err))
505 }
506 defer rows.Close()
507
508 all_rankings := make([]Ranking, 0)
509 for rows.Next() {
510 var ranking Ranking
511 var id int
512 err = rows.Scan(&id,
513 &ranking.Losses, &ranking.Wins, &ranking.Ties,
514 &ranking.Rank, &ranking.Dq, &ranking.TeamNumber)
515 if err != nil {
516 return nil, errors.New(fmt.Sprint("Failed to scan from rankings: ", err))
517 }
518 all_rankings = append(all_rankings, ranking)
519 }
520 return all_rankings, nil
521}
522
Alex Perry871eab92022-03-12 17:43:52 -0800523func (database *Database) AddNotes(data NotesData) error {
524 if len(data.Notes) > 1 {
525 return errors.New("Can only insert one row of notes at a time")
526 }
527 statement, err := database.Prepare("INSERT INTO " +
528 "team_notes(TeamNumber, Notes)" +
Philipp Schrader7365d322022-03-06 16:40:08 -0800529 "VALUES ($1, $2)")
Alex Perry871eab92022-03-12 17:43:52 -0800530 if err != nil {
531 return errors.New(fmt.Sprint("Failed to prepare insertion into notes table: ", err))
532 }
533 defer statement.Close()
534
535 _, err = statement.Exec(data.TeamNumber, data.Notes[0])
536 if err != nil {
537 return errors.New(fmt.Sprint("Failed to insert into Notes database: ", err))
538 }
539 return nil
540}