Simpify scoring model and fix RungIsLevel bonus logic.

This commit is contained in:
Patrick Fairbank
2020-03-21 12:41:01 -07:00
parent a32d0c78b2
commit 712d739290
13 changed files with 135 additions and 106 deletions

View File

@@ -14,8 +14,8 @@ func TestAddScoreSummary(t *testing.T) {
rand.Seed(0)
redScore := TestScore1()
blueScore := TestScore2()
redSummary := redScore.Summarize(blueScore.Fouls)
blueSummary := blueScore.Summarize(redScore.Fouls)
redSummary := redScore.Summarize(blueScore.Fouls, true)
blueSummary := blueScore.Summarize(redScore.Fouls, true)
rankingFields := RankingFields{}
// Add a loss.

View File

@@ -10,16 +10,14 @@ type Score struct {
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
ControlPanelStatus
EndgameStatuses [3]EndgameStatus
RungIsLevel bool
Fouls []Foul
ElimDq bool
}
type ScoreSummary struct {
@@ -54,17 +52,25 @@ const (
StageExtra
)
type ControlPanelStatus int
const (
ControlPanelNone ControlPanelStatus = iota
ControlPanelRotation
ControlPanelPosition
)
// Represents the state of a robot at the end of the match.
type EndgameStatus int
const (
None EndgameStatus = iota
Park
Hang
EndgameNone EndgameStatus = iota
EndgamePark
EndgameHang
)
// Calculates and returns the summary fields used for ranking and display.
func (score *Score) Summarize(opponentFouls []Foul) *ScoreSummary {
func (score *Score) Summarize(opponentFouls []Foul, teleopStarted bool) *ScoreSummary {
summary := new(ScoreSummary)
// Leave the score at zero if the team was disqualified.
@@ -94,8 +100,8 @@ func (score *Score) Summarize(opponentFouls []Foul) *ScoreSummary {
// 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.StagesAtCapacity[i] = score.stageAtCapacity(i, teleopStarted)
summary.StagesActivated[i] = score.stageActivated(i, teleopStarted)
}
if summary.StagesActivated[Stage2] {
summary.ControlPanelPoints += 10
@@ -106,14 +112,16 @@ func (score *Score) Summarize(opponentFouls []Foul) *ScoreSummary {
}
// Calculate endgame points.
anyHang := false
for _, status := range score.EndgameStatuses {
if status == Park {
if status == EndgamePark {
summary.EndgamePoints += 5
} else if status == Hang {
} else if status == EndgameHang {
summary.EndgamePoints += 25
anyHang = true
}
}
if summary.EndgamePoints > 0 && score.RungIsLevel {
if score.RungIsLevel && anyHang {
summary.EndgamePoints += 15
}
summary.EndgameRankingPoint = summary.EndgamePoints >= 65
@@ -143,12 +151,10 @@ func (score *Score) Equals(other *Score) bool {
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.ControlPanelStatus != other.ControlPanelStatus ||
score.EndgameStatuses != other.EndgameStatuses ||
score.RungIsLevel != other.RungIsLevel ||
score.ElimDq != other.ElimDq ||
@@ -166,22 +172,22 @@ func (score *Score) Equals(other *Score) bool {
}
// 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) {
func (score *Score) CellCountingStage(teleopStarted bool) Stage {
if score.stageActivated(Stage3, teleopStarted) {
return StageExtra
}
if score.StageActivated(Stage2) {
if score.stageActivated(Stage2, teleopStarted) {
return Stage3
}
if score.StageActivated(Stage1) {
if score.stageActivated(Stage1, teleopStarted) {
return Stage2
}
return Stage1
}
// 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) {
func (score *Score) stageAtCapacity(stage Stage, teleopStarted bool) bool {
if stage > Stage1 && !score.stageActivated(stage-1, teleopStarted) {
return false
}
if capacity, ok := StageCapacities[stage]; ok && score.stagePowerCells(stage) >= capacity {
@@ -191,15 +197,15 @@ func (score *Score) StageAtCapacity(stage Stage) bool {
}
// Returns true if the given Stage has been activated.
func (score *Score) StageActivated(stage Stage) bool {
if score.StageAtCapacity(stage) {
func (score *Score) stageActivated(stage Stage, teleopStarted bool) bool {
if score.stageAtCapacity(stage, teleopStarted) {
switch stage {
case Stage1:
return score.TeleopPeriodStarted
return teleopStarted
case Stage2:
return score.RotationControl
return score.ControlPanelStatus >= ControlPanelRotation
case Stage3:
return score.PositionControl
return score.ControlPanelStatus == ControlPanelPosition
}
}
return false

View File

@@ -12,7 +12,7 @@ func TestScoreSummary(t *testing.T) {
redScore := TestScore1()
blueScore := TestScore2()
redSummary := redScore.Summarize(blueScore.Fouls)
redSummary := redScore.Summarize(blueScore.Fouls, true)
assert.Equal(t, 10, redSummary.InitiationLinePoints)
assert.Equal(t, 84, redSummary.AutoPowerCellPoints)
assert.Equal(t, 94, redSummary.AutoPoints)
@@ -26,7 +26,7 @@ func TestScoreSummary(t *testing.T) {
assert.Equal(t, false, redSummary.ControlPanelRankingPoint)
assert.Equal(t, true, redSummary.EndgameRankingPoint)
blueSummary := blueScore.Summarize(redScore.Fouls)
blueSummary := blueScore.Summarize(redScore.Fouls, true)
assert.Equal(t, 5, blueSummary.InitiationLinePoints)
assert.Equal(t, 12, blueSummary.AutoPowerCellPoints)
assert.Equal(t, 17, blueSummary.AutoPoints)
@@ -42,74 +42,109 @@ func TestScoreSummary(t *testing.T) {
// Test invalid foul.
redScore.Fouls[0].RuleId = 0
assert.Equal(t, 18, blueScore.Summarize(redScore.Fouls).FoulPoints)
assert.Equal(t, 18, blueScore.Summarize(redScore.Fouls, true).FoulPoints)
// Test elimination disqualification.
redScore.ElimDq = true
assert.Equal(t, 0, redScore.Summarize(blueScore.Fouls).Score)
assert.NotEqual(t, 0, blueScore.Summarize(blueScore.Fouls).Score)
assert.Equal(t, 0, redScore.Summarize(blueScore.Fouls, true).Score)
assert.NotEqual(t, 0, blueScore.Summarize(blueScore.Fouls, true).Score)
blueScore.ElimDq = true
assert.Equal(t, 0, blueScore.Summarize(redScore.Fouls).Score)
assert.Equal(t, 0, blueScore.Summarize(redScore.Fouls, true).Score)
}
func TestScoreSummaryRungIsLevel(t *testing.T) {
var score Score
assert.Equal(t, 0, score.Summarize([]Foul{}, true).EndgamePoints)
score.RungIsLevel = true
assert.Equal(t, 0, score.Summarize([]Foul{}, true).EndgamePoints)
score.RungIsLevel = false
score.EndgameStatuses = [3]EndgameStatus{EndgamePark, EndgamePark, EndgamePark}
assert.Equal(t, 15, score.Summarize([]Foul{}, true).EndgamePoints)
score.RungIsLevel = true
assert.Equal(t, 15, score.Summarize([]Foul{}, true).EndgamePoints)
score.RungIsLevel = false
score.EndgameStatuses = [3]EndgameStatus{EndgameHang, EndgamePark, EndgamePark}
assert.Equal(t, 35, score.Summarize([]Foul{}, true).EndgamePoints)
score.RungIsLevel = true
assert.Equal(t, 50, score.Summarize([]Foul{}, true).EndgamePoints)
score.RungIsLevel = false
score.EndgameStatuses = [3]EndgameStatus{EndgameHang, EndgamePark, EndgameHang}
assert.Equal(t, 55, score.Summarize([]Foul{}, true).EndgamePoints)
score.RungIsLevel = true
assert.Equal(t, 70, score.Summarize([]Foul{}, true).EndgamePoints)
score.RungIsLevel = false
score.EndgameStatuses = [3]EndgameStatus{EndgameHang, EndgameHang, EndgameHang}
assert.Equal(t, 75, score.Summarize([]Foul{}, true).EndgamePoints)
score.RungIsLevel = true
assert.Equal(t, 90, score.Summarize([]Foul{}, true).EndgamePoints)
score.RungIsLevel = false
score.EndgameStatuses = [3]EndgameStatus{EndgameNone, EndgameNone, EndgameNone}
assert.Equal(t, 0, score.Summarize([]Foul{}, true).EndgamePoints)
score.RungIsLevel = true
assert.Equal(t, 0, score.Summarize([]Foul{}, true).EndgamePoints)
}
func TestScoreSummaryBoundaryConditions(t *testing.T) {
// Test control panel boundary conditions.
score := TestScore2()
summary := score.Summarize(score.Fouls)
assert.Equal(t, StageExtra, score.CellCountingStage())
summary := score.Summarize(score.Fouls, true)
assert.Equal(t, StageExtra, score.CellCountingStage(true))
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())
summary = score.Summarize(score.Fouls, true)
assert.Equal(t, Stage1, score.CellCountingStage(true))
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())
summary = score.Summarize(score.Fouls, false)
assert.Equal(t, Stage1, score.CellCountingStage(false))
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())
summary = score.Summarize(score.Fouls, true)
assert.Equal(t, Stage2, score.CellCountingStage(true))
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())
score.ControlPanelStatus = ControlPanelNone
summary = score.Summarize(score.Fouls, true)
assert.Equal(t, Stage2, score.CellCountingStage(true))
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.ControlPanelStatus = ControlPanelPosition
score.TeleopCellsInner[2] -= 3
summary = score.Summarize(score.Fouls)
assert.Equal(t, Stage3, score.CellCountingStage())
summary = score.Summarize(score.Fouls, true)
assert.Equal(t, Stage3, score.CellCountingStage(true))
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())
score.ControlPanelStatus = ControlPanelRotation
summary = score.Summarize(score.Fouls, true)
assert.Equal(t, Stage3, score.CellCountingStage(true))
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)
@@ -117,13 +152,13 @@ func TestScoreSummaryBoundaryConditions(t *testing.T) {
// 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)
assert.Equal(t, true, score.Summarize(score.Fouls, true).EndgameRankingPoint)
score.EndgameStatuses[0] = EndgameNone
assert.Equal(t, false, score.Summarize(score.Fouls, true).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)
assert.Equal(t, true, score.Summarize(score.Fouls, true).EndgameRankingPoint)
score.EndgameStatuses[2] = EndgamePark
assert.Equal(t, false, score.Summarize(score.Fouls, true).EndgameRankingPoint)
}
func TestScoreSummaryRankingPointFoul(t *testing.T) {
@@ -131,20 +166,20 @@ func TestScoreSummaryRankingPointFoul(t *testing.T) {
score1 := TestScore1()
score2 := TestScore2()
summary := score1.Summarize([]Foul{})
summary := score1.Summarize([]Foul{}, true)
assert.Equal(t, 0, summary.FoulPoints)
assert.Equal(t, false, summary.ControlPanelRankingPoint)
assert.Equal(t, true, summary.EndgameRankingPoint)
summary = score1.Summarize(fouls)
summary = score1.Summarize(fouls, true)
assert.Equal(t, 0, summary.FoulPoints)
assert.Equal(t, true, summary.ControlPanelRankingPoint)
assert.Equal(t, true, summary.EndgameRankingPoint)
summary = score2.Summarize([]Foul{})
summary = score2.Summarize([]Foul{}, true)
assert.Equal(t, 0, summary.FoulPoints)
assert.Equal(t, true, summary.ControlPanelRankingPoint)
assert.Equal(t, false, summary.EndgameRankingPoint)
summary = score2.Summarize(fouls)
summary = score2.Summarize(fouls, true)
assert.Equal(t, 0, summary.FoulPoints)
assert.Equal(t, true, summary.ControlPanelRankingPoint)
assert.Equal(t, false, summary.EndgameRankingPoint)
@@ -180,11 +215,6 @@ func TestScoreEquals(t *testing.T) {
assert.False(t, score1.Equals(score2))
assert.False(t, score2.Equals(score1))
score2 = TestScore1()
score2.TeleopPeriodStarted = !score2.TeleopPeriodStarted
assert.False(t, score1.Equals(score2))
assert.False(t, score2.Equals(score1))
score2 = TestScore1()
score2.TeleopCellsBottom[2] = 30
assert.False(t, score1.Equals(score2))
@@ -201,17 +231,12 @@ func TestScoreEquals(t *testing.T) {
assert.False(t, score2.Equals(score1))
score2 = TestScore1()
score2.RotationControl = !score2.RotationControl
score2.ControlPanelStatus = ControlPanelNone
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
score2.EndgameStatuses[1] = EndgameNone
assert.False(t, score1.Equals(score2))
assert.False(t, score2.Equals(score1))

View File

@@ -16,13 +16,11 @@ func TestScore1() *Score {
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},
ControlPanelStatus: ControlPanelRotation,
EndgameStatuses: [3]EndgameStatus{EndgameHang, EndgameHang, EndgameHang},
RungIsLevel: false,
Fouls: fouls,
ElimDq: false,
@@ -35,13 +33,11 @@ func TestScore2() *Score {
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},
ControlPanelStatus: ControlPanelPosition,
EndgameStatuses: [3]EndgameStatus{EndgamePark, EndgamePark, EndgameHang},
RungIsLevel: true,
Fouls: []Foul{},
ElimDq: false,