Add New 2024 Actions + Stats
Signed-off-by: Emily Markova <emily.markova@gmail.com>
Change-Id: I945b6e4450695119ad1edc72701f4a9afe79c3c4
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_ &&