scouting: adding support for requests with shift schedule
Signed-off-by: Milo Lin <100027790@mvla.net>
Change-Id: I653e2874b1c74a9ac65105f05dd3af00dcca8fb9
diff --git a/BUILD b/BUILD
index 8b45953..9368a1f 100644
--- a/BUILD
+++ b/BUILD
@@ -28,6 +28,10 @@
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches //scouting/webserver/requests/messages:request_all_matches_go_fbs
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/refresh_match_list //scouting/webserver/requests/messages:refresh_match_list_go_fbs
# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/refresh_match_list_response //scouting/webserver/requests/messages:refresh_match_list_response_go_fbs
+# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule //scouting/webserver/requests/messages:request_shift_schedule_go_fbs
+# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule_response //scouting/webserver/requests/messages:request_shift_schedule_response_go_fbs
+# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_shift_schedule //scouting/webserver/requests/messages:submit_shift_schedule_go_fbs
+# gazelle:resolve go github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_shift_schedule_response //scouting/webserver/requests/messages:submit_shift_schedule_response_go_fbs
gazelle(
name = "gazelle",
diff --git a/scouting/webserver/requests/BUILD b/scouting/webserver/requests/BUILD
index 744772c..87575a9 100644
--- a/scouting/webserver/requests/BUILD
+++ b/scouting/webserver/requests/BUILD
@@ -20,10 +20,14 @@
"//scouting/webserver/requests/messages:request_matches_for_team_response_go_fbs",
"//scouting/webserver/requests/messages:request_notes_for_team_go_fbs",
"//scouting/webserver/requests/messages:request_notes_for_team_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_shift_schedule_go_fbs",
+ "//scouting/webserver/requests/messages:request_shift_schedule_response_go_fbs",
"//scouting/webserver/requests/messages:submit_data_scouting_go_fbs",
"//scouting/webserver/requests/messages:submit_data_scouting_response_go_fbs",
"//scouting/webserver/requests/messages:submit_notes_go_fbs",
"//scouting/webserver/requests/messages:submit_notes_response_go_fbs",
+ "//scouting/webserver/requests/messages:submit_shift_schedule_go_fbs",
+ "//scouting/webserver/requests/messages:submit_shift_schedule_response_go_fbs",
"//scouting/webserver/server",
"@com_github_google_flatbuffers//go:go_default_library",
],
@@ -48,9 +52,12 @@
"//scouting/webserver/requests/messages:request_matches_for_team_go_fbs",
"//scouting/webserver/requests/messages:request_matches_for_team_response_go_fbs",
"//scouting/webserver/requests/messages:request_notes_for_team_go_fbs",
+ "//scouting/webserver/requests/messages:request_shift_schedule_go_fbs",
+ "//scouting/webserver/requests/messages:request_shift_schedule_response_go_fbs",
"//scouting/webserver/requests/messages:submit_data_scouting_go_fbs",
"//scouting/webserver/requests/messages:submit_data_scouting_response_go_fbs",
"//scouting/webserver/requests/messages:submit_notes_go_fbs",
+ "//scouting/webserver/requests/messages:submit_shift_schedule_go_fbs",
"//scouting/webserver/server",
"@com_github_google_flatbuffers//go:go_default_library",
],
diff --git a/scouting/webserver/requests/debug/BUILD b/scouting/webserver/requests/debug/BUILD
index 6adaee5..04c4ffa 100644
--- a/scouting/webserver/requests/debug/BUILD
+++ b/scouting/webserver/requests/debug/BUILD
@@ -13,8 +13,10 @@
"//scouting/webserver/requests/messages:request_data_scouting_response_go_fbs",
"//scouting/webserver/requests/messages:request_matches_for_team_response_go_fbs",
"//scouting/webserver/requests/messages:request_notes_for_team_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_shift_schedule_response_go_fbs",
"//scouting/webserver/requests/messages:submit_data_scouting_response_go_fbs",
"//scouting/webserver/requests/messages:submit_notes_response_go_fbs",
+ "//scouting/webserver/requests/messages:submit_shift_schedule_response_go_fbs",
"@com_github_google_flatbuffers//go:go_default_library",
],
)
diff --git a/scouting/webserver/requests/debug/debug.go b/scouting/webserver/requests/debug/debug.go
index 21f0f05..b3df518 100644
--- a/scouting/webserver/requests/debug/debug.go
+++ b/scouting/webserver/requests/debug/debug.go
@@ -15,8 +15,10 @@
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_data_scouting_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_data_scouting_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_notes_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_shift_schedule_response"
flatbuffers "github.com/google/flatbuffers/go"
)
@@ -143,3 +145,15 @@
server+"/requests/request/notes_for_team", requestBytes,
request_notes_for_team_response.GetRootAsRequestNotesForTeamResponse)
}
+
+func RequestShiftSchedule(server string, requestBytes []byte) (*request_shift_schedule_response.RequestShiftScheduleResponseT, error) {
+ return sendMessage[request_shift_schedule_response.RequestShiftScheduleResponseT](
+ server+"/requests/request/shift_schedule", requestBytes,
+ request_shift_schedule_response.GetRootAsRequestShiftScheduleResponse)
+}
+
+func SubmitShiftSchedule(server string, requestBytes []byte) (*submit_shift_schedule_response.SubmitShiftScheduleResponseT, error) {
+ return sendMessage[submit_shift_schedule_response.SubmitShiftScheduleResponseT](
+ server+"/requests/submit/shift_schedule", requestBytes,
+ submit_shift_schedule_response.GetRootAsSubmitShiftScheduleResponse)
+}
diff --git a/scouting/webserver/requests/messages/BUILD b/scouting/webserver/requests/messages/BUILD
index f7e194b..d804ea6 100644
--- a/scouting/webserver/requests/messages/BUILD
+++ b/scouting/webserver/requests/messages/BUILD
@@ -16,6 +16,10 @@
"submit_notes_response",
"request_notes_for_team",
"request_notes_for_team_response",
+ "request_shift_schedule",
+ "request_shift_schedule_response",
+ "submit_shift_schedule",
+ "submit_shift_schedule_response",
)
filegroup(
diff --git a/scouting/webserver/requests/messages/request_shift_schedule.fbs b/scouting/webserver/requests/messages/request_shift_schedule.fbs
new file mode 100644
index 0000000..8f2a61c
--- /dev/null
+++ b/scouting/webserver/requests/messages/request_shift_schedule.fbs
@@ -0,0 +1,6 @@
+namespace scouting.webserver.requests;
+
+table RequestShiftSchedule {
+}
+
+root_type RequestShiftSchedule;
\ No newline at end of file
diff --git a/scouting/webserver/requests/messages/request_shift_schedule_response.fbs b/scouting/webserver/requests/messages/request_shift_schedule_response.fbs
new file mode 100644
index 0000000..611db49
--- /dev/null
+++ b/scouting/webserver/requests/messages/request_shift_schedule_response.fbs
@@ -0,0 +1,17 @@
+namespace scouting.webserver.requests;
+
+table MatchAssignment {
+ match_number:int (id:0);
+ R1scouter:string (id:1);
+ R2scouter:string (id:2);
+ R3scouter:string (id:3);
+ B1scouter:string (id:4);
+ B2scouter:string (id:5);
+ B3scouter:string (id:6);
+}
+
+table RequestShiftScheduleResponse {
+ shift_schedule:[MatchAssignment] (id:0);
+}
+
+root_type RequestShiftScheduleResponse;
\ No newline at end of file
diff --git a/scouting/webserver/requests/messages/submit_shift_schedule.fbs b/scouting/webserver/requests/messages/submit_shift_schedule.fbs
new file mode 100644
index 0000000..1f1833e
--- /dev/null
+++ b/scouting/webserver/requests/messages/submit_shift_schedule.fbs
@@ -0,0 +1,17 @@
+namespace scouting.webserver.requests;
+
+table MatchAssignment {
+ match_number:int (id:0);
+ R1scouter:string (id:1);
+ R2scouter:string (id:2);
+ R3scouter:string (id:3);
+ B1scouter:string (id:4);
+ B2scouter:string (id:5);
+ B3scouter:string (id:6);
+}
+
+table SubmitShiftSchedule {
+ shift_schedule:[MatchAssignment] (id:0);
+}
+
+root_type SubmitShiftSchedule;
\ No newline at end of file
diff --git a/scouting/webserver/requests/messages/submit_shift_schedule_response.fbs b/scouting/webserver/requests/messages/submit_shift_schedule_response.fbs
new file mode 100644
index 0000000..17eadbc
--- /dev/null
+++ b/scouting/webserver/requests/messages/submit_shift_schedule_response.fbs
@@ -0,0 +1,6 @@
+namespace scouting.webserver.requests;
+
+table SubmitShiftScheduleResponse {
+}
+
+root_type SubmitShiftScheduleResponse;
\ No newline at end of file
diff --git a/scouting/webserver/requests/requests.go b/scouting/webserver/requests/requests.go
index cef87aa..67a1722 100644
--- a/scouting/webserver/requests/requests.go
+++ b/scouting/webserver/requests/requests.go
@@ -23,10 +23,14 @@
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule_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/requests/messages/submit_notes"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_notes_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_shift_schedule"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_shift_schedule_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/server"
flatbuffers "github.com/google/flatbuffers/go"
)
@@ -45,15 +49,22 @@
type SubmitNotesResponseT = submit_notes_response.SubmitNotesResponseT
type RequestNotesForTeam = request_notes_for_team.RequestNotesForTeam
type RequestNotesForTeamResponseT = request_notes_for_team_response.RequestNotesForTeamResponseT
+type RequestShiftSchedule = request_shift_schedule.RequestShiftSchedule
+type RequestShiftScheduleResponseT = request_shift_schedule_response.RequestShiftScheduleResponseT
+type SubmitShiftSchedule = submit_shift_schedule.SubmitShiftSchedule
+type SubmitShiftScheduleResponseT = submit_shift_schedule_response.SubmitShiftScheduleResponseT
// The interface we expect the database abstraction to conform to.
// We use an interface here because it makes unit testing easier.
type Database interface {
AddToMatch(db.Match) error
+ AddToShift(db.Shift) error
AddToStats(db.Stats) error
ReturnMatches() ([]db.Match, error)
+ ReturnAllShifts() ([]db.Shift, error)
ReturnStats() ([]db.Stats, error)
QueryMatches(int32) ([]db.Match, error)
+ QueryAllShifts(int) ([]db.Shift, error)
QueryStats(int) ([]db.Stats, error)
QueryNotes(int32) (db.NotesData, error)
AddNotes(db.NotesData) error
@@ -480,6 +491,91 @@
w.Write(builder.FinishedBytes())
}
+type requestShiftScheduleHandler struct {
+ db Database
+}
+
+func (handler requestShiftScheduleHandler) 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 := parseRequest(w, requestBytes, "RequestShiftSchedule", request_shift_schedule.GetRootAsRequestShiftSchedule)
+ if !success {
+ return
+ }
+
+ shiftData, err := handler.db.ReturnAllShifts()
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to query shift schedule: %v", err))
+ return
+ }
+
+ var response RequestShiftScheduleResponseT
+ for _, shifts := range shiftData {
+ response.ShiftSchedule = append(response.ShiftSchedule, &request_shift_schedule_response.MatchAssignmentT{
+ MatchNumber: shifts.MatchNumber,
+ R1scouter: shifts.R1scouter,
+ R2scouter: shifts.R2scouter,
+ R3scouter: shifts.R3scouter,
+ B1scouter: shifts.B1scouter,
+ B2scouter: shifts.B2scouter,
+ B3scouter: shifts.B3scouter,
+ })
+ }
+
+ builder := flatbuffers.NewBuilder(1024)
+ builder.Finish((&response).Pack(builder))
+ w.Write(builder.FinishedBytes())
+}
+
+type submitShiftScheduleHandler struct {
+ db Database
+}
+
+func (handler submitShiftScheduleHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ // Get the username of the person submitting the data.
+ username := parseUsername(req)
+
+ requestBytes, err := io.ReadAll(req.Body)
+ if err != nil {
+ respondWithError(w, http.StatusBadRequest, fmt.Sprint("Failed to read request bytes:", err))
+ return
+ }
+
+ request, success := parseRequest[SubmitShiftSchedule](w, requestBytes, "SubmitShiftSchedule", submit_shift_schedule.GetRootAsSubmitShiftSchedule)
+ if !success {
+ return
+ }
+
+ log.Println("Got shift schedule from", username)
+ shift_schedule_length := request.ShiftScheduleLength()
+ for i := 0; i < shift_schedule_length; i++ {
+ var match_assignment submit_shift_schedule.MatchAssignment
+ request.ShiftSchedule(&match_assignment, i)
+ current_shift := db.Shift{
+ MatchNumber: match_assignment.MatchNumber(),
+ R1scouter: string(match_assignment.R1scouter()),
+ R2scouter: string(match_assignment.R2scouter()),
+ R3scouter: string(match_assignment.R3scouter()),
+ B1scouter: string(match_assignment.B1scouter()),
+ B2scouter: string(match_assignment.B2scouter()),
+ B3scouter: string(match_assignment.B3scouter()),
+ }
+ err = handler.db.AddToShift(current_shift)
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Failed to submit shift schedule: ", err))
+ return
+ }
+ }
+
+ builder := flatbuffers.NewBuilder(50 * 1024)
+ builder.Finish((&SubmitShiftScheduleResponseT{}).Pack(builder))
+ w.Write(builder.FinishedBytes())
+}
+
func HandleRequests(db Database, scrape ScrapeMatchList, scoutingServer server.ScoutingServer) {
scoutingServer.HandleFunc("/requests", unknown)
scoutingServer.Handle("/requests/submit/data_scouting", submitDataScoutingHandler{db})
@@ -489,4 +585,6 @@
scoutingServer.Handle("/requests/refresh_match_list", refreshMatchListHandler{db, scrape})
scoutingServer.Handle("/requests/submit/submit_notes", submitNoteScoutingHandler{db})
scoutingServer.Handle("/requests/request/notes_for_team", requestNotesForTeamHandler{db})
+ scoutingServer.Handle("/requests/submit/shift_schedule", submitShiftScheduleHandler{db})
+ scoutingServer.Handle("/requests/request/shift_schedule", requestShiftScheduleHandler{db})
}
diff --git a/scouting/webserver/requests/requests_test.go b/scouting/webserver/requests/requests_test.go
index 4dda143..44fd5db 100644
--- a/scouting/webserver/requests/requests_test.go
+++ b/scouting/webserver/requests/requests_test.go
@@ -20,9 +20,12 @@
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_matches_for_team_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_notes_for_team"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_shift_schedule_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/requests/messages/submit_notes"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_shift_schedule"
"github.com/frc971/971-Robot-Code/scouting/webserver/server"
flatbuffers "github.com/google/flatbuffers/go"
)
@@ -355,6 +358,113 @@
}
}
+func TestRequestShiftSchedule(t *testing.T) {
+ db := MockDatabase{
+ shiftSchedule: []db.Shift{
+ {
+ MatchNumber: 1,
+ R1scouter: "Bob",
+ R2scouter: "James",
+ R3scouter: "Robert",
+ B1scouter: "Alice",
+ B2scouter: "Mary",
+ B3scouter: "Patricia",
+ },
+ {
+ MatchNumber: 2,
+ R1scouter: "Liam",
+ R2scouter: "Noah",
+ R3scouter: "Oliver",
+ B1scouter: "Emma",
+ B2scouter: "Charlotte",
+ B3scouter: "Amelia",
+ },
+ },
+ }
+ scoutingServer := server.NewScoutingServer()
+ HandleRequests(&db, scrapeEmtpyMatchList, scoutingServer)
+ scoutingServer.Start(8080)
+ defer scoutingServer.Stop()
+
+ builder := flatbuffers.NewBuilder(1024)
+ builder.Finish((&request_shift_schedule.RequestShiftScheduleT{}).Pack(builder))
+
+ response, err := debug.RequestShiftSchedule("http://localhost:8080", builder.FinishedBytes())
+ if err != nil {
+ t.Fatal("Failed to request shift schedule: ", err)
+ }
+
+ expected := request_shift_schedule_response.RequestShiftScheduleResponseT{
+ ShiftSchedule: []*request_shift_schedule_response.MatchAssignmentT{
+ {
+ MatchNumber: 1,
+ R1scouter: "Bob",
+ R2scouter: "James",
+ R3scouter: "Robert",
+ B1scouter: "Alice",
+ B2scouter: "Mary",
+ B3scouter: "Patricia",
+ },
+ {
+ MatchNumber: 2,
+ R1scouter: "Liam",
+ R2scouter: "Noah",
+ R3scouter: "Oliver",
+ B1scouter: "Emma",
+ B2scouter: "Charlotte",
+ B3scouter: "Amelia",
+ },
+ },
+ }
+ if len(expected.ShiftSchedule) != len(response.ShiftSchedule) {
+ t.Fatal("Expected ", expected, ", but got ", *response)
+ }
+ for i, match := range expected.ShiftSchedule {
+ if !reflect.DeepEqual(*match, *response.ShiftSchedule[i]) {
+ t.Fatal("Expected for shift schedule", i, ":", *match, ", but got:", *response.ShiftSchedule[i])
+ }
+ }
+}
+
+func TestSubmitShiftSchedule(t *testing.T) {
+ database := MockDatabase{}
+ scoutingServer := server.NewScoutingServer()
+ HandleRequests(&database, scrapeEmtpyMatchList, scoutingServer)
+ scoutingServer.Start(8080)
+ defer scoutingServer.Stop()
+
+ builder := flatbuffers.NewBuilder(1024)
+ builder.Finish((&submit_shift_schedule.SubmitShiftScheduleT{
+ ShiftSchedule: []*submit_shift_schedule.MatchAssignmentT{
+ {MatchNumber: 1,
+ R1scouter: "Bob",
+ R2scouter: "James",
+ R3scouter: "Robert",
+ B1scouter: "Alice",
+ B2scouter: "Mary",
+ B3scouter: "Patricia"},
+ },
+ }).Pack(builder))
+
+ _, err := debug.SubmitShiftSchedule("http://localhost:8080", builder.FinishedBytes())
+ if err != nil {
+ t.Fatal("Failed to submit shift schedule: ", err)
+ }
+
+ expected := []db.Shift{
+ {MatchNumber: 1,
+ R1scouter: "Bob",
+ R2scouter: "James",
+ R3scouter: "Robert",
+ B1scouter: "Alice",
+ B2scouter: "Mary",
+ B3scouter: "Patricia"},
+ }
+ if !reflect.DeepEqual(expected, database.shiftSchedule) {
+ t.Fatal("Expected ", expected, ", but got:", database.shiftSchedule)
+ }
+}
+
// Validates that we can download the schedule from The Blue Alliance.
func TestRefreshMatchList(t *testing.T) {
scrapeMockSchedule := func(int32, string) ([]scraping.Match, error) {
@@ -433,9 +543,10 @@
// needed for your tests.
type MockDatabase struct {
- matches []db.Match
- stats []db.Stats
- notes []db.NotesData
+ matches []db.Match
+ stats []db.Stats
+ notes []db.NotesData
+ shiftSchedule []db.Shift
}
func (database *MockDatabase) AddToMatch(match db.Match) error {
@@ -488,6 +599,19 @@
return nil
}
+func (database *MockDatabase) AddToShift(data db.Shift) error {
+ database.shiftSchedule = append(database.shiftSchedule, data)
+ return nil
+}
+
+func (database *MockDatabase) ReturnAllShifts() ([]db.Shift, error) {
+ return database.shiftSchedule, nil
+}
+
+func (database *MockDatabase) QueryAllShifts(int) ([]db.Shift, error) {
+ return []db.Shift{}, nil
+}
+
// Returns an empty match list from the fake The Blue Alliance scraping.
func scrapeEmtpyMatchList(int32, string) ([]scraping.Match, error) {
return nil, nil