scouting: Add support /requests/request/all_matches

This patch adds a new endpoint that accepts the `RequestAllMatches`
message. It simply returns the full list of matches that the database
knows about.

I decided to change public `int` members in the `db` module to `int32`
so they match the flatbuffer definition. This makes comparison
simpler.

Signed-off-by: Philipp Schrader <philipp.schrader@gmail.com>
Change-Id: I9bb2eed020e2889644f5a122105a232a68f2f4bd
diff --git a/scouting/webserver/requests/requests.go b/scouting/webserver/requests/requests.go
index 2462ccb..0a28ca0 100644
--- a/scouting/webserver/requests/requests.go
+++ b/scouting/webserver/requests/requests.go
@@ -7,12 +7,18 @@
 
 	"github.com/frc971/971-Robot-Code/scouting/db"
 	"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/error_response"
+	"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches"
+	"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response"
 	"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting"
 	_ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting_response"
 	"github.com/frc971/971-Robot-Code/scouting/webserver/server"
 	flatbuffers "github.com/google/flatbuffers/go"
 )
 
+type SubmitDataScouting = submit_data_scouting.SubmitDataScouting
+type RequestAllMatches = request_all_matches.RequestAllMatches
+type RequestAllMatchesResponseT = request_all_matches_response.RequestAllMatchesResponseT
+
 // The interface we expect the database abstraction to conform to.
 // We use an interface here because it makes unit testing easier.
 type Database interface {
@@ -43,7 +49,7 @@
 }
 
 // TODO(phil): Can we turn this into a generic?
-func parseSubmitDataScouting(w http.ResponseWriter, buf []byte) (*submit_data_scouting.SubmitDataScouting, bool) {
+func parseSubmitDataScouting(w http.ResponseWriter, buf []byte) (*SubmitDataScouting, bool) {
 	success := true
 	defer func() {
 		if r := recover(); r != nil {
@@ -79,7 +85,63 @@
 	respondNotImplemented(w)
 }
 
+// TODO(phil): Can we turn this into a generic?
+func parseRequestAllMatches(w http.ResponseWriter, buf []byte) (*RequestAllMatches, bool) {
+	success := true
+	defer func() {
+		if r := recover(); r != nil {
+			respondWithError(w, http.StatusBadRequest, fmt.Sprintf("Failed to parse SubmitDataScouting: %v", r))
+			success = false
+		}
+	}()
+	result := request_all_matches.GetRootAsRequestAllMatches(buf, 0)
+	return result, success
+}
+
+// Handles a RequestAllMaches request.
+type requestAllMatchesHandler struct {
+	db Database
+}
+
+func (handler requestAllMatchesHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+	requestBytes, err := io.ReadAll(req.Body)
+	if err != nil {
+		respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
+		return
+	}
+
+	_, success := parseRequestAllMatches(w, requestBytes)
+	if !success {
+		return
+	}
+
+	matches, err := handler.db.ReturnMatches()
+	if err != nil {
+		respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Faled to query database: ", err))
+	}
+
+	var response RequestAllMatchesResponseT
+	for _, match := range matches {
+		response.MatchList = append(response.MatchList, &request_all_matches_response.MatchT{
+			MatchNumber: match.MatchNumber,
+			Round:       match.Round,
+			CompLevel:   match.CompLevel,
+			R1:          match.R1,
+			R2:          match.R2,
+			R3:          match.R3,
+			B1:          match.B1,
+			B2:          match.B2,
+			B3:          match.B3,
+		})
+	}
+
+	builder := flatbuffers.NewBuilder(50 * 1024)
+	builder.Finish((&response).Pack(builder))
+	w.Write(builder.FinishedBytes())
+}
+
 func HandleRequests(db Database, scoutingServer server.ScoutingServer) {
 	scoutingServer.HandleFunc("/requests", unknown)
 	scoutingServer.Handle("/requests/submit/data_scouting", submitDataScoutingHandler{db})
+	scoutingServer.Handle("/requests/request/all_matches", requestAllMatchesHandler{db})
 }