blob: 26b79c528862fdf4b20232c5e48f44ee08905417 [file] [log] [blame]
Philipp Schradercdb5cfc2022-02-20 14:57:07 -08001package requests
2
3import (
4 "bytes"
5 "io"
6 "net/http"
Philipp Schradercbf5c6a2022-02-27 23:25:19 -08007 "reflect"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -08008 "testing"
9
Philipp Schrader8747f1b2022-02-23 23:56:22 -080010 "github.com/frc971/971-Robot-Code/scouting/db"
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080011 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/debug"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080012 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/error_response"
Emily Markova290147d2023-03-03 22:40:06 -080013 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2023_data_scouting"
14 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2023_data_scouting_response"
Filip Kujawaf882e022022-12-14 13:14:08 -080015 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_driver_rankings"
16 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_driver_rankings_response"
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080017 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches"
18 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response"
Filip Kujawaf882e022022-12-14 13:14:08 -080019 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_notes"
20 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_notes_response"
Philipp Schraderacf96232022-03-01 22:03:30 -080021 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting"
22 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting_response"
Alex Perry81f96ba2022-03-13 18:26:19 -070023 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team"
Milo Lin1d59f0c2022-06-22 20:30:58 -070024 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule"
25 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule_response"
Emily Markova1abe9782023-03-11 19:45:38 -080026 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_actions"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080027 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting"
Philipp Schrader30005e42022-03-06 13:53:58 -080028 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting_response"
Filip Kujawa210a03b2022-11-24 14:41:11 -080029 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_driver_ranking"
Alex Perry81f96ba2022-03-13 18:26:19 -070030 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_notes"
Milo Lin1d59f0c2022-06-22 20:30:58 -070031 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_shift_schedule"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080032 "github.com/frc971/971-Robot-Code/scouting/webserver/server"
33 flatbuffers "github.com/google/flatbuffers/go"
34)
35
36// Validates that an unhandled address results in a 404.
37func Test404(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080038 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080039 scoutingServer := server.NewScoutingServer()
Philipp Schrader43c730b2023-02-26 20:27:44 -080040 HandleRequests(&db, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080041 scoutingServer.Start(8080)
42 defer scoutingServer.Stop()
43
44 resp, err := http.Get("http://localhost:8080/requests/foo")
45 if err != nil {
46 t.Fatalf("Failed to get data: %v", err)
47 }
48 if resp.StatusCode != http.StatusNotFound {
49 t.Fatalf("Expected error code 404, but got %d instead", resp.Status)
50 }
51}
52
53// Validates that we can submit new data scouting data.
54func TestSubmitDataScoutingError(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080055 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080056 scoutingServer := server.NewScoutingServer()
Philipp Schrader43c730b2023-02-26 20:27:44 -080057 HandleRequests(&db, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080058 scoutingServer.Start(8080)
59 defer scoutingServer.Stop()
60
61 resp, err := http.Post("http://localhost:8080/requests/submit/data_scouting", "application/octet-stream", bytes.NewReader([]byte("")))
62 if err != nil {
63 t.Fatalf("Failed to send request: %v", err)
64 }
65 if resp.StatusCode != http.StatusBadRequest {
66 t.Fatal("Unexpected status code. Got", resp.Status)
67 }
68
69 responseBytes, err := io.ReadAll(resp.Body)
70 if err != nil {
71 t.Fatal("Failed to read response bytes:", err)
72 }
73 errorResponse := error_response.GetRootAsErrorResponse(responseBytes, 0)
74
75 errorMessage := string(errorResponse.ErrorMessage())
76 if errorMessage != "Failed to parse SubmitDataScouting: runtime error: index out of range [3] with length 0" {
77 t.Fatal("Got mismatched error message:", errorMessage)
78 }
79}
80
81// Validates that we can submit new data scouting data.
82func TestSubmitDataScouting(t *testing.T) {
Philipp Schrader8747f1b2022-02-23 23:56:22 -080083 db := MockDatabase{}
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080084 scoutingServer := server.NewScoutingServer()
Philipp Schrader43c730b2023-02-26 20:27:44 -080085 HandleRequests(&db, scoutingServer)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080086 scoutingServer.Start(8080)
87 defer scoutingServer.Stop()
88
89 builder := flatbuffers.NewBuilder(1024)
90 builder.Finish((&submit_data_scouting.SubmitDataScoutingT{
Philipp Schraderfa45d742022-03-18 19:29:05 -070091 Team: 971,
92 Match: 1,
Philipp Schrader30b4a682022-04-16 14:36:17 -070093 SetNumber: 8,
Philipp Schrader4535b7e2022-04-08 20:27:00 -070094 CompLevel: "quals",
Philipp Schraderfa45d742022-03-18 19:29:05 -070095 StartingQuadrant: 2,
96 AutoBall1: true,
97 AutoBall2: false,
98 AutoBall3: false,
99 AutoBall4: false,
100 AutoBall5: false,
101 MissedShotsAuto: 9971,
102 UpperGoalAuto: 9971,
103 LowerGoalAuto: 9971,
104 MissedShotsTele: 9971,
105 UpperGoalTele: 9971,
106 LowerGoalTele: 9971,
107 DefenseRating: 9971,
108 DefenseReceivedRating: 4,
109 ClimbLevel: submit_data_scouting.ClimbLevelLow,
110 Comment: "this is a comment",
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800111 }).Pack(builder))
112
Philipp Schrader30005e42022-03-06 13:53:58 -0800113 response, err := debug.SubmitDataScouting("http://localhost:8080", builder.FinishedBytes())
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800114 if err != nil {
Philipp Schrader30005e42022-03-06 13:53:58 -0800115 t.Fatal("Failed to submit data scouting: ", err)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800116 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800117
118 // We get an empty response back. Validate that.
119 expected := submit_data_scouting_response.SubmitDataScoutingResponseT{}
120 if !reflect.DeepEqual(expected, *response) {
121 t.Fatal("Expected ", expected, ", but got:", *response)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800122 }
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800123}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800124
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800125// Validates that we can request the full match list.
126func TestRequestAllMatches(t *testing.T) {
127 db := MockDatabase{
Emily Markovabf24c9e2023-02-08 20:31:11 -0800128 matches: []db.TeamMatch{
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800129 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800130 MatchNumber: 1, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800131 Alliance: "R", AlliancePosition: 1, TeamNumber: 5,
132 },
133 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800134 MatchNumber: 1, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800135 Alliance: "R", AlliancePosition: 2, TeamNumber: 42,
136 },
137 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800138 MatchNumber: 1, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800139 Alliance: "R", AlliancePosition: 3, TeamNumber: 600,
140 },
141 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800142 MatchNumber: 1, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800143 Alliance: "B", AlliancePosition: 1, TeamNumber: 971,
144 },
145 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800146 MatchNumber: 1, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800147 Alliance: "B", AlliancePosition: 2, TeamNumber: 400,
148 },
149 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800150 MatchNumber: 1, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800151 Alliance: "B", AlliancePosition: 3, TeamNumber: 200,
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800152 },
153 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800154 MatchNumber: 2, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800155 Alliance: "R", AlliancePosition: 1, TeamNumber: 6,
156 },
157 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800158 MatchNumber: 2, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800159 Alliance: "R", AlliancePosition: 2, TeamNumber: 43,
160 },
161 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800162 MatchNumber: 2, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800163 Alliance: "R", AlliancePosition: 3, TeamNumber: 601,
164 },
165 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800166 MatchNumber: 2, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800167 Alliance: "B", AlliancePosition: 1, TeamNumber: 972,
168 },
169 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800170 MatchNumber: 2, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800171 Alliance: "B", AlliancePosition: 2, TeamNumber: 401,
172 },
173 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800174 MatchNumber: 2, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800175 Alliance: "B", AlliancePosition: 3, TeamNumber: 201,
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800176 },
177 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800178 MatchNumber: 3, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800179 Alliance: "R", AlliancePosition: 1, TeamNumber: 7,
180 },
181 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800182 MatchNumber: 3, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800183 Alliance: "R", AlliancePosition: 2, TeamNumber: 44,
184 },
185 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800186 MatchNumber: 3, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800187 Alliance: "R", AlliancePosition: 3, TeamNumber: 602,
188 },
189 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800190 MatchNumber: 3, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800191 Alliance: "B", AlliancePosition: 1, TeamNumber: 973,
192 },
193 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800194 MatchNumber: 3, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800195 Alliance: "B", AlliancePosition: 2, TeamNumber: 402,
196 },
197 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800198 MatchNumber: 3, SetNumber: 1, CompLevel: "qm",
Emily Markovabf24c9e2023-02-08 20:31:11 -0800199 Alliance: "B", AlliancePosition: 3, TeamNumber: 202,
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800200 },
201 },
202 }
203 scoutingServer := server.NewScoutingServer()
Philipp Schrader43c730b2023-02-26 20:27:44 -0800204 HandleRequests(&db, scoutingServer)
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800205 scoutingServer.Start(8080)
206 defer scoutingServer.Stop()
207
208 builder := flatbuffers.NewBuilder(1024)
209 builder.Finish((&request_all_matches.RequestAllMatchesT{}).Pack(builder))
210
211 response, err := debug.RequestAllMatches("http://localhost:8080", builder.FinishedBytes())
212 if err != nil {
213 t.Fatal("Failed to request all matches: ", err)
214 }
215
216 expected := request_all_matches_response.RequestAllMatchesResponseT{
217 MatchList: []*request_all_matches_response.MatchT{
Philipp Schrader30b4a682022-04-16 14:36:17 -0700218 // MatchNumber, SetNumber, CompLevel
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800219 // R1, R2, R3, B1, B2, B3
220 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800221 1, 1, "qm",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800222 5, 42, 600, 971, 400, 200,
223 },
224 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800225 2, 1, "qm",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800226 6, 43, 601, 972, 401, 201,
227 },
228 {
Emily Markovaabcac6e2023-02-18 17:50:03 -0800229 3, 1, "qm",
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800230 7, 44, 602, 973, 402, 202,
231 },
232 },
233 }
234 if len(expected.MatchList) != len(response.MatchList) {
235 t.Fatal("Expected ", expected, ", but got ", *response)
236 }
237 for i, match := range expected.MatchList {
238 if !reflect.DeepEqual(*match, *response.MatchList[i]) {
239 t.Fatal("Expected for match", i, ":", *match, ", but got:", *response.MatchList[i])
240 }
241 }
Philipp Schrader30005e42022-03-06 13:53:58 -0800242
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800243}
244
Philipp Schraderacf96232022-03-01 22:03:30 -0800245// Validates that we can request the stats.
246func TestRequestDataScouting(t *testing.T) {
247 db := MockDatabase{
248 stats: []db.Stats{
249 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700250 TeamNumber: 971, MatchNumber: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700251 StartingQuadrant: 1,
252 AutoBallPickedUp: [5]bool{true, false, false, false, true},
253 ShotsMissed: 1, UpperGoalShots: 2, LowerGoalShots: 3,
Philipp Schraderacf96232022-03-01 22:03:30 -0800254 ShotsMissedAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700255 PlayedDefense: 7, DefenseReceivedScore: 3, Climbing: 2,
256 Comment: "a lovely comment", CollectedBy: "john",
Philipp Schraderacf96232022-03-01 22:03:30 -0800257 },
258 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700259 TeamNumber: 972, MatchNumber: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schraderfee07e12022-03-17 22:19:47 -0700260 StartingQuadrant: 2,
261 AutoBallPickedUp: [5]bool{false, false, true, false, false},
262 ShotsMissed: 2, UpperGoalShots: 3, LowerGoalShots: 4,
Philipp Schraderacf96232022-03-01 22:03:30 -0800263 ShotsMissedAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700264 PlayedDefense: 8, DefenseReceivedScore: 1, Climbing: 4,
265 Comment: "another lovely comment", CollectedBy: "andrea",
Philipp Schraderacf96232022-03-01 22:03:30 -0800266 },
267 },
268 }
269 scoutingServer := server.NewScoutingServer()
Philipp Schrader43c730b2023-02-26 20:27:44 -0800270 HandleRequests(&db, scoutingServer)
Philipp Schraderacf96232022-03-01 22:03:30 -0800271 scoutingServer.Start(8080)
272 defer scoutingServer.Stop()
273
274 builder := flatbuffers.NewBuilder(1024)
275 builder.Finish((&request_data_scouting.RequestDataScoutingT{}).Pack(builder))
276
277 response, err := debug.RequestDataScouting("http://localhost:8080", builder.FinishedBytes())
278 if err != nil {
279 t.Fatal("Failed to request all matches: ", err)
280 }
281
282 expected := request_data_scouting_response.RequestDataScoutingResponseT{
283 StatsList: []*request_data_scouting_response.StatsT{
Philipp Schraderacf96232022-03-01 22:03:30 -0800284 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700285 Team: 971, Match: 1, SetNumber: 2, CompLevel: "quals",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700286 MissedShotsAuto: 4, UpperGoalAuto: 5, LowerGoalAuto: 6,
287 MissedShotsTele: 1, UpperGoalTele: 2, LowerGoalTele: 3,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700288 DefenseRating: 7,
289 DefenseReceivedRating: 3,
290 CollectedBy: "john",
291 AutoBall1: true, AutoBall2: false, AutoBall3: false,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700292 AutoBall4: false, AutoBall5: true,
293 StartingQuadrant: 1,
294 ClimbLevel: request_data_scouting_response.ClimbLevelFailedWithPlentyOfTime,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700295 Comment: "a lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800296 },
297 {
Philipp Schrader30b4a682022-04-16 14:36:17 -0700298 Team: 972, Match: 1, SetNumber: 4, CompLevel: "extra",
Philipp Schrader36df73a2022-03-17 23:27:24 -0700299 MissedShotsAuto: 5, UpperGoalAuto: 6, LowerGoalAuto: 7,
300 MissedShotsTele: 2, UpperGoalTele: 3, LowerGoalTele: 4,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700301 DefenseRating: 8,
302 DefenseReceivedRating: 1,
303 CollectedBy: "andrea",
304 AutoBall1: false, AutoBall2: false, AutoBall3: true,
Philipp Schrader36df73a2022-03-17 23:27:24 -0700305 AutoBall4: false, AutoBall5: false,
306 StartingQuadrant: 2,
307 ClimbLevel: request_data_scouting_response.ClimbLevelMedium,
Philipp Schraderfa45d742022-03-18 19:29:05 -0700308 Comment: "another lovely comment",
Philipp Schraderacf96232022-03-01 22:03:30 -0800309 },
310 },
311 }
312 if len(expected.StatsList) != len(response.StatsList) {
313 t.Fatal("Expected ", expected, ", but got ", *response)
314 }
315 for i, match := range expected.StatsList {
316 if !reflect.DeepEqual(*match, *response.StatsList[i]) {
317 t.Fatal("Expected for stats", i, ":", *match, ", but got:", *response.StatsList[i])
318 }
319 }
320}
321
Emily Markova290147d2023-03-03 22:40:06 -0800322// Validates that we can request the 2023 stats.
323func TestRequest2023DataScouting(t *testing.T) {
324 db := MockDatabase{
325 stats2023: []db.Stats2023{
326 {
327 TeamNumber: "3634", MatchNumber: 1, SetNumber: 2,
328 CompLevel: "quals", StartingQuadrant: 3, LowCubesAuto: 10,
329 MiddleCubesAuto: 1, HighCubesAuto: 1, CubesDroppedAuto: 0,
330 LowConesAuto: 1, MiddleConesAuto: 2, HighConesAuto: 1,
331 ConesDroppedAuto: 0, LowCubes: 1, MiddleCubes: 1,
332 HighCubes: 2, CubesDropped: 1, LowCones: 1,
333 MiddleCones: 2, HighCones: 0, ConesDropped: 1,
334 AvgCycle: 34, CollectedBy: "isaac",
335 },
336 {
337 TeamNumber: "2343", MatchNumber: 1, SetNumber: 2,
338 CompLevel: "quals", StartingQuadrant: 1, LowCubesAuto: 0,
339 MiddleCubesAuto: 1, HighCubesAuto: 1, CubesDroppedAuto: 2,
340 LowConesAuto: 0, MiddleConesAuto: 0, HighConesAuto: 0,
341 ConesDroppedAuto: 1, LowCubes: 0, MiddleCubes: 0,
342 HighCubes: 1, CubesDropped: 0, LowCones: 0,
343 MiddleCones: 2, HighCones: 1, ConesDropped: 1,
344 AvgCycle: 53, CollectedBy: "unknown",
345 },
346 },
347 }
348 scoutingServer := server.NewScoutingServer()
349 HandleRequests(&db, scoutingServer)
350 scoutingServer.Start(8080)
351 defer scoutingServer.Stop()
352
353 builder := flatbuffers.NewBuilder(1024)
354 builder.Finish((&request_2023_data_scouting.Request2023DataScoutingT{}).Pack(builder))
355
356 response, err := debug.Request2023DataScouting("http://localhost:8080", builder.FinishedBytes())
357 if err != nil {
358 t.Fatal("Failed to request all matches: ", err)
359 }
360
361 expected := request_2023_data_scouting_response.Request2023DataScoutingResponseT{
362 StatsList: []*request_2023_data_scouting_response.Stats2023T{
363 {
364 TeamNumber: "3634", MatchNumber: 1, SetNumber: 2,
365 CompLevel: "quals", StartingQuadrant: 3, LowCubesAuto: 10,
366 MiddleCubesAuto: 1, HighCubesAuto: 1, CubesDroppedAuto: 0,
367 LowConesAuto: 1, MiddleConesAuto: 2, HighConesAuto: 1,
368 ConesDroppedAuto: 0, LowCubes: 1, MiddleCubes: 1,
369 HighCubes: 2, CubesDropped: 1, LowCones: 1,
370 MiddleCones: 2, HighCones: 0, ConesDropped: 1,
371 AvgCycle: 34, CollectedBy: "isaac",
372 },
373 {
374 TeamNumber: "2343", MatchNumber: 1, SetNumber: 2,
375 CompLevel: "quals", StartingQuadrant: 1, LowCubesAuto: 0,
376 MiddleCubesAuto: 1, HighCubesAuto: 1, CubesDroppedAuto: 2,
377 LowConesAuto: 0, MiddleConesAuto: 0, HighConesAuto: 0,
378 ConesDroppedAuto: 1, LowCubes: 0, MiddleCubes: 0,
379 HighCubes: 1, CubesDropped: 0, LowCones: 0,
380 MiddleCones: 2, HighCones: 1, ConesDropped: 1,
381 AvgCycle: 53, CollectedBy: "unknown",
382 },
383 },
384 }
385 if len(expected.StatsList) != len(response.StatsList) {
386 t.Fatal("Expected ", expected, ", but got ", *response)
387 }
388 for i, match := range expected.StatsList {
389 if !reflect.DeepEqual(*match, *response.StatsList[i]) {
390 t.Fatal("Expected for stats", i, ":", *match, ", but got:", *response.StatsList[i])
391 }
392 }
393}
394
Emily Markova1abe9782023-03-11 19:45:38 -0800395// Validates that we can request the 2023 stats.
396func TestConvertActionsToStat(t *testing.T) {
397 builder := flatbuffers.NewBuilder(1024)
398 builder.Finish((&submit_actions.SubmitActionsT{
399 TeamNumber: "4244",
400 MatchNumber: 3,
401 SetNumber: 1,
402 CompLevel: "quals",
403 CollectedBy: "katie",
404 ActionsList: []*submit_actions.ActionT{
405 {
406 ActionTaken: &submit_actions.ActionTypeT{
407 Type: submit_actions.ActionTypeStartMatchAction,
408 Value: &submit_actions.StartMatchActionT{
409 Position: 1,
410 },
411 },
412 Timestamp: 0,
413 },
414 {
415 ActionTaken: &submit_actions.ActionTypeT{
416 Type: submit_actions.ActionTypePickupObjectAction,
417 Value: &submit_actions.PickupObjectActionT{
418 ObjectType: submit_actions.ObjectTypekCube,
419 Auto: true,
420 },
421 },
422 Timestamp: 400,
423 },
424 {
425 ActionTaken: &submit_actions.ActionTypeT{
426 Type: submit_actions.ActionTypePickupObjectAction,
427 Value: &submit_actions.PickupObjectActionT{
428 ObjectType: submit_actions.ObjectTypekCube,
429 Auto: true,
430 },
431 },
432 Timestamp: 800,
433 },
434 {
435 ActionTaken: &submit_actions.ActionTypeT{
436 Type: submit_actions.ActionTypePlaceObjectAction,
437 Value: &submit_actions.PlaceObjectActionT{
438 ObjectType: submit_actions.ObjectTypekCube,
439 ScoreLevel: submit_actions.ScoreLevelkLow,
440 Auto: true,
441 },
442 },
443 Timestamp: 2000,
444 },
445 {
446 ActionTaken: &submit_actions.ActionTypeT{
447 Type: submit_actions.ActionTypePickupObjectAction,
448 Value: &submit_actions.PickupObjectActionT{
449 ObjectType: submit_actions.ObjectTypekCone,
450 Auto: false,
451 },
452 },
453 Timestamp: 2800,
454 },
455 {
456 ActionTaken: &submit_actions.ActionTypeT{
457 Type: submit_actions.ActionTypePlaceObjectAction,
458 Value: &submit_actions.PlaceObjectActionT{
459 ObjectType: submit_actions.ObjectTypekCone,
460 ScoreLevel: submit_actions.ScoreLevelkHigh,
461 Auto: false,
462 },
463 },
464 Timestamp: 3100,
465 },
466 },
467 }).Pack(builder))
468
469 submitActions := submit_actions.GetRootAsSubmitActions(builder.FinishedBytes(), 0)
470 response, err := ConvertActionsToStat(submitActions)
471
472 if err != nil {
473 t.Fatal("Failed to convert actions to stats: ", err)
474 }
475
476 expected := db.Stats2023{
477 TeamNumber: "4244", MatchNumber: 3, SetNumber: 1,
478 CompLevel: "quals", StartingQuadrant: 1, LowCubesAuto: 1,
479 MiddleCubesAuto: 0, HighCubesAuto: 0, CubesDroppedAuto: 1,
480 LowConesAuto: 0, MiddleConesAuto: 0, HighConesAuto: 0,
481 ConesDroppedAuto: 0, LowCubes: 0, MiddleCubes: 0,
482 HighCubes: 0, CubesDropped: 0, LowCones: 0,
483 MiddleCones: 0, HighCones: 1, ConesDropped: 0,
484 AvgCycle: 1100, CollectedBy: "katie",
485 }
486
487 if expected != response {
488 t.Fatal("Expected ", expected, ", but got ", response)
489 }
490}
491
Alex Perry81f96ba2022-03-13 18:26:19 -0700492func TestSubmitNotes(t *testing.T) {
493 database := MockDatabase{}
494 scoutingServer := server.NewScoutingServer()
Philipp Schrader43c730b2023-02-26 20:27:44 -0800495 HandleRequests(&database, scoutingServer)
Alex Perry81f96ba2022-03-13 18:26:19 -0700496 scoutingServer.Start(8080)
497 defer scoutingServer.Stop()
498
499 builder := flatbuffers.NewBuilder(1024)
500 builder.Finish((&submit_notes.SubmitNotesT{
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800501 Team: 971,
502 Notes: "Notes",
503 GoodDriving: true,
504 BadDriving: false,
505 SketchyPickup: true,
506 SketchyPlacing: false,
507 GoodDefense: true,
508 BadDefense: false,
509 EasilyDefended: true,
Alex Perry81f96ba2022-03-13 18:26:19 -0700510 }).Pack(builder))
511
512 _, err := debug.SubmitNotes("http://localhost:8080", builder.FinishedBytes())
513 if err != nil {
514 t.Fatal("Failed to submit notes: ", err)
515 }
516
517 expected := []db.NotesData{
Filip Kujawaf947cb42022-11-21 10:00:30 -0800518 {
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800519 TeamNumber: 971,
520 Notes: "Notes",
521 GoodDriving: true,
522 BadDriving: false,
523 SketchyPickup: true,
524 SketchyPlacing: false,
525 GoodDefense: true,
526 BadDefense: false,
527 EasilyDefended: true,
Filip Kujawaf947cb42022-11-21 10:00:30 -0800528 },
Alex Perry81f96ba2022-03-13 18:26:19 -0700529 }
530
531 if !reflect.DeepEqual(database.notes, expected) {
532 t.Fatal("Submitted notes did not match", expected, database.notes)
533 }
534}
535
536func TestRequestNotes(t *testing.T) {
537 database := MockDatabase{
538 notes: []db.NotesData{{
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800539 TeamNumber: 971,
540 Notes: "Notes",
541 GoodDriving: true,
542 BadDriving: false,
543 SketchyPickup: true,
544 SketchyPlacing: false,
545 GoodDefense: true,
546 BadDefense: false,
547 EasilyDefended: true,
Alex Perry81f96ba2022-03-13 18:26:19 -0700548 }},
549 }
550 scoutingServer := server.NewScoutingServer()
Philipp Schrader43c730b2023-02-26 20:27:44 -0800551 HandleRequests(&database, scoutingServer)
Alex Perry81f96ba2022-03-13 18:26:19 -0700552 scoutingServer.Start(8080)
553 defer scoutingServer.Stop()
554
555 builder := flatbuffers.NewBuilder(1024)
556 builder.Finish((&request_notes_for_team.RequestNotesForTeamT{
557 Team: 971,
558 }).Pack(builder))
559 response, err := debug.RequestNotes("http://localhost:8080", builder.FinishedBytes())
560 if err != nil {
561 t.Fatal("Failed to submit notes: ", err)
562 }
563
564 if response.Notes[0].Data != "Notes" {
565 t.Fatal("requested notes did not match", response)
566 }
567}
568
Milo Lin1d59f0c2022-06-22 20:30:58 -0700569func TestRequestShiftSchedule(t *testing.T) {
570 db := MockDatabase{
571 shiftSchedule: []db.Shift{
572 {
573 MatchNumber: 1,
574 R1scouter: "Bob",
575 R2scouter: "James",
576 R3scouter: "Robert",
577 B1scouter: "Alice",
578 B2scouter: "Mary",
579 B3scouter: "Patricia",
580 },
581 {
582 MatchNumber: 2,
583 R1scouter: "Liam",
584 R2scouter: "Noah",
585 R3scouter: "Oliver",
586 B1scouter: "Emma",
587 B2scouter: "Charlotte",
588 B3scouter: "Amelia",
589 },
590 },
591 }
592 scoutingServer := server.NewScoutingServer()
Philipp Schrader43c730b2023-02-26 20:27:44 -0800593 HandleRequests(&db, scoutingServer)
Milo Lin1d59f0c2022-06-22 20:30:58 -0700594 scoutingServer.Start(8080)
595 defer scoutingServer.Stop()
596
597 builder := flatbuffers.NewBuilder(1024)
598 builder.Finish((&request_shift_schedule.RequestShiftScheduleT{}).Pack(builder))
599
600 response, err := debug.RequestShiftSchedule("http://localhost:8080", builder.FinishedBytes())
601 if err != nil {
602 t.Fatal("Failed to request shift schedule: ", err)
603 }
604
605 expected := request_shift_schedule_response.RequestShiftScheduleResponseT{
606 ShiftSchedule: []*request_shift_schedule_response.MatchAssignmentT{
607 {
608 MatchNumber: 1,
609 R1scouter: "Bob",
610 R2scouter: "James",
611 R3scouter: "Robert",
612 B1scouter: "Alice",
613 B2scouter: "Mary",
614 B3scouter: "Patricia",
615 },
616 {
617 MatchNumber: 2,
618 R1scouter: "Liam",
619 R2scouter: "Noah",
620 R3scouter: "Oliver",
621 B1scouter: "Emma",
622 B2scouter: "Charlotte",
623 B3scouter: "Amelia",
624 },
625 },
626 }
627 if len(expected.ShiftSchedule) != len(response.ShiftSchedule) {
628 t.Fatal("Expected ", expected, ", but got ", *response)
629 }
630 for i, match := range expected.ShiftSchedule {
631 if !reflect.DeepEqual(*match, *response.ShiftSchedule[i]) {
632 t.Fatal("Expected for shift schedule", i, ":", *match, ", but got:", *response.ShiftSchedule[i])
633 }
634 }
635}
636
637func TestSubmitShiftSchedule(t *testing.T) {
638 database := MockDatabase{}
639 scoutingServer := server.NewScoutingServer()
Philipp Schrader43c730b2023-02-26 20:27:44 -0800640 HandleRequests(&database, scoutingServer)
Milo Lin1d59f0c2022-06-22 20:30:58 -0700641 scoutingServer.Start(8080)
642 defer scoutingServer.Stop()
643
644 builder := flatbuffers.NewBuilder(1024)
645 builder.Finish((&submit_shift_schedule.SubmitShiftScheduleT{
646 ShiftSchedule: []*submit_shift_schedule.MatchAssignmentT{
647 {MatchNumber: 1,
648 R1scouter: "Bob",
649 R2scouter: "James",
650 R3scouter: "Robert",
651 B1scouter: "Alice",
652 B2scouter: "Mary",
653 B3scouter: "Patricia"},
654 },
655 }).Pack(builder))
656
657 _, err := debug.SubmitShiftSchedule("http://localhost:8080", builder.FinishedBytes())
658 if err != nil {
659 t.Fatal("Failed to submit shift schedule: ", err)
660 }
661
662 expected := []db.Shift{
663 {MatchNumber: 1,
664 R1scouter: "Bob",
665 R2scouter: "James",
666 R3scouter: "Robert",
667 B1scouter: "Alice",
668 B2scouter: "Mary",
669 B3scouter: "Patricia"},
670 }
671 if !reflect.DeepEqual(expected, database.shiftSchedule) {
672 t.Fatal("Expected ", expected, ", but got:", database.shiftSchedule)
673 }
674}
675
Filip Kujawa210a03b2022-11-24 14:41:11 -0800676func TestSubmitDriverRanking(t *testing.T) {
677 database := MockDatabase{}
678 scoutingServer := server.NewScoutingServer()
Philipp Schrader43c730b2023-02-26 20:27:44 -0800679 HandleRequests(&database, scoutingServer)
Filip Kujawa210a03b2022-11-24 14:41:11 -0800680 scoutingServer.Start(8080)
681 defer scoutingServer.Stop()
682
683 builder := flatbuffers.NewBuilder(1024)
684 builder.Finish((&submit_driver_ranking.SubmitDriverRankingT{
685 MatchNumber: 36,
686 Rank1: 1234,
687 Rank2: 1235,
688 Rank3: 1236,
689 }).Pack(builder))
690
691 _, err := debug.SubmitDriverRanking("http://localhost:8080", builder.FinishedBytes())
692 if err != nil {
693 t.Fatal("Failed to submit driver ranking: ", err)
694 }
695
696 expected := []db.DriverRankingData{
697 {MatchNumber: 36, Rank1: 1234, Rank2: 1235, Rank3: 1236},
698 }
699
700 if !reflect.DeepEqual(database.driver_ranking, expected) {
701 t.Fatal("Submitted notes did not match", expected, database.notes)
702 }
703}
704
Filip Kujawaf882e022022-12-14 13:14:08 -0800705// Validates that we can request the driver rankings.
706func TestRequestDriverRankings(t *testing.T) {
707 db := MockDatabase{
708 driver_ranking: []db.DriverRankingData{
709 {
710 MatchNumber: 36,
711 Rank1: 1234,
712 Rank2: 1235,
713 Rank3: 1236,
714 },
715 {
716 MatchNumber: 36,
717 Rank1: 101,
718 Rank2: 202,
719 Rank3: 303,
720 },
721 },
722 }
723 scoutingServer := server.NewScoutingServer()
Philipp Schrader43c730b2023-02-26 20:27:44 -0800724 HandleRequests(&db, scoutingServer)
Filip Kujawaf882e022022-12-14 13:14:08 -0800725 scoutingServer.Start(8080)
726 defer scoutingServer.Stop()
727
728 builder := flatbuffers.NewBuilder(1024)
729 builder.Finish((&request_all_driver_rankings.RequestAllDriverRankingsT{}).Pack(builder))
730
731 response, err := debug.RequestAllDriverRankings("http://localhost:8080", builder.FinishedBytes())
732 if err != nil {
733 t.Fatal("Failed to request all driver rankings: ", err)
734 }
735
736 expected := request_all_driver_rankings_response.RequestAllDriverRankingsResponseT{
737 DriverRankingList: []*request_all_driver_rankings_response.RankingT{
738 {
739 MatchNumber: 36,
740 Rank1: 1234,
741 Rank2: 1235,
742 Rank3: 1236,
743 },
744 {
745 MatchNumber: 36,
746 Rank1: 101,
747 Rank2: 202,
748 Rank3: 303,
749 },
750 },
751 }
752 if len(expected.DriverRankingList) != len(response.DriverRankingList) {
753 t.Fatal("Expected ", expected, ", but got ", *response)
754 }
755 for i, match := range expected.DriverRankingList {
756 if !reflect.DeepEqual(*match, *response.DriverRankingList[i]) {
757 t.Fatal("Expected for driver ranking", i, ":", *match, ", but got:", *response.DriverRankingList[i])
758 }
759 }
760}
761
762// Validates that we can request all notes.
763func TestRequestAllNotes(t *testing.T) {
764 db := MockDatabase{
765 notes: []db.NotesData{
766 {
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800767 TeamNumber: 971,
768 Notes: "Notes",
769 GoodDriving: true,
770 BadDriving: false,
771 SketchyPickup: true,
772 SketchyPlacing: false,
773 GoodDefense: true,
774 BadDefense: false,
775 EasilyDefended: false,
Filip Kujawaf882e022022-12-14 13:14:08 -0800776 },
777 {
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800778 TeamNumber: 972,
779 Notes: "More Notes",
780 GoodDriving: false,
781 BadDriving: false,
782 SketchyPickup: false,
783 SketchyPlacing: true,
784 GoodDefense: false,
785 BadDefense: true,
786 EasilyDefended: false,
Filip Kujawaf882e022022-12-14 13:14:08 -0800787 },
788 },
789 }
790 scoutingServer := server.NewScoutingServer()
Philipp Schrader43c730b2023-02-26 20:27:44 -0800791 HandleRequests(&db, scoutingServer)
Filip Kujawaf882e022022-12-14 13:14:08 -0800792 scoutingServer.Start(8080)
793 defer scoutingServer.Stop()
794
795 builder := flatbuffers.NewBuilder(1024)
796 builder.Finish((&request_all_notes.RequestAllNotesT{}).Pack(builder))
797
798 response, err := debug.RequestAllNotes("http://localhost:8080", builder.FinishedBytes())
799 if err != nil {
800 t.Fatal("Failed to request all notes: ", err)
801 }
802
803 expected := request_all_notes_response.RequestAllNotesResponseT{
804 NoteList: []*request_all_notes_response.NoteT{
805 {
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800806 Team: 971,
807 Notes: "Notes",
808 GoodDriving: true,
809 BadDriving: false,
810 SketchyPickup: true,
811 SketchyPlacing: false,
812 GoodDefense: true,
813 BadDefense: false,
814 EasilyDefended: false,
Filip Kujawaf882e022022-12-14 13:14:08 -0800815 },
816 {
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800817 Team: 972,
818 Notes: "More Notes",
819 GoodDriving: false,
820 BadDriving: false,
821 SketchyPickup: false,
822 SketchyPlacing: true,
823 GoodDefense: false,
824 BadDefense: true,
825 EasilyDefended: false,
Filip Kujawaf882e022022-12-14 13:14:08 -0800826 },
827 },
828 }
829 if len(expected.NoteList) != len(response.NoteList) {
830 t.Fatal("Expected ", expected, ", but got ", *response)
831 }
832 for i, note := range expected.NoteList {
833 if !reflect.DeepEqual(*note, *response.NoteList[i]) {
834 t.Fatal("Expected for note", i, ":", *note, ", but got:", *response.NoteList[i])
835 }
836 }
837}
838
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800839// A mocked database we can use for testing. Add functionality to this as
840// needed for your tests.
841
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800842type MockDatabase struct {
Emily Markovabf24c9e2023-02-08 20:31:11 -0800843 matches []db.TeamMatch
Filip Kujawa210a03b2022-11-24 14:41:11 -0800844 stats []db.Stats
845 notes []db.NotesData
846 shiftSchedule []db.Shift
847 driver_ranking []db.DriverRankingData
Emily Markova290147d2023-03-03 22:40:06 -0800848 stats2023 []db.Stats2023
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800849}
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800850
Emily Markovabf24c9e2023-02-08 20:31:11 -0800851func (database *MockDatabase) AddToMatch(match db.TeamMatch) error {
Philipp Schraderd3fac192022-03-02 20:35:46 -0800852 database.matches = append(database.matches, match)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800853 return nil
854}
855
Philipp Schrader30005e42022-03-06 13:53:58 -0800856func (database *MockDatabase) AddToStats(stats db.Stats) error {
857 database.stats = append(database.stats, stats)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800858 return nil
859}
860
Emily Markova290147d2023-03-03 22:40:06 -0800861func (database *MockDatabase) AddToStats2023(stats2023 db.Stats2023) error {
862 database.stats2023 = append(database.stats2023, stats2023)
863 return nil
864}
Emily Markovabf24c9e2023-02-08 20:31:11 -0800865func (database *MockDatabase) ReturnMatches() ([]db.TeamMatch, error) {
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800866 return database.matches, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800867}
868
869func (database *MockDatabase) ReturnStats() ([]db.Stats, error) {
Philipp Schraderacf96232022-03-01 22:03:30 -0800870 return database.stats, nil
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800871}
872
Emily Markova290147d2023-03-03 22:40:06 -0800873func (database *MockDatabase) ReturnStats2023() ([]db.Stats2023, error) {
874 return database.stats2023, nil
875}
876
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800877func (database *MockDatabase) QueryStats(int) ([]db.Stats, error) {
878 return []db.Stats{}, nil
879}
Philipp Schraderd3fac192022-03-02 20:35:46 -0800880
Philipp Schradereecb8962022-06-01 21:02:42 -0700881func (database *MockDatabase) QueryNotes(requestedTeam int32) ([]string, error) {
Alex Perry81f96ba2022-03-13 18:26:19 -0700882 var results []string
883 for _, data := range database.notes {
884 if data.TeamNumber == requestedTeam {
Philipp Schradereecb8962022-06-01 21:02:42 -0700885 results = append(results, data.Notes)
Alex Perry81f96ba2022-03-13 18:26:19 -0700886 }
887 }
Philipp Schradereecb8962022-06-01 21:02:42 -0700888 return results, nil
Alex Perry81f96ba2022-03-13 18:26:19 -0700889}
890
Filip Kujawaf947cb42022-11-21 10:00:30 -0800891func (database *MockDatabase) AddNotes(data db.NotesData) error {
892 database.notes = append(database.notes, data)
Alex Perry81f96ba2022-03-13 18:26:19 -0700893 return nil
894}
895
Filip Kujawaf882e022022-12-14 13:14:08 -0800896func (database *MockDatabase) ReturnAllNotes() ([]db.NotesData, error) {
897 return database.notes, nil
898}
899
Milo Lin1d59f0c2022-06-22 20:30:58 -0700900func (database *MockDatabase) AddToShift(data db.Shift) error {
901 database.shiftSchedule = append(database.shiftSchedule, data)
902 return nil
903}
904
905func (database *MockDatabase) ReturnAllShifts() ([]db.Shift, error) {
906 return database.shiftSchedule, nil
907}
908
909func (database *MockDatabase) QueryAllShifts(int) ([]db.Shift, error) {
910 return []db.Shift{}, nil
911}
912
Filip Kujawa210a03b2022-11-24 14:41:11 -0800913func (database *MockDatabase) AddDriverRanking(data db.DriverRankingData) error {
914 database.driver_ranking = append(database.driver_ranking, data)
915 return nil
916}
917
Filip Kujawaf882e022022-12-14 13:14:08 -0800918func (database *MockDatabase) ReturnAllDriverRankings() ([]db.DriverRankingData, error) {
919 return database.driver_ranking, nil
920}