From afcaa0e07cb8f0c94d115c619d7e031f36a7c2fd Mon Sep 17 00:00:00 2001 From: Patrick Fairbank Date: Wed, 18 Mar 2020 22:42:36 -0700 Subject: [PATCH] Update score/ranking models for 2020. --- field/arena.go | 11 +- field/arena_notifiers.go | 1 - field/arena_test.go | 10 -- game/foul.go | 2 +- game/ranking_fields.go | 49 +++---- game/ranking_fields_test.go | 60 ++++---- game/score.go | 265 +++++++++++++++++++----------------- game/score_test.go | 225 ++++++++++++++++-------------- game/test_helpers.go | 66 ++++----- model/match_result_test.go | 3 +- partner/tba.go | 137 ++++++++++--------- templates/base.html | 2 +- templates/rankings.csv | 2 +- web/match_play_test.go | 16 +-- web/match_review_test.go | 16 ++- web/reports.go | 9 +- web/reports_test.go | 2 +- web/scoring_panel.go | 107 ++++++++------- web/scoring_panel_test.go | 96 ++++++------- 19 files changed, 549 insertions(+), 530 deletions(-) diff --git a/field/arena.go b/field/arena.go index 91840d8..e329c39 100644 --- a/field/arena.go +++ b/field/arena.go @@ -158,7 +158,8 @@ func (arena *Arena) LoadSettings() error { game.UpdateMatchSounds() arena.MatchTimingNotifier.Notify() - game.HabDockingThreshold = settings.HabDockingThreshold + // TODO(pat): Customize 2020 scoring settings here. + //game.HabDockingThreshold = settings.HabDockingThreshold return nil } @@ -638,8 +639,7 @@ func (arena *Arena) checkCanStartMatch() error { return err } - if !arena.BypassPreMatchScore && (!arena.RedRealtimeScore.CurrentScore.IsValidPreMatch() || - !arena.BlueRealtimeScore.CurrentScore.IsValidPreMatch()) { + if !arena.BypassPreMatchScore { return fmt.Errorf("Cannot start match until pre-match scoring is set") } @@ -734,8 +734,7 @@ func (arena *Arena) handlePlcOutput() { // not input, or blinking green if ready. redAllianceReady := arena.checkAllianceStationsReady("R1", "R2", "R3") == nil blueAllianceReady := arena.checkAllianceStationsReady("B1", "B2", "B3") == nil - preMatchScoreReady := arena.BypassPreMatchScore || arena.RedRealtimeScore.CurrentScore.IsValidPreMatch() && - arena.BlueRealtimeScore.CurrentScore.IsValidPreMatch() + preMatchScoreReady := arena.BypassPreMatchScore greenStackLight := redAllianceReady && blueAllianceReady && preMatchScoreReady && arena.Plc.GetCycleState(2, 0, 2) arena.Plc.SetStackLights(!redAllianceReady, !blueAllianceReady, !preMatchScoreReady, greenStackLight) @@ -775,7 +774,7 @@ func (arena *Arena) handlePlcOutput() { } arena.Plc.SetCargoShipLights(false) arena.Plc.SetCargoShipMagnets(false) - arena.Plc.SetRocketLights(arena.RedScoreSummary().CompleteRocket, arena.BlueScoreSummary().CompleteRocket) + arena.Plc.SetRocketLights(false, false) } } diff --git a/field/arena_notifiers.go b/field/arena_notifiers.go index 83babed..79726ce 100644 --- a/field/arena_notifiers.go +++ b/field/arena_notifiers.go @@ -234,7 +234,6 @@ func getAudienceAllianceScoreFields(allianceScore *RealtimeScore, fields := new(audienceAllianceScoreFields) fields.Score = &allianceScore.CurrentScore fields.ScoreSummary = allianceScoreSummary - fields.IsPreMatchScoreReady = allianceScore.CurrentScore.IsValidPreMatch() return fields } diff --git a/field/arena_test.go b/field/arena_test.go index 3b6a6b2..f490538 100644 --- a/field/arena_test.go +++ b/field/arena_test.go @@ -76,16 +76,6 @@ func TestArenaCheckCanStartMatch(t *testing.T) { } // Check scoring constraints. - arena.RedRealtimeScore.CurrentScore = *game.TestScoreValidPreMatch() - err = arena.checkCanStartMatch() - if assert.NotNil(t, err) { - assert.Contains(t, err.Error(), "Cannot start match until pre-match scoring is set") - } - arena.BlueRealtimeScore.CurrentScore = *game.TestScoreValidPreMatch() - assert.Nil(t, arena.checkCanStartMatch()) - arena.RedRealtimeScore.CurrentScore = game.Score{} - arena.BlueRealtimeScore.CurrentScore = game.Score{} - assert.NotNil(t, arena.checkCanStartMatch()) arena.BypassPreMatchScore = true assert.Nil(t, arena.checkCanStartMatch()) diff --git a/game/foul.go b/game/foul.go index 7b54412..fe28ca2 100644 --- a/game/foul.go +++ b/game/foul.go @@ -22,7 +22,7 @@ func (foul *Foul) PointValue() int { return 0 } if foul.Rule().IsTechnical { - return 10 + return 15 } else { return 3 } diff --git a/game/ranking_fields.go b/game/ranking_fields.go index 746d57b..6544a9a 100644 --- a/game/ranking_fields.go +++ b/game/ranking_fields.go @@ -8,17 +8,16 @@ package game import "math/rand" type RankingFields struct { - RankingPoints int - CargoPoints int - HatchPanelPoints int - HabClimbPoints int - SandstormBonusPoints int - Random float64 - Wins int - Losses int - Ties int - Disqualifications int - Played int + RankingPoints int + AutoPoints int + EndgamePoints int + TeleopPoints int + Random float64 + Wins int + Losses int + Ties int + Disqualifications int + Played int } type Ranking struct { @@ -48,18 +47,17 @@ func (fields *RankingFields) AddScoreSummary(ownScore *ScoreSummary, opponentSco } else { fields.Losses += 1 } - if ownScore.CompleteRocket { + if ownScore.ControlPanelRankingPoint { fields.RankingPoints += 1 } - if ownScore.HabDocking { + if ownScore.EndgameRankingPoint { fields.RankingPoints += 1 } // Assign tiebreaker points. - fields.CargoPoints += ownScore.CargoPoints - fields.HatchPanelPoints += ownScore.HatchPanelPoints - fields.HabClimbPoints += ownScore.HabClimbPoints - fields.SandstormBonusPoints += ownScore.SandstormBonusPoints + fields.AutoPoints += ownScore.AutoPoints + fields.EndgamePoints += ownScore.EndgamePoints + fields.TeleopPoints += ownScore.TeleopPowerCellPoints + ownScore.ControlPanelPoints // Store a random value to be used as the last tiebreaker if necessary. fields.Random = rand.Float64() @@ -77,19 +75,16 @@ func (rankings Rankings) Less(i, j int) bool { // Use cross-multiplication to keep it in integer math. if a.RankingPoints*b.Played == b.RankingPoints*a.Played { - if a.CargoPoints*b.Played == b.CargoPoints*a.Played { - if a.HatchPanelPoints*b.Played == b.HatchPanelPoints*a.Played { - if a.HabClimbPoints*b.Played == b.HabClimbPoints*a.Played { - if a.SandstormBonusPoints*b.Played == b.SandstormBonusPoints*a.Played { - return a.Random > b.Random - } - return a.SandstormBonusPoints*b.Played > b.SandstormBonusPoints*a.Played + if a.AutoPoints*b.Played == b.AutoPoints*a.Played { + if a.EndgamePoints*b.Played == b.EndgamePoints*a.Played { + if a.TeleopPoints*b.Played == b.TeleopPoints*a.Played { + return a.Random > b.Random } - return a.HabClimbPoints*b.Played > b.HabClimbPoints*a.Played + return a.TeleopPoints*b.Played > b.TeleopPoints*a.Played } - return a.HatchPanelPoints*b.Played > b.HatchPanelPoints*a.Played + return a.EndgamePoints*b.Played > b.EndgamePoints*a.Played } - return a.CargoPoints*b.Played > b.CargoPoints*a.Played + return a.AutoPoints*b.Played > b.AutoPoints*a.Played } return a.RankingPoints*b.Played > b.RankingPoints*a.Played } diff --git a/game/ranking_fields_test.go b/game/ranking_fields_test.go index 4dd2cc0..5d38ea8 100644 --- a/game/ranking_fields_test.go +++ b/game/ranking_fields_test.go @@ -20,55 +20,51 @@ func TestAddScoreSummary(t *testing.T) { // Add a loss. rankingFields.AddScoreSummary(redSummary, blueSummary, false) - assert.Equal(t, RankingFields{1, 30, 20, 12, 9, 0.9451961492941164, 0, 1, 0, 0, 1}, rankingFields) + assert.Equal(t, RankingFields{1, 94, 75, 48, 0.9451961492941164, 0, 1, 0, 0, 1}, rankingFields) // Add a win. rankingFields.AddScoreSummary(blueSummary, redSummary, false) - assert.Equal(t, RankingFields{4, 48, 24, 33, 15, 0.24496508529377975, 1, 1, 0, 0, 2}, rankingFields) + assert.Equal(t, RankingFields{4, 111, 125, 200, 0.24496508529377975, 1, 1, 0, 0, 2}, rankingFields) // Add a tie. rankingFields.AddScoreSummary(redSummary, redSummary, false) - assert.Equal(t, RankingFields{6, 78, 44, 45, 24, 0.6559562651954052, 1, 1, 1, 0, 3}, rankingFields) + assert.Equal(t, RankingFields{6, 205, 200, 248, 0.6559562651954052, 1, 1, 1, 0, 3}, rankingFields) // Add a disqualification. rankingFields.AddScoreSummary(blueSummary, redSummary, true) - assert.Equal(t, RankingFields{6, 78, 44, 45, 24, 0.6559562651954052, 1, 1, 1, 1, 4}, rankingFields) + assert.Equal(t, RankingFields{6, 205, 200, 248, 0.6559562651954052, 1, 1, 1, 1, 4}, rankingFields) } func TestSortRankings(t *testing.T) { // Check tiebreakers. - rankings := make(Rankings, 12) - rankings[0] = &Ranking{1, 0, RankingFields{50, 50, 50, 50, 50, 0.49, 3, 2, 1, 0, 10}} - rankings[1] = &Ranking{2, 0, RankingFields{50, 50, 50, 50, 50, 0.51, 3, 2, 1, 0, 10}} - rankings[2] = &Ranking{3, 0, RankingFields{50, 50, 50, 50, 49, 0.50, 3, 2, 1, 0, 10}} - rankings[3] = &Ranking{4, 0, RankingFields{50, 50, 50, 50, 51, 0.50, 3, 2, 1, 0, 10}} - rankings[4] = &Ranking{5, 0, RankingFields{50, 50, 50, 49, 50, 0.50, 3, 2, 1, 0, 10}} - rankings[5] = &Ranking{6, 0, RankingFields{50, 50, 50, 51, 50, 0.50, 3, 2, 1, 0, 10}} - rankings[6] = &Ranking{7, 0, RankingFields{50, 50, 49, 50, 50, 0.50, 3, 2, 1, 0, 10}} - rankings[7] = &Ranking{8, 0, RankingFields{50, 50, 51, 50, 50, 0.50, 3, 2, 1, 0, 10}} - rankings[8] = &Ranking{9, 0, RankingFields{50, 49, 50, 50, 50, 0.50, 3, 2, 1, 0, 10}} - rankings[9] = &Ranking{10, 0, RankingFields{50, 51, 50, 50, 50, 0.50, 3, 2, 1, 0, 10}} - rankings[10] = &Ranking{11, 0, RankingFields{49, 50, 50, 50, 50, 0.50, 3, 2, 1, 0, 10}} - rankings[11] = &Ranking{12, 0, RankingFields{51, 50, 50, 50, 50, 0.50, 3, 2, 1, 0, 10}} + rankings := make(Rankings, 10) + rankings[0] = &Ranking{1, 0, RankingFields{50, 50, 50, 50, 0.49, 3, 2, 1, 0, 10}} + rankings[1] = &Ranking{2, 0, RankingFields{50, 50, 50, 50, 0.51, 3, 2, 1, 0, 10}} + rankings[2] = &Ranking{3, 0, RankingFields{50, 50, 50, 49, 0.50, 3, 2, 1, 0, 10}} + rankings[3] = &Ranking{4, 0, RankingFields{50, 50, 50, 51, 0.50, 3, 2, 1, 0, 10}} + rankings[4] = &Ranking{5, 0, RankingFields{50, 50, 49, 50, 0.50, 3, 2, 1, 0, 10}} + rankings[5] = &Ranking{6, 0, RankingFields{50, 50, 51, 50, 0.50, 3, 2, 1, 0, 10}} + rankings[6] = &Ranking{7, 0, RankingFields{50, 49, 50, 50, 0.50, 3, 2, 1, 0, 10}} + rankings[7] = &Ranking{8, 0, RankingFields{50, 51, 50, 50, 0.50, 3, 2, 1, 0, 10}} + rankings[8] = &Ranking{9, 0, RankingFields{49, 50, 50, 50, 0.50, 3, 2, 1, 0, 10}} + rankings[9] = &Ranking{10, 0, RankingFields{51, 50, 50, 50, 0.50, 3, 2, 1, 0, 10}} sort.Sort(rankings) - assert.Equal(t, 12, rankings[0].TeamId) - assert.Equal(t, 10, rankings[1].TeamId) - assert.Equal(t, 8, rankings[2].TeamId) - assert.Equal(t, 6, rankings[3].TeamId) - assert.Equal(t, 4, rankings[4].TeamId) - assert.Equal(t, 2, rankings[5].TeamId) - assert.Equal(t, 1, rankings[6].TeamId) - assert.Equal(t, 3, rankings[7].TeamId) - assert.Equal(t, 5, rankings[8].TeamId) - assert.Equal(t, 7, rankings[9].TeamId) - assert.Equal(t, 9, rankings[10].TeamId) - assert.Equal(t, 11, rankings[11].TeamId) + assert.Equal(t, 10, rankings[0].TeamId) + assert.Equal(t, 8, rankings[1].TeamId) + assert.Equal(t, 6, rankings[2].TeamId) + assert.Equal(t, 4, rankings[3].TeamId) + assert.Equal(t, 2, rankings[4].TeamId) + assert.Equal(t, 1, rankings[5].TeamId) + assert.Equal(t, 3, rankings[6].TeamId) + assert.Equal(t, 5, rankings[7].TeamId) + assert.Equal(t, 7, rankings[8].TeamId) + assert.Equal(t, 9, rankings[9].TeamId) // Check with unequal number of matches played. rankings = make(Rankings, 3) - rankings[0] = &Ranking{1, 0, RankingFields{10, 25, 25, 25, 25, 0.49, 3, 2, 1, 0, 5}} - rankings[1] = &Ranking{2, 0, RankingFields{19, 50, 50, 50, 50, 0.51, 3, 2, 1, 0, 9}} - rankings[2] = &Ranking{3, 0, RankingFields{20, 50, 50, 50, 50, 0.51, 3, 2, 1, 0, 10}} + rankings[0] = &Ranking{1, 0, RankingFields{10, 25, 25, 25, 0.49, 3, 2, 1, 0, 5}} + rankings[1] = &Ranking{2, 0, RankingFields{19, 50, 50, 50, 0.51, 3, 2, 1, 0, 9}} + rankings[2] = &Ranking{3, 0, RankingFields{20, 50, 50, 50, 0.51, 3, 2, 1, 0, 10}} sort.Sort(rankings) assert.Equal(t, 2, rankings[0].TeamId) assert.Equal(t, 3, rankings[1].TeamId) diff --git a/game/score.go b/game/score.go index d95d9ef..b641439 100644 --- a/game/score.go +++ b/game/score.go @@ -1,4 +1,4 @@ -// Copyright 2017 Team 254. All Rights Reserved. +// Copyright 2020 Team 254. All Rights Reserved. // Author: pat@patfairbank.com (Patrick Fairbank) // // Model representing the instantaneous score of a match. @@ -6,41 +6,62 @@ package game type Score struct { - RobotStartLevels [3]int - SandstormBonuses [3]bool - CargoBaysPreMatch [8]BayStatus - CargoBays [8]BayStatus - RocketNearLeftBays [3]BayStatus - RocketNearRightBays [3]BayStatus - RocketFarLeftBays [3]BayStatus - RocketFarRightBays [3]BayStatus - RobotEndLevels [3]int - Fouls []Foul - ElimDq bool + ExitedInitiationLine [3]bool + AutoCellsBottom [2]int + AutoCellsOuter [2]int + AutoCellsInner [2]int + TeleopPeriodStarted bool + TeleopCellsBottom [4]int + TeleopCellsOuter [4]int + TeleopCellsInner [4]int + RotationControl bool + PositionControl bool + EndgameStatuses [3]EndgameStatus + RungIsLevel bool + Fouls []Foul + ElimDq bool } type ScoreSummary struct { - CargoPoints int - HatchPanelPoints int - HabClimbPoints int - SandstormBonusPoints int - FoulPoints int - Score int - CompleteRocket bool - HabDocking bool + InitiationLinePoints int + AutoPowerCellPoints int + AutoPoints int + TeleopPowerCellPoints int + ControlPanelPoints int + EndgamePoints int + FoulPoints int + Score int + StagesAtCapacity [3]bool + StagesActivated [3]bool + ControlPanelRankingPoint bool + EndgameRankingPoint bool } -// Represents the state of a cargo ship or rocket bay. -type BayStatus int +// Defines the number of power cells that must be scored within each Stage before it can be activated. +var StageCapacities = map[Stage]int{ + Stage1: 9, + Stage2: 20, + Stage3: 20, +} + +// Represents a Stage towards whose capacity scored power cells are counted. +type Stage int const ( - BayEmpty BayStatus = iota - BayHatch - BayHatchCargo - BayCargo + Stage1 Stage = iota + Stage2 + Stage3 + StageExtra ) -var HabDockingThreshold = 15 +// Represents the state of a robot at the end of the match. +type EndgameStatus int + +const ( + None EndgameStatus = iota + Park + Hang +) // Calculates and returns the summary fields used for ranking and display. func (score *Score) Summarize(opponentFouls []Foul) *ScoreSummary { @@ -51,85 +72,77 @@ func (score *Score) Summarize(opponentFouls []Foul) *ScoreSummary { return summary } - // Calculate sandstorm bonus points. - for i, robotStartLevel := range score.RobotStartLevels { - if score.SandstormBonuses[i] { - if robotStartLevel == 1 { - summary.SandstormBonusPoints += 3 - } else if robotStartLevel == 2 { - summary.SandstormBonusPoints += 6 - } + // Calculate autonomous period points. + for _, exited := range score.ExitedInitiationLine { + if exited { + summary.InitiationLinePoints += 5 } } + for i := 0; i < len(score.AutoCellsBottom); i++ { + summary.AutoPowerCellPoints += 2 * score.AutoCellsBottom[i] + summary.AutoPowerCellPoints += 4 * score.AutoCellsOuter[i] + summary.AutoPowerCellPoints += 6 * score.AutoCellsInner[i] + } + summary.AutoPoints = summary.InitiationLinePoints + summary.AutoPowerCellPoints + + // Calculate teleoperated period power cell points. + for i := 0; i < len(score.TeleopCellsBottom); i++ { + summary.TeleopPowerCellPoints += score.TeleopCellsBottom[i] + summary.TeleopPowerCellPoints += 2 * score.TeleopCellsOuter[i] + summary.TeleopPowerCellPoints += 3 * score.TeleopCellsInner[i] + } - // Calculate cargo and hatch panel points. - for i, bayStatus := range score.CargoBays { - if bayStatus == BayHatchCargo { - summary.CargoPoints += 3 - if score.CargoBaysPreMatch[i] != BayHatch { - summary.HatchPanelPoints += 2 - } - } else if bayStatus == BayHatch && score.CargoBaysPreMatch[i] != BayHatch { - summary.HatchPanelPoints += 2 - } + // Calculate control panel points and stages. + for i := Stage1; i <= Stage3; i++ { + summary.StagesAtCapacity[i] = score.StageAtCapacity(i) + summary.StagesActivated[i] = score.StageActivated(i) } - summary.addRocketHalfPoints(score.RocketNearLeftBays) - summary.addRocketHalfPoints(score.RocketNearRightBays) - summary.addRocketHalfPoints(score.RocketFarLeftBays) - summary.addRocketHalfPoints(score.RocketFarRightBays) - - // Calculate hab climb points. - for _, level := range score.RobotEndLevels { - switch level { - case 1: - summary.HabClimbPoints += 3 - case 2: - summary.HabClimbPoints += 6 - case 3: - summary.HabClimbPoints += 12 - } + if summary.StagesActivated[Stage2] { + summary.ControlPanelPoints += 10 + } + if summary.StagesActivated[Stage3] { + summary.ControlPanelPoints += 20 + summary.ControlPanelRankingPoint = true } - // Calculate bonus ranking points. - if score.isLevelComplete(0) && score.isLevelComplete(1) && score.isLevelComplete(2) { - summary.CompleteRocket = true - } else { - // Check for the opponent fouls that automatically trigger the ranking point. - for _, foul := range opponentFouls { - if foul.Rule() == nil { - continue - } - if foul.Rule().IsRankingPoint { - summary.CompleteRocket = true - break - } + // Calculate endgame points. + for _, status := range score.EndgameStatuses { + if status == Park { + summary.EndgamePoints += 5 + } else if status == Hang { + summary.EndgamePoints += 25 } } - if summary.HabClimbPoints >= HabDockingThreshold { - summary.HabDocking = true + if summary.EndgamePoints > 0 && score.RungIsLevel { + summary.EndgamePoints += 15 } + summary.EndgameRankingPoint = summary.EndgamePoints >= 65 // Calculate penalty points. for _, foul := range opponentFouls { summary.FoulPoints += foul.PointValue() } - summary.Score = summary.CargoPoints + summary.HatchPanelPoints + summary.HabClimbPoints + - summary.SandstormBonusPoints + summary.FoulPoints + summary.Score = summary.AutoPoints + summary.TeleopPowerCellPoints + summary.ControlPanelPoints + + summary.EndgamePoints + summary.FoulPoints return summary } +// Returns true if and only if all fields of the two scores are equal. func (score *Score) Equals(other *Score) bool { - if score.RobotStartLevels != other.RobotStartLevels || - score.SandstormBonuses != other.SandstormBonuses || - score.CargoBaysPreMatch != other.CargoBaysPreMatch || - score.CargoBays != other.CargoBays || - score.RocketNearLeftBays != other.RocketNearLeftBays || - score.RocketNearRightBays != other.RocketNearRightBays || - score.RocketFarLeftBays != other.RocketFarLeftBays || - score.RocketFarRightBays != other.RocketFarRightBays || - score.RobotEndLevels != other.RobotEndLevels || + if score.ExitedInitiationLine != other.ExitedInitiationLine || + score.AutoCellsBottom != other.AutoCellsBottom || + score.AutoCellsOuter != other.AutoCellsOuter || + score.AutoCellsInner != other.AutoCellsInner || + score.TeleopPeriodStarted != other.TeleopPeriodStarted || + score.TeleopCellsBottom != other.TeleopCellsBottom || + score.TeleopCellsOuter != other.TeleopCellsOuter || + score.TeleopCellsInner != other.TeleopCellsInner || + score.RotationControl != other.RotationControl || + score.PositionControl != other.PositionControl || + score.EndgameStatuses != other.EndgameStatuses || + score.RungIsLevel != other.RungIsLevel || score.ElimDq != other.ElimDq || len(score.Fouls) != len(other.Fouls) { return false @@ -144,51 +157,51 @@ func (score *Score) Equals(other *Score) bool { return true } -// Returns true if the score represents a valid pre-match state. -func (score *Score) IsValidPreMatch() bool { - for i := 0; i < 3; i++ { - // Ensure robot start level is set. - if score.RobotStartLevels[i] == 0 || score.RobotStartLevels[i] > 3 { - return false - } - - // Ensure other robot fields and rocket bays are empty. - if score.SandstormBonuses[i] || score.RobotEndLevels[i] != 0 || score.RocketNearLeftBays[i] != BayEmpty || - score.RocketNearRightBays[i] != BayEmpty || score.RocketFarLeftBays[i] != BayEmpty || - score.RocketFarRightBays[i] != BayEmpty { - return false - } +// Returns the Stage (1-3) that the score represents, in terms of which Stage scored power cells should count towards. +func (score *Score) CellCountingStage() Stage { + if score.StageActivated(Stage3) { + return StageExtra } - for i := 0; i < 8; i++ { - if i == 3 || i == 4 { - // Ensure cargo ship front bays are empty. - if score.CargoBaysPreMatch[i] != BayEmpty { - return false - } - } else { - // Ensure cargo ship side bays have either a hatch or cargo but not both. - if !(score.CargoBaysPreMatch[i] == BayHatch || score.CargoBaysPreMatch[i] == BayCargo) { - return false - } - } + if score.StageActivated(Stage2) { + return Stage3 } - return score.CargoBays == score.CargoBaysPreMatch + if score.StageActivated(Stage1) { + return Stage2 + } + return Stage1 } -// Calculates the cargo and hatch panel points for the given rocket half and adds them to the summary. -func (summary *ScoreSummary) addRocketHalfPoints(rocketHalf [3]BayStatus) { - for _, bayStatus := range rocketHalf { - if bayStatus == BayHatchCargo { - summary.CargoPoints += 3 - summary.HatchPanelPoints += 2 - } else if bayStatus == BayHatch { - summary.HatchPanelPoints += 2 - } +// Returns true if the preconditions are satisfied for the given Stage to be activated. +func (score *Score) StageAtCapacity(stage Stage) bool { + if stage > Stage1 && !score.StageActivated(stage-1) { + return false } + if capacity, ok := StageCapacities[stage]; ok && score.stagePowerCells(stage) >= capacity { + return true + } + return false } -// Returns true if the level is complete for at least one rocket. -func (score *Score) isLevelComplete(level int) bool { - return score.RocketNearLeftBays[level] == BayHatchCargo && score.RocketNearRightBays[level] == BayHatchCargo || - score.RocketFarLeftBays[level] == BayHatchCargo && score.RocketFarRightBays[level] == BayHatchCargo +// Returns true if the given Stage has been activated. +func (score *Score) StageActivated(stage Stage) bool { + if score.StageAtCapacity(stage) { + switch stage { + case Stage1: + return score.TeleopPeriodStarted + case Stage2: + return score.RotationControl + case Stage3: + return score.PositionControl + } + } + return false +} + +// Returns the total count of scored power cells within the given Stage. +func (score *Score) stagePowerCells(stage Stage) int { + cells := score.TeleopCellsBottom[stage] + score.TeleopCellsOuter[stage] + score.TeleopCellsInner[stage] + if stage < Stage3 { + cells += score.AutoCellsBottom[stage] + score.AutoCellsOuter[stage] + score.AutoCellsInner[stage] + } + return cells } diff --git a/game/score_test.go b/game/score_test.go index 64505e9..c09c47b 100644 --- a/game/score_test.go +++ b/game/score_test.go @@ -13,47 +13,36 @@ func TestScoreSummary(t *testing.T) { blueScore := TestScore2() redSummary := redScore.Summarize(blueScore.Fouls) - assert.Equal(t, 30, redSummary.CargoPoints) - assert.Equal(t, 20, redSummary.HatchPanelPoints) - assert.Equal(t, 12, redSummary.HabClimbPoints) - assert.Equal(t, 9, redSummary.SandstormBonusPoints) + assert.Equal(t, 10, redSummary.InitiationLinePoints) + assert.Equal(t, 84, redSummary.AutoPowerCellPoints) + assert.Equal(t, 94, redSummary.AutoPoints) + assert.Equal(t, 38, redSummary.TeleopPowerCellPoints) + assert.Equal(t, 10, redSummary.ControlPanelPoints) + assert.Equal(t, 75, redSummary.EndgamePoints) assert.Equal(t, 0, redSummary.FoulPoints) - assert.Equal(t, 71, redSummary.Score) - assert.Equal(t, true, redSummary.CompleteRocket) - assert.Equal(t, false, redSummary.HabDocking) + assert.Equal(t, 217, redSummary.Score) + assert.Equal(t, [3]bool{true, true, false}, redSummary.StagesAtCapacity) + assert.Equal(t, [3]bool{true, true, false}, redSummary.StagesActivated) + assert.Equal(t, false, redSummary.ControlPanelRankingPoint) + assert.Equal(t, true, redSummary.EndgameRankingPoint) blueSummary := blueScore.Summarize(redScore.Fouls) - assert.Equal(t, 18, blueSummary.CargoPoints) - assert.Equal(t, 4, blueSummary.HatchPanelPoints) - assert.Equal(t, 21, blueSummary.HabClimbPoints) - assert.Equal(t, 6, blueSummary.SandstormBonusPoints) - assert.Equal(t, 23, blueSummary.FoulPoints) - assert.Equal(t, 72, blueSummary.Score) - assert.Equal(t, false, blueSummary.CompleteRocket) - assert.Equal(t, true, blueSummary.HabDocking) + assert.Equal(t, 5, blueSummary.InitiationLinePoints) + assert.Equal(t, 12, blueSummary.AutoPowerCellPoints) + assert.Equal(t, 17, blueSummary.AutoPoints) + assert.Equal(t, 122, blueSummary.TeleopPowerCellPoints) + assert.Equal(t, 30, blueSummary.ControlPanelPoints) + assert.Equal(t, 50, blueSummary.EndgamePoints) + assert.Equal(t, 33, blueSummary.FoulPoints) + assert.Equal(t, 252, blueSummary.Score) + assert.Equal(t, [3]bool{true, true, true}, blueSummary.StagesAtCapacity) + assert.Equal(t, [3]bool{true, true, true}, blueSummary.StagesActivated) + assert.Equal(t, true, blueSummary.ControlPanelRankingPoint) + assert.Equal(t, false, blueSummary.EndgameRankingPoint) // Test invalid foul. redScore.Fouls[0].RuleId = 0 - assert.Equal(t, 13, blueScore.Summarize(redScore.Fouls).FoulPoints) - - // Test rocket completion boundary conditions. - assert.Equal(t, true, redScore.Summarize(blueScore.Fouls).CompleteRocket) - redScore.RocketFarLeftBays[1] = BayHatch - assert.Equal(t, false, redScore.Summarize(blueScore.Fouls).CompleteRocket) - redScore.RocketNearLeftBays[1] = BayHatchCargo - redScore.RocketNearRightBays[1] = BayHatchCargo - assert.Equal(t, true, redScore.Summarize(blueScore.Fouls).CompleteRocket) - redScore.RocketNearLeftBays[2] = BayHatch - assert.Equal(t, false, redScore.Summarize(blueScore.Fouls).CompleteRocket) - redScore.Fouls[2].RuleId = 15 - assert.Equal(t, true, redScore.Summarize(redScore.Fouls).CompleteRocket) - - // Test hab docking boundary conditions. - assert.Equal(t, true, blueScore.Summarize(redScore.Fouls).HabDocking) - HabDockingThreshold = 24 - assert.Equal(t, false, blueScore.Summarize(redScore.Fouls).HabDocking) - blueScore.RobotEndLevels[0] = 3 - assert.Equal(t, true, blueScore.Summarize(redScore.Fouls).HabDocking) + assert.Equal(t, 18, blueScore.Summarize(redScore.Fouls).FoulPoints) // Test elimination disqualification. redScore.ElimDq = true @@ -63,6 +52,80 @@ func TestScoreSummary(t *testing.T) { assert.Equal(t, 0, blueScore.Summarize(redScore.Fouls).Score) } +func TestScoreSummaryBoundaryConditions(t *testing.T) { + // Test control panel boundary conditions. + score := TestScore2() + summary := score.Summarize(score.Fouls) + assert.Equal(t, StageExtra, score.CellCountingStage()) + assert.Equal(t, [3]bool{true, true, true}, summary.StagesAtCapacity) + assert.Equal(t, [3]bool{true, true, true}, summary.StagesActivated) + assert.Equal(t, true, summary.ControlPanelRankingPoint) + assert.Equal(t, 219, summary.Score) + + score.TeleopCellsInner[0]-- + summary = score.Summarize(score.Fouls) + assert.Equal(t, Stage1, score.CellCountingStage()) + assert.Equal(t, [3]bool{false, false, false}, summary.StagesAtCapacity) + assert.Equal(t, [3]bool{false, false, false}, summary.StagesActivated) + assert.Equal(t, false, summary.ControlPanelRankingPoint) + assert.Equal(t, 186, summary.Score) + score.TeleopCellsInner[0]++ + + score.TeleopPeriodStarted = false + summary = score.Summarize(score.Fouls) + assert.Equal(t, Stage1, score.CellCountingStage()) + assert.Equal(t, [3]bool{true, false, false}, summary.StagesAtCapacity) + assert.Equal(t, [3]bool{false, false, false}, summary.StagesActivated) + assert.Equal(t, false, summary.ControlPanelRankingPoint) + assert.Equal(t, 189, summary.Score) + score.TeleopPeriodStarted = true + + score.TeleopCellsOuter[1]-- + summary = score.Summarize(score.Fouls) + assert.Equal(t, Stage2, score.CellCountingStage()) + assert.Equal(t, [3]bool{true, false, false}, summary.StagesAtCapacity) + assert.Equal(t, [3]bool{true, false, false}, summary.StagesActivated) + assert.Equal(t, false, summary.ControlPanelRankingPoint) + assert.Equal(t, 187, summary.Score) + score.TeleopCellsOuter[1]++ + + score.RotationControl = false + summary = score.Summarize(score.Fouls) + assert.Equal(t, Stage2, score.CellCountingStage()) + assert.Equal(t, [3]bool{true, true, false}, summary.StagesAtCapacity) + assert.Equal(t, [3]bool{true, false, false}, summary.StagesActivated) + assert.Equal(t, false, summary.ControlPanelRankingPoint) + assert.Equal(t, 189, summary.Score) + score.RotationControl = true + + score.TeleopCellsInner[2] -= 3 + summary = score.Summarize(score.Fouls) + assert.Equal(t, Stage3, score.CellCountingStage()) + assert.Equal(t, [3]bool{true, true, false}, summary.StagesAtCapacity) + assert.Equal(t, [3]bool{true, true, false}, summary.StagesActivated) + assert.Equal(t, false, summary.ControlPanelRankingPoint) + assert.Equal(t, 190, summary.Score) + score.TeleopCellsInner[2] += 3 + + score.PositionControl = false + summary = score.Summarize(score.Fouls) + assert.Equal(t, Stage3, score.CellCountingStage()) + assert.Equal(t, [3]bool{true, true, true}, summary.StagesAtCapacity) + assert.Equal(t, [3]bool{true, true, false}, summary.StagesActivated) + assert.Equal(t, false, summary.ControlPanelRankingPoint) + assert.Equal(t, 199, summary.Score) + + // Test endgame boundary conditions. + score = TestScore1() + assert.Equal(t, true, score.Summarize(score.Fouls).EndgameRankingPoint) + score.EndgameStatuses[0] = None + assert.Equal(t, false, score.Summarize(score.Fouls).EndgameRankingPoint) + score.RungIsLevel = true + assert.Equal(t, true, score.Summarize(score.Fouls).EndgameRankingPoint) + score.EndgameStatuses[2] = Park + assert.Equal(t, false, score.Summarize(score.Fouls).EndgameRankingPoint) +} + func TestScoreEquals(t *testing.T) { score1 := TestScore1() score2 := TestScore1() @@ -73,47 +136,63 @@ func TestScoreEquals(t *testing.T) { assert.False(t, score1.Equals(score3)) assert.False(t, score3.Equals(score1)) - score2.RobotStartLevels[2] = 3 + score2 = TestScore1() + score2.ExitedInitiationLine[0] = false assert.False(t, score1.Equals(score2)) assert.False(t, score2.Equals(score1)) score2 = TestScore1() - score2.SandstormBonuses[0] = false + score2.AutoCellsBottom[1] = 3 assert.False(t, score1.Equals(score2)) assert.False(t, score2.Equals(score1)) score2 = TestScore1() - score2.CargoBaysPreMatch[7] = BayCargo + score2.AutoCellsOuter[0] = 7 assert.False(t, score1.Equals(score2)) assert.False(t, score2.Equals(score1)) score2 = TestScore1() - score2.CargoBays[5] = BayHatchCargo + score2.AutoCellsInner[1] = 8 assert.False(t, score1.Equals(score2)) assert.False(t, score2.Equals(score1)) score2 = TestScore1() - score2.RocketNearLeftBays[0] = BayEmpty + score2.TeleopPeriodStarted = !score2.TeleopPeriodStarted assert.False(t, score1.Equals(score2)) assert.False(t, score2.Equals(score1)) score2 = TestScore1() - score2.RocketNearRightBays[1] = BayHatchCargo + score2.TeleopCellsBottom[2] = 30 assert.False(t, score1.Equals(score2)) assert.False(t, score2.Equals(score1)) score2 = TestScore1() - score2.RocketFarLeftBays[2] = BayCargo + score2.TeleopCellsOuter[1] = 31 assert.False(t, score1.Equals(score2)) assert.False(t, score2.Equals(score1)) score2 = TestScore1() - score2.RocketFarRightBays[0] = BayHatch + score2.TeleopCellsInner[0] = 32 assert.False(t, score1.Equals(score2)) assert.False(t, score2.Equals(score1)) score2 = TestScore1() - score2.RobotEndLevels[1] = 2 + score2.RotationControl = !score2.RotationControl + assert.False(t, score1.Equals(score2)) + assert.False(t, score2.Equals(score1)) + + score2 = TestScore1() + score2.PositionControl = !score2.PositionControl + assert.False(t, score1.Equals(score2)) + assert.False(t, score2.Equals(score1)) + + score2 = TestScore1() + score2.EndgameStatuses[1] = None + assert.False(t, score1.Equals(score2)) + assert.False(t, score2.Equals(score1)) + + score2 = TestScore1() + score2.RungIsLevel = !score2.RungIsLevel assert.False(t, score1.Equals(score2)) assert.False(t, score2.Equals(score1)) @@ -142,61 +221,3 @@ func TestScoreEquals(t *testing.T) { assert.False(t, score1.Equals(score2)) assert.False(t, score2.Equals(score1)) } - -func TestIsValidPreMatch(t *testing.T) { - score := &Score{} - assert.False(t, score.IsValidPreMatch()) - - score = TestScoreValidPreMatch() - score.RobotStartLevels = [3]int{1, 2, 3} - score.CargoBaysPreMatch = [8]BayStatus{1, 3, 3, 0, 0, 1, 1, 3} - score.CargoBays = score.CargoBaysPreMatch - assert.True(t, score.IsValidPreMatch()) - - score = TestScoreValidPreMatch() - score.RobotStartLevels[0] = 0 - assert.False(t, score.IsValidPreMatch()) - - score = TestScoreValidPreMatch() - score.SandstormBonuses[1] = true - assert.False(t, score.IsValidPreMatch()) - - score = TestScoreValidPreMatch() - score.RobotEndLevels[2] = 3 - assert.False(t, score.IsValidPreMatch()) - - score = TestScoreValidPreMatch() - score.CargoBaysPreMatch[0] = BayEmpty - assert.False(t, score.IsValidPreMatch()) - - score = TestScoreValidPreMatch() - score.CargoBaysPreMatch[1] = BayHatchCargo - assert.False(t, score.IsValidPreMatch()) - - score = TestScoreValidPreMatch() - score.CargoBaysPreMatch[3] = BayHatch - score.CargoBaysPreMatch[4] = BayCargo - score.CargoBaysPreMatch[5] = BayEmpty - score.CargoBaysPreMatch[6] = BayEmpty - assert.False(t, score.IsValidPreMatch()) - - score = TestScoreValidPreMatch() - score.CargoBays[0] = BayCargo - assert.False(t, score.IsValidPreMatch()) - - score = TestScoreValidPreMatch() - score.RocketNearLeftBays[0] = BayHatch - assert.False(t, score.IsValidPreMatch()) - - score = TestScoreValidPreMatch() - score.RocketNearRightBays[1] = BayHatchCargo - assert.False(t, score.IsValidPreMatch()) - - score = TestScoreValidPreMatch() - score.RocketFarLeftBays[2] = BayCargo - assert.False(t, score.IsValidPreMatch()) - - score = TestScoreValidPreMatch() - score.RocketFarRightBays[0] = BayHatchCargo - assert.False(t, score.IsValidPreMatch()) -} diff --git a/game/test_helpers.go b/game/test_helpers.go index 8c6b665..1170198 100644 --- a/game/test_helpers.go +++ b/game/test_helpers.go @@ -12,52 +12,46 @@ func TestScore1() *Score { {21, 25, 25.2}, } return &Score{ - RobotStartLevels: [3]int{2, 1, 2}, - SandstormBonuses: [3]bool{true, true, false}, - CargoBaysPreMatch: [8]BayStatus{BayHatch, BayEmpty, BayEmpty, BayCargo, BayHatch, BayCargo, BayHatch, - BayHatch}, - CargoBays: [8]BayStatus{BayHatchCargo, BayHatch, BayEmpty, BayHatchCargo, BayHatchCargo, BayEmpty, - BayHatch, BayHatchCargo}, - RocketNearLeftBays: [3]BayStatus{BayHatchCargo, BayEmpty, BayHatchCargo}, - RocketNearRightBays: [3]BayStatus{BayHatchCargo, BayHatch, BayHatchCargo}, - RocketFarLeftBays: [3]BayStatus{BayEmpty, BayHatchCargo, BayHatch}, - RocketFarRightBays: [3]BayStatus{BayEmpty, BayHatchCargo, BayEmpty}, - RobotEndLevels: [3]int{0, 0, 3}, - Fouls: fouls, - ElimDq: false, + ExitedInitiationLine: [3]bool{true, true, false}, + AutoCellsBottom: [2]int{2, 1}, + AutoCellsOuter: [2]int{6, 0}, + AutoCellsInner: [2]int{4, 5}, + TeleopPeriodStarted: true, + TeleopCellsBottom: [4]int{0, 11, 2, 0}, + TeleopCellsOuter: [4]int{0, 5, 0, 0}, + TeleopCellsInner: [4]int{0, 5, 0, 0}, + RotationControl: true, + PositionControl: false, + EndgameStatuses: [3]EndgameStatus{Hang, Hang, Hang}, + RungIsLevel: false, + Fouls: fouls, + ElimDq: false, } } func TestScore2() *Score { return &Score{ - RobotStartLevels: [3]int{1, 2, 1}, - SandstormBonuses: [3]bool{false, true, false}, - CargoBaysPreMatch: [8]BayStatus{BayEmpty, BayEmpty, BayHatch, BayHatch, BayHatch, BayHatch, BayHatch, - BayHatch}, - CargoBays: [8]BayStatus{BayEmpty, BayEmpty, BayHatchCargo, BayHatchCargo, BayHatchCargo, BayHatch, BayHatch, - BayHatchCargo}, - RocketNearLeftBays: [3]BayStatus{BayEmpty, BayEmpty, BayEmpty}, - RocketNearRightBays: [3]BayStatus{BayEmpty, BayEmpty, BayEmpty}, - RocketFarLeftBays: [3]BayStatus{BayHatchCargo, BayEmpty, BayEmpty}, - RocketFarRightBays: [3]BayStatus{BayEmpty, BayEmpty, BayHatchCargo}, - RobotEndLevels: [3]int{1, 3, 2}, - Fouls: []Foul{}, - ElimDq: false, - } -} - -func TestScoreValidPreMatch() *Score { - return &Score{ - RobotStartLevels: [3]int{1, 2, 3}, - CargoBaysPreMatch: [8]BayStatus{1, 3, 3, 0, 0, 1, 1, 3}, - CargoBays: [8]BayStatus{1, 3, 3, 0, 0, 1, 1, 3}, + ExitedInitiationLine: [3]bool{false, true, false}, + AutoCellsBottom: [2]int{0, 0}, + AutoCellsOuter: [2]int{3, 0}, + AutoCellsInner: [2]int{0, 0}, + TeleopPeriodStarted: true, + TeleopCellsBottom: [4]int{2, 0, 2, 0}, + TeleopCellsOuter: [4]int{2, 14, 0, 1}, + TeleopCellsInner: [4]int{2, 6, 20, 0}, + RotationControl: true, + PositionControl: true, + EndgameStatuses: [3]EndgameStatus{Park, Park, Hang}, + RungIsLevel: true, + Fouls: []Foul{}, + ElimDq: false, } } func TestRanking1() *Ranking { - return &Ranking{254, 1, RankingFields{20, 625, 90, 554, 10, 0.254, 3, 2, 1, 0, 10}} + return &Ranking{254, 1, RankingFields{20, 625, 90, 554, 0.254, 3, 2, 1, 0, 10}} } func TestRanking2() *Ranking { - return &Ranking{1114, 2, RankingFields{18, 700, 625, 90, 554, 0.1114, 1, 3, 2, 0, 10}} + return &Ranking{1114, 2, RankingFields{18, 700, 625, 90, 0.1114, 1, 3, 2, 0, 10}} } diff --git a/model/match_result_test.go b/model/match_result_test.go index 872f3dc..d055e21 100644 --- a/model/match_result_test.go +++ b/model/match_result_test.go @@ -4,6 +4,7 @@ package model import ( + "github.com/Team254/cheesy-arena/game" "github.com/stretchr/testify/assert" "testing" ) @@ -25,7 +26,7 @@ func TestMatchResultCrud(t *testing.T) { assert.Nil(t, err) assert.Equal(t, matchResult, matchResult2) - matchResult.BlueScore.RobotEndLevels = [3]int{3, 3, 3} + matchResult.BlueScore.EndgameStatuses = [3]game.EndgameStatus{game.Hang, game.None, game.Park} db.SaveMatchResult(matchResult) matchResult2, err = db.GetMatchResultForMatch(254) assert.Nil(t, err) diff --git a/partner/tba.go b/partner/tba.go index 8404678..8a9178c 100644 --- a/partner/tba.go +++ b/partner/tba.go @@ -11,7 +11,6 @@ import ( "encoding/base64" "encoding/json" "fmt" - "github.com/Team254/cheesy-arena/game" "github.com/Team254/cheesy-arena/model" "io/ioutil" "net/http" @@ -101,10 +100,9 @@ type TbaRanking struct { TeamKey string `json:"team_key"` Rank int `json:"rank"` RP float32 - ParkClimb int Auto int - Ownership int - Vault int + Endgame int + Teleop int WinLossTie string Dqs int `json:"dqs"` Played int `json:"played"` @@ -386,12 +384,12 @@ func (client *TbaClient) PublishRankings(database *model.Database) error { } // Build a JSON object of TBA-format rankings. - breakdowns := []string{"RP", "ParkClimb", "Auto", "Ownership", "Vault", "WinLossTie"} + breakdowns := []string{"RP", "Auto", "Endgame", "Teleop", "WinLossTie"} tbaRankings := make([]TbaRanking, len(rankings)) for i, ranking := range rankings { tbaRankings[i] = TbaRanking{getTbaTeam(ranking.TeamId), ranking.Rank, - float32(ranking.RankingPoints) / float32(ranking.Played), ranking.CargoPoints, ranking.HatchPanelPoints, - ranking.HabClimbPoints, ranking.SandstormBonusPoints, + float32(ranking.RankingPoints) / float32(ranking.Played), ranking.AutoPoints, ranking.EndgamePoints, + ranking.TeleopPoints, fmt.Sprintf("%d-%d-%d", ranking.Wins, ranking.Losses, ranking.Ties), ranking.Disqualifications, ranking.Played} } @@ -534,68 +532,71 @@ func createTbaAlliance(teamIds [3]int, surrogates [3]bool, score *int, cards map func createTbaScoringBreakdown(match *model.Match, matchResult *model.MatchResult, alliance string) *TbaScoreBreakdown { var breakdown TbaScoreBreakdown - var score *game.Score - var scoreSummary, opponentScoreSummary *game.ScoreSummary - if alliance == "red" { - score = matchResult.RedScore - scoreSummary = matchResult.RedScoreSummary() - opponentScoreSummary = matchResult.BlueScoreSummary() - } else { - score = matchResult.BlueScore - scoreSummary = matchResult.BlueScoreSummary() - opponentScoreSummary = matchResult.RedScoreSummary() - } + // TODO(pat): Update for 2020. + /* + var score *game.Score + var scoreSummary, opponentScoreSummary *game.ScoreSummary + if alliance == "red" { + score = matchResult.RedScore + scoreSummary = matchResult.RedScoreSummary() + opponentScoreSummary = matchResult.BlueScoreSummary() + } else { + score = matchResult.BlueScore + scoreSummary = matchResult.BlueScoreSummary() + opponentScoreSummary = matchResult.RedScoreSummary() + } - breakdown.PreMatchLevelRobot1 = habLevelMapping[score.RobotStartLevels[0]] - breakdown.PreMatchLevelRobot2 = habLevelMapping[score.RobotStartLevels[1]] - breakdown.PreMatchLevelRobot3 = habLevelMapping[score.RobotStartLevels[2]] - breakdown.PreMatchBay1 = bayStatusMapping[score.CargoBaysPreMatch[0]] - breakdown.PreMatchBay2 = bayStatusMapping[score.CargoBaysPreMatch[1]] - breakdown.PreMatchBay3 = bayStatusMapping[score.CargoBaysPreMatch[2]] - breakdown.PreMatchBay6 = bayStatusMapping[score.CargoBaysPreMatch[5]] - breakdown.PreMatchBay7 = bayStatusMapping[score.CargoBaysPreMatch[6]] - breakdown.PreMatchBay8 = bayStatusMapping[score.CargoBaysPreMatch[7]] - breakdown.HabLineRobot1 = sandstormBonusMapping[score.SandstormBonuses[0]] - breakdown.HabLineRobot2 = sandstormBonusMapping[score.SandstormBonuses[1]] - breakdown.HabLineRobot3 = sandstormBonusMapping[score.SandstormBonuses[2]] - breakdown.SandstormBonusPoints = scoreSummary.SandstormBonusPoints - breakdown.Bay1 = bayStatusMapping[score.CargoBays[0]] - breakdown.Bay2 = bayStatusMapping[score.CargoBays[1]] - breakdown.Bay3 = bayStatusMapping[score.CargoBays[2]] - breakdown.Bay4 = bayStatusMapping[score.CargoBays[3]] - breakdown.Bay5 = bayStatusMapping[score.CargoBays[4]] - breakdown.Bay6 = bayStatusMapping[score.CargoBays[5]] - breakdown.Bay7 = bayStatusMapping[score.CargoBays[6]] - breakdown.Bay8 = bayStatusMapping[score.CargoBays[7]] - breakdown.LowLeftRocketNear = bayStatusMapping[score.RocketNearLeftBays[0]] - breakdown.MidLeftRocketNear = bayStatusMapping[score.RocketNearLeftBays[1]] - breakdown.TopLeftRocketNear = bayStatusMapping[score.RocketNearLeftBays[2]] - breakdown.LowRightRocketNear = bayStatusMapping[score.RocketNearRightBays[0]] - breakdown.MidRightRocketNear = bayStatusMapping[score.RocketNearRightBays[1]] - breakdown.TopRightRocketNear = bayStatusMapping[score.RocketNearRightBays[2]] - breakdown.LowLeftRocketFar = bayStatusMapping[score.RocketFarLeftBays[0]] - breakdown.MidLeftRocketFar = bayStatusMapping[score.RocketFarLeftBays[1]] - breakdown.TopLeftRocketFar = bayStatusMapping[score.RocketFarLeftBays[2]] - breakdown.LowRightRocketFar = bayStatusMapping[score.RocketFarRightBays[0]] - breakdown.MidRightRocketFar = bayStatusMapping[score.RocketFarRightBays[1]] - breakdown.TopRightRocketFar = bayStatusMapping[score.RocketFarRightBays[2]] - breakdown.CargoPoints = scoreSummary.CargoPoints - breakdown.HatchPanelPoints = scoreSummary.HatchPanelPoints - breakdown.EndgameRobot1 = habLevelMapping[score.RobotEndLevels[0]] - breakdown.EndgameRobot2 = habLevelMapping[score.RobotEndLevels[1]] - breakdown.EndgameRobot3 = habLevelMapping[score.RobotEndLevels[2]] - breakdown.HabClimbPoints = scoreSummary.HabClimbPoints - breakdown.TeleopPoints = scoreSummary.CargoPoints + scoreSummary.HatchPanelPoints + scoreSummary.HabClimbPoints - breakdown.CompleteRocketRankingPoint = scoreSummary.CompleteRocket - breakdown.HabDockingRankingPoint = scoreSummary.HabDocking - breakdown.FoulPoints = scoreSummary.FoulPoints - breakdown.TotalPoints = scoreSummary.Score - if match.ShouldUpdateRankings() { - // Calculate and set the ranking points for the match. - var ranking game.Ranking - ranking.AddScoreSummary(scoreSummary, opponentScoreSummary, false) - breakdown.RP = ranking.RankingPoints - } + breakdown.PreMatchLevelRobot1 = habLevelMapping[score.RobotStartLevels[0]] + breakdown.PreMatchLevelRobot2 = habLevelMapping[score.RobotStartLevels[1]] + breakdown.PreMatchLevelRobot3 = habLevelMapping[score.RobotStartLevels[2]] + breakdown.PreMatchBay1 = bayStatusMapping[score.CargoBaysPreMatch[0]] + breakdown.PreMatchBay2 = bayStatusMapping[score.CargoBaysPreMatch[1]] + breakdown.PreMatchBay3 = bayStatusMapping[score.CargoBaysPreMatch[2]] + breakdown.PreMatchBay6 = bayStatusMapping[score.CargoBaysPreMatch[5]] + breakdown.PreMatchBay7 = bayStatusMapping[score.CargoBaysPreMatch[6]] + breakdown.PreMatchBay8 = bayStatusMapping[score.CargoBaysPreMatch[7]] + breakdown.HabLineRobot1 = sandstormBonusMapping[score.SandstormBonuses[0]] + breakdown.HabLineRobot2 = sandstormBonusMapping[score.SandstormBonuses[1]] + breakdown.HabLineRobot3 = sandstormBonusMapping[score.SandstormBonuses[2]] + breakdown.SandstormBonusPoints = scoreSummary.SandstormBonusPoints + breakdown.Bay1 = bayStatusMapping[score.CargoBays[0]] + breakdown.Bay2 = bayStatusMapping[score.CargoBays[1]] + breakdown.Bay3 = bayStatusMapping[score.CargoBays[2]] + breakdown.Bay4 = bayStatusMapping[score.CargoBays[3]] + breakdown.Bay5 = bayStatusMapping[score.CargoBays[4]] + breakdown.Bay6 = bayStatusMapping[score.CargoBays[5]] + breakdown.Bay7 = bayStatusMapping[score.CargoBays[6]] + breakdown.Bay8 = bayStatusMapping[score.CargoBays[7]] + breakdown.LowLeftRocketNear = bayStatusMapping[score.RocketNearLeftBays[0]] + breakdown.MidLeftRocketNear = bayStatusMapping[score.RocketNearLeftBays[1]] + breakdown.TopLeftRocketNear = bayStatusMapping[score.RocketNearLeftBays[2]] + breakdown.LowRightRocketNear = bayStatusMapping[score.RocketNearRightBays[0]] + breakdown.MidRightRocketNear = bayStatusMapping[score.RocketNearRightBays[1]] + breakdown.TopRightRocketNear = bayStatusMapping[score.RocketNearRightBays[2]] + breakdown.LowLeftRocketFar = bayStatusMapping[score.RocketFarLeftBays[0]] + breakdown.MidLeftRocketFar = bayStatusMapping[score.RocketFarLeftBays[1]] + breakdown.TopLeftRocketFar = bayStatusMapping[score.RocketFarLeftBays[2]] + breakdown.LowRightRocketFar = bayStatusMapping[score.RocketFarRightBays[0]] + breakdown.MidRightRocketFar = bayStatusMapping[score.RocketFarRightBays[1]] + breakdown.TopRightRocketFar = bayStatusMapping[score.RocketFarRightBays[2]] + breakdown.CargoPoints = scoreSummary.CargoPoints + breakdown.HatchPanelPoints = scoreSummary.HatchPanelPoints + breakdown.EndgameRobot1 = habLevelMapping[score.RobotEndLevels[0]] + breakdown.EndgameRobot2 = habLevelMapping[score.RobotEndLevels[1]] + breakdown.EndgameRobot3 = habLevelMapping[score.RobotEndLevels[2]] + breakdown.HabClimbPoints = scoreSummary.HabClimbPoints + breakdown.TeleopPoints = scoreSummary.CargoPoints + scoreSummary.HatchPanelPoints + scoreSummary.HabClimbPoints + breakdown.CompleteRocketRankingPoint = scoreSummary.CompleteRocket + breakdown.HabDockingRankingPoint = scoreSummary.HabDocking + breakdown.FoulPoints = scoreSummary.FoulPoints + breakdown.TotalPoints = scoreSummary.Score + if match.ShouldUpdateRankings() { + // Calculate and set the ranking points for the match. + var ranking game.Ranking + ranking.AddScoreSummary(scoreSummary, opponentScoreSummary, false) + breakdown.RP = ranking.RankingPoints + } + */ return &breakdown } diff --git a/templates/base.html b/templates/base.html index 77b9aa0..632fe61 100644 --- a/templates/base.html +++ b/templates/base.html @@ -120,7 +120,7 @@