Break down vault cubes by power up in score object.

This commit is contained in:
Patrick Fairbank
2018-05-22 21:35:14 -07:00
parent c522186d4f
commit 3dc83bcdbf
9 changed files with 158 additions and 78 deletions

View File

@@ -724,10 +724,12 @@ func (arena *Arena) handlePlcInput() {
redForce, redLevitate, redBoost, blueForce, blueLevitate, blueBoost := arena.Plc.GetPowerUpButtons()
arena.redVault.UpdateButtons(redForce, redLevitate, redBoost, currentTime)
arena.blueVault.UpdateButtons(blueForce, blueLevitate, blueBoost, currentTime)
redScore.VaultCubes = arena.redVault.GetNumCubes()
redScore.Levitate = arena.redVault.LevitatePlayed
blueScore.VaultCubes = arena.blueVault.GetNumCubes()
blueScore.Levitate = arena.blueVault.LevitatePlayed
redScore.ForceCubes, redScore.ForcePlayed = arena.redVault.ForceCubes, arena.redVault.ForcePowerUp != nil
redScore.LevitateCubes, redScore.LevitatePlayed = arena.redVault.LevitateCubes, arena.redVault.LevitatePlayed
redScore.BoostCubes, redScore.BoostPlayed = arena.redVault.BoostCubes, arena.redVault.BoostPowerUp != nil
blueScore.ForceCubes, blueScore.ForcePlayed = arena.blueVault.ForceCubes, arena.blueVault.ForcePowerUp != nil
blueScore.LevitateCubes, blueScore.LevitatePlayed = arena.blueVault.LevitateCubes, arena.blueVault.LevitatePlayed
blueScore.BoostCubes, blueScore.BoostPlayed = arena.blueVault.BoostCubes, arena.blueVault.BoostPowerUp != nil
if !oldRedScore.Equals(redScore) || !oldBlueScore.Equals(blueScore) {
arena.RealtimeScoreNotifier.Notify(nil)

View File

@@ -10,8 +10,12 @@ type Score struct {
AutoOwnershipPoints int
AutoEndSwitchOwnership bool
TeleopOwnershipPoints int
VaultCubes int
Levitate bool
ForceCubes int
ForcePlayed bool
LevitateCubes int
LevitatePlayed bool
BoostCubes int
BoostPlayed bool
Climbs int
Parks int
Fouls []Foul
@@ -49,16 +53,24 @@ func (score *Score) Summarize(opponentFouls []Foul) *ScoreSummary {
// Calculate teleop score.
summary.OwnershipPoints = score.AutoOwnershipPoints + score.TeleopOwnershipPoints
vaultCubes := score.VaultCubes
if vaultCubes > 9 {
vaultCubes = 9
forceCubes := score.ForceCubes
if forceCubes > 3 {
forceCubes = 3
}
summary.VaultPoints = 5 * vaultCubes
levitateCubes := score.LevitateCubes
if levitateCubes > 3 {
levitateCubes = 3
}
boostCubes := score.BoostCubes
if boostCubes > 3 {
boostCubes = 3
}
summary.VaultPoints = 5 * (forceCubes + levitateCubes + boostCubes)
climbs := score.Climbs
if climbs > 3 {
climbs = 3
}
if score.Levitate && score.Climbs < 3 {
if score.LevitatePlayed && score.Climbs < 3 {
climbs++
}
parks := score.Parks
@@ -89,8 +101,10 @@ func (score *Score) Summarize(opponentFouls []Foul) *ScoreSummary {
func (score *Score) Equals(other *Score) bool {
if score.AutoRuns != other.AutoRuns || score.AutoEndSwitchOwnership != other.AutoEndSwitchOwnership ||
score.AutoOwnershipPoints != other.AutoOwnershipPoints ||
score.TeleopOwnershipPoints != other.TeleopOwnershipPoints || score.VaultCubes != other.VaultCubes ||
score.Levitate != other.Levitate || score.Parks != other.Parks || score.Climbs != other.Climbs ||
score.TeleopOwnershipPoints != other.TeleopOwnershipPoints || score.ForceCubes != other.ForceCubes ||
score.ForcePlayed != other.ForcePlayed || score.LevitateCubes != other.LevitateCubes ||
score.LevitatePlayed != other.LevitatePlayed || score.BoostCubes != other.BoostCubes ||
score.BoostPlayed != other.BoostPlayed || score.Parks != other.Parks || score.Climbs != other.Climbs ||
score.ElimDq != other.ElimDq || len(score.Fouls) != len(other.Fouls) {
return false
}

View File

@@ -37,12 +37,12 @@ func TestScoreSummary(t *testing.T) {
// Test limits on fields with a natural cap.
blueScore.AutoRuns = 5
assert.Equal(t, 15, blueScore.Summarize(redScore.Fouls).AutoRunPoints)
redScore.VaultCubes = 20
assert.Equal(t, 45, redScore.Summarize(blueScore.Fouls).VaultPoints)
redScore.Levitate = false
redScore.ForceCubes = 20
assert.Equal(t, 30, redScore.Summarize(blueScore.Fouls).VaultPoints)
redScore.LevitatePlayed = false
redScore.Climbs = 3
assert.Equal(t, 90, redScore.Summarize(blueScore.Fouls).ParkClimbPoints)
redScore.Levitate = true
redScore.LevitatePlayed = true
assert.Equal(t, 90, redScore.Summarize(blueScore.Fouls).ParkClimbPoints)
redScore.Climbs = 4
assert.Equal(t, 90, redScore.Summarize(blueScore.Fouls).ParkClimbPoints)
@@ -64,7 +64,7 @@ func TestScoreSummary(t *testing.T) {
assert.Equal(t, false, blueScore.Summarize(redScore.Fouls).AutoQuest)
// Test Face the Boss boundary conditions.
redScore.Levitate = false
redScore.LevitatePlayed = false
assert.Equal(t, false, redScore.Summarize(blueScore.Fouls).FaceTheBoss)
redScore.Climbs = 3
assert.Equal(t, true, redScore.Summarize(blueScore.Fouls).FaceTheBoss)
@@ -110,12 +110,32 @@ func TestScoreEquals(t *testing.T) {
assert.False(t, score2.Equals(score1))
score2 = TestScore1()
score2.VaultCubes += 1
score2.ForceCubes += 1
assert.False(t, score1.Equals(score2))
assert.False(t, score2.Equals(score1))
score2 = TestScore1()
score2.Levitate = !score2.Levitate
score2.ForcePlayed = !score2.ForcePlayed
assert.False(t, score1.Equals(score2))
assert.False(t, score2.Equals(score1))
score2 = TestScore1()
score2.LevitateCubes += 1
assert.False(t, score1.Equals(score2))
assert.False(t, score2.Equals(score1))
score2 = TestScore1()
score2.LevitatePlayed = !score2.LevitatePlayed
assert.False(t, score1.Equals(score2))
assert.False(t, score2.Equals(score1))
score2 = TestScore1()
score2.BoostCubes += 1
assert.False(t, score1.Equals(score2))
assert.False(t, score2.Equals(score1))
score2 = TestScore1()
score2.BoostPlayed = !score2.BoostPlayed
assert.False(t, score1.Equals(score2))
assert.False(t, score2.Equals(score1))

View File

@@ -6,13 +6,12 @@
package game
func TestScore1() *Score {
fouls := []Foul{{Rule{"G22", false}, 25, 25.2}, {Rule{"G18", true}, 25, 150},
{Rule{"G20", true}, 1868, 0}}
return &Score{1, 12, true, 47, 3, true, 2, 0, fouls, false}
fouls := []Foul{{Rule{"G22", false}, 25, 25.2}, {Rule{"G18", true}, 25, 150}, {Rule{"G20", true}, 1868, 0}}
return &Score{1, 12, true, 47, 0, false, 3, true, 0, false, 2, 0, fouls, false}
}
func TestScore2() *Score {
return &Score{3, 20, true, 73, 6, false, 1, 1, []Foul{}, false}
return &Score{3, 20, true, 73, 3, true, 0, false, 3, true, 1, 1, []Foul{}, false}
}
func TestRanking1() *Ranking {

View File

@@ -10,44 +10,39 @@ import (
)
type Vault struct {
alliance alliance
numForceCubes int
numLevitateCubes int
numBoostCubes int
LevitatePlayed bool
ForcePowerUp *PowerUp
BoostPowerUp *PowerUp
alliance alliance
ForceCubes int
LevitateCubes int
BoostCubes int
LevitatePlayed bool
ForcePowerUp *PowerUp
BoostPowerUp *PowerUp
}
// Updates the state of the vault given the state of the individual power cube sensors.
func (vault *Vault) UpdateCubes(forceDistance, levitateDistance, boostDistance uint16) {
vault.numForceCubes = countCubes(forceDistance)
vault.numLevitateCubes = countCubes(levitateDistance)
vault.numBoostCubes = countCubes(boostDistance)
vault.ForceCubes = countCubes(forceDistance)
vault.LevitateCubes = countCubes(levitateDistance)
vault.BoostCubes = countCubes(boostDistance)
}
// Updates the state of the vault given the state of the power up buttons.
func (vault *Vault) UpdateButtons(forceButton, levitateButton, boostButton bool, currentTime time.Time) {
if levitateButton && vault.numLevitateCubes == 3 && !vault.LevitatePlayed {
if levitateButton && vault.LevitateCubes == 3 && !vault.LevitatePlayed {
vault.LevitatePlayed = true
}
if forceButton && vault.numForceCubes > 0 && vault.ForcePowerUp == nil {
if forceButton && vault.ForceCubes > 0 && vault.ForcePowerUp == nil {
vault.ForcePowerUp = maybeActivatePowerUp(&PowerUp{effect: force, alliance: vault.alliance,
level: vault.numForceCubes}, currentTime)
level: vault.ForceCubes}, currentTime)
}
if boostButton && vault.numBoostCubes > 0 && vault.BoostPowerUp == nil {
if boostButton && vault.BoostCubes > 0 && vault.BoostPowerUp == nil {
vault.BoostPowerUp = maybeActivatePowerUp(&PowerUp{effect: boost, alliance: vault.alliance,
level: vault.numBoostCubes}, currentTime)
level: vault.BoostCubes}, currentTime)
}
}
// Returns the total count of power cubes that have been placed in the vault.
func (vault *Vault) GetNumCubes() int {
return vault.numForceCubes + vault.numLevitateCubes + vault.numBoostCubes
}
func countCubes(distance uint16) int {
// TODO(patrick): Update with real values once there is a physical setup to test with.
if distance >= 3000 {

View File

@@ -12,22 +12,34 @@ import (
func TestVaultNumCubes(t *testing.T) {
// TODO(patrick): Update with real values once there is a physical setup to test with.
vault := Vault{}
assert.Equal(t, 0, vault.GetNumCubes())
assert.Equal(t, 0, vault.ForceCubes)
assert.Equal(t, 0, vault.LevitateCubes)
assert.Equal(t, 0, vault.BoostCubes)
vault.UpdateCubes(1000, 0, 0)
assert.Equal(t, 1, vault.GetNumCubes())
assert.Equal(t, 1, vault.ForceCubes)
assert.Equal(t, 0, vault.LevitateCubes)
assert.Equal(t, 0, vault.BoostCubes)
vault.UpdateCubes(0, 1000, 1000)
assert.Equal(t, 2, vault.GetNumCubes())
assert.Equal(t, 0, vault.ForceCubes)
assert.Equal(t, 1, vault.LevitateCubes)
assert.Equal(t, 1, vault.BoostCubes)
vault.UpdateCubes(0, 0, 2000)
assert.Equal(t, 2, vault.GetNumCubes())
assert.Equal(t, 0, vault.ForceCubes)
assert.Equal(t, 0, vault.LevitateCubes)
assert.Equal(t, 2, vault.BoostCubes)
vault.UpdateCubes(2000, 2000, 3000)
assert.Equal(t, 7, vault.GetNumCubes())
assert.Equal(t, 2, vault.ForceCubes)
assert.Equal(t, 2, vault.LevitateCubes)
assert.Equal(t, 3, vault.BoostCubes)
vault.UpdateCubes(3000, 3000, 3000)
assert.Equal(t, 9, vault.GetNumCubes())
assert.Equal(t, 3, vault.ForceCubes)
assert.Equal(t, 3, vault.LevitateCubes)
assert.Equal(t, 3, vault.BoostCubes)
}
func TestVaultLevitate(t *testing.T) {

View File

@@ -37,8 +37,12 @@ var renderResults = function(alliance) {
$("input[name=" + alliance + "AutoEndSwitchOwnership]").prop("checked", result.score.AutoEndSwitchOwnership);
$("input[name=" + alliance + "TeleopOwnershipPoints]").val(result.score.TeleopOwnershipPoints);
$("input[name=" + alliance + "VaultCubes]").val(result.score.VaultCubes);
$("input[name=" + alliance + "Levitate]").prop("checked", result.score.Levitate);
$("input[name=" + alliance + "ForceCubes]").val(result.score.ForceCubes);
$("input[name=" + alliance + "ForcePlayed]").prop("checked", result.score.ForcePlayed);
$("input[name=" + alliance + "LevitateCubes]").val(result.score.LevitateCubes);
$("input[name=" + alliance + "LevitatePlayed]").prop("checked", result.score.LevitatePlayed);
$("input[name=" + alliance + "BoostCubes]").val(result.score.BoostCubes);
$("input[name=" + alliance + "BoostPlayed]").prop("checked", result.score.BoostPlayed);
$("input[name=" + alliance + "Climbs]").val(result.score.Climbs);
$("input[name=" + alliance + "Parks]").val(result.score.Parks);
@@ -70,8 +74,12 @@ var updateResults = function(alliance) {
result.score.AutoOwnershipPoints = parseInt(formData[alliance + "AutoOwnershipPoints"]);
result.score.AutoEndSwitchOwnership = formData[alliance + "AutoEndSwitchOwnership"] === "on";
result.score.TeleopOwnershipPoints = parseInt(formData[alliance + "TeleopOwnershipPoints"]);
result.score.VaultCubes = parseInt(formData[alliance + "VaultCubes"]);
result.score.Levitate = formData[alliance + "Levitate"] === "on";
result.score.ForceCubes = parseInt(formData[alliance + "ForceCubes"]);
result.score.ForcePlayed = formData[alliance + "ForcePlayed"] === "on";
result.score.LevitateCubes = parseInt(formData[alliance + "LevitateCubes"]);
result.score.LevitatePlayed = formData[alliance + "LevitatePlayed"] === "on";
result.score.BoostCubes = parseInt(formData[alliance + "BoostCubes"]);
result.score.BoostPlayed = formData[alliance + "BoostPlayed"] === "on";
result.score.Climbs = parseInt(formData[alliance + "Climbs"]);
result.score.Parks = parseInt(formData[alliance + "Parks"]);

View File

@@ -27,24 +27,24 @@
<div class="well well-{{"{{alliance}}"}}">
<legend>Autonomous</legend>
<div class="form-group">
<div class="col-lg-6">
<div class="row">
<div class="row">
<div class="col-lg-6">
<label class="col-lg-8 control-label">Auto Runs</label>
<div class="col-lg-4">
<input type="text" class="form-control input-sm" name="{{"{{alliance}}"}}AutoRuns">
</div>
</div>
</div>
<div class="col-lg-6">
<div class="row">
<div class="row">
<div class="col-lg-6">
<label class="col-lg-8 control-label">Ownership Points</label>
<div class="col-lg-4">
<input type="text" class="form-control input-sm" name="{{"{{alliance}}"}}AutoOwnershipPoints">
</div>
</div>
<div class="row">
<label class="col-lg-8 control-label">Owned Switch at End</label>
<div class="col-lg-4">
<div class="col-lg-6">
<label class="col-lg-9 control-label">Owned Switch at End</label>
<div class="col-lg-3">
<input type="checkbox" class="input-sm" name="{{"{{alliance}}"}}AutoEndSwitchOwnership">
</div>
</div>
@@ -52,39 +52,69 @@
</div>
<legend>Teleoperated</legend>
<div class="form-group">
<div class="col-lg-6">
<div class="row">
<div class="row">
<div class="col-lg-6">
<label class="col-lg-8 control-label">Ownership Points</label>
<div class="col-lg-4">
<input type="text" class="form-control input-sm" name="{{"{{alliance}}"}}TeleopOwnershipPoints">
</div>
</div>
<div class="row">
<label class="col-lg-8 control-label">Vault Cubes</label>
</div>
<div class="row">
<div class="col-lg-6">
<label class="col-lg-8 control-label">Force Cubes</label>
<div class="col-lg-4">
<input type="text" class="form-control input-sm" name="{{"{{alliance}}"}}VaultCubes">
<input type="text" class="form-control input-sm" name="{{"{{alliance}}"}}ForceCubes">
</div>
</div>
<div class="row">
<label class="col-lg-8 control-label">Levitate Played</label>
<div class="col-lg-4">
<input type="checkbox" class="input-sm" name="{{"{{alliance}}"}}Levitate">
<div class="col-lg-6">
<label class="col-lg-9 control-label">Force Played</label>
<div class="col-lg-3">
<input type="checkbox" class="input-sm" name="{{"{{alliance}}"}}ForcePlayed">
</div>
</div>
</div>
<div class="col-lg-6">
<div class="row">
<label class="col-lg-8 control-label">Climbs</label>
<div class="row">
<div class="col-lg-6">
<label class="col-lg-8 control-label">Levitate Cubes</label>
<div class="col-lg-4">
<input type="text" class="form-control input-sm" name="{{"{{alliance}}"}}Climbs">
<input type="text" class="form-control input-sm" name="{{"{{alliance}}"}}LevitateCubes">
</div>
</div>
<div class="row">
<div class="col-lg-6">
<label class="col-lg-9 control-label">Levitate Played</label>
<div class="col-lg-3">
<input type="checkbox" class="input-sm" name="{{"{{alliance}}"}}LevitatePlayed">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<label class="col-lg-8 control-label">Boost Cubes</label>
<div class="col-lg-4">
<input type="text" class="form-control input-sm" name="{{"{{alliance}}"}}BoostCubes">
</div>
</div>
<div class="col-lg-6">
<label class="col-lg-9 control-label">Boost Played</label>
<div class="col-lg-3">
<input type="checkbox" class="input-sm" name="{{"{{alliance}}"}}BoostPlayed">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<label class="col-lg-8 control-label">Parks</label>
<div class="col-lg-4">
<input type="text" class="form-control input-sm" name="{{"{{alliance}}"}}Parks">
</div>
</div>
<div class="col-lg-6">
<label class="col-lg-8 control-label">Climbs</label>
<div class="col-lg-4">
<input type="text" class="form-control input-sm" name="{{"{{alliance}}"}}Climbs">
</div>
</div>
</div>
</div>
<br /><br />

View File

@@ -177,7 +177,7 @@ func TestCommitEliminationTie(t *testing.T) {
match := &model.Match{Id: 0, Type: "qualification", Red1: 1, Red2: 2, Red3: 3, Blue1: 4, Blue2: 5, Blue3: 6}
web.arena.Database.CreateMatch(match)
matchResult := &model.MatchResult{MatchId: match.Id, RedScore: &game.Score{VaultCubes: 1, Fouls: []game.Foul{{}}},
matchResult := &model.MatchResult{MatchId: match.Id, RedScore: &game.Score{ForceCubes: 1, Fouls: []game.Foul{{}}},
BlueScore: &game.Score{}}
err := web.commitMatchScore(match, matchResult, false)
assert.Nil(t, err)
@@ -304,11 +304,11 @@ func TestMatchPlayWebsocketCommands(t *testing.T) {
readWebsocketType(t, ws, "setAudienceDisplay")
assert.Equal(t, field.PostMatch, web.arena.MatchState)
web.arena.RedRealtimeScore.CurrentScore.AutoRuns = 1
web.arena.BlueRealtimeScore.CurrentScore.VaultCubes = 2
web.arena.BlueRealtimeScore.CurrentScore.BoostCubes = 2
ws.Write("commitResults", nil)
readWebsocketMultiple(t, ws, 3) // reload, realtimeScore, setAllianceStationDisplay
assert.Equal(t, 1, web.arena.SavedMatchResult.RedScore.AutoRuns)
assert.Equal(t, 2, web.arena.SavedMatchResult.BlueScore.VaultCubes)
assert.Equal(t, 2, web.arena.SavedMatchResult.BlueScore.BoostCubes)
assert.Equal(t, field.PreMatch, web.arena.MatchState)
ws.Write("discardResults", nil)
readWebsocketMultiple(t, ws, 3) // reload, realtimeScore, setAllianceStationDisplay