blob: 788e6e3d68dccd99da452a88acafade1c0424f42 [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
8 _ "github.com/mattn/go-sqlite3"
9)
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 Schrader80ccb662022-03-01 21:47:30 -080024 TeamNumber, MatchNumber int32
25 ShotsMissed, UpperGoalShots, LowerGoalShots int32
26 ShotsMissedAuto, UpperGoalAuto, LowerGoalAuto, PlayedDefense int32
27 Climbing int32
Sabina Leaverc5fd2772022-01-29 17:00:23 -080028}
29
Philipp Schrader4953cc32022-02-25 18:09:02 -080030// Opens a database at the specified path. If the path refers to a non-existent
31// file, the database will be created and initialized with empty tables.
32func NewDatabase(path string) (*Database, error) {
Sabina Leaverc5fd2772022-01-29 17:00:23 -080033 database := new(Database)
Philipp Schrader4953cc32022-02-25 18:09:02 -080034 database.DB, _ = sql.Open("sqlite3", path)
Sabina Leaverc5fd2772022-01-29 17:00:23 -080035 statement, error_ := database.Prepare("CREATE TABLE IF NOT EXISTS matches " +
Philipp Schrader1e6c0a92022-02-27 23:30:57 -080036 "(id INTEGER PRIMARY KEY, MatchNumber INTEGER, Round INTEGER, CompLevel INTEGER, R1 INTEGER, R2 INTEGER, R3 INTEGER, B1 INTEGER, B2 INTEGER, B3 INTEGER, r1ID INTEGER, r2ID INTEGER, r3ID INTEGER, b1ID INTEGER, b2ID INTEGER, b3ID INTEGER)")
Sabina Leaverc5fd2772022-01-29 17:00:23 -080037 defer statement.Close()
38 if error_ != nil {
39 fmt.Println(error_)
40 return nil, error_
41 }
42 _, error_ = statement.Exec()
Philipp Schrader80ccb662022-03-01 21:47:30 -080043 statement, error_ = database.Prepare("CREATE TABLE IF NOT EXISTS team_match_stats (id INTEGER PRIMARY KEY, TeamNumber INTEGER, MatchNumber DOUBLE, ShotsMissed INTEGER, UpperGoalShots INTEGER, LowerGoalShots INTEGER, ShotsMissedAuto INTEGER, UpperGoalAuto INTEGER, LowerGoalAuto INTEGER, PlayedDefense INTEGER, Climbing INTEGER)")
Sabina Leaverc5fd2772022-01-29 17:00:23 -080044 defer statement.Close()
45 if error_ != nil {
46 fmt.Println(error_)
47 return nil, error_
48 }
49 _, error_ = statement.Exec()
50 return database, nil
51}
52
53func (database *Database) Delete() error {
54 statement, error_ := database.Prepare("DROP TABLE IF EXISTS matches")
55 if error_ != nil {
56 fmt.Println(error_)
57 return (error_)
58 }
59 _, error_ = statement.Exec()
60 statement, error_ = database.Prepare("DROP TABLE IF EXISTS team_match_stats")
61 if error_ != nil {
62 fmt.Println(error_)
63 return (error_)
64 }
65 _, error_ = statement.Exec()
66 return nil
67}
68
69// This function will also populate the Stats table with six empty rows every time a match is added
70func (database *Database) AddToMatch(m Match) error {
Philipp Schrader80ccb662022-03-01 21:47:30 -080071 statement, error_ := database.Prepare("INSERT INTO team_match_stats(TeamNumber, MatchNumber, ShotsMissed, UpperGoalShots, LowerGoalShots, ShotsMissedAuto, UpperGoalAuto, LowerGoalAuto, PlayedDefense, Climbing) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
Sabina Leaverc5fd2772022-01-29 17:00:23 -080072 defer statement.Close()
73 if error_ != nil {
74 fmt.Println("failed to prepare stats database:", error_)
75 return (error_)
76 }
77 var rowIds [6]int64
Philipp Schrader80ccb662022-03-01 21:47:30 -080078 for i, TeamNumber := range []int32{m.R1, m.R2, m.R3, m.B1, m.B2, m.B3} {
79 result, error_ := statement.Exec(TeamNumber, m.MatchNumber, 0, 0, 0, 0, 0, 0, 0, 0)
Sabina Leaverc5fd2772022-01-29 17:00:23 -080080 if error_ != nil {
81 fmt.Println("failed to execute statement 2:", error_)
82 return (error_)
83 }
84 rowIds[i], error_ = result.LastInsertId()
85 }
Philipp Schrader1e6c0a92022-02-27 23:30:57 -080086 statement, error_ = database.Prepare("INSERT INTO matches(MatchNumber, Round, CompLevel, R1, R2, R3, B1, B2, B3, r1ID, r2ID, r3ID, b1ID, b2ID, b3ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
Sabina Leaverc5fd2772022-01-29 17:00:23 -080087 defer statement.Close()
88 if error_ != nil {
89 fmt.Println("failed to prepare match database:", error_)
90 return (error_)
91 }
Philipp Schrader1e6c0a92022-02-27 23:30:57 -080092 _, error_ = statement.Exec(m.MatchNumber, m.Round, m.CompLevel, m.R1, m.R2, m.R3, m.B1, m.B2, m.B3, rowIds[0], rowIds[1], rowIds[2], rowIds[3], rowIds[4], rowIds[5])
Sabina Leaverc5fd2772022-01-29 17:00:23 -080093 if error_ != nil {
94 fmt.Println(error_)
95 return (error_)
96 }
97 return nil
98}
99
100func (database *Database) AddToStats(s Stats) error {
Philipp Schrader80ccb662022-03-01 21:47:30 -0800101 statement, error_ := database.Prepare("UPDATE team_match_stats SET TeamNumber = ?, MatchNumber = ?, ShotsMissed = ?, UpperGoalShots = ?, LowerGoalShots = ?, ShotsMissedAuto = ?, UpperGoalAuto = ?, LowerGoalAuto = ?, PlayedDefense = ?, Climbing = ? WHERE MatchNumber = ? AND TeamNumber = ?")
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800102 if error_ != nil {
103 fmt.Println(error_)
104 return (error_)
105 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800106 result, error_ := statement.Exec(s.TeamNumber, s.MatchNumber, s.ShotsMissed, s.UpperGoalShots, s.LowerGoalShots, s.ShotsMissedAuto, s.UpperGoalAuto, s.LowerGoalAuto, s.PlayedDefense, s.Climbing, s.MatchNumber, s.TeamNumber)
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800107 if error_ != nil {
108 fmt.Println(error_)
109 return (error_)
110 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800111 numRowsAffected, error_ := result.RowsAffected()
112 if error_ != nil {
113 return errors.New(fmt.Sprint("Failed to query rows affected: ", error_))
114 }
115 if numRowsAffected == 0 {
116 return errors.New(fmt.Sprint(
117 "Failed to find team ", s.TeamNumber,
118 " in match ", s.MatchNumber, " in the schedule."))
119 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800120 return nil
121}
122
123func (database *Database) ReturnMatches() ([]Match, error) {
124 matches := make([]Match, 0)
125 rows, _ := database.Query("SELECT * FROM matches")
126 defer rows.Close()
127 for rows.Next() {
128 var match Match
129 var id int
Philipp Schrader1e6c0a92022-02-27 23:30:57 -0800130 error_ := rows.Scan(&id, &match.MatchNumber, &match.Round, &match.CompLevel, &match.R1, &match.R2, &match.R3, &match.B1, &match.B2, &match.B3, &match.r1ID, &match.r2ID, &match.r3ID, &match.b1ID, &match.b2ID, &match.b3ID)
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800131 if error_ != nil {
132 fmt.Println(nil, error_)
133 return nil, error_
134 }
135 matches = append(matches, match)
136 }
137 return matches, nil
138}
139
140func (database *Database) ReturnStats() ([]Stats, error) {
Philipp Schrader30005e42022-03-06 13:53:58 -0800141 rows, error_ := database.Query("SELECT * FROM team_match_stats")
142 if error_ != nil {
143 return nil, errors.New(fmt.Sprint("Failed to SELECT * FROM team_match_stats: ", error_))
144 }
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800145 defer rows.Close()
146 teams := make([]Stats, 0)
147 var id int
148 for rows.Next() {
149 var team Stats
Philipp Schrader80ccb662022-03-01 21:47:30 -0800150 error_ := rows.Scan(&id, &team.TeamNumber, &team.MatchNumber, &team.ShotsMissed, &team.UpperGoalShots, &team.LowerGoalShots, &team.ShotsMissedAuto, &team.UpperGoalAuto, &team.LowerGoalAuto, &team.PlayedDefense, &team.Climbing)
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800151 if error_ != nil {
152 fmt.Println(error_)
153 return nil, error_
154 }
155 teams = append(teams, team)
156 }
157 return teams, nil
158}
159
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800160func (database *Database) QueryMatches(teamNumber_ int32) ([]Match, error) {
Philipp Schrader1e6c0a92022-02-27 23:30:57 -0800161 rows, error_ := database.Query("SELECT * FROM matches WHERE R1 = ? OR R2 = ? OR R3 = ? OR B1 = ? OR B2 = ? OR B3 = ?", teamNumber_, teamNumber_, teamNumber_, teamNumber_, teamNumber_, teamNumber_)
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800162 if error_ != nil {
163 fmt.Println("failed to execute statement 1:", error_)
164 return nil, error_
165 }
166 defer rows.Close()
167 var matches []Match
168 var id int
169 for rows.Next() {
170 var match Match
Philipp Schrader1e6c0a92022-02-27 23:30:57 -0800171 rows.Scan(&id, &match.MatchNumber, &match.Round, &match.CompLevel, &match.R1, &match.R2, &match.R3, &match.B1, &match.B2, &match.B3, &match.r1ID, &match.r2ID, &match.r3ID, &match.b1ID, &match.b2ID, &match.b3ID)
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800172 matches = append(matches, match)
173 }
174 return matches, nil
175}
176
177func (database *Database) QueryStats(teamNumber_ int) ([]Stats, error) {
Philipp Schrader80ccb662022-03-01 21:47:30 -0800178 rows, error_ := database.Query("SELECT * FROM team_match_stats WHERE TeamNumber = ?", teamNumber_)
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800179 if error_ != nil {
180 fmt.Println("failed to execute statement 3:", error_)
181 return nil, error_
182 }
183 defer rows.Close()
184 var teams []Stats
185 for rows.Next() {
186 var team Stats
187 var id int
Philipp Schrader80ccb662022-03-01 21:47:30 -0800188 error_ = rows.Scan(&id, &team.TeamNumber, &team.MatchNumber, &team.ShotsMissed,
189 &team.UpperGoalShots, &team.LowerGoalShots, &team.ShotsMissedAuto, &team.UpperGoalAuto,
190 &team.LowerGoalAuto, &team.PlayedDefense, &team.Climbing)
Sabina Leaverc5fd2772022-01-29 17:00:23 -0800191 teams = append(teams, team)
192 }
193 if error_ != nil {
194 fmt.Println("failed to execute statement 3:", error_)
195 return nil, error_
196 }
197 return teams, nil
198}