Add New 2024 Actions + Stats
Signed-off-by: Emily Markova <emily.markova@gmail.com>
Change-Id: I945b6e4450695119ad1edc72701f4a9afe79c3c4
diff --git a/scouting/webserver/requests/BUILD b/scouting/webserver/requests/BUILD
index 7be151e..846414c 100644
--- a/scouting/webserver/requests/BUILD
+++ b/scouting/webserver/requests/BUILD
@@ -10,9 +10,13 @@
"//scouting/db",
"//scouting/webserver/requests/messages:delete_2023_data_scouting_go_fbs",
"//scouting/webserver/requests/messages:delete_2023_data_scouting_response_go_fbs",
+ "//scouting/webserver/requests/messages:delete_2024_data_scouting_go_fbs",
+ "//scouting/webserver/requests/messages:delete_2024_data_scouting_response_go_fbs",
"//scouting/webserver/requests/messages:error_response_go_fbs",
"//scouting/webserver/requests/messages:request_2023_data_scouting_go_fbs",
"//scouting/webserver/requests/messages:request_2023_data_scouting_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_2024_data_scouting_go_fbs",
+ "//scouting/webserver/requests/messages:request_2024_data_scouting_response_go_fbs",
"//scouting/webserver/requests/messages:request_all_driver_rankings_go_fbs",
"//scouting/webserver/requests/messages:request_all_driver_rankings_response_go_fbs",
"//scouting/webserver/requests/messages:request_all_matches_go_fbs",
@@ -27,6 +31,8 @@
"//scouting/webserver/requests/messages:request_pit_images_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_2024_actions_go_fbs",
+ "//scouting/webserver/requests/messages:submit_2024_actions_response_go_fbs",
"//scouting/webserver/requests/messages:submit_actions_go_fbs",
"//scouting/webserver/requests/messages:submit_actions_response_go_fbs",
"//scouting/webserver/requests/messages:submit_driver_ranking_go_fbs",
@@ -51,8 +57,11 @@
"//scouting/db",
"//scouting/webserver/requests/debug",
"//scouting/webserver/requests/messages:delete_2023_data_scouting_go_fbs",
+ "//scouting/webserver/requests/messages:delete_2024_data_scouting_go_fbs",
"//scouting/webserver/requests/messages:request_2023_data_scouting_go_fbs",
"//scouting/webserver/requests/messages:request_2023_data_scouting_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_2024_data_scouting_go_fbs",
+ "//scouting/webserver/requests/messages:request_2024_data_scouting_response_go_fbs",
"//scouting/webserver/requests/messages:request_all_driver_rankings_go_fbs",
"//scouting/webserver/requests/messages:request_all_driver_rankings_response_go_fbs",
"//scouting/webserver/requests/messages:request_all_matches_go_fbs",
@@ -66,6 +75,7 @@
"//scouting/webserver/requests/messages:request_pit_images_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_2024_actions_go_fbs",
"//scouting/webserver/requests/messages:submit_actions_go_fbs",
"//scouting/webserver/requests/messages:submit_driver_ranking_go_fbs",
"//scouting/webserver/requests/messages:submit_notes_go_fbs",
diff --git a/scouting/webserver/requests/debug/BUILD b/scouting/webserver/requests/debug/BUILD
index 1224710..ff85206 100644
--- a/scouting/webserver/requests/debug/BUILD
+++ b/scouting/webserver/requests/debug/BUILD
@@ -8,8 +8,10 @@
visibility = ["//visibility:public"],
deps = [
"//scouting/webserver/requests/messages:delete_2023_data_scouting_response_go_fbs",
+ "//scouting/webserver/requests/messages:delete_2024_data_scouting_response_go_fbs",
"//scouting/webserver/requests/messages:error_response_go_fbs",
"//scouting/webserver/requests/messages:request_2023_data_scouting_response_go_fbs",
+ "//scouting/webserver/requests/messages:request_2024_data_scouting_response_go_fbs",
"//scouting/webserver/requests/messages:request_all_driver_rankings_response_go_fbs",
"//scouting/webserver/requests/messages:request_all_matches_response_go_fbs",
"//scouting/webserver/requests/messages:request_all_notes_response_go_fbs",
@@ -17,6 +19,7 @@
"//scouting/webserver/requests/messages:request_notes_for_team_response_go_fbs",
"//scouting/webserver/requests/messages:request_pit_images_response_go_fbs",
"//scouting/webserver/requests/messages:request_shift_schedule_response_go_fbs",
+ "//scouting/webserver/requests/messages:submit_2024_actions_response_go_fbs",
"//scouting/webserver/requests/messages:submit_actions_response_go_fbs",
"//scouting/webserver/requests/messages:submit_driver_ranking_response_go_fbs",
"//scouting/webserver/requests/messages:submit_notes_response_go_fbs",
diff --git a/scouting/webserver/requests/debug/debug.go b/scouting/webserver/requests/debug/debug.go
index faf4a9d..ed8a1b7 100644
--- a/scouting/webserver/requests/debug/debug.go
+++ b/scouting/webserver/requests/debug/debug.go
@@ -10,8 +10,10 @@
"net/http"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/delete_2023_data_scouting_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/delete_2024_data_scouting_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/error_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2023_data_scouting_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2024_data_scouting_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_driver_rankings_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_notes_response"
@@ -19,6 +21,7 @@
"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_pit_images_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_2024_actions_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_actions_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_driver_ranking_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_notes_response"
@@ -127,6 +130,12 @@
request_2023_data_scouting_response.GetRootAsRequest2023DataScoutingResponse)
}
+func Request2024DataScouting(server string, requestBytes []byte) (*request_2024_data_scouting_response.Request2024DataScoutingResponseT, error) {
+ return sendMessage[request_2024_data_scouting_response.Request2024DataScoutingResponseT](
+ server+"/requests/request/2024_data_scouting", requestBytes,
+ request_2024_data_scouting_response.GetRootAsRequest2024DataScoutingResponse)
+}
+
func SubmitNotes(server string, requestBytes []byte) (*submit_notes_response.SubmitNotesResponseT, error) {
return sendMessage[submit_notes_response.SubmitNotesResponseT](
server+"/requests/submit/submit_notes", requestBytes,
@@ -175,6 +184,12 @@
submit_driver_ranking_response.GetRootAsSubmitDriverRankingResponse)
}
+func Submit2024Actions(server string, requestBytes []byte) (*submit_2024_actions_response.Submit2024ActionsResponseT, error) {
+ return sendMessage[submit_2024_actions_response.Submit2024ActionsResponseT](
+ server+"/requests/submit/submit_2024_actions", requestBytes,
+ submit_2024_actions_response.GetRootAsSubmit2024ActionsResponse)
+}
+
func SubmitActions(server string, requestBytes []byte) (*submit_actions_response.SubmitActionsResponseT, error) {
return sendMessage[submit_actions_response.SubmitActionsResponseT](
server+"/requests/submit/submit_actions", requestBytes,
@@ -192,3 +207,9 @@
server+"/requests/delete/delete_2023_data_scouting", requestBytes,
delete_2023_data_scouting_response.GetRootAsDelete2023DataScoutingResponse)
}
+
+func Delete2024DataScouting(server string, requestBytes []byte) (*delete_2024_data_scouting_response.Delete2024DataScoutingResponseT, error) {
+ return sendMessage[delete_2024_data_scouting_response.Delete2024DataScoutingResponseT](
+ server+"/requests/delete/delete_2024_data_scouting", requestBytes,
+ delete_2024_data_scouting_response.GetRootAsDelete2024DataScoutingResponse)
+}
diff --git a/scouting/webserver/requests/messages/BUILD b/scouting/webserver/requests/messages/BUILD
index 735caab..d0534a51 100644
--- a/scouting/webserver/requests/messages/BUILD
+++ b/scouting/webserver/requests/messages/BUILD
@@ -11,6 +11,8 @@
"request_all_notes_response",
"request_2023_data_scouting",
"request_2023_data_scouting_response",
+ "request_2024_data_scouting",
+ "request_2024_data_scouting_response",
"submit_notes",
"submit_notes_response",
"request_notes_for_team",
@@ -29,8 +31,12 @@
"submit_driver_ranking_response",
"submit_actions",
"submit_actions_response",
+ "submit_2024_actions",
+ "submit_2024_actions_response",
"delete_2023_data_scouting",
"delete_2023_data_scouting_response",
+ "delete_2024_data_scouting",
+ "delete_2024_data_scouting_response",
)
filegroup(
diff --git a/scouting/webserver/requests/messages/delete_2024_data_scouting.fbs b/scouting/webserver/requests/messages/delete_2024_data_scouting.fbs
new file mode 100644
index 0000000..827aa98
--- /dev/null
+++ b/scouting/webserver/requests/messages/delete_2024_data_scouting.fbs
@@ -0,0 +1,10 @@
+namespace scouting.webserver.requests;
+
+table Delete2024DataScouting {
+ comp_level:string (id: 0);
+ match_number:int (id: 1);
+ set_number:int (id: 2);
+ team_number:string (id: 3);
+}
+
+root_type Delete2024DataScouting;
diff --git a/scouting/webserver/requests/messages/delete_2024_data_scouting_response.fbs b/scouting/webserver/requests/messages/delete_2024_data_scouting_response.fbs
new file mode 100644
index 0000000..2dbb81f
--- /dev/null
+++ b/scouting/webserver/requests/messages/delete_2024_data_scouting_response.fbs
@@ -0,0 +1,7 @@
+namespace scouting.webserver.requests;
+
+table Delete2024DataScoutingResponse {
+ // empty response
+}
+
+root_type Delete2024DataScoutingResponse;
diff --git a/scouting/webserver/requests/messages/request_2024_data_scouting.fbs b/scouting/webserver/requests/messages/request_2024_data_scouting.fbs
new file mode 100644
index 0000000..738aade
--- /dev/null
+++ b/scouting/webserver/requests/messages/request_2024_data_scouting.fbs
@@ -0,0 +1,7 @@
+namespace scouting.webserver.requests;
+
+table Request2024DataScouting {
+
+}
+
+root_type Request2024DataScouting;
diff --git a/scouting/webserver/requests/messages/request_2024_data_scouting_response.fbs b/scouting/webserver/requests/messages/request_2024_data_scouting_response.fbs
new file mode 100644
index 0000000..d653f04
--- /dev/null
+++ b/scouting/webserver/requests/messages/request_2024_data_scouting_response.fbs
@@ -0,0 +1,37 @@
+namespace scouting.webserver.requests;
+
+table Stats2024 {
+ team_number:string (id: 0);
+ match_number:int (id: 1);
+ set_number:int (id: 18);
+ comp_level:string (id: 19);
+
+ starting_quadrant:int (id: 2);
+ speaker_auto:int (id:3);
+ amp_auto:int (id:4);
+ notes_dropped_auto:int (id: 5);
+ mobility_auto: bool (id: 6);
+
+ speaker:int (id:7);
+ amp:int (id:8);
+ speaker_amplified:int (id:9);
+ amp_amplified:int (id:10);
+ notes_dropped:int (id:11);
+
+ penalties:int (id:12);
+ trap_note:bool (id:13);
+ // Time in nanoseconds.
+ avg_cycle: int64 (id:14);
+ park: bool (id:15);
+ on_stage: bool (id:16);
+ harmony: bool (id:17);
+
+ pre_scouting:bool (id:20);
+ collected_by:string (id:21);
+}
+
+table Request2024DataScoutingResponse {
+ stats_list:[Stats2024] (id:0);
+}
+
+root_type Request2024DataScoutingResponse;
diff --git a/scouting/webserver/requests/messages/submit_2024_actions.fbs b/scouting/webserver/requests/messages/submit_2024_actions.fbs
new file mode 100644
index 0000000..5cb3cbe
--- /dev/null
+++ b/scouting/webserver/requests/messages/submit_2024_actions.fbs
@@ -0,0 +1,71 @@
+namespace scouting.webserver.requests;
+
+table StartMatchAction {
+ position:int (id:0);
+}
+
+enum ScoreType: short {
+ kAMP,
+ kAMP_AMPLIFIED,
+ kSPEAKER,
+ kSPEAKER_AMPLIFIED,
+}
+
+table MobilityAction {
+ mobility:bool (id:0);
+}
+
+table PenaltyAction {}
+
+table PickupNoteAction {
+ auto:bool (id:0);
+}
+
+table PlaceNoteAction {
+ score_type:ScoreType (id:0);
+ auto:bool (id:1);
+}
+
+table RobotDeathAction {
+ robot_dead:bool (id:0);
+}
+
+enum StageType: short {
+ kON_STAGE,
+ kPARK,
+ kHARMONY,
+ kMISSING,
+}
+
+table EndMatchAction {
+ stage_type:StageType (id:0);
+ trap_note:bool (id:1);
+}
+
+union ActionType {
+ MobilityAction,
+ StartMatchAction,
+ PickupNoteAction,
+ PlaceNoteAction,
+ PenaltyAction,
+ RobotDeathAction,
+ EndMatchAction
+}
+
+table Action {
+ timestamp:int64 (id:0);
+ action_taken:ActionType (id:2);
+}
+
+table Submit2024Actions {
+ team_number:string (id: 0);
+ match_number:int (id: 1);
+ set_number:int (id: 2);
+ comp_level:string (id: 3);
+ actions_list:[Action] (id:4);
+
+ // If this is for pre-scouting, then the server should accept this
+ // submission. I.e. checking that the match information exists in the match
+ // list should be skipped.
+ pre_scouting:bool (id: 5);
+}
\ No newline at end of file
diff --git a/scouting/webserver/requests/messages/submit_2024_actions_response.fbs b/scouting/webserver/requests/messages/submit_2024_actions_response.fbs
new file mode 100644
index 0000000..100172b
--- /dev/null
+++ b/scouting/webserver/requests/messages/submit_2024_actions_response.fbs
@@ -0,0 +1,7 @@
+namespace scouting.webserver.requests;
+
+table Submit2024ActionsResponse {
+ // empty response
+}
+
+root_type Submit2024ActionsResponse;
\ No newline at end of file
diff --git a/scouting/webserver/requests/requests.go b/scouting/webserver/requests/requests.go
index 9628c0d..75b438b 100644
--- a/scouting/webserver/requests/requests.go
+++ b/scouting/webserver/requests/requests.go
@@ -14,9 +14,13 @@
"github.com/frc971/971-Robot-Code/scouting/db"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/delete_2023_data_scouting"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/delete_2023_data_scouting_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/delete_2024_data_scouting"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/delete_2024_data_scouting_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/error_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2023_data_scouting"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2023_data_scouting_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2024_data_scouting"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2024_data_scouting_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_driver_rankings"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_driver_rankings_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches"
@@ -31,6 +35,8 @@
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_pit_images_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_2024_actions"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_2024_actions_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_actions"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_actions_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_driver_ranking"
@@ -53,6 +59,8 @@
type RequestAllNotesResponseT = request_all_notes_response.RequestAllNotesResponseT
type Request2023DataScouting = request_2023_data_scouting.Request2023DataScouting
type Request2023DataScoutingResponseT = request_2023_data_scouting_response.Request2023DataScoutingResponseT
+type Request2024DataScouting = request_2024_data_scouting.Request2024DataScouting
+type Request2024DataScoutingResponseT = request_2024_data_scouting_response.Request2024DataScoutingResponseT
type SubmitNotes = submit_notes.SubmitNotes
type SubmitNotesResponseT = submit_notes_response.SubmitNotesResponseT
type SubmitPitImage = submit_pit_image.SubmitPitImage
@@ -71,9 +79,14 @@
type SubmitDriverRankingResponseT = submit_driver_ranking_response.SubmitDriverRankingResponseT
type SubmitActions = submit_actions.SubmitActions
type Action = submit_actions.Action
+type Action2024 = submit_2024_actions.Action
type SubmitActionsResponseT = submit_actions_response.SubmitActionsResponseT
+type Submit2024Actions = submit_2024_actions.Submit2024Actions
+type Submit2024ActionsResponseT = submit_2024_actions_response.Submit2024ActionsResponseT
type Delete2023DataScouting = delete_2023_data_scouting.Delete2023DataScouting
type Delete2023DataScoutingResponseT = delete_2023_data_scouting_response.Delete2023DataScoutingResponseT
+type Delete2024DataScouting = delete_2024_data_scouting.Delete2024DataScouting
+type Delete2024DataScoutingResponseT = delete_2024_data_scouting_response.Delete2024DataScoutingResponseT
// The interface we expect the database abstraction to conform to.
// We use an interface here because it makes unit testing easier.
@@ -81,12 +94,15 @@
AddToMatch(db.TeamMatch) error
AddToShift(db.Shift) error
AddToStats2023(db.Stats2023) error
+ AddToStats2024(db.Stats2024) error
ReturnMatches() ([]db.TeamMatch, error)
ReturnAllNotes() ([]db.NotesData, error)
ReturnAllDriverRankings() ([]db.DriverRankingData, error)
ReturnAllShifts() ([]db.Shift, error)
ReturnStats2023() ([]db.Stats2023, error)
ReturnStats2023ForTeam(teamNumber string, matchNumber int32, setNumber int32, compLevel string, preScouting bool) ([]db.Stats2023, error)
+ ReturnStats2024() ([]db.Stats2024, error)
+ ReturnStats2024ForTeam(teamNumber string, matchNumber int32, setNumber int32, compLevel string, preScouting bool) ([]db.Stats2024, error)
QueryAllShifts(int) ([]db.Shift, error)
QueryNotes(string) ([]string, error)
QueryPitImages(string) ([]db.RequestedPitImage, error)
@@ -96,6 +112,7 @@
AddDriverRanking(db.DriverRankingData) error
AddAction(db.Action) error
DeleteFromStats(string, int32, int32, string) error
+ DeleteFromStats2024(string, int32, int32, string) error
DeleteFromActions(string, int32, int32, string) error
}
@@ -182,6 +199,7 @@
}
func (handler requestAllMatchesHandler) teamHasBeenDataScouted(key MatchAssemblyKey, teamNumber string) (bool, error) {
+ // TODO change this to reference 2024 stats
stats, err := handler.db.ReturnStats2023ForTeam(
teamNumber, key.MatchNumber, key.SetNumber, key.CompLevel, false)
if err != nil {
@@ -426,6 +444,165 @@
w.Write(builder.FinishedBytes())
}
+func ConvertActionsToStat2024(submit2024Actions *submit_2024_actions.Submit2024Actions) (db.Stats2024, error) {
+ overall_time := int64(0)
+ cycles := int64(0)
+ picked_up := false
+ lastPlacedTime := int64(0)
+ stat := db.Stats2024{
+ PreScouting: submit2024Actions.PreScouting(), TeamNumber: string(submit2024Actions.TeamNumber()), MatchNumber: submit2024Actions.MatchNumber(), SetNumber: submit2024Actions.SetNumber(), CompLevel: string(submit2024Actions.CompLevel()),
+ StartingQuadrant: 0, SpeakerAuto: 0, AmpAuto: 0, NotesDroppedAuto: 0, MobilityAuto: false,
+ Speaker: 0, Amp: 0, SpeakerAmplified: 0, AmpAmplified: 0, NotesDropped: 0, Penalties: 0,
+ TrapNote: false, AvgCycle: 0, Park: false, OnStage: false, Harmony: false, CollectedBy: "",
+ }
+ // Loop over all actions.
+ for i := 0; i < submit2024Actions.ActionsListLength(); i++ {
+ var action submit_2024_actions.Action
+ if !submit2024Actions.ActionsList(&action, i) {
+ return db.Stats2024{}, errors.New(fmt.Sprintf("Failed to parse submit_2024_actions.Action"))
+ }
+ actionTable := new(flatbuffers.Table)
+ action_type := action.ActionTakenType()
+ if !action.ActionTaken(actionTable) {
+ return db.Stats2024{}, errors.New(fmt.Sprint("Failed to parse sub-action or sub-action was missing"))
+ }
+ if action_type == submit_2024_actions.ActionTypeStartMatchAction {
+ var startMatchAction submit_2024_actions.StartMatchAction
+ startMatchAction.Init(actionTable.Bytes, actionTable.Pos)
+ stat.StartingQuadrant = startMatchAction.Position()
+ } else if action_type == submit_2024_actions.ActionTypeMobilityAction {
+ var mobilityAction submit_2024_actions.MobilityAction
+ mobilityAction.Init(actionTable.Bytes, actionTable.Pos)
+ if mobilityAction.Mobility() {
+ stat.MobilityAuto = true
+ }
+
+ } else if action_type == submit_2024_actions.ActionTypePenaltyAction {
+ var penaltyAction submit_2024_actions.PenaltyAction
+ penaltyAction.Init(actionTable.Bytes, actionTable.Pos)
+ stat.Penalties += 1
+
+ } else if action_type == submit_2024_actions.ActionTypePickupNoteAction {
+ var pick_up_action submit_2024_actions.PickupNoteAction
+ pick_up_action.Init(actionTable.Bytes, actionTable.Pos)
+ if picked_up == true {
+ auto := pick_up_action.Auto()
+ if auto == false {
+ stat.NotesDropped += 1
+ } else {
+ stat.NotesDroppedAuto += 1
+ }
+ } else {
+ picked_up = true
+ }
+ } else if action_type == submit_2024_actions.ActionTypePlaceNoteAction {
+ var place_action submit_2024_actions.PlaceNoteAction
+ place_action.Init(actionTable.Bytes, actionTable.Pos)
+ if !picked_up {
+ return db.Stats2024{}, errors.New(fmt.Sprintf("Got PlaceNoteAction without corresponding PickupObjectAction"))
+ }
+ score_type := place_action.ScoreType()
+ auto := place_action.Auto()
+ if score_type == submit_2024_actions.ScoreTypekAMP && auto {
+ stat.AmpAuto += 1
+ } else if score_type == submit_2024_actions.ScoreTypekAMP && !auto {
+ stat.Amp += 1
+ } else if score_type == submit_2024_actions.ScoreTypekAMP_AMPLIFIED && !auto {
+ stat.AmpAmplified += 1
+ } else if score_type == submit_2024_actions.ScoreTypekSPEAKER && !auto {
+ stat.Speaker += 1
+ } else if score_type == submit_2024_actions.ScoreTypekSPEAKER && auto {
+ stat.SpeakerAuto += 1
+ } else if score_type == submit_2024_actions.ScoreTypekSPEAKER_AMPLIFIED && !auto {
+ stat.SpeakerAmplified += 1
+ } else {
+ return db.Stats2024{}, errors.New(fmt.Sprintf("Got unknown ObjectType/ScoreLevel/Auto combination"))
+ }
+ picked_up = false
+ if lastPlacedTime != int64(0) {
+ // If this is not the first time we place,
+ // start counting cycle time. We define cycle
+ // time as the time between placements.
+ overall_time += int64(action.Timestamp()) - lastPlacedTime
+ cycles += 1
+ }
+ lastPlacedTime = int64(action.Timestamp())
+ } else if action_type == submit_2024_actions.ActionTypeEndMatchAction {
+ var endMatchAction submit_2024_actions.EndMatchAction
+ endMatchAction.Init(actionTable.Bytes, actionTable.Pos)
+ if endMatchAction.StageType() == submit_2024_actions.StageTypekON_STAGE {
+ stat.OnStage = true
+ } else if endMatchAction.StageType() == submit_2024_actions.StageTypekPARK {
+ stat.Park = true
+ } else if endMatchAction.StageType() == submit_2024_actions.StageTypekHARMONY {
+ stat.Harmony = true
+ }
+ stat.TrapNote = endMatchAction.TrapNote()
+ }
+ }
+ if cycles != 0 {
+ stat.AvgCycle = overall_time / cycles
+ } else {
+ stat.AvgCycle = 0
+ }
+ return stat, nil
+}
+
+// Handles a Request2024DataScouting request.
+type request2024DataScoutingHandler struct {
+ db Database
+}
+
+func (handler request2024DataScoutingHandler) 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, "Request2024DataScouting", request_2024_data_scouting.GetRootAsRequest2024DataScouting)
+ if !success {
+ return
+ }
+
+ stats, err := handler.db.ReturnStats2024()
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Failed to query database: ", err))
+ return
+ }
+
+ var response Request2024DataScoutingResponseT
+ for _, stat := range stats {
+ response.StatsList = append(response.StatsList, &request_2024_data_scouting_response.Stats2024T{
+ TeamNumber: stat.TeamNumber,
+ MatchNumber: stat.MatchNumber,
+ SetNumber: stat.SetNumber,
+ CompLevel: stat.CompLevel,
+ StartingQuadrant: stat.StartingQuadrant,
+ SpeakerAuto: stat.SpeakerAuto,
+ AmpAuto: stat.AmpAuto,
+ NotesDroppedAuto: stat.NotesDroppedAuto,
+ MobilityAuto: stat.MobilityAuto,
+ Speaker: stat.Speaker,
+ Amp: stat.Amp,
+ SpeakerAmplified: stat.SpeakerAmplified,
+ AmpAmplified: stat.AmpAmplified,
+ NotesDropped: stat.NotesDropped,
+ Penalties: stat.Penalties,
+ TrapNote: stat.TrapNote,
+ AvgCycle: stat.AvgCycle,
+ Park: stat.Park,
+ OnStage: stat.OnStage,
+ Harmony: stat.Harmony,
+ CollectedBy: stat.CollectedBy,
+ })
+ }
+
+ builder := flatbuffers.NewBuilder(50 * 1024)
+ builder.Finish((&response).Pack(builder))
+ w.Write(builder.FinishedBytes())
+}
+
func ConvertActionsToStat(submitActions *submit_actions.SubmitActions) (db.Stats2023, error) {
overall_time := int64(0)
cycles := int64(0)
@@ -926,6 +1103,77 @@
w.Write(builder.FinishedBytes())
}
+type submit2024ActionsHandler struct {
+ db Database
+}
+
+func (handler submit2024ActionsHandler) 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(w, requestBytes, "Submit2024Actions", submit_2024_actions.GetRootAsSubmit2024Actions)
+ if !success {
+ return
+ }
+
+ log.Println("Got actions for match", request.MatchNumber(), "team", request.TeamNumber(), "from", username)
+
+ for i := 0; i < request.ActionsListLength(); i++ {
+
+ var action Action2024
+ request.ActionsList(&action, i)
+
+ dbAction := db.Action{
+ PreScouting: request.PreScouting(),
+ TeamNumber: string(request.TeamNumber()),
+ MatchNumber: request.MatchNumber(),
+ SetNumber: request.SetNumber(),
+ CompLevel: string(request.CompLevel()),
+ //TODO: Serialize CompletedAction
+ CompletedAction: []byte{},
+ Timestamp: action.Timestamp(),
+ CollectedBy: username,
+ }
+
+ // Do some error checking.
+ if action.Timestamp() < 0 {
+ respondWithError(w, http.StatusBadRequest, fmt.Sprint(
+ "Invalid timestamp field value of ", action.Timestamp()))
+ return
+ }
+
+ err = handler.db.AddAction(dbAction)
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Failed to add action to database: ", err))
+ return
+ }
+ }
+
+ stats, err := ConvertActionsToStat2024(request)
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Failed to convert actions to stats: ", err))
+ return
+ }
+
+ stats.CollectedBy = username
+
+ err = handler.db.AddToStats2024(stats)
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprint("Failed to submit stats: ", stats, ": ", err))
+ return
+ }
+
+ builder := flatbuffers.NewBuilder(50 * 1024)
+ builder.Finish((&SubmitActionsResponseT{}).Pack(builder))
+ w.Write(builder.FinishedBytes())
+}
+
type submitActionsHandler struct {
db Database
}
@@ -997,6 +1245,50 @@
w.Write(builder.FinishedBytes())
}
+type Delete2024DataScoutingHandler struct {
+ db Database
+}
+
+func (handler Delete2024DataScoutingHandler) 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
+ }
+
+ request, success := parseRequest(w, requestBytes, "Delete2024DataScouting", delete_2024_data_scouting.GetRootAsDelete2024DataScouting)
+ if !success {
+ return
+ }
+
+ err = handler.db.DeleteFromStats2024(
+ string(request.CompLevel()),
+ request.MatchNumber(),
+ request.SetNumber(),
+ string(request.TeamNumber()))
+
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to delete from stats2024: %v", err))
+ return
+ }
+
+ err = handler.db.DeleteFromActions(
+ string(request.CompLevel()),
+ request.MatchNumber(),
+ request.SetNumber(),
+ string(request.TeamNumber()))
+
+ if err != nil {
+ respondWithError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to delete from actions: %v", err))
+ return
+ }
+
+ var response Delete2024DataScoutingResponseT
+ builder := flatbuffers.NewBuilder(10)
+ builder.Finish((&response).Pack(builder))
+ w.Write(builder.FinishedBytes())
+}
+
type Delete2023DataScoutingHandler struct {
db Database
}
@@ -1047,6 +1339,7 @@
scoutingServer.Handle("/requests/request/all_notes", requestAllNotesHandler{db})
scoutingServer.Handle("/requests/request/all_driver_rankings", requestAllDriverRankingsHandler{db})
scoutingServer.Handle("/requests/request/2023_data_scouting", request2023DataScoutingHandler{db})
+ scoutingServer.Handle("/requests/request/2024_data_scouting", request2024DataScoutingHandler{db})
scoutingServer.Handle("/requests/submit/submit_notes", submitNoteScoutingHandler{db})
scoutingServer.Handle("/requests/submit/submit_pit_image", submitPitImageScoutingHandler{db})
scoutingServer.Handle("/requests/request/pit_images", requestPitImagesHandler{db})
@@ -1056,5 +1349,7 @@
scoutingServer.Handle("/requests/request/shift_schedule", requestShiftScheduleHandler{db})
scoutingServer.Handle("/requests/submit/submit_driver_ranking", SubmitDriverRankingHandler{db})
scoutingServer.Handle("/requests/submit/submit_actions", submitActionsHandler{db})
+ scoutingServer.Handle("/requests/submit/submit_2024_actions", submit2024ActionsHandler{db})
scoutingServer.Handle("/requests/delete/delete_2023_data_scouting", Delete2023DataScoutingHandler{db})
+ scoutingServer.Handle("/requests/delete/delete_2024_data_scouting", Delete2024DataScoutingHandler{db})
}
diff --git a/scouting/webserver/requests/requests_test.go b/scouting/webserver/requests/requests_test.go
index d81b659..67244d3 100644
--- a/scouting/webserver/requests/requests_test.go
+++ b/scouting/webserver/requests/requests_test.go
@@ -8,8 +8,11 @@
"github.com/frc971/971-Robot-Code/scouting/db"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/debug"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/delete_2023_data_scouting"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/delete_2024_data_scouting"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2023_data_scouting"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2023_data_scouting_response"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2024_data_scouting"
+ "github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_2024_data_scouting_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_driver_rankings"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_driver_rankings_response"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_all_matches"
@@ -23,6 +26,7 @@
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/request_pit_images_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_2024_actions"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_actions"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_driver_ranking"
"github.com/frc971/971-Robot-Code/scouting/webserver/requests/messages/submit_notes"
@@ -209,6 +213,71 @@
}
+// Validates that we can request the 2024 stats.
+func TestRequest2024DataScouting(t *testing.T) {
+ db := MockDatabase{
+ stats2024: []db.Stats2024{
+ {
+ PreScouting: false, TeamNumber: "342",
+ MatchNumber: 3, SetNumber: 1, CompLevel: "quals", StartingQuadrant: 4,
+ SpeakerAuto: 1, AmpAuto: 1, NotesDroppedAuto: 0, MobilityAuto: true,
+ Speaker: 4, Amp: 2, SpeakerAmplified: 1, AmpAmplified: 0,
+ NotesDropped: 2, Penalties: 2, TrapNote: true, AvgCycle: 0,
+ Park: true, OnStage: false, Harmony: false, CollectedBy: "alex",
+ },
+ {
+ PreScouting: false, TeamNumber: "982",
+ MatchNumber: 3, SetNumber: 1, CompLevel: "quals", StartingQuadrant: 2,
+ SpeakerAuto: 0, AmpAuto: 0, NotesDroppedAuto: 0, MobilityAuto: false,
+ Speaker: 0, Amp: 2, SpeakerAmplified: 3, AmpAmplified: 2,
+ NotesDropped: 1, Penalties: 0, TrapNote: false, AvgCycle: 0,
+ Park: false, OnStage: true, Harmony: false, CollectedBy: "george",
+ },
+ },
+ }
+ scoutingServer := server.NewScoutingServer()
+ HandleRequests(&db, scoutingServer)
+ scoutingServer.Start(8080)
+ defer scoutingServer.Stop()
+
+ builder := flatbuffers.NewBuilder(1024)
+ builder.Finish((&request_2024_data_scouting.Request2024DataScoutingT{}).Pack(builder))
+
+ response, err := debug.Request2024DataScouting("http://localhost:8080", builder.FinishedBytes())
+ if err != nil {
+ t.Fatal("Failed to request all matches: ", err)
+ }
+
+ expected := request_2024_data_scouting_response.Request2024DataScoutingResponseT{
+ StatsList: []*request_2024_data_scouting_response.Stats2024T{
+ {
+ PreScouting: false, TeamNumber: "342",
+ MatchNumber: 3, SetNumber: 1, CompLevel: "quals", StartingQuadrant: 4,
+ SpeakerAuto: 1, AmpAuto: 1, NotesDroppedAuto: 0, MobilityAuto: true,
+ Speaker: 4, Amp: 2, SpeakerAmplified: 1, AmpAmplified: 0,
+ NotesDropped: 2, Penalties: 2, TrapNote: true, AvgCycle: 0,
+ Park: true, OnStage: false, Harmony: false, CollectedBy: "alex",
+ },
+ {
+ PreScouting: false, TeamNumber: "982",
+ MatchNumber: 3, SetNumber: 1, CompLevel: "quals", StartingQuadrant: 2,
+ SpeakerAuto: 0, AmpAuto: 0, NotesDroppedAuto: 0, MobilityAuto: false,
+ Speaker: 0, Amp: 2, SpeakerAmplified: 3, AmpAmplified: 2,
+ NotesDropped: 1, Penalties: 0, TrapNote: false, AvgCycle: 0,
+ Park: false, OnStage: true, Harmony: false, CollectedBy: "george",
+ },
+ },
+ }
+ if len(expected.StatsList) != len(response.StatsList) {
+ t.Fatal("Expected ", expected, ", but got ", *response)
+ }
+ for i, match := range expected.StatsList {
+ if !reflect.DeepEqual(*match, *response.StatsList[i]) {
+ t.Fatal("Expected for stats", i, ":", *match, ", but got:", *response.StatsList[i])
+ }
+ }
+}
+
// Validates that we can request the 2023 stats.
func TestRequest2023DataScouting(t *testing.T) {
db := MockDatabase{
@@ -290,6 +359,141 @@
}
}
+// Validates that we can request the 2024 stats.
+func TestConvertActionsToStat2024(t *testing.T) {
+ builder := flatbuffers.NewBuilder(1024)
+ builder.Finish((&submit_2024_actions.Submit2024ActionsT{
+ TeamNumber: "4244",
+ MatchNumber: 3,
+ SetNumber: 1,
+ CompLevel: "quals",
+ ActionsList: []*submit_2024_actions.ActionT{
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypeStartMatchAction,
+ Value: &submit_2024_actions.StartMatchActionT{
+ Position: 2,
+ },
+ },
+ Timestamp: 0,
+ },
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypePickupNoteAction,
+ Value: &submit_2024_actions.PickupNoteActionT{
+ Auto: true,
+ },
+ },
+ Timestamp: 400,
+ },
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypePickupNoteAction,
+ Value: &submit_2024_actions.PickupNoteActionT{
+ Auto: true,
+ },
+ },
+ Timestamp: 800,
+ },
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypePlaceNoteAction,
+ Value: &submit_2024_actions.PlaceNoteActionT{
+ ScoreType: submit_2024_actions.ScoreTypekAMP,
+ Auto: true,
+ },
+ },
+ Timestamp: 2000,
+ },
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypeMobilityAction,
+ Value: &submit_2024_actions.MobilityActionT{
+ Mobility: true,
+ },
+ },
+ Timestamp: 2200,
+ },
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypePenaltyAction,
+ Value: &submit_2024_actions.PenaltyActionT{},
+ },
+ Timestamp: 2400,
+ },
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypePickupNoteAction,
+ Value: &submit_2024_actions.PickupNoteActionT{
+ Auto: false,
+ },
+ },
+ Timestamp: 2800,
+ },
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypePlaceNoteAction,
+ Value: &submit_2024_actions.PlaceNoteActionT{
+ ScoreType: submit_2024_actions.ScoreTypekAMP_AMPLIFIED,
+ Auto: false,
+ },
+ },
+ Timestamp: 3100,
+ },
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypePickupNoteAction,
+ Value: &submit_2024_actions.PickupNoteActionT{
+ Auto: false,
+ },
+ },
+ Timestamp: 3500,
+ },
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypePlaceNoteAction,
+ Value: &submit_2024_actions.PlaceNoteActionT{
+ ScoreType: submit_2024_actions.ScoreTypekSPEAKER_AMPLIFIED,
+ Auto: false,
+ },
+ },
+ Timestamp: 3900,
+ },
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypeEndMatchAction,
+ Value: &submit_2024_actions.EndMatchActionT{
+ StageType: submit_2024_actions.StageTypekHARMONY,
+ TrapNote: false,
+ },
+ },
+ Timestamp: 4200,
+ },
+ },
+ PreScouting: false,
+ }).Pack(builder))
+
+ submit2024Actions := submit_2024_actions.GetRootAsSubmit2024Actions(builder.FinishedBytes(), 0)
+ response, err := ConvertActionsToStat2024(submit2024Actions)
+
+ if err != nil {
+ t.Fatal("Failed to convert actions to stats: ", err)
+ }
+
+ expected := db.Stats2024{
+ PreScouting: false, TeamNumber: "4244",
+ MatchNumber: 3, SetNumber: 1, CompLevel: "quals", StartingQuadrant: 2,
+ SpeakerAuto: 0, AmpAuto: 1, NotesDroppedAuto: 1, MobilityAuto: true,
+ Speaker: 0, Amp: 0, SpeakerAmplified: 1, AmpAmplified: 1,
+ NotesDropped: 0, Penalties: 1, TrapNote: false, AvgCycle: 950,
+ Park: false, OnStage: false, Harmony: true, CollectedBy: "",
+ }
+
+ if expected != response {
+ t.Fatal("Expected ", expected, ", but got ", response)
+ }
+}
+
// Validates that we can request the 2023 stats.
func TestConvertActionsToStat(t *testing.T) {
builder := flatbuffers.NewBuilder(1024)
@@ -931,6 +1135,90 @@
return (builder.FinishedBytes())
}
+func TestAddingActions2024(t *testing.T) {
+ database := MockDatabase{}
+ scoutingServer := server.NewScoutingServer()
+ HandleRequests(&database, scoutingServer)
+ scoutingServer.Start(8080)
+ defer scoutingServer.Stop()
+
+ builder := flatbuffers.NewBuilder(1024)
+ builder.Finish((&submit_2024_actions.Submit2024ActionsT{
+ TeamNumber: "3421",
+ MatchNumber: 2,
+ SetNumber: 1,
+ CompLevel: "quals",
+ ActionsList: []*submit_2024_actions.ActionT{
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypePickupNoteAction,
+ Value: &submit_2024_actions.PickupNoteActionT{
+ Auto: true,
+ },
+ },
+ Timestamp: 1800,
+ },
+ {
+ ActionTaken: &submit_2024_actions.ActionTypeT{
+ Type: submit_2024_actions.ActionTypePlaceNoteAction,
+ Value: &submit_2024_actions.PlaceNoteActionT{
+ ScoreType: submit_2024_actions.ScoreTypekSPEAKER,
+ Auto: false,
+ },
+ },
+ Timestamp: 2500,
+ },
+ },
+ PreScouting: true,
+ }).Pack(builder))
+
+ _, err := debug.Submit2024Actions("http://localhost:8080", builder.FinishedBytes())
+ if err != nil {
+ t.Fatal("Failed to submit actions: ", err)
+ }
+
+ expectedActions := []db.Action{
+ {
+ PreScouting: true,
+ TeamNumber: "3421",
+ MatchNumber: 2,
+ SetNumber: 1,
+ CompLevel: "quals",
+ CollectedBy: "debug_cli",
+ CompletedAction: []byte{},
+ Timestamp: 1800,
+ },
+ {
+ PreScouting: true,
+ TeamNumber: "3421",
+ MatchNumber: 2,
+ SetNumber: 1,
+ CompLevel: "quals",
+ CollectedBy: "debug_cli",
+ CompletedAction: []byte{},
+ Timestamp: 2500,
+ },
+ }
+
+ expectedStats := []db.Stats2024{
+ db.Stats2024{
+ PreScouting: true, TeamNumber: "3421",
+ MatchNumber: 2, SetNumber: 1, CompLevel: "quals", StartingQuadrant: 0,
+ SpeakerAuto: 0, AmpAuto: 0, NotesDroppedAuto: 0, MobilityAuto: false,
+ Speaker: 1, Amp: 0, SpeakerAmplified: 0, AmpAmplified: 0,
+ NotesDropped: 0, Penalties: 0, TrapNote: false, AvgCycle: 0,
+ Park: false, OnStage: false, Harmony: false, CollectedBy: "debug_cli",
+ },
+ }
+
+ if !reflect.DeepEqual(expectedActions, database.actions) {
+ t.Fatal("Expected ", expectedActions, ", but got:", database.actions)
+ }
+ if !reflect.DeepEqual(expectedStats, database.stats2024) {
+ t.Fatal("Expected ", expectedStats, ", but got:", database.stats2024)
+ }
+}
+
func TestAddingActions(t *testing.T) {
database := MockDatabase{}
scoutingServer := server.NewScoutingServer()
@@ -1155,6 +1443,100 @@
}
}
+// Validates that we can delete 2024 stats.
+func TestDeleteFromStats2024(t *testing.T) {
+ database := MockDatabase{
+ stats2024: []db.Stats2024{
+ {
+ PreScouting: false, TeamNumber: "746",
+ MatchNumber: 3, SetNumber: 1, CompLevel: "quals", StartingQuadrant: 2,
+ SpeakerAuto: 0, AmpAuto: 1, NotesDroppedAuto: 1, MobilityAuto: true,
+ Speaker: 0, Amp: 1, SpeakerAmplified: 1, AmpAmplified: 1,
+ NotesDropped: 0, Penalties: 1, TrapNote: true, AvgCycle: 233,
+ Park: false, OnStage: false, Harmony: true, CollectedBy: "alek",
+ },
+ {
+ PreScouting: false, TeamNumber: "244",
+ MatchNumber: 5, SetNumber: 3, CompLevel: "quals", StartingQuadrant: 1,
+ SpeakerAuto: 0, AmpAuto: 0, NotesDroppedAuto: 0, MobilityAuto: false,
+ Speaker: 0, Amp: 0, SpeakerAmplified: 3, AmpAmplified: 1,
+ NotesDropped: 0, Penalties: 1, TrapNote: false, AvgCycle: 120,
+ Park: false, OnStage: true, Harmony: false, CollectedBy: "kacey",
+ },
+ },
+ actions: []db.Action{
+ {
+ PreScouting: true,
+ TeamNumber: "746",
+ MatchNumber: 3,
+ SetNumber: 1,
+ CompLevel: "quals",
+ CollectedBy: "debug_cli",
+ CompletedAction: []byte{},
+ Timestamp: 2400,
+ },
+ {
+ PreScouting: true,
+ TeamNumber: "244",
+ MatchNumber: 5,
+ SetNumber: 3,
+ CompLevel: "quals",
+ CollectedBy: "debug_cli",
+ CompletedAction: []byte{},
+ Timestamp: 1009,
+ },
+ },
+ }
+ scoutingServer := server.NewScoutingServer()
+ HandleRequests(&database, scoutingServer)
+ scoutingServer.Start(8080)
+ defer scoutingServer.Stop()
+
+ builder := flatbuffers.NewBuilder(1024)
+ builder.Finish((&delete_2024_data_scouting.Delete2024DataScoutingT{
+ CompLevel: "quals",
+ MatchNumber: 3,
+ SetNumber: 1,
+ TeamNumber: "746",
+ }).Pack(builder))
+
+ _, err := debug.Delete2024DataScouting("http://localhost:8080", builder.FinishedBytes())
+ if err != nil {
+ t.Fatal("Failed to delete from data scouting 2024", err)
+ }
+
+ expectedActions := []db.Action{
+ {
+ PreScouting: true,
+ TeamNumber: "244",
+ MatchNumber: 5,
+ SetNumber: 3,
+ CompLevel: "quals",
+ CollectedBy: "debug_cli",
+ CompletedAction: []byte{},
+ Timestamp: 1009,
+ },
+ }
+
+ expectedStats := []db.Stats2024{
+ {
+ PreScouting: false, TeamNumber: "244",
+ MatchNumber: 5, SetNumber: 3, CompLevel: "quals", StartingQuadrant: 1,
+ SpeakerAuto: 0, AmpAuto: 0, NotesDroppedAuto: 0, MobilityAuto: false,
+ Speaker: 0, Amp: 0, SpeakerAmplified: 3, AmpAmplified: 1,
+ NotesDropped: 0, Penalties: 1, TrapNote: false, AvgCycle: 120,
+ Park: false, OnStage: true, Harmony: false, CollectedBy: "kacey",
+ },
+ }
+
+ if !reflect.DeepEqual(expectedActions, database.actions) {
+ t.Fatal("Expected ", expectedActions, ", but got:", database.actions)
+ }
+ if !reflect.DeepEqual(expectedStats, database.stats2024) {
+ t.Fatal("Expected ", expectedStats, ", but got:", database.stats2024)
+ }
+}
+
// A mocked database we can use for testing. Add functionality to this as
// needed for your tests.
@@ -1164,6 +1546,7 @@
shiftSchedule []db.Shift
driver_ranking []db.DriverRankingData
stats2023 []db.Stats2023
+ stats2024 []db.Stats2024
actions []db.Action
images []db.PitImage
}
@@ -1177,6 +1560,11 @@
database.stats2023 = append(database.stats2023, stats2023)
return nil
}
+
+func (database *MockDatabase) AddToStats2024(stats2024 db.Stats2024) error {
+ database.stats2024 = append(database.stats2024, stats2024)
+ return nil
+}
func (database *MockDatabase) ReturnMatches() ([]db.TeamMatch, error) {
return database.matches, nil
}
@@ -1185,6 +1573,10 @@
return database.stats2023, nil
}
+func (database *MockDatabase) ReturnStats2024() ([]db.Stats2024, error) {
+ return database.stats2024, nil
+}
+
func (database *MockDatabase) ReturnStats2023ForTeam(teamNumber string, matchNumber int32, setNumber int32, compLevel string, preScouting bool) ([]db.Stats2023, error) {
var results []db.Stats2023
for _, stats := range database.stats2023 {
@@ -1195,6 +1587,16 @@
return results, nil
}
+func (database *MockDatabase) ReturnStats2024ForTeam(teamNumber string, matchNumber int32, setNumber int32, compLevel string, preScouting bool) ([]db.Stats2024, error) {
+ var results []db.Stats2024
+ for _, stats := range database.stats2024 {
+ if stats.TeamNumber == teamNumber && stats.MatchNumber == matchNumber && stats.SetNumber == setNumber && stats.CompLevel == compLevel && stats.PreScouting == preScouting {
+ results = append(results, stats)
+ }
+ }
+ return results, nil
+}
+
func (database *MockDatabase) QueryNotes(requestedTeam string) ([]string, error) {
var results []string
for _, data := range database.notes {
@@ -1281,6 +1683,19 @@
return nil
}
+func (database *MockDatabase) DeleteFromStats2024(compLevel_ string, matchNumber_ int32, setNumber_ int32, teamNumber_ string) error {
+ for i, stat := range database.stats2024 {
+ if stat.CompLevel == compLevel_ &&
+ stat.MatchNumber == matchNumber_ &&
+ stat.SetNumber == setNumber_ &&
+ stat.TeamNumber == teamNumber_ {
+ // Match found, remove the element from the array.
+ database.stats2024 = append(database.stats2024[:i], database.stats2024[i+1:]...)
+ }
+ }
+ return nil
+}
+
func (database *MockDatabase) DeleteFromActions(compLevel_ string, matchNumber_ int32, setNumber_ int32, teamNumber_ string) error {
for i, action := range database.actions {
if action.CompLevel == compLevel_ &&