Update score/ranking models for 2020.

This commit is contained in:
Patrick Fairbank
2020-03-18 22:42:36 -07:00
parent 24a069d959
commit afcaa0e07c
19 changed files with 549 additions and 530 deletions

View File

@@ -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)
}
}

View File

@@ -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
}

View File

@@ -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())

View File

@@ -22,7 +22,7 @@ func (foul *Foul) PointValue() int {
return 0
}
if foul.Rule().IsTechnical {
return 10
return 15
} else {
return 3
}

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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())
}

View File

@@ -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}}
}

View File

@@ -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)

View File

@@ -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
}

View File

@@ -120,7 +120,7 @@
</div>
<div class="modal-body">
<p>A field management system that just works.</p>
<p>Copyright &copy; 2014-2019 Team 254. All Rights Reserved.</p>
<p>Copyright &copy; 2014-2020 Team 254. All Rights Reserved.</p>
<p><a href="https://github.com/Team254/cheesy-arena">https://github.com/Team254/cheesy-arena</a></p>
</div>
<div class="modal-footer">

View File

@@ -1,3 +1,3 @@
Rank,TeamId,RankingPoints,CargoPoints,HatchPanelPoints,HabClimbPoints,SandstormBonusPoints,Wins,Losses,Ties,Disqualifications,Played
{{range $ranking := .}}{{$ranking.Rank}},{{$ranking.TeamId}},{{$ranking.RankingPoints}},{{$ranking.CargoPoints}},{{$ranking.HatchPanelPoints}},{{$ranking.HabClimbPoints}},{{$ranking.SandstormBonusPoints}},{{$ranking.Wins}},{{$ranking.Losses}},{{$ranking.Ties}},{{$ranking.Disqualifications}},{{$ranking.Played}}
{{range $ranking := .}}{{$ranking.Rank}},{{$ranking.TeamId}},{{$ranking.RankingPoints}},{{$ranking.AutoPoints}},{{$ranking.EndgamePoints}},{{$ranking.TeleopPoints}},{{$ranking.Wins}},{{$ranking.Losses}},{{$ranking.Ties}},{{$ranking.Disqualifications}},{{$ranking.Played}}
{{end}}
1 Rank,TeamId,RankingPoints,CargoPoints,HatchPanelPoints,HabClimbPoints,SandstormBonusPoints,Wins,Losses,Ties,Disqualifications,Played
2 {{range $ranking := .}}{{$ranking.Rank}},{{$ranking.TeamId}},{{$ranking.RankingPoints}},{{$ranking.CargoPoints}},{{$ranking.HatchPanelPoints}},{{$ranking.HabClimbPoints}},{{$ranking.SandstormBonusPoints}},{{$ranking.Wins}},{{$ranking.Losses}},{{$ranking.Ties}},{{$ranking.Disqualifications}},{{$ranking.Played}} {{range $ranking := .}}{{$ranking.Rank}},{{$ranking.TeamId}},{{$ranking.RankingPoints}},{{$ranking.AutoPoints}},{{$ranking.EndgamePoints}},{{$ranking.TeleopPoints}},{{$ranking.Wins}},{{$ranking.Losses}},{{$ranking.Ties}},{{$ranking.Disqualifications}},{{$ranking.Played}}
3 {{end}}

View File

@@ -133,7 +133,7 @@ func TestCommitMatch(t *testing.T) {
web.arena.Database.CreateMatch(match)
matchResult = model.NewMatchResult()
matchResult.MatchId = match.Id
matchResult.BlueScore = &game.Score{RobotEndLevels: [3]int{3, 3, 3}}
matchResult.BlueScore = &game.Score{ExitedInitiationLine: [3]bool{true, false, false}}
err = web.commitMatchScore(match, matchResult, false)
assert.Nil(t, err)
assert.Equal(t, 1, matchResult.PlayNumber)
@@ -142,7 +142,7 @@ func TestCommitMatch(t *testing.T) {
matchResult = model.NewMatchResult()
matchResult.MatchId = match.Id
matchResult.RedScore = &game.Score{RobotEndLevels: [3]int{2, 2, 2}}
matchResult.RedScore = &game.Score{ExitedInitiationLine: [3]bool{true, false, true}}
err = web.commitMatchScore(match, matchResult, false)
assert.Nil(t, err)
assert.Equal(t, 2, matchResult.PlayNumber)
@@ -177,8 +177,8 @@ func TestCommitEliminationTie(t *testing.T) {
matchResult := &model.MatchResult{
MatchId: match.Id,
RedScore: &game.Score{
RocketFarRightBays: [3]game.BayStatus{game.BayHatchCargo, game.BayHatch, game.BayHatch},
Fouls: []game.Foul{{RuleId: 1}, {RuleId: 2}, {RuleId: 4}}},
TeleopCellsInner: [4]int{1, 2, 0, 0},
Fouls: []game.Foul{{RuleId: 1}, {RuleId: 2}, {RuleId: 4}}},
BlueScore: &game.Score{},
}
err := web.commitMatchScore(match, matchResult, false)
@@ -309,12 +309,12 @@ func TestMatchPlayWebsocketCommands(t *testing.T) {
readWebsocketType(t, ws, "audienceDisplayMode")
readWebsocketType(t, ws, "allianceStationDisplayMode")
assert.Equal(t, field.PostMatch, web.arena.MatchState)
web.arena.RedRealtimeScore.CurrentScore.RobotEndLevels = [3]int{1, 2, 3}
web.arena.BlueRealtimeScore.CurrentScore.SandstormBonuses = [3]bool{true, false, true}
web.arena.RedRealtimeScore.CurrentScore.TeleopCellsOuter = [4]int{1, 1, 1, 4}
web.arena.BlueRealtimeScore.CurrentScore.ExitedInitiationLine = [3]bool{true, false, true}
ws.Write("commitResults", nil)
readWebsocketMultiple(t, ws, 3) // reload, realtimeScore, setAllianceStationDisplay
assert.Equal(t, [3]int{1, 2, 3}, web.arena.SavedMatchResult.RedScore.RobotEndLevels)
assert.Equal(t, [3]bool{true, false, true}, web.arena.SavedMatchResult.BlueScore.SandstormBonuses)
assert.Equal(t, [4]int{1, 1, 1, 4}, web.arena.SavedMatchResult.RedScore.TeleopCellsOuter)
assert.Equal(t, [3]bool{true, false, true}, web.arena.SavedMatchResult.BlueScore.ExitedInitiationLine)
assert.Equal(t, field.PreMatch, web.arena.MatchState)
ws.Write("discardResults", nil)
readWebsocketMultiple(t, ws, 3) // reload, realtimeScore, setAllianceStationDisplay

View File

@@ -49,8 +49,8 @@ func TestMatchReviewEditExistingResult(t *testing.T) {
recorder := web.getHttpResponse("/match_review")
assert.Equal(t, 200, recorder.Code)
assert.Contains(t, recorder.Body.String(), ">QF4-3<")
assert.Contains(t, recorder.Body.String(), ">71<") // The red score
assert.Contains(t, recorder.Body.String(), ">72<") // The blue score
assert.Contains(t, recorder.Body.String(), ">217<") // The red score
assert.Contains(t, recorder.Body.String(), ">252<") // The blue score
// Check response for non-existent match.
recorder = web.getHttpResponse(fmt.Sprintf("/match_review/%d/edit", 12345))
@@ -62,17 +62,18 @@ func TestMatchReviewEditExistingResult(t *testing.T) {
assert.Contains(t, recorder.Body.String(), " QF4-3 ")
// Update the score to something else.
postBody := "redScoreJson={\"RobotEndLevels\":[0,3,0]}&blueScoreJson={\"CargoBays\":[0,2,1,2,2,0,1]," +
postBody := "redScoreJson={\"RobotEndLevels\":[0,3,0]}&blueScoreJson={\"AutoCellsOuter\":[3, 4]," +
"\"Fouls\":[{\"TeamId\":973,\"RuleId\":1}]}&redCardsJson={\"105\":\"yellow\"}&blueCardsJson={}"
recorder = web.postHttpResponse(fmt.Sprintf("/match_review/%d/edit", match.Id), postBody)
assert.Equal(t, 303, recorder.Code)
// TODO(pat): Update for 2020.
// Check for the updated scores back on the match list page.
recorder = web.getHttpResponse("/match_review")
assert.Equal(t, 200, recorder.Code)
assert.Contains(t, recorder.Body.String(), ">QF4-3<")
assert.Contains(t, recorder.Body.String(), ">15<") // The red score
assert.Contains(t, recorder.Body.String(), ">19<") // The blue score
assert.Contains(t, recorder.Body.String(), ">0<") // The red score
assert.Contains(t, recorder.Body.String(), ">0<") // The blue score
}
func TestMatchReviewCreateNewResult(t *testing.T) {
@@ -99,10 +100,11 @@ func TestMatchReviewCreateNewResult(t *testing.T) {
recorder = web.postHttpResponse(fmt.Sprintf("/match_review/%d/edit", match.Id), postBody)
assert.Equal(t, 303, recorder.Code)
// TODO(pat): Update for 2020.
// Check for the updated scores back on the match list page.
recorder = web.getHttpResponse("/match_review")
assert.Equal(t, 200, recorder.Code)
assert.Contains(t, recorder.Body.String(), ">QF4-3<")
assert.Contains(t, recorder.Body.String(), ">10<") // The red score
assert.Contains(t, recorder.Body.String(), ">15<") // The blue score
assert.Contains(t, recorder.Body.String(), ">0<") // The red score
assert.Contains(t, recorder.Body.String(), ">0<") // The blue score
}

View File

@@ -73,12 +73,9 @@ func (web *Web) rankingsPdfReportHandler(w http.ResponseWriter, r *http.Request)
pdf.SetFont("Arial", "", 10)
pdf.CellFormat(colWidths["Team"], rowHeight, strconv.Itoa(ranking.TeamId), "1", 0, "C", false, 0, "")
pdf.CellFormat(colWidths["RP"], rowHeight, strconv.Itoa(ranking.RankingPoints), "1", 0, "C", false, 0, "")
pdf.CellFormat(colWidths["Cargo"], rowHeight, strconv.Itoa(ranking.CargoPoints), "1", 0, "C", false, 0, "")
pdf.CellFormat(colWidths["Hatch"], rowHeight, strconv.Itoa(ranking.HatchPanelPoints), "1", 0, "C", false, 0, "")
pdf.CellFormat(colWidths["Hab Climb"], rowHeight, strconv.Itoa(ranking.HabClimbPoints), "1", 0, "C", false, 0,
"")
pdf.CellFormat(colWidths["Sandstorm"], rowHeight, strconv.Itoa(ranking.SandstormBonusPoints), "1", 0, "C",
false, 0, "")
pdf.CellFormat(colWidths["Cargo"], rowHeight, strconv.Itoa(ranking.AutoPoints), "1", 0, "C", false, 0, "")
pdf.CellFormat(colWidths["Hatch"], rowHeight, strconv.Itoa(ranking.EndgamePoints), "1", 0, "C", false, 0, "")
pdf.CellFormat(colWidths["Hab Climb"], rowHeight, strconv.Itoa(ranking.TeleopPoints), "1", 0, "C", false, 0, "")
record := fmt.Sprintf("%d-%d-%d", ranking.Wins, ranking.Losses, ranking.Ties)
pdf.CellFormat(colWidths["W-L-T"], rowHeight, record, "1", 0, "C", false, 0, "")
pdf.CellFormat(colWidths["DQ"], rowHeight, strconv.Itoa(ranking.Disqualifications), "1", 0, "C", false, 0, "")

View File

@@ -23,7 +23,7 @@ func TestRankingsCsvReport(t *testing.T) {
assert.Equal(t, 200, recorder.Code)
assert.Equal(t, "text/plain", recorder.HeaderMap["Content-Type"][0])
expectedBody := "Rank,TeamId,RankingPoints,CargoPoints,HatchPanelPoints,HabClimbPoints,SandstormBonusPoints,Wins," +
"Losses,Ties,Disqualifications,Played\n1,254,20,625,90,554,10,3,2,1,0,10\n2,1114,18,700,625,90,554,1,3,2,0,10" +
"Losses,Ties,Disqualifications,Played\n1,254,20,625,90,554,3,2,1,0,10\n2,1114,18,700,625,90,1,3,2,0,10" +
"\n\n"
assert.Equal(t, expectedBody, recorder.Body.String())
}

View File

@@ -8,7 +8,6 @@ package web
import (
"fmt"
"github.com/Team254/cheesy-arena/field"
"github.com/Team254/cheesy-arena/game"
"github.com/Team254/cheesy-arena/model"
"github.com/Team254/cheesy-arena/websocket"
"github.com/gorilla/mux"
@@ -93,12 +92,15 @@ func (web *Web) scoringPanelWebsocketHandler(w http.ResponseWriter, r *http.Requ
handleWebErr(w, fmt.Errorf("Invalid alliance '%s'.", alliance))
return
}
var realtimeScore **field.RealtimeScore
if alliance == "red" {
realtimeScore = &web.arena.RedRealtimeScore
} else {
realtimeScore = &web.arena.BlueRealtimeScore
}
// TODO(pat): Update for 2020.
/*
var realtimeScore **field.RealtimeScore
if alliance == "red" {
realtimeScore = &web.arena.RedRealtimeScore
} else {
realtimeScore = &web.arena.BlueRealtimeScore
}
*/
ws, err := websocket.NewWebsocket(w, r)
if err != nil {
@@ -127,7 +129,8 @@ func (web *Web) scoringPanelWebsocketHandler(w http.ResponseWriter, r *http.Requ
return
}
score := &(*realtimeScore).CurrentScore
// TODO(pat): Update for 2020.
//score := &(*realtimeScore).CurrentScore
scoreChanged := false
if command == "commitMatch" {
@@ -139,27 +142,30 @@ func (web *Web) scoringPanelWebsocketHandler(w http.ResponseWriter, r *http.Requ
web.arena.ScoringPanelRegistry.SetScoreCommitted(alliance, ws)
web.arena.ScoringStatusNotifier.Notify()
} else if number, err := strconv.Atoi(command); err == nil && number >= 1 && number <= 9 {
// Handle per-robot scoring fields.
if number <= 3 && web.arena.MatchState == field.PreMatch {
index := number - 1
score.RobotStartLevels[index]++
if score.RobotStartLevels[index] == 4 {
score.RobotStartLevels[index] = 0
// TODO(pat): Update for 2020.
/*
// Handle per-robot scoring fields.
if number <= 3 && web.arena.MatchState == field.PreMatch {
index := number - 1
score.RobotStartLevels[index]++
if score.RobotStartLevels[index] == 4 {
score.RobotStartLevels[index] = 0
}
scoreChanged = true
} else if number > 3 && number <= 6 && web.arena.MatchState != field.PreMatch {
index := number - 4
score.SandstormBonuses[index] =
!score.SandstormBonuses[index]
scoreChanged = true
} else if number > 6 && web.arena.MatchState != field.PreMatch {
index := number - 7
score.RobotEndLevels[index]++
if score.RobotEndLevels[index] == 4 {
score.RobotEndLevels[index] = 0
}
scoreChanged = true
}
scoreChanged = true
} else if number > 3 && number <= 6 && web.arena.MatchState != field.PreMatch {
index := number - 4
score.SandstormBonuses[index] =
!score.SandstormBonuses[index]
scoreChanged = true
} else if number > 6 && web.arena.MatchState != field.PreMatch {
index := number - 7
score.RobotEndLevels[index]++
if score.RobotEndLevels[index] == 4 {
score.RobotEndLevels[index] = 0
}
scoreChanged = true
}
*/
} else {
// Handle cargo bays.
var bayMapping *bayMapping
@@ -170,36 +176,38 @@ func (web *Web) scoringPanelWebsocketHandler(w http.ResponseWriter, r *http.Requ
}
}
if bayMapping != nil {
element := bayMapping.RedElement
index := bayMapping.RedIndex
if alliance == "blue" {
element = bayMapping.BlueElement
index = bayMapping.BlueIndex
}
switch element {
case "cargoShip":
scoreChanged = web.toggleCargoShipBay(&score.CargoBays[index], index)
case "rocketNearLeft":
scoreChanged = web.toggleRocketBay(&score.RocketNearLeftBays[index])
case "rocketNearRight":
scoreChanged = web.toggleRocketBay(&score.RocketNearRightBays[index])
case "rocketFarLeft":
scoreChanged = web.toggleRocketBay(&score.RocketFarLeftBays[index])
case "rocketFarRight":
scoreChanged = web.toggleRocketBay(&score.RocketFarRightBays[index])
}
// TODO(pat): Update for 2020.
/*
element := bayMapping.RedElement
index := bayMapping.RedIndex
if alliance == "blue" {
element = bayMapping.BlueElement
index = bayMapping.BlueIndex
}
switch element {
case "cargoShip":
scoreChanged = web.toggleCargoShipBay(&score.CargoBays[index], index)
case "rocketNearLeft":
scoreChanged = web.toggleRocketBay(&score.RocketNearLeftBays[index])
case "rocketNearRight":
scoreChanged = web.toggleRocketBay(&score.RocketNearRightBays[index])
case "rocketFarLeft":
scoreChanged = web.toggleRocketBay(&score.RocketFarLeftBays[index])
case "rocketFarRight":
scoreChanged = web.toggleRocketBay(&score.RocketFarRightBays[index])
}
*/
}
}
if scoreChanged {
if web.arena.MatchState == field.PreMatch {
score.CargoBaysPreMatch = score.CargoBays
}
web.arena.RealtimeScoreNotifier.Notify()
}
}
}
// TODO(pat): Update for 2020.
/*
// Advances the given cargo ship bay through the states applicable to the current status of the field.
func (web *Web) toggleCargoShipBay(bay *game.BayStatus, index int) bool {
if (index == 3 || index == 4) && web.arena.MatchState == field.PreMatch {
@@ -242,3 +250,4 @@ func (web *Web) toggleRocketBay(bay *game.BayStatus) bool {
}
return false
}
*/

View File

@@ -5,7 +5,6 @@ package web
import (
"github.com/Team254/cheesy-arena/field"
"github.com/Team254/cheesy-arena/game"
"github.com/Team254/cheesy-arena/websocket"
gorillawebsocket "github.com/gorilla/websocket"
"github.com/stretchr/testify/assert"
@@ -54,53 +53,56 @@ func TestScoringPanelWebsocket(t *testing.T) {
readWebsocketType(t, blueWs, "matchTime")
readWebsocketType(t, blueWs, "realtimeScore")
// Send a some pre-match scoring commands.
redWs.Write("1", nil)
blueWs.Write("2", nil)
blueWs.Write("2", nil)
blueWs.Write("2", nil)
blueWs.Write("2", nil)
for i := 0; i < 5; i++ {
readWebsocketType(t, redWs, "realtimeScore")
readWebsocketType(t, blueWs, "realtimeScore")
}
assert.Equal(t, 1, web.arena.RedRealtimeScore.CurrentScore.RobotStartLevels[0])
assert.Equal(t, 0, web.arena.BlueRealtimeScore.CurrentScore.RobotStartLevels[1])
redWs.Write("e", nil)
redWs.Write("i", nil)
redWs.Write("i", nil)
redWs.Write("v", nil)
redWs.Write("q", nil)
redWs.Write(",", nil)
for i := 0; i < 3; i++ {
readWebsocketType(t, redWs, "realtimeScore")
readWebsocketType(t, blueWs, "realtimeScore")
}
assert.Equal(t, [8]game.BayStatus{1, 0, 0, 0, 0, 0, 0, 3},
web.arena.RedRealtimeScore.CurrentScore.CargoBaysPreMatch)
assert.Equal(t, [8]game.BayStatus{1, 0, 0, 0, 0, 0, 0, 3}, web.arena.RedRealtimeScore.CurrentScore.CargoBays)
assert.Equal(t, [3]game.BayStatus{0, 0, 0}, web.arena.RedRealtimeScore.CurrentScore.RocketNearLeftBays)
assert.Equal(t, [3]game.BayStatus{0, 0, 0}, web.arena.RedRealtimeScore.CurrentScore.RocketNearRightBays)
assert.Equal(t, [3]game.BayStatus{0, 0, 0}, web.arena.RedRealtimeScore.CurrentScore.RocketFarLeftBays)
assert.Equal(t, [3]game.BayStatus{0, 0, 0}, web.arena.RedRealtimeScore.CurrentScore.RocketFarRightBays)
// TODO(pat): Update for 2020.
/*
// Send a some pre-match scoring commands.
redWs.Write("1", nil)
blueWs.Write("2", nil)
blueWs.Write("2", nil)
blueWs.Write("2", nil)
blueWs.Write("2", nil)
for i := 0; i < 5; i++ {
readWebsocketType(t, redWs, "realtimeScore")
readWebsocketType(t, blueWs, "realtimeScore")
}
assert.Equal(t, 1, web.arena.RedRealtimeScore.CurrentScore.RobotStartLevels[0])
assert.Equal(t, 0, web.arena.BlueRealtimeScore.CurrentScore.RobotStartLevels[1])
redWs.Write("e", nil)
redWs.Write("i", nil)
redWs.Write("i", nil)
redWs.Write("v", nil)
redWs.Write("q", nil)
redWs.Write(",", nil)
for i := 0; i < 3; i++ {
readWebsocketType(t, redWs, "realtimeScore")
readWebsocketType(t, blueWs, "realtimeScore")
}
assert.Equal(t, [8]game.BayStatus{1, 0, 0, 0, 0, 0, 0, 3},
web.arena.RedRealtimeScore.CurrentScore.CargoBaysPreMatch)
assert.Equal(t, [8]game.BayStatus{1, 0, 0, 0, 0, 0, 0, 3}, web.arena.RedRealtimeScore.CurrentScore.CargoBays)
assert.Equal(t, [3]game.BayStatus{0, 0, 0}, web.arena.RedRealtimeScore.CurrentScore.RocketNearLeftBays)
assert.Equal(t, [3]game.BayStatus{0, 0, 0}, web.arena.RedRealtimeScore.CurrentScore.RocketNearRightBays)
assert.Equal(t, [3]game.BayStatus{0, 0, 0}, web.arena.RedRealtimeScore.CurrentScore.RocketFarLeftBays)
assert.Equal(t, [3]game.BayStatus{0, 0, 0}, web.arena.RedRealtimeScore.CurrentScore.RocketFarRightBays)
// Send some in-match scoring commands.
web.arena.MatchState = field.AutoPeriod
redWs.Write("e", nil)
redWs.Write("i", nil)
redWs.Write("k", nil)
redWs.Write("4", nil)
blueWs.Write("9", nil)
for i := 0; i < 5; i++ {
readWebsocketType(t, redWs, "realtimeScore")
readWebsocketType(t, blueWs, "realtimeScore")
}
assert.Equal(t, [8]game.BayStatus{1, 0, 0, 0, 0, 0, 0, 3},
web.arena.RedRealtimeScore.CurrentScore.CargoBaysPreMatch)
assert.Equal(t, [8]game.BayStatus{2, 0, 0, 0, 0, 0, 0, 2}, web.arena.RedRealtimeScore.CurrentScore.CargoBays)
assert.Equal(t, [3]game.BayStatus{0, 1, 0}, web.arena.RedRealtimeScore.CurrentScore.RocketFarRightBays)
assert.True(t, web.arena.RedRealtimeScore.CurrentScore.SandstormBonuses[0])
assert.Equal(t, 1, web.arena.BlueRealtimeScore.CurrentScore.RobotEndLevels[2])
// Send some in-match scoring commands.
web.arena.MatchState = field.AutoPeriod
redWs.Write("e", nil)
redWs.Write("i", nil)
redWs.Write("k", nil)
redWs.Write("4", nil)
blueWs.Write("9", nil)
for i := 0; i < 5; i++ {
readWebsocketType(t, redWs, "realtimeScore")
readWebsocketType(t, blueWs, "realtimeScore")
}
assert.Equal(t, [8]game.BayStatus{1, 0, 0, 0, 0, 0, 0, 3},
web.arena.RedRealtimeScore.CurrentScore.CargoBaysPreMatch)
assert.Equal(t, [8]game.BayStatus{2, 0, 0, 0, 0, 0, 0, 2}, web.arena.RedRealtimeScore.CurrentScore.CargoBays)
assert.Equal(t, [3]game.BayStatus{0, 1, 0}, web.arena.RedRealtimeScore.CurrentScore.RocketFarRightBays)
assert.True(t, web.arena.RedRealtimeScore.CurrentScore.SandstormBonuses[0])
assert.Equal(t, 1, web.arena.BlueRealtimeScore.CurrentScore.RobotEndLevels[2])
*/
// Test committing logic.
redWs.Write("commitMatch", nil)