blob: 5a469b5b3d922310a769e7f4fd2b9f5014493b00 [file] [log] [blame]
Philipp Schradercdb5cfc2022-02-20 14:57:07 -08001package requests
2
3import (
Philipp Schraderfae8a7e2022-03-13 22:51:54 -07004 "encoding/base64"
Philipp Schraderd3fac192022-03-02 20:35:46 -08005 "errors"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -08006 "fmt"
7 "io"
Philipp Schraderfae8a7e2022-03-13 22:51:54 -07008 "log"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -08009 "net/http"
Philipp Schraderd3fac192022-03-02 20:35:46 -080010 "strconv"
11 "strings"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080012
Philipp Schrader8747f1b2022-02-23 23:56:22 -080013 "github.com/frc971/971-Robot-Code/scouting/db"
Philipp Schraderd3fac192022-03-02 20:35:46 -080014 "github.com/frc971/971-Robot-Code/scouting/scraping"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080015 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/error_response"
Philipp Schraderd3fac192022-03-02 20:35:46 -080016 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/refresh_match_list"
17 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/refresh_match_list_response"
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080018 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches"
19 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response"
Philipp Schraderacf96232022-03-01 22:03:30 -080020 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting"
21 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting_response"
Philipp Schraderd1c4bef2022-02-28 22:51:30 -080022 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team"
23 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team_response"
Alex Perry81f96ba2022-03-13 18:26:19 -070024 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team"
25 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team_response"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080026 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting"
Philipp Schrader30005e42022-03-06 13:53:58 -080027 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting_response"
Alex Perry81f96ba2022-03-13 18:26:19 -070028 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_notes"
29 "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_notes_response"
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080030 "github.com/frc971/971-Robot-Code/scouting/webserver/server"
31 flatbuffers "github.com/google/flatbuffers/go"
32)
33
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080034type SubmitDataScouting = submit_data_scouting.SubmitDataScouting
Philipp Schrader30005e42022-03-06 13:53:58 -080035type SubmitDataScoutingResponseT = submit_data_scouting_response.SubmitDataScoutingResponseT
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080036type RequestAllMatches = request_all_matches.RequestAllMatches
37type RequestAllMatchesResponseT = request_all_matches_response.RequestAllMatchesResponseT
Philipp Schraderd1c4bef2022-02-28 22:51:30 -080038type RequestMatchesForTeam = request_matches_for_team.RequestMatchesForTeam
39type RequestMatchesForTeamResponseT = request_matches_for_team_response.RequestMatchesForTeamResponseT
Philipp Schraderacf96232022-03-01 22:03:30 -080040type RequestDataScouting = request_data_scouting.RequestDataScouting
41type RequestDataScoutingResponseT = request_data_scouting_response.RequestDataScoutingResponseT
Philipp Schraderd3fac192022-03-02 20:35:46 -080042type RefreshMatchList = refresh_match_list.RefreshMatchList
43type RefreshMatchListResponseT = refresh_match_list_response.RefreshMatchListResponseT
Alex Perry81f96ba2022-03-13 18:26:19 -070044type SubmitNotes = submit_notes.SubmitNotes
45type SubmitNotesResponseT = submit_notes_response.SubmitNotesResponseT
46type RequestNotesForTeam = request_notes_for_team.RequestNotesForTeam
47type RequestNotesForTeamResponseT = request_notes_for_team_response.RequestNotesForTeamResponseT
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080048
Philipp Schrader8747f1b2022-02-23 23:56:22 -080049// The interface we expect the database abstraction to conform to.
50// We use an interface here because it makes unit testing easier.
51type Database interface {
52 AddToMatch(db.Match) error
53 AddToStats(db.Stats) error
54 ReturnMatches() ([]db.Match, error)
55 ReturnStats() ([]db.Stats, error)
Philipp Schraderd1c4bef2022-02-28 22:51:30 -080056 QueryMatches(int32) ([]db.Match, error)
Philipp Schrader8747f1b2022-02-23 23:56:22 -080057 QueryStats(int) ([]db.Stats, error)
Alex Perry81f96ba2022-03-13 18:26:19 -070058 QueryNotes(int32) (db.NotesData, error)
59 AddNotes(db.NotesData) error
Philipp Schrader8747f1b2022-02-23 23:56:22 -080060}
61
Philipp Schraderd3fac192022-03-02 20:35:46 -080062type ScrapeMatchList func(int32, string) ([]scraping.Match, error)
63
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080064// Handles unknown requests. Just returns a 404.
65func unknown(w http.ResponseWriter, req *http.Request) {
66 w.WriteHeader(http.StatusNotFound)
67}
68
69func respondWithError(w http.ResponseWriter, statusCode int, errorMessage string) {
70 builder := flatbuffers.NewBuilder(1024)
71 builder.Finish((&error_response.ErrorResponseT{
72 ErrorMessage: errorMessage,
73 }).Pack(builder))
74 w.WriteHeader(statusCode)
75 w.Write(builder.FinishedBytes())
76}
77
78func respondNotImplemented(w http.ResponseWriter) {
79 respondWithError(w, http.StatusNotImplemented, "")
80}
81
82// TODO(phil): Can we turn this into a generic?
Philipp Schradercbf5c6a2022-02-27 23:25:19 -080083func parseSubmitDataScouting(w http.ResponseWriter, buf []byte) (*SubmitDataScouting, bool) {
Philipp Schradercdb5cfc2022-02-20 14:57:07 -080084 success := true
85 defer func() {
86 if r := recover(); r != nil {
87 respondWithError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse SubmitDataScouting: %v", r))
88 success = false
89 }
90 }()
91 result := submit_data_scouting.GetRootAsSubmitDataScouting(buf, 0)
92 return result, success
93}
94
Philipp Schraderfae8a7e2022-03-13 22:51:54 -070095// Parses the authorization information that the browser inserts into the
96// headers. The authorization follows this format:
97//
98// req.Headers["Authorization"] = []string{"Basic <base64 encoded username:password>"}
99func parseUsername(req *http.Request) string {
100 auth, ok := req.Header["Authorization"]
101 if !ok {
102 return "unknown"
103 }
104
105 parts := strings.Split(auth[0], " ")
106 if !(len(parts) == 2 && parts[0] == "Basic") {
107 return "unknown"
108 }
109
110 info, err := base64.StdEncoding.DecodeString(parts[1])
111 if err != nil {
112 log.Println("ERROR: Failed to parse Basic authentication.")
113 return "unknown"
114 }
115
116 loginParts := strings.Split(string(info), ":")
117 if len(loginParts) != 2 {
118 return "unknown"
119 }
120 return loginParts[0]
121}
122
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800123// Handles a SubmitDataScouting request.
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800124type submitDataScoutingHandler struct {
125 db Database
126}
127
128func (handler submitDataScoutingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
Philipp Schraderfae8a7e2022-03-13 22:51:54 -0700129 // Get the username of the person submitting the data.
130 username := parseUsername(req)
131 log.Println("Got data scouting data from", username)
132
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800133 requestBytes, err := io.ReadAll(req.Body)
134 if err != nil {
135 respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
136 return
137 }
138
Philipp Schrader30005e42022-03-06 13:53:58 -0800139 request, success := parseSubmitDataScouting(w, requestBytes)
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800140 if !success {
141 return
142 }
143
Philipp Schrader30005e42022-03-06 13:53:58 -0800144 stats := db.Stats{
145 TeamNumber: request.Team(),
146 MatchNumber: request.Match(),
147 ShotsMissedAuto: request.MissedShotsAuto(),
148 UpperGoalAuto: request.UpperGoalAuto(),
149 LowerGoalAuto: request.LowerGoalAuto(),
150 ShotsMissed: request.MissedShotsTele(),
151 UpperGoalShots: request.UpperGoalTele(),
152 LowerGoalShots: request.LowerGoalTele(),
153 PlayedDefense: request.DefenseRating(),
154 Climbing: request.Climbing(),
Philipp Schraderfae8a7e2022-03-13 22:51:54 -0700155 CollectedBy: username,
Philipp Schrader30005e42022-03-06 13:53:58 -0800156 }
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800157
Philipp Schrader30005e42022-03-06 13:53:58 -0800158 err = handler.db.AddToStats(stats)
159 if err != nil {
160 respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Failed to submit datascouting data: ", err))
161 }
162
163 builder := flatbuffers.NewBuilder(50 * 1024)
164 builder.Finish((&SubmitDataScoutingResponseT{}).Pack(builder))
165 w.Write(builder.FinishedBytes())
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800166}
167
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800168// TODO(phil): Can we turn this into a generic?
169func parseRequestAllMatches(w http.ResponseWriter, buf []byte) (*RequestAllMatches, bool) {
170 success := true
171 defer func() {
172 if r := recover(); r != nil {
173 respondWithError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse SubmitDataScouting: %v", r))
174 success = false
175 }
176 }()
177 result := request_all_matches.GetRootAsRequestAllMatches(buf, 0)
178 return result, success
179}
180
181// Handles a RequestAllMaches request.
182type requestAllMatchesHandler struct {
183 db Database
184}
185
186func (handler requestAllMatchesHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
187 requestBytes, err := io.ReadAll(req.Body)
188 if err != nil {
189 respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
190 return
191 }
192
193 _, success := parseRequestAllMatches(w, requestBytes)
194 if !success {
195 return
196 }
197
198 matches, err := handler.db.ReturnMatches()
199 if err != nil {
Philipp Schraderfae8a7e2022-03-13 22:51:54 -0700200 respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Failed to query database: ", err))
Philipp Schrader2e7eb0002022-03-02 22:52:39 -0800201 return
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800202 }
203
204 var response RequestAllMatchesResponseT
205 for _, match := range matches {
206 response.MatchList = append(response.MatchList, &request_all_matches_response.MatchT{
207 MatchNumber: match.MatchNumber,
208 Round: match.Round,
209 CompLevel: match.CompLevel,
210 R1: match.R1,
211 R2: match.R2,
212 R3: match.R3,
213 B1: match.B1,
214 B2: match.B2,
215 B3: match.B3,
216 })
217 }
218
219 builder := flatbuffers.NewBuilder(50 * 1024)
220 builder.Finish((&response).Pack(builder))
221 w.Write(builder.FinishedBytes())
222}
223
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800224// TODO(phil): Can we turn this into a generic?
225func parseRequestMatchesForTeam(w http.ResponseWriter, buf []byte) (*RequestMatchesForTeam, bool) {
226 success := true
227 defer func() {
228 if r := recover(); r != nil {
229 respondWithError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse SubmitDataScouting: %v", r))
230 success = false
231 }
232 }()
233 result := request_matches_for_team.GetRootAsRequestMatchesForTeam(buf, 0)
234 return result, success
235}
236
237// Handles a RequestMatchesForTeam request.
238type requestMatchesForTeamHandler struct {
239 db Database
240}
241
242func (handler requestMatchesForTeamHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
243 requestBytes, err := io.ReadAll(req.Body)
244 if err != nil {
245 respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
246 return
247 }
248
249 request, success := parseRequestMatchesForTeam(w, requestBytes)
250 if !success {
251 return
252 }
253
254 matches, err := handler.db.QueryMatches(request.Team())
255 if err != nil {
256 respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Faled to query database: ", err))
Philipp Schrader2e7eb0002022-03-02 22:52:39 -0800257 return
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800258 }
259
260 var response RequestAllMatchesResponseT
261 for _, match := range matches {
262 response.MatchList = append(response.MatchList, &request_all_matches_response.MatchT{
263 MatchNumber: match.MatchNumber,
264 Round: match.Round,
265 CompLevel: match.CompLevel,
266 R1: match.R1,
267 R2: match.R2,
268 R3: match.R3,
269 B1: match.B1,
270 B2: match.B2,
271 B3: match.B3,
272 })
273 }
274
275 builder := flatbuffers.NewBuilder(50 * 1024)
276 builder.Finish((&response).Pack(builder))
277 w.Write(builder.FinishedBytes())
278}
279
Philipp Schraderacf96232022-03-01 22:03:30 -0800280// TODO(phil): Can we turn this into a generic?
281func parseRequestDataScouting(w http.ResponseWriter, buf []byte) (*RequestDataScouting, bool) {
282 success := true
283 defer func() {
284 if r := recover(); r != nil {
285 respondWithError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse SubmitDataScouting: %v", r))
286 success = false
287 }
288 }()
289 result := request_data_scouting.GetRootAsRequestDataScouting(buf, 0)
290 return result, success
291}
292
293// Handles a RequestDataScouting request.
294type requestDataScoutingHandler struct {
295 db Database
296}
297
298func (handler requestDataScoutingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
299 requestBytes, err := io.ReadAll(req.Body)
300 if err != nil {
301 respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
302 return
303 }
304
305 _, success := parseRequestDataScouting(w, requestBytes)
306 if !success {
307 return
308 }
309
310 stats, err := handler.db.ReturnStats()
311 if err != nil {
312 respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Faled to query database: ", err))
Philipp Schrader2e7eb0002022-03-02 22:52:39 -0800313 return
Philipp Schraderacf96232022-03-01 22:03:30 -0800314 }
315
316 var response RequestDataScoutingResponseT
317 for _, stat := range stats {
318 response.StatsList = append(response.StatsList, &request_data_scouting_response.StatsT{
319 Team: stat.TeamNumber,
320 Match: stat.MatchNumber,
321 MissedShotsAuto: stat.ShotsMissedAuto,
322 UpperGoalAuto: stat.UpperGoalAuto,
323 LowerGoalAuto: stat.LowerGoalAuto,
324 MissedShotsTele: stat.ShotsMissed,
325 UpperGoalTele: stat.UpperGoalShots,
326 LowerGoalTele: stat.LowerGoalShots,
327 DefenseRating: stat.PlayedDefense,
328 Climbing: stat.Climbing,
Philipp Schraderfae8a7e2022-03-13 22:51:54 -0700329 CollectedBy: stat.CollectedBy,
Philipp Schraderacf96232022-03-01 22:03:30 -0800330 })
331 }
332
333 builder := flatbuffers.NewBuilder(50 * 1024)
334 builder.Finish((&response).Pack(builder))
335 w.Write(builder.FinishedBytes())
336}
337
Philipp Schraderd3fac192022-03-02 20:35:46 -0800338// TODO(phil): Can we turn this into a generic?
339func parseRefreshMatchList(w http.ResponseWriter, buf []byte) (*RefreshMatchList, bool) {
340 success := true
341 defer func() {
342 if r := recover(); r != nil {
343 respondWithError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse RefreshMatchList: %v", r))
344 success = false
345 }
346 }()
347 result := refresh_match_list.GetRootAsRefreshMatchList(buf, 0)
348 return result, success
349}
350
351func parseTeamKey(teamKey string) (int, error) {
352 // TBA prefixes teams with "frc". Not sure why. Get rid of that.
353 teamKey = strings.TrimPrefix(teamKey, "frc")
354 return strconv.Atoi(teamKey)
355}
356
357// Parses the alliance data from the specified match and returns the three red
358// teams and the three blue teams.
359func parseTeamKeys(match *scraping.Match) ([3]int32, [3]int32, error) {
360 redKeys := match.Alliances.Red.TeamKeys
361 blueKeys := match.Alliances.Blue.TeamKeys
362
363 if len(redKeys) != 3 || len(blueKeys) != 3 {
364 return [3]int32{}, [3]int32{}, errors.New(fmt.Sprintf(
365 "Found %d red teams and %d blue teams.", len(redKeys), len(blueKeys)))
366 }
367
368 var red [3]int32
369 for i, key := range redKeys {
370 team, err := parseTeamKey(key)
371 if err != nil {
372 return [3]int32{}, [3]int32{}, errors.New(fmt.Sprintf(
373 "Failed to parse red %d team '%s' as integer: %v", i+1, key, err))
374 }
375 red[i] = int32(team)
376 }
377 var blue [3]int32
378 for i, key := range blueKeys {
379 team, err := parseTeamKey(key)
380 if err != nil {
381 return [3]int32{}, [3]int32{}, errors.New(fmt.Sprintf(
382 "Failed to parse blue %d team '%s' as integer: %v", i+1, key, err))
383 }
384 blue[i] = int32(team)
385 }
386 return red, blue, nil
387}
388
389type refreshMatchListHandler struct {
390 db Database
391 scrape ScrapeMatchList
392}
393
394func (handler refreshMatchListHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
395 requestBytes, err := io.ReadAll(req.Body)
396 if err != nil {
397 respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
398 return
399 }
400
401 request, success := parseRefreshMatchList(w, requestBytes)
402 if !success {
403 return
404 }
405
406 matches, err := handler.scrape(request.Year(), string(request.EventCode()))
407 if err != nil {
408 respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Faled to scrape match list: ", err))
409 return
410 }
411
412 for _, match := range matches {
413 // Make sure the data is valid.
414 red, blue, err := parseTeamKeys(&match)
415 if err != nil {
416 respondWithError(w, http.StatusInternalServerError, fmt.Sprintf(
417 "TheBlueAlliance data for match %d is malformed: %v", match.MatchNumber, err))
418 return
419 }
420 // Add the match to the database.
Philipp Schrader7365d322022-03-06 16:40:08 -0800421 err = handler.db.AddToMatch(db.Match{
Philipp Schraderd3fac192022-03-02 20:35:46 -0800422 MatchNumber: int32(match.MatchNumber),
423 // TODO(phil): What does Round mean?
424 Round: 1,
425 CompLevel: match.CompLevel,
426 R1: red[0],
427 R2: red[1],
428 R3: red[2],
429 B1: blue[0],
430 B2: blue[1],
431 B3: blue[2],
432 })
Philipp Schrader7365d322022-03-06 16:40:08 -0800433 if err != nil {
434 respondWithError(w, http.StatusInternalServerError, fmt.Sprintf(
435 "Failed to add match %d to the database: %v", match.MatchNumber, err))
436 return
437 }
Philipp Schraderd3fac192022-03-02 20:35:46 -0800438 }
439
440 var response RefreshMatchListResponseT
441 builder := flatbuffers.NewBuilder(1024)
442 builder.Finish((&response).Pack(builder))
443 w.Write(builder.FinishedBytes())
444}
445
Alex Perry81f96ba2022-03-13 18:26:19 -0700446func parseSubmitNotes(w http.ResponseWriter, buf []byte) (*SubmitNotes, bool) {
447 success := true
448 defer func() {
449 if r := recover(); r != nil {
450 respondWithError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse RefreshMatchList: %v", r))
451 success = false
452 }
453 }()
454 result := submit_notes.GetRootAsSubmitNotes(buf, 0)
455 return result, success
456}
457
458type submitNoteScoutingHandler struct {
459 db Database
460}
461
462func (handler submitNoteScoutingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
463 requestBytes, err := io.ReadAll(req.Body)
464 if err != nil {
465 respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
466 return
467 }
468
469 request, success := parseSubmitNotes(w, requestBytes)
470 if !success {
471 return
472 }
473
474 err = handler.db.AddNotes(db.NotesData{
475 TeamNumber: request.Team(),
476 Notes: []string{string(request.Notes())},
477 })
478 if err != nil {
479 respondWithError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to insert notes: %v", err))
480 return
481 }
482
483 var response SubmitNotesResponseT
484 builder := flatbuffers.NewBuilder(10)
485 builder.Finish((&response).Pack(builder))
486 w.Write(builder.FinishedBytes())
487}
488
489func parseRequestNotesForTeam(w http.ResponseWriter, buf []byte) (*RequestNotesForTeam, bool) {
490 success := true
491 defer func() {
492 if r := recover(); r != nil {
493 respondWithError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse RefreshMatchList: %v", r))
494 success = false
495 }
496 }()
497 result := request_notes_for_team.GetRootAsRequestNotesForTeam(buf, 0)
498 return result, success
499}
500
501type requestNotesForTeamHandler struct {
502 db Database
503}
504
505func (handler requestNotesForTeamHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
506 requestBytes, err := io.ReadAll(req.Body)
507 if err != nil {
508 respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
509 return
510 }
511
512 request, success := parseRequestNotesForTeam(w, requestBytes)
513 if !success {
514 return
515 }
516
517 notesData, err := handler.db.QueryNotes(request.Team())
518 if err != nil {
519 respondWithError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to query notes: %v", err))
520 return
521 }
522
523 var response RequestNotesForTeamResponseT
524 for _, data := range notesData.Notes {
525 response.Notes = append(response.Notes, &request_notes_for_team_response.NoteT{data})
526 }
527
528 builder := flatbuffers.NewBuilder(1024)
529 builder.Finish((&response).Pack(builder))
530 w.Write(builder.FinishedBytes())
531}
532
Philipp Schraderd3fac192022-03-02 20:35:46 -0800533func HandleRequests(db Database, scrape ScrapeMatchList, scoutingServer server.ScoutingServer) {
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800534 scoutingServer.HandleFunc("/requests", unknown)
Philipp Schrader8747f1b2022-02-23 23:56:22 -0800535 scoutingServer.Handle("/requests/submit/data_scouting", submitDataScoutingHandler{db})
Philipp Schradercbf5c6a2022-02-27 23:25:19 -0800536 scoutingServer.Handle("/requests/request/all_matches", requestAllMatchesHandler{db})
Philipp Schraderd1c4bef2022-02-28 22:51:30 -0800537 scoutingServer.Handle("/requests/request/matches_for_team", requestMatchesForTeamHandler{db})
Philipp Schraderacf96232022-03-01 22:03:30 -0800538 scoutingServer.Handle("/requests/request/data_scouting", requestDataScoutingHandler{db})
Philipp Schraderd3fac192022-03-02 20:35:46 -0800539 scoutingServer.Handle("/requests/refresh_match_list", refreshMatchListHandler{db, scrape})
Alex Perry81f96ba2022-03-13 18:26:19 -0700540 scoutingServer.Handle("/requests/submit/submit_notes", submitNoteScoutingHandler{db})
541 scoutingServer.Handle("/requests/request/notes_for_team", requestNotesForTeamHandler{db})
Philipp Schradercdb5cfc2022-02-20 14:57:07 -0800542}