blob: 759f7e1df708f54eb25022c91b73936d821c2574 [file] [log] [blame]
Sabina Leaverc5fd2772022-01-29 17:00:23 -08001package db
2
3import (
Emily Markovafaecfe12023-07-01 12:40:03 -07004 "crypto/sha256"
Philipp Schrader30005e42022-03-06 13:53:58 -08005 "errors"
Sabina Leaverc5fd2772022-01-29 17:00:23 -08006 "fmt"
Philipp Schradereecb8962022-06-01 21:02:42 -07007 "gorm.io/driver/postgres"
8 "gorm.io/gorm"
9 "gorm.io/gorm/clause"
10 "gorm.io/gorm/logger"
Sabina Leaverc5fd2772022-01-29 17:00:23 -080011)
12
13type Database struct {
Philipp Schradereecb8962022-06-01 21:02:42 -070014 *gorm.DB
Sabina Leaverc5fd2772022-01-29 17:00:23 -080015}
16
Emily Markovabf24c9e2023-02-08 20:31:11 -080017type TeamMatch struct {
18 MatchNumber int32 `gorm:"primaryKey"`
19 SetNumber int32 `gorm:"primaryKey"`
20 CompLevel string `gorm:"primaryKey"`
21 Alliance string `gorm:"primaryKey"` // "R" or "B"
22 AlliancePosition int32 `gorm:"primaryKey"` // 1, 2, or 3
Emily Markovab8551572023-03-22 19:49:39 -070023 TeamNumber string
Sabina Leaverc5fd2772022-01-29 17:00:23 -080024}
25
Milo Lina72e2002022-04-06 20:31:13 -070026type Shift struct {
Philipp Schradereecb8962022-06-01 21:02:42 -070027 MatchNumber int32 `gorm:"primaryKey"`
Milo Lina72e2002022-04-06 20:31:13 -070028 R1scouter, R2scouter, R3scouter, B1scouter, B2scouter, B3scouter string
29}
30
Emily Markovafaecfe12023-07-01 12:40:03 -070031type PitImage struct {
32 TeamNumber string `gorm:"primaryKey"`
33 CheckSum string `gorm:"primaryKey"`
34 ImagePath string
35 ImageData []byte
36}
37
38type RequestedPitImage struct {
39 TeamNumber string
40 CheckSum string `gorm:"primaryKey"`
41 ImagePath string
42}
43
Sabina Leaver759090b2023-01-14 20:42:56 -080044type Stats2023 struct {
Philipp Schrader8fdfadf2023-04-15 16:26:10 -070045 // This is set to `true` for "pre-scouted" matches. This means that the
46 // match information is unlikely to correspond with an entry in the
47 // `TeamMatch` table.
48 PreScouting bool `gorm:"primaryKey"`
49
Sabina Leaver759090b2023-01-14 20:42:56 -080050 TeamNumber string `gorm:"primaryKey"`
51 MatchNumber int32 `gorm:"primaryKey"`
52 SetNumber int32 `gorm:"primaryKey"`
53 CompLevel string `gorm:"primaryKey"`
54 StartingQuadrant int32
55 LowCubesAuto, MiddleCubesAuto, HighCubesAuto, CubesDroppedAuto int32
56 LowConesAuto, MiddleConesAuto, HighConesAuto, ConesDroppedAuto int32
57 LowCubes, MiddleCubes, HighCubes, CubesDropped int32
58 LowCones, MiddleCones, HighCones, ConesDropped int32
Filip Kujawa7a045e72023-04-13 08:41:09 -070059 SuperchargedPieces int32
Philipp Schrader8c878a22023-03-20 22:36:38 -070060 AvgCycle int64
Filip Kujawa0b4b1e52023-04-15 14:05:40 -070061 Mobility bool
Emily Markova63c63f62023-03-29 20:57:35 -070062 DockedAuto, EngagedAuto, BalanceAttemptAuto bool
63 Docked, Engaged, BalanceAttempt bool
64
Sabina Leaver759090b2023-01-14 20:42:56 -080065 // The username of the person who collected these statistics.
66 // "unknown" if submitted without logging in.
67 // Empty if the stats have not yet been collected.
68 CollectedBy string
69}
70
Emily Markova8cb91312024-02-02 12:30:37 -080071type Stats2024 struct {
72 // This is set to `true` for "pre-scouted" matches. This means that the
73 // match information is unlikely to correspond with an entry in the
74 // `TeamMatch` table.
75 PreScouting bool `gorm:"primaryKey"`
76
77 TeamNumber string `gorm:"primaryKey"`
78 MatchNumber int32 `gorm:"primaryKey"`
79 SetNumber int32 `gorm:"primaryKey"`
80 CompLevel string `gorm:"primaryKey"`
81 StartingQuadrant int32
82 SpeakerAuto, AmpAuto int32
83 NotesDroppedAuto int32
84 MobilityAuto bool
85 Speaker, Amp, SpeakerAmplified, AmpAmplified int32
86 NotesDropped int32
87 Penalties int32
88 AvgCycle int64
89 Park, OnStage, Harmony, TrapNote bool
90
91 // The username of the person who collected these statistics.
92 // "unknown" if submitted without logging in.
93 // Empty if the stats have not yet been collected.
94 CollectedBy string
95}
96
Sabina Leaver759090b2023-01-14 20:42:56 -080097type Action struct {
Philipp Schrader8fdfadf2023-04-15 16:26:10 -070098 PreScouting bool `gorm:"primaryKey"`
Sabina Leaver9b4eb312023-02-20 19:58:17 -080099 TeamNumber string `gorm:"primaryKey"`
100 MatchNumber int32 `gorm:"primaryKey"`
101 SetNumber int32 `gorm:"primaryKey"`
102 CompLevel string `gorm:"primaryKey"`
Sabina Leaver759090b2023-01-14 20:42:56 -0800103 // This contains a serialized scouting.webserver.requests.ActionType flatbuffer.
Sabina Leaver9b4eb312023-02-20 19:58:17 -0800104 CompletedAction []byte
Philipp Schrader670a1c82023-05-17 19:42:43 -0700105 Timestamp int64 `gorm:"primaryKey"`
106 CollectedBy string
Sabina Leaver759090b2023-01-14 20:42:56 -0800107}
108
Alex Perry871eab92022-03-12 17:43:52 -0800109type NotesData struct {
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800110 ID uint `gorm:"primaryKey"`
Emily Markovae68b7632023-12-30 14:17:55 -0800111 TeamNumber string
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800112 Notes string
113 GoodDriving bool
114 BadDriving bool
Filip Kujawa11dc4c92023-04-13 08:55:43 -0700115 SolidPlacing bool
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800116 SketchyPlacing bool
117 GoodDefense bool
118 BadDefense bool
119 EasilyDefended bool
Alex Perry871eab92022-03-12 17:43:52 -0800120}
121
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700122type Ranking struct {
Emily Markovae68b7632023-12-30 14:17:55 -0800123 TeamNumber string `gorm:"primaryKey"`
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700124 Losses, Wins, Ties int32
125 Rank, Dq int32
126}
127
Filip Kujawa210a03b2022-11-24 14:41:11 -0800128type DriverRankingData struct {
129 // Each entry in the table is a single scout's ranking.
130 // Multiple scouts can submit a driver ranking for the same
131 // teams in the same match.
132 // The teams being ranked are stored in Rank1, Rank2, Rank3,
133 // Rank1 being the best driving and Rank3 being the worst driving.
134
135 ID uint `gorm:"primaryKey"`
136 MatchNumber int32
Emily Markovae68b7632023-12-30 14:17:55 -0800137 Rank1 string
138 Rank2 string
139 Rank3 string
Filip Kujawa210a03b2022-11-24 14:41:11 -0800140}
141
Philipp Schradera8955fb2023-03-05 15:47:19 -0800142type ParsedDriverRankingData struct {
143 // This data stores the output of DriverRank.jl.
144
145 TeamNumber string `gorm:"primaryKey"`
146
147 // The score of the team. A difference of 100 in two team's scores
148 // indicates that one team will outperform the other in 90% of the
149 // matches.
150 Score float32
151}
152
Philipp Schrader7365d322022-03-06 16:40:08 -0800153// Opens a database at the specified port on localhost. We currently don't
154// support connecting to databases on other hosts.
155func NewDatabase(user string, password string, port int) (*Database, error) {
Philipp Schrader83fc2722022-03-10 21:59:20 -0800156 var err error
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800157 database := new(Database)
Philipp Schrader83fc2722022-03-10 21:59:20 -0800158
Philipp Schradereecb8962022-06-01 21:02:42 -0700159 dsn := fmt.Sprintf("host=localhost user=%s password=%s dbname=postgres port=%d sslmode=disable", user, password, port)
160 database.DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{
161 Logger: logger.Default.LogMode(logger.Silent),
162 })
Philipp Schrader7365d322022-03-06 16:40:08 -0800163 if err != nil {
Philipp Schradereecb8962022-06-01 21:02:42 -0700164 database.Delete()
Philipp Schrader7365d322022-03-06 16:40:08 -0800165 return nil, errors.New(fmt.Sprint("Failed to connect to postgres: ", err))
166 }
Philipp Schrader36df73a2022-03-17 23:27:24 -0700167
Emily Markova8cb91312024-02-02 12:30:37 -0800168 err = database.AutoMigrate(&TeamMatch{}, &Shift{}, &Stats2023{}, &Stats2024{}, &Action{}, &PitImage{}, &NotesData{}, &Ranking{}, &DriverRankingData{}, &ParsedDriverRankingData{})
Philipp Schrader83fc2722022-03-10 21:59:20 -0800169 if err != nil {
Philipp Schradereecb8962022-06-01 21:02:42 -0700170 database.Delete()
171 return nil, errors.New(fmt.Sprint("Failed to create/migrate tables: ", err))
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700172 }
173
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800174 return database, nil
175}
176
177func (database *Database) Delete() error {
Philipp Schradereecb8962022-06-01 21:02:42 -0700178 sql, err := database.DB.DB()
Philipp Schrader83fc2722022-03-10 21:59:20 -0800179 if err != nil {
Philipp Schradereecb8962022-06-01 21:02:42 -0700180 return err
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800181 }
Philipp Schradereecb8962022-06-01 21:02:42 -0700182 return sql.Close()
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800183}
184
Philipp Schradereecb8962022-06-01 21:02:42 -0700185func (database *Database) SetDebugLogLevel() {
186 database.DB.Logger = database.DB.Logger.LogMode(logger.Info)
187}
Philipp Schradercd12c952022-04-08 18:58:49 -0700188
Emily Markovabf24c9e2023-02-08 20:31:11 -0800189func (database *Database) AddToMatch(m TeamMatch) error {
Philipp Schradereecb8962022-06-01 21:02:42 -0700190 result := database.Clauses(clause.OnConflict{
191 UpdateAll: true,
192 }).Create(&m)
193 return result.Error
Philipp Schradercd12c952022-04-08 18:58:49 -0700194}
195
Milo Lina72e2002022-04-06 20:31:13 -0700196func (database *Database) AddToShift(sh Shift) error {
Philipp Schradereecb8962022-06-01 21:02:42 -0700197 result := database.Clauses(clause.OnConflict{
198 UpdateAll: true,
199 }).Create(&sh)
200 return result.Error
Milo Lina72e2002022-04-06 20:31:13 -0700201}
202
Sabina Leaver759090b2023-01-14 20:42:56 -0800203func (database *Database) AddAction(a Action) error {
Philipp Schrader8fdfadf2023-04-15 16:26:10 -0700204 // TODO(phil): Add check for a corresponding match in the `TeamMatch`
205 // table. Similar to `AddToStats2023()` below.
206 result := database.Create(&a)
Sabina Leaver759090b2023-01-14 20:42:56 -0800207 return result.Error
208}
209
Emily Markovafaecfe12023-07-01 12:40:03 -0700210func (database *Database) AddPitImage(p PitImage) error {
211 result := database.Create(&p)
212 return result.Error
213}
214
Sabina Leaver759090b2023-01-14 20:42:56 -0800215func (database *Database) AddToStats2023(s Stats2023) error {
Philipp Schrader8fdfadf2023-04-15 16:26:10 -0700216 if !s.PreScouting {
217 matches, err := database.QueryMatchesString(s.TeamNumber)
218 if err != nil {
219 return err
Sabina Leaver759090b2023-01-14 20:42:56 -0800220 }
Philipp Schrader8fdfadf2023-04-15 16:26:10 -0700221 foundMatch := false
222 for _, match := range matches {
223 if match.MatchNumber == s.MatchNumber {
224 foundMatch = true
225 break
226 }
227 }
228 if !foundMatch {
229 return errors.New(fmt.Sprint(
230 "Failed to find team ", s.TeamNumber,
231 " in match ", s.MatchNumber, " in the schedule."))
232 }
Sabina Leaver759090b2023-01-14 20:42:56 -0800233 }
234
235 result := database.Create(&s)
236 return result.Error
237}
238
Emily Markova8cb91312024-02-02 12:30:37 -0800239func (database *Database) AddToStats2024(s Stats2024) error {
240 if !s.PreScouting {
241 matches, err := database.QueryMatchesString(s.TeamNumber)
242 if err != nil {
243 return err
244 }
245 foundMatch := false
246 for _, match := range matches {
247 if match.MatchNumber == s.MatchNumber {
248 foundMatch = true
249 break
250 }
251 }
252 if !foundMatch {
253 return errors.New(fmt.Sprint(
254 "Failed to find team ", s.TeamNumber,
255 " in match ", s.MatchNumber, " in the schedule."))
256 }
257 }
258
259 result := database.Create(&s)
260 return result.Error
261}
262
Emily Markova6b551e02023-02-18 17:37:40 -0800263func (database *Database) DeleteFromStats(compLevel_ string, matchNumber_ int32, setNumber_ int32, teamNumber_ string) error {
264 var stats2023 []Stats2023
265 result := database.
266 Where("comp_level = ? AND match_number = ? AND set_number = ? AND team_number = ?", compLevel_, matchNumber_, setNumber_, teamNumber_).
267 Delete(&stats2023)
268 return result.Error
269}
270
Emily Markova8cb91312024-02-02 12:30:37 -0800271func (database *Database) DeleteFromStats2024(compLevel_ string, matchNumber_ int32, setNumber_ int32, teamNumber_ string) error {
272 var stats2024 []Stats2024
273 result := database.
274 Where("comp_level = ? AND match_number = ? AND set_number = ? AND team_number = ?", compLevel_, matchNumber_, setNumber_, teamNumber_).
275 Delete(&stats2024)
276 return result.Error
277}
278
Filip Kujawac1ded372023-05-27 14:33:43 -0700279func (database *Database) DeleteFromActions(compLevel_ string, matchNumber_ int32, setNumber_ int32, teamNumber_ string) error {
280 var actions []Action
281 result := database.
282 Where("comp_level = ? AND match_number = ? AND set_number = ? AND team_number = ?", compLevel_, matchNumber_, setNumber_, teamNumber_).
283 Delete(&actions)
284 return result.Error
285}
286
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700287func (database *Database) AddOrUpdateRankings(r Ranking) error {
Philipp Schradereecb8962022-06-01 21:02:42 -0700288 result := database.Clauses(clause.OnConflict{
289 UpdateAll: true,
290 }).Create(&r)
291 return result.Error
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700292}
293
Emily Markovabf24c9e2023-02-08 20:31:11 -0800294func (database *Database) ReturnMatches() ([]TeamMatch, error) {
295 var matches []TeamMatch
Philipp Schradereecb8962022-06-01 21:02:42 -0700296 result := database.Find(&matches)
297 return matches, result.Error
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800298}
299
Filip Kujawaf882e022022-12-14 13:14:08 -0800300func (database *Database) ReturnAllNotes() ([]NotesData, error) {
301 var notes []NotesData
302 result := database.Find(&notes)
303 return notes, result.Error
304}
305
306func (database *Database) ReturnAllDriverRankings() ([]DriverRankingData, error) {
307 var rankings []DriverRankingData
308 result := database.Find(&rankings)
309 return rankings, result.Error
310}
311
Philipp Schradera8955fb2023-03-05 15:47:19 -0800312func (database *Database) ReturnAllParsedDriverRankings() ([]ParsedDriverRankingData, error) {
313 var rankings []ParsedDriverRankingData
314 result := database.Find(&rankings)
315 return rankings, result.Error
316}
317
Milo Lina72e2002022-04-06 20:31:13 -0700318func (database *Database) ReturnAllShifts() ([]Shift, error) {
Philipp Schradereecb8962022-06-01 21:02:42 -0700319 var shifts []Shift
320 result := database.Find(&shifts)
321 return shifts, result.Error
322}
Milo Lina72e2002022-04-06 20:31:13 -0700323
Sabina Leaver759090b2023-01-14 20:42:56 -0800324func (database *Database) ReturnActions() ([]Action, error) {
325 var actions []Action
326 result := database.Find(&actions)
327 return actions, result.Error
328}
329
Emily Markovafaecfe12023-07-01 12:40:03 -0700330func (database *Database) ReturnPitImages() ([]PitImage, error) {
331 var images []PitImage
332 result := database.Find(&images)
333 return images, result.Error
334}
335
Emily Markova6b551e02023-02-18 17:37:40 -0800336func (database *Database) ReturnStats2023() ([]Stats2023, error) {
337 var stats2023 []Stats2023
338 result := database.Find(&stats2023)
339 return stats2023, result.Error
340}
341
Emily Markova8cb91312024-02-02 12:30:37 -0800342func (database *Database) ReturnStats2024() ([]Stats2024, error) {
343 var stats2024 []Stats2024
344 result := database.Find(&stats2024)
345 return stats2024, result.Error
346}
347
Filip Kujawaf3f9def2023-04-20 13:46:46 -0700348func (database *Database) ReturnStats2023ForTeam(teamNumber string, matchNumber int32, setNumber int32, compLevel string, preScouting bool) ([]Stats2023, error) {
Philipp Schrader78dc96b2023-03-11 15:23:44 -0800349 var stats2023 []Stats2023
350 result := database.
Filip Kujawaf3f9def2023-04-20 13:46:46 -0700351 Where("team_number = ? AND match_number = ? AND set_number = ? AND comp_level = ? AND pre_scouting = ?",
352 teamNumber, matchNumber, setNumber, compLevel, preScouting).
Philipp Schrader78dc96b2023-03-11 15:23:44 -0800353 Find(&stats2023)
354 return stats2023, result.Error
355}
356
Emily Markova8cb91312024-02-02 12:30:37 -0800357func (database *Database) ReturnStats2024ForTeam(teamNumber string, matchNumber int32, setNumber int32, compLevel string, preScouting bool) ([]Stats2024, error) {
358 var stats2024 []Stats2024
359 result := database.
360 Where("team_number = ? AND match_number = ? AND set_number = ? AND comp_level = ? AND pre_scouting = ?",
361 teamNumber, matchNumber, setNumber, compLevel, preScouting).
362 Find(&stats2024)
363 return stats2024, result.Error
364}
365
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700366func (database *Database) ReturnRankings() ([]Ranking, error) {
Philipp Schradereecb8962022-06-01 21:02:42 -0700367 var rankins []Ranking
368 result := database.Find(&rankins)
369 return rankins, result.Error
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700370}
371
Emily Markovab8551572023-03-22 19:49:39 -0700372func (database *Database) queryMatches(teamNumber_ string) ([]TeamMatch, error) {
Emily Markovabf24c9e2023-02-08 20:31:11 -0800373 var matches []TeamMatch
Philipp Schradereecb8962022-06-01 21:02:42 -0700374 result := database.
Emily Markovabf24c9e2023-02-08 20:31:11 -0800375 Where("team_number = $1", teamNumber_).
Philipp Schradereecb8962022-06-01 21:02:42 -0700376 Find(&matches)
377 return matches, result.Error
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800378}
379
Emily Markovafaecfe12023-07-01 12:40:03 -0700380func (database *Database) QueryPitImages(teamNumber_ string) ([]RequestedPitImage, error) {
381 var requestedPitImages []RequestedPitImage
382 result := database.Model(&PitImage{}).
383 Where("team_number = $1", teamNumber_).
384 Find(&requestedPitImages)
385
386 return requestedPitImages, result.Error
387}
388
389func (database *Database) QueryPitImageByChecksum(checksum_ string) (PitImage, error) {
390 var pitImage PitImage
391 result := database.
392 Where("check_sum = $1", checksum_).
393 Find(&pitImage)
394 return pitImage, result.Error
395}
396
397func ComputeSha256FromByteArray(arr []byte) string {
398 sum := sha256.Sum256(arr)
399 return fmt.Sprintf("%x", sum)
400}
401
Emily Markovabf24c9e2023-02-08 20:31:11 -0800402func (database *Database) QueryMatchesString(teamNumber_ string) ([]TeamMatch, error) {
403 var matches []TeamMatch
Sabina Leaver759090b2023-01-14 20:42:56 -0800404 result := database.
Emily Markovabf24c9e2023-02-08 20:31:11 -0800405 Where("team_number = $1", teamNumber_).
Sabina Leaver759090b2023-01-14 20:42:56 -0800406 Find(&matches)
407 return matches, result.Error
408}
409
Milo Lina72e2002022-04-06 20:31:13 -0700410func (database *Database) QueryAllShifts(matchNumber_ int) ([]Shift, error) {
Milo Lina72e2002022-04-06 20:31:13 -0700411 var shifts []Shift
Philipp Schradereecb8962022-06-01 21:02:42 -0700412 result := database.Where("match_number = ?", matchNumber_).Find(&shifts)
413 return shifts, result.Error
Milo Lina72e2002022-04-06 20:31:13 -0700414}
415
Emily Markovae68b7632023-12-30 14:17:55 -0800416func (database *Database) QueryActions(teamNumber_ string) ([]Action, error) {
Sabina Leaver759090b2023-01-14 20:42:56 -0800417 var actions []Action
418 result := database.
419 Where("team_number = ?", teamNumber_).Find(&actions)
420 return actions, result.Error
421}
422
Emily Markovae68b7632023-12-30 14:17:55 -0800423func (database *Database) QueryNotes(TeamNumber string) ([]string, error) {
Philipp Schradereecb8962022-06-01 21:02:42 -0700424 var rawNotes []NotesData
425 result := database.Where("team_number = ?", TeamNumber).Find(&rawNotes)
426 if result.Error != nil {
427 return nil, result.Error
Alex Perry871eab92022-03-12 17:43:52 -0800428 }
Alex Perry871eab92022-03-12 17:43:52 -0800429
Philipp Schradereecb8962022-06-01 21:02:42 -0700430 notes := make([]string, len(rawNotes))
431 for i := range rawNotes {
432 notes[i] = rawNotes[i].Notes
Alex Perry871eab92022-03-12 17:43:52 -0800433 }
Philipp Schradereecb8962022-06-01 21:02:42 -0700434 return notes, nil
Alex Perry871eab92022-03-12 17:43:52 -0800435}
436
Emily Markovae68b7632023-12-30 14:17:55 -0800437func (database *Database) QueryRankings(TeamNumber string) ([]Ranking, error) {
Philipp Schradereecb8962022-06-01 21:02:42 -0700438 var rankins []Ranking
439 result := database.Where("team_number = ?", TeamNumber).Find(&rankins)
440 return rankins, result.Error
Yash Chainanibcd1bb32022-04-02 17:10:24 -0700441}
442
Filip Kujawaf947cb42022-11-21 10:00:30 -0800443func (database *Database) AddNotes(data NotesData) error {
Philipp Schradereecb8962022-06-01 21:02:42 -0700444 result := database.Create(&NotesData{
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800445 TeamNumber: data.TeamNumber,
446 Notes: data.Notes,
447 GoodDriving: data.GoodDriving,
448 BadDriving: data.BadDriving,
Filip Kujawa11dc4c92023-04-13 08:55:43 -0700449 SolidPlacing: data.SolidPlacing,
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800450 SketchyPlacing: data.SketchyPlacing,
451 GoodDefense: data.GoodDefense,
452 BadDefense: data.BadDefense,
453 EasilyDefended: data.EasilyDefended,
Philipp Schradereecb8962022-06-01 21:02:42 -0700454 })
455 return result.Error
Alex Perry871eab92022-03-12 17:43:52 -0800456}
Filip Kujawa210a03b2022-11-24 14:41:11 -0800457
458func (database *Database) AddDriverRanking(data DriverRankingData) error {
459 result := database.Create(&DriverRankingData{
460 MatchNumber: data.MatchNumber,
461 Rank1: data.Rank1,
462 Rank2: data.Rank2,
463 Rank3: data.Rank3,
464 })
465 return result.Error
466}
467
Philipp Schradera8955fb2023-03-05 15:47:19 -0800468func (database *Database) AddParsedDriverRanking(data ParsedDriverRankingData) error {
469 result := database.Clauses(clause.OnConflict{
470 UpdateAll: true,
471 }).Create(&data)
472 return result.Error
473}
474
Filip Kujawa210a03b2022-11-24 14:41:11 -0800475func (database *Database) QueryDriverRanking(MatchNumber int) ([]DriverRankingData, error) {
476 var data []DriverRankingData
477 result := database.Where("match_number = ?", MatchNumber).Find(&data)
478 return data, result.Error
479}