diff --git a/partner/tba.go b/partner/tba.go index 32c9e613..b0fc4daa 100644 --- a/partner/tba.go +++ b/partner/tba.go @@ -14,6 +14,7 @@ import ( "github.com/Team254/cheesy-arena/game" "github.com/Team254/cheesy-arena/model" "github.com/mitchellh/mapstructure" + "io" "io/ioutil" "net/http" "strconv" @@ -52,45 +53,42 @@ type TbaAlliance struct { } type TbaScoreBreakdown struct { - TaxiRobot1 string `mapstructure:"taxiRobot1"` - TaxiRobot2 string `mapstructure:"taxiRobot2"` - TaxiRobot3 string `mapstructure:"taxiRobot3"` - AutoCargoLowerBlue int `mapstructure:"autoCargoLowerBlue"` - AutoCargoLowerFar int `mapstructure:"autoCargoLowerFar"` - AutoCargoLowerNear int `mapstructure:"autoCargoLowerNear"` - AutoCargoLowerRed int `mapstructure:"autoCargoLowerRed"` - AutoCargoUpperBlue int `mapstructure:"autoCargoUpperBlue"` - AutoCargoUpperFar int `mapstructure:"autoCargoUpperFar"` - AutoCargoUpperNear int `mapstructure:"autoCargoUpperNear"` - AutoCargoUpperRed int `mapstructure:"autoCargoUpperRed"` - AutoCargoTotal int `mapstructure:"autoCargoTotal"` - TeleopCargoLowerBlue int `mapstructure:"teleopCargoLowerBlue"` - TeleopCargoLowerFar int `mapstructure:"teleopCargoLowerFar"` - TeleopCargoLowerNear int `mapstructure:"teleopCargoLowerNear"` - TeleopCargoLowerRed int `mapstructure:"teleopCargoLowerRed"` - TeleopCargoUpperBlue int `mapstructure:"teleopCargoUpperBlue"` - TeleopCargoUpperFar int `mapstructure:"teleopCargoUpperFar"` - TeleopCargoUpperNear int `mapstructure:"teleopCargoUpperNear"` - TeleopCargoUpperRed int `mapstructure:"teleopCargoUpperRed"` - TeleopCargoTotal int `mapstructure:"teleopCargoTotal"` - MatchCargoTotal int `mapstructure:"matchCargoTotal"` - EndgameRobot1 string `mapstructure:"endgameRobot1"` - EndgameRobot2 string `mapstructure:"endgameRobot2"` - EndgameRobot3 string `mapstructure:"endgameRobot3"` - AutoTaxiPoints int `mapstructure:"autoTaxiPoints"` - AutoCargoPoints int `mapstructure:"autoCargoPoints"` - AutoPoints int `mapstructure:"autoPoints"` - TeleopCargoPoints int `mapstructure:"teleopCargoPoints"` - EndgamePoints int `mapstructure:"endgamePoints"` - TeleopPoints int `mapstructure:"teleopPoints"` - QuintetAchieved bool `mapstructure:"quintetAchieved"` - CargoBonusRankingPoint bool `mapstructure:"cargoBonusRankingPoint"` - HangarBonusRankingPoint bool `mapstructure:"hangarBonusRankingPoint"` - FoulCount int `mapstructure:"foulCount"` - TechFoulCount int `mapstructure:"techFoulCount"` - FoulPoints int `mapstructure:"foulPoints"` - TotalPoints int `mapstructure:"totalPoints"` - RP int `mapstructure:"rp"` + MobilityRobot1 string `mapstructure:"mobilityRobot1"` + MobilityRobot2 string `mapstructure:"mobilityRobot2"` + MobilityRobot3 string `mapstructure:"mobilityRobot3"` + AutoMobilityPoints int `mapstructure:"autoMobilityPoints"` + AutoChargeStationRobot1 string `mapstructure:"autoChargeStationRobot1"` + AutoChargeStationRobot2 string `mapstructure:"autoChargeStationRobot2"` + AutoChargeStationRobot3 string `mapstructure:"autoChargeStationRobot3"` + AutoBridgeState string `mapstructure:"autoBridgeState"` + AutoCommunity map[string][9]string `mapstructure:"autoCommunity"` + AutoGamePieceCount int `mapstructure:"autoGamePieceCount"` + AutoGamePiecePoints int `mapstructure:"autoGamePiecePoints"` + AutoPoints int `mapstructure:"autoPoints"` + TeleopCommunity map[string][9]string `mapstructure:"teleopCommunity"` + TeleopGamePieceCount int `mapstructure:"teleopGamePieceCount"` + TeleopGamePiecePoints int `mapstructure:"teleopGamePiecePoints"` + Links []TbaLink `mapstructure:"links"` + LinkPoints int `mapstructure:"linkPoints"` + ExtraGamePieceCount int `mapstructure:"extraGamePieceCount"` + EndGameChargeStationRobot1 string `mapstructure:"endGameChargeStationRobot1"` + EndGameChargeStationRobot2 string `mapstructure:"endGameChargeStationRobot2"` + EndGameChargeStationRobot3 string `mapstructure:"endGameChargeStationRobot3"` + EndGameBridgeState string `mapstructure:"endGameBridgeState"` + TeleopPoints int `mapstructure:"teleopPoints"` + CoopertitionCriteriaMet bool `mapstructure:"coopertitionCriteriaMet"` + SustainabilityBonusAchieved bool `mapstructure:"sustainabilityBonusAchieved"` + ActivationBonusAchieved bool `mapstructure:"activationBonusAchieved"` + FoulCount int `mapstructure:"foulCount"` + TechFoulCount int `mapstructure:"techFoulCount"` + FoulPoints int `mapstructure:"foulPoints"` + TotalPoints int `mapstructure:"totalPoints"` + RP int `mapstructure:"rp"` +} + +type TbaLink struct { + Nodes [3]int `json:"nodes"` + Row string `json:"row"` } type TbaRanking struct { @@ -149,8 +147,15 @@ type TbaPublishedAward struct { Awardee string `json:"awardee"` } -var taxiMapping = map[bool]string{false: "No", true: "Yes"} -var endgameMapping = []string{"None", "Low", "Mid", "High", "Traversal"} +var mobilityMapping = map[bool]string{false: "No", true: "Yes"} +var autoChargeStationMapping = map[bool]string{false: "None", true: "Docked"} +var endGameChargeStationMapping = map[game.EndgameStatus]string{ + game.EndgameNone: "None", + game.EndgameParked: "Park", + game.EndgameDocked: "Docked", +} +var chargeStationLevelMapping = map[bool]string{false: "NotLevel", true: "Level"} +var gridRowMapping = map[int]string{0: "Bottom", 1: "Mid", 2: "Top"} func NewTbaClient(eventCode, secretId, secret string) *TbaClient { return &TbaClient{BaseUrl: tbaBaseUrl, eventCode: eventCode, secretId: secretId, secret: secret, @@ -166,7 +171,7 @@ func (client *TbaClient) GetTeam(teamNumber int) (*TbaTeam, error) { // Get the response and handle errors defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } @@ -186,7 +191,7 @@ func (client *TbaClient) GetRobotName(teamNumber int, year int) (string, error) // Get the response and handle errors defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return "", err } @@ -213,7 +218,7 @@ func (client *TbaClient) GetTeamAwards(teamNumber int) ([]*TbaAward, error) { // Get the response and handle errors defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } @@ -246,7 +251,7 @@ func (client *TbaClient) DownloadTeamAvatar(teamNumber, year int) error { // Get the response and handle errors defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return err } @@ -301,7 +306,7 @@ func (client *TbaClient) PublishTeams(database *model.Database) error { } if resp.StatusCode != 200 { defer resp.Body.Close() - body, _ := ioutil.ReadAll(resp.Body) + body, _ := io.ReadAll(resp.Body) return fmt.Errorf("Got status code %d from TBA: %s", resp.StatusCode, body) } return nil @@ -374,7 +379,7 @@ func (client *TbaClient) PublishMatches(database *model.Database) error { } if resp.StatusCode != 200 { defer resp.Body.Close() - body, _ := ioutil.ReadAll(resp.Body) + body, _ := io.ReadAll(resp.Body) return fmt.Errorf("Got status code %d from TBA: %s", resp.StatusCode, body) } return nil @@ -388,7 +393,7 @@ func (client *TbaClient) PublishRankings(database *model.Database) error { } // Build a JSON object of TBA-format rankings. - breakdowns := []string{"RP", "Match", "Hangar", "TaxiAndAutoCargo"} + breakdowns := []string{"RP", "Match", "ChargeStation", "Auto"} tbaRankings := make([]TbaRanking, len(rankings)) for i, ranking := range rankings { tbaRankings[i] = TbaRanking{ @@ -416,7 +421,7 @@ func (client *TbaClient) PublishRankings(database *model.Database) error { } if resp.StatusCode != 200 { defer resp.Body.Close() - body, _ := ioutil.ReadAll(resp.Body) + body, _ := io.ReadAll(resp.Body) return fmt.Errorf("Got status code %d from TBA: %s", resp.StatusCode, body) } return nil @@ -447,7 +452,7 @@ func (client *TbaClient) PublishAlliances(database *model.Database) error { } if resp.StatusCode != 200 { defer resp.Body.Close() - body, _ := ioutil.ReadAll(resp.Body) + body, _ := io.ReadAll(resp.Body) return fmt.Errorf("Got status code %d from TBA: %s", resp.StatusCode, body) } return nil @@ -478,7 +483,7 @@ func (client *TbaClient) PublishAwards(database *model.Database) error { } if resp.StatusCode != 200 { defer resp.Body.Close() - body, _ := ioutil.ReadAll(resp.Body) + body, _ := io.ReadAll(resp.Body) return fmt.Errorf("Got status code %d from TBA: %s", resp.StatusCode, body) } return nil @@ -492,7 +497,7 @@ func (client *TbaClient) DeletePublishedMatches() error { } if resp.StatusCode != 200 { defer resp.Body.Close() - body, _ := ioutil.ReadAll(resp.Body) + body, _ := io.ReadAll(resp.Body) return fmt.Errorf("Got status code %d from TBA: %s", resp.StatusCode, body) } return nil @@ -507,7 +512,7 @@ func (client *TbaClient) getEventName(eventCode string) (string, error) { // Get the response and handle errors defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { return "", err } @@ -556,8 +561,11 @@ func (client *TbaClient) postRequest(resource string, action string, body []byte } func createTbaAlliance(teamIds [3]int, surrogates [3]bool, score *int, cards map[string]string) *TbaAlliance { - alliance := TbaAlliance{Surrogates: []string{}, Dqs: []string{}, Score: score} + alliance := TbaAlliance{Teams: []string{}, Surrogates: []string{}, Dqs: []string{}, Score: score} for i, teamId := range teamIds { + if teamId == 0 { + continue + } teamKey := getTbaTeam(teamId) alliance.Teams = append(alliance.Teams, teamKey) if surrogates[i] { @@ -592,51 +600,58 @@ func createTbaScoringBreakdown( opponentScoreSummary = matchResult.RedScoreSummary() } - // TODO(pat): Update for 2023. - //breakdown.TaxiRobot1 = taxiMapping[score.TaxiStatuses[0]] - //breakdown.TaxiRobot2 = taxiMapping[score.TaxiStatuses[1]] - //breakdown.TaxiRobot3 = taxiMapping[score.TaxiStatuses[2]] - //breakdown.AutoCargoLowerBlue = score.AutoCargoLower[game.BlueQuadrant] - //breakdown.AutoCargoLowerFar = score.AutoCargoLower[game.FarQuadrant] - //breakdown.AutoCargoLowerNear = score.AutoCargoLower[game.NearQuadrant] - //breakdown.AutoCargoLowerRed = score.AutoCargoLower[game.RedQuadrant] - //breakdown.AutoCargoUpperBlue = score.AutoCargoUpper[game.BlueQuadrant] - //breakdown.AutoCargoUpperFar = score.AutoCargoUpper[game.FarQuadrant] - //breakdown.AutoCargoUpperNear = score.AutoCargoUpper[game.NearQuadrant] - //breakdown.AutoCargoUpperRed = score.AutoCargoUpper[game.RedQuadrant] - //breakdown.AutoCargoTotal = scoreSummary.AutoCargoCount - //breakdown.TeleopCargoLowerBlue = score.TeleopCargoLower[game.BlueQuadrant] - //breakdown.TeleopCargoLowerFar = score.TeleopCargoLower[game.FarQuadrant] - //breakdown.TeleopCargoLowerNear = score.TeleopCargoLower[game.NearQuadrant] - //breakdown.TeleopCargoLowerRed = score.TeleopCargoLower[game.RedQuadrant] - //breakdown.TeleopCargoUpperBlue = score.TeleopCargoUpper[game.BlueQuadrant] - //breakdown.TeleopCargoUpperFar = score.TeleopCargoUpper[game.FarQuadrant] - //breakdown.TeleopCargoUpperNear = score.TeleopCargoUpper[game.NearQuadrant] - //breakdown.TeleopCargoUpperRed = score.TeleopCargoUpper[game.RedQuadrant] - //breakdown.TeleopCargoTotal = scoreSummary.CargoCount - scoreSummary.AutoCargoCount - //breakdown.MatchCargoTotal = scoreSummary.CargoCount - //breakdown.EndgameRobot1 = endgameMapping[score.EndgameStatuses[0]] - //breakdown.EndgameRobot2 = endgameMapping[score.EndgameStatuses[1]] - //breakdown.EndgameRobot3 = endgameMapping[score.EndgameStatuses[2]] - //breakdown.AutoTaxiPoints = scoreSummary.TaxiPoints - //breakdown.AutoCargoPoints = scoreSummary.AutoCargoPoints - //breakdown.AutoPoints = scoreSummary.TaxiPoints + scoreSummary.AutoCargoPoints - //breakdown.TeleopCargoPoints = scoreSummary.CargoPoints - scoreSummary.AutoCargoPoints - //breakdown.EndgamePoints = scoreSummary.HangarPoints - //breakdown.TeleopPoints = scoreSummary.CargoPoints - scoreSummary.AutoCargoPoints + - // scoreSummary.HangarPoints - //breakdown.QuintetAchieved = scoreSummary.QuintetAchieved - //breakdown.CargoBonusRankingPoint = scoreSummary.CargoBonusRankingPoint - //breakdown.HangarBonusRankingPoint = scoreSummary.ActivationBonusRankingPoint - for _, foul := range score.Fouls { - if foul.Rule() != nil && !foul.Rule().IsRankingPoint { - if foul.Rule().IsTechnical { - breakdown.TechFoulCount++ - } else { - breakdown.FoulCount++ + breakdown.MobilityRobot1 = mobilityMapping[score.MobilityStatuses[0]] + breakdown.MobilityRobot2 = mobilityMapping[score.MobilityStatuses[1]] + breakdown.MobilityRobot3 = mobilityMapping[score.MobilityStatuses[2]] + breakdown.AutoMobilityPoints = scoreSummary.MobilityPoints + breakdown.AutoChargeStationRobot1 = autoChargeStationMapping[score.AutoDockStatuses[0]] + breakdown.AutoChargeStationRobot2 = autoChargeStationMapping[score.AutoDockStatuses[1]] + breakdown.AutoChargeStationRobot3 = autoChargeStationMapping[score.AutoDockStatuses[2]] + breakdown.AutoBridgeState = chargeStationLevelMapping[score.AutoChargeStationLevel] + breakdown.AutoCommunity = make(map[string][9]string) + breakdown.TeleopCommunity = make(map[string][9]string) + for rowIndex, rowName := range gridRowMapping { + shortRowName := string([]rune(rowName)[0]) + breakdown.AutoCommunity[shortRowName] = createTbaGridRow(&score.Grid, rowIndex, true) + breakdown.TeleopCommunity[shortRowName] = createTbaGridRow(&score.Grid, rowIndex, false) + } + for i := 0; i < 3; i++ { + for j := 0; j < 9; j++ { + if score.Grid.Nodes[i][j] != game.Empty { + if score.Grid.AutoScoring[i][j] { + breakdown.AutoGamePieceCount++ + } + breakdown.TeleopGamePieceCount++ } } } + for _, link := range score.Grid.Links() { + tbaLink := TbaLink{ + Nodes: [3]int{link.StartColumn, link.StartColumn + 1, link.StartColumn + 2}, + Row: gridRowMapping[int(link.Row)], + } + breakdown.Links = append(breakdown.Links, tbaLink) + } + breakdown.LinkPoints = score.Grid.LinkPoints() + breakdown.AutoGamePiecePoints = score.Grid.AutoGamePiecePoints() + breakdown.TeleopGamePiecePoints = score.Grid.TeleopGamePiecePoints() + score.Grid.SuperchargedPoints() + breakdown.AutoPoints = scoreSummary.AutoPoints + breakdown.ExtraGamePieceCount = score.Grid.NumSuperchargedNodes() + breakdown.EndGameChargeStationRobot1 = endGameChargeStationMapping[score.EndgameStatuses[0]] + breakdown.EndGameChargeStationRobot2 = endGameChargeStationMapping[score.EndgameStatuses[1]] + breakdown.EndGameChargeStationRobot3 = endGameChargeStationMapping[score.EndgameStatuses[2]] + breakdown.EndGameBridgeState = chargeStationLevelMapping[score.EndgameChargeStationLevel] + breakdown.TeleopPoints = breakdown.TeleopGamePiecePoints + scoreSummary.EndgamePoints + breakdown.CoopertitionCriteriaMet = score.Grid.IsCoopertitionThresholdAchieved() + breakdown.SustainabilityBonusAchieved = scoreSummary.SustainabilityBonusRankingPoint + breakdown.ActivationBonusAchieved = scoreSummary.ActivationBonusRankingPoint + for _, foul := range score.Fouls { + if foul.IsTechnical { + breakdown.TechFoulCount++ + } else { + breakdown.FoulCount++ + } + } breakdown.FoulPoints = scoreSummary.FoulPoints breakdown.TotalPoints = scoreSummary.Score @@ -652,8 +667,30 @@ func createTbaScoringBreakdown( breakdownMap := make(map[string]any) _ = mapstructure.Decode(breakdown, &breakdownMap) if eventSettings.SustainabilityBonusLinkThresholdWithCoop == 0 { - delete(breakdownMap, "quintetAchieved") + delete(breakdownMap, "coopertitionCriteriaMet") } return breakdownMap } + +func createTbaGridRow(grid *game.Grid, row int, isAuto bool) [9]string { + var gridRow [9]string + for column := 0; column < 9; column++ { + gridRow[column] = createTbaGridNode(grid, row, column, isAuto) + } + return gridRow +} + +func createTbaGridNode(grid *game.Grid, row int, column int, isAuto bool) string { + if isAuto && !grid.AutoScoring[row][column] { + return "None" + } + switch grid.Nodes[row][column] { + case game.Cone, game.ConeThenCube, game.TwoCones: + return "Cone" + case game.Cube, game.CubeThenCone, game.TwoCubes: + return "Cube" + default: + return "None" + } +} diff --git a/partner/tba_test.go b/partner/tba_test.go index 3d9df32f..f7879baa 100644 --- a/partner/tba_test.go +++ b/partner/tba_test.go @@ -9,7 +9,7 @@ import ( "github.com/Team254/cheesy-arena/game" "github.com/Team254/cheesy-arena/model" "github.com/stretchr/testify/assert" - "io/ioutil" + "io" "net/http" "net/http/httptest" "testing" @@ -62,7 +62,7 @@ func TestPublishMatches(t *testing.T) { // Mock the TBA server. tbaServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, _ := ioutil.ReadAll(r.Body) + body, _ := io.ReadAll(r.Body) var matches []*TbaMatch json.Unmarshal(body, &matches) assert.Equal(t, 2, len(matches)) @@ -88,7 +88,7 @@ func TestPublishRankings(t *testing.T) { // Mock the TBA server. tbaServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, _ := ioutil.ReadAll(r.Body) + body, _ := io.ReadAll(r.Body) var response TbaRankings json.Unmarshal(body, &response) assert.Equal(t, 2, len(response.Rankings))