Update audience display for 2020.

This commit is contained in:
Patrick Fairbank
2020-03-21 19:27:05 -07:00
parent 877f846984
commit fd84cdcd73
7 changed files with 116 additions and 56 deletions

View File

@@ -5,6 +5,8 @@
package game
import "math"
type Score struct {
ExitedInitiationLine [3]bool
AutoCellsBottom [2]int
@@ -30,7 +32,7 @@ type ScoreSummary struct {
EndgamePoints int
FoulPoints int
Score int
StagesAtCapacity [3]bool
StagePowerCellsRemaining [3]int
StagesActivated [3]bool
ControlPanelRankingPoint bool
EndgameRankingPoint bool
@@ -102,8 +104,8 @@ func (score *Score) Summarize(opponentFouls []Foul, teleopStarted bool) *ScoreSu
// Calculate control panel points and stages.
for i := Stage1; i <= Stage3; i++ {
summary.StagesAtCapacity[i] = score.stageAtCapacity(i, teleopStarted)
summary.StagesActivated[i] = score.stageActivated(i, teleopStarted)
summary.StagePowerCellsRemaining[i] = int(math.Max(0, float64(StageCapacities[i]-score.stagePowerCells(i))))
}
if summary.StagesActivated[Stage2] {
summary.ControlPanelPoints += 10

View File

@@ -22,7 +22,7 @@ func TestScoreSummary(t *testing.T) {
assert.Equal(t, 75, redSummary.EndgamePoints)
assert.Equal(t, 0, redSummary.FoulPoints)
assert.Equal(t, 217, redSummary.Score)
assert.Equal(t, [3]bool{true, true, false}, redSummary.StagesAtCapacity)
assert.Equal(t, [3]int{0, 0, 18}, redSummary.StagePowerCellsRemaining)
assert.Equal(t, [3]bool{true, true, false}, redSummary.StagesActivated)
assert.Equal(t, false, redSummary.ControlPanelRankingPoint)
assert.Equal(t, true, redSummary.EndgameRankingPoint)
@@ -37,7 +37,7 @@ func TestScoreSummary(t *testing.T) {
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]int{0, 0, 0}, blueSummary.StagePowerCellsRemaining)
assert.Equal(t, [3]bool{true, true, true}, blueSummary.StagesActivated)
assert.Equal(t, true, blueSummary.ControlPanelRankingPoint)
assert.Equal(t, false, blueSummary.EndgameRankingPoint)
@@ -96,7 +96,7 @@ func TestScoreSummaryBoundaryConditions(t *testing.T) {
score := TestScore2()
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]int{0, 0, 0}, summary.StagePowerCellsRemaining)
assert.Equal(t, [3]bool{true, true, true}, summary.StagesActivated)
assert.Equal(t, true, summary.ControlPanelRankingPoint)
assert.Equal(t, 219, summary.Score)
@@ -104,7 +104,7 @@ func TestScoreSummaryBoundaryConditions(t *testing.T) {
score.TeleopCellsInner[0]--
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]int{1, 0, 0}, summary.StagePowerCellsRemaining)
assert.Equal(t, [3]bool{false, false, false}, summary.StagesActivated)
assert.Equal(t, false, summary.ControlPanelRankingPoint)
assert.Equal(t, 186, summary.Score)
@@ -112,42 +112,42 @@ func TestScoreSummaryBoundaryConditions(t *testing.T) {
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]int{0, 0, 0}, summary.StagePowerCellsRemaining)
assert.Equal(t, [3]bool{false, false, false}, summary.StagesActivated)
assert.Equal(t, false, summary.ControlPanelRankingPoint)
assert.Equal(t, 189, summary.Score)
score.TeleopCellsOuter[1]--
score.TeleopCellsOuter[1] -= 2
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]int{0, 2, 0}, summary.StagePowerCellsRemaining)
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]++
assert.Equal(t, 185, summary.Score)
score.TeleopCellsOuter[1] += 2
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]int{0, 0, 0}, summary.StagePowerCellsRemaining)
assert.Equal(t, [3]bool{true, false, false}, summary.StagesActivated)
assert.Equal(t, false, summary.ControlPanelRankingPoint)
assert.Equal(t, 189, summary.Score)
score.ControlPanelStatus = ControlPanelPosition
score.TeleopCellsInner[2] -= 3
score.TeleopCellsInner[2] -= 5
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]int{0, 0, 3}, summary.StagePowerCellsRemaining)
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
assert.Equal(t, 184, summary.Score)
score.TeleopCellsInner[2] += 5
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]int{0, 0, 0}, summary.StagePowerCellsRemaining)
assert.Equal(t, [3]bool{true, true, false}, summary.StagesActivated)
assert.Equal(t, false, summary.ControlPanelRankingPoint)
assert.Equal(t, 199, summary.Score)

View File

@@ -57,10 +57,13 @@ html {
width: 0;
height: 100%;
display: flex;
justify-content: space-between;
justify-content: flex-start;
}
.score-right {
justify-content: flex-end;
}
.avatars {
width: 50px;
min-width: 50px;
height: 100%;
display: none;
flex-direction: column;
@@ -81,6 +84,19 @@ html {
color: #fff;
opacity: 0;
}
.score-fields {
height: 100%;
width: 0;
display: none;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
font-family: "FuturaLTBold";
font-size: 20px;
line-height: 25px;
color: #fff;
opacity: 0;
}
#matchCircle {
position: absolute;
top: -25px;

View File

@@ -27,7 +27,8 @@ var logoUp = "10px";
var logoDown = $("#logo").css("top");
var scoreIn = $(".score").css("width");
var scoreMid = "135px";
var scoreOut = "205px";
var scoreOut = "255px";
var scoreFieldsOut = "40px";
// Handles a websocket message to change which screen is displayed.
var handleAudienceDisplayMode = function(targetScreen) {
@@ -82,8 +83,14 @@ var handleMatchTime = function(data) {
// Handles a websocket message to update the match score.
var handleRealtimeScore = function(data) {
$("#" + redSide + "ScoreNumber").text(data.Red.ScoreSummary.Score - data.Red.ScoreSummary.HabClimbPoints);
$("#" + blueSide + "ScoreNumber").text(data.Blue.ScoreSummary.Score - data.Blue.ScoreSummary.HabClimbPoints);
$("#" + redSide + "ScoreNumber").text(data.Red.ScoreSummary.Score - data.Red.ScoreSummary.EndgamePoints);
$("#" + blueSide + "ScoreNumber").text(data.Blue.ScoreSummary.Score - data.Blue.ScoreSummary.EndgamePoints);
for (var i = 0; i < 3; i++) {
var i1 = i + 1;
setPowerCellText($("#" + redSide + "Stage" + i1), data.Red.ScoreSummary, i);
setPowerCellText($("#" + blueSide + "Stage" + i1), data.Blue.ScoreSummary, i);
}
};
// Handles a websocket message to populate the final score data.
@@ -95,15 +102,15 @@ var handleScorePosted = function(data) {
$("#" + redSide + "FinalTeam1Avatar").attr("src", getAvatarUrl(data.Match.Red1));
$("#" + redSide + "FinalTeam2Avatar").attr("src", getAvatarUrl(data.Match.Red2));
$("#" + redSide + "FinalTeam3Avatar").attr("src", getAvatarUrl(data.Match.Red3));
$("#" + redSide + "FinalSandstormBonusPoints").text(data.RedScoreSummary.SandstormBonusPoints);
$("#" + redSide + "FinalHatchPanelPoints").text(data.RedScoreSummary.HatchPanelPoints);
$("#" + redSide + "FinalCargoPoints").text(data.RedScoreSummary.CargoPoints);
$("#" + redSide + "FinalHabClimbPoints").text(data.RedScoreSummary.HabClimbPoints);
$("#" + redSide + "FinalInitiationLinePoints").text(data.RedScoreSummary.InitiationLinePoints);
$("#" + redSide + "FinalPowerCellPoints").text(data.RedScoreSummary.PowerCellPoints);
$("#" + redSide + "FinalControlPanelPoints").text(data.RedScoreSummary.ControlPanelPoints);
$("#" + redSide + "FinalEndgamePoints").text(data.RedScoreSummary.EndgamePoints);
$("#" + redSide + "FinalFoulPoints").text(data.RedScoreSummary.FoulPoints);
$("#" + redSide + "FinalCompleteRocket").html(data.RedScoreSummary.CompleteRocket ? "&#x2714;" : "&#x2718;");
$("#" + redSide + "FinalCompleteRocket").attr("data-checked", data.RedScoreSummary.CompleteRocket);
$("#" + redSide + "FinalHabDocking").html(data.RedScoreSummary.HabDocking ? "&#x2714;" : "&#x2718;");
$("#" + redSide + "FinalHabDocking").attr("data-checked", data.RedScoreSummary.HabDocking);
$("#" + redSide + "FinalControlPanelRankingPoint").html(data.RedScoreSummary.ControlPanelRankingPoint ? "&#x2714;" : "&#x2718;");
$("#" + redSide + "FinalControlPanelRankingPoint").attr("data-checked", data.RedScoreSummary.ControlPanelRankingPoint);
$("#" + redSide + "FinalEndgameRankingPoint").html(data.RedScoreSummary.EndgameRankingPoint ? "&#x2714;" : "&#x2718;");
$("#" + redSide + "FinalEndgameRankingPoint").attr("data-checked", data.RedScoreSummary.EndgameRankingPoint);
$("#" + blueSide + "FinalScore").text(data.BlueScoreSummary.Score);
$("#" + blueSide + "FinalTeam1").text(data.Match.Blue1);
$("#" + blueSide + "FinalTeam2").text(data.Match.Blue2);
@@ -111,15 +118,15 @@ var handleScorePosted = function(data) {
$("#" + blueSide + "FinalTeam1Avatar").attr("src", getAvatarUrl(data.Match.Blue1));
$("#" + blueSide + "FinalTeam2Avatar").attr("src", getAvatarUrl(data.Match.Blue2));
$("#" + blueSide + "FinalTeam3Avatar").attr("src", getAvatarUrl(data.Match.Blue3));
$("#" + blueSide + "FinalSandstormBonusPoints").text(data.BlueScoreSummary.SandstormBonusPoints);
$("#" + blueSide + "FinalHatchPanelPoints").text(data.BlueScoreSummary.HatchPanelPoints);
$("#" + blueSide + "FinalCargoPoints").text(data.BlueScoreSummary.CargoPoints);
$("#" + blueSide + "FinalHabClimbPoints").text(data.BlueScoreSummary.HabClimbPoints);
$("#" + blueSide + "FinalInitiationLinePoints").text(data.BlueScoreSummary.InitiationLinePoints);
$("#" + blueSide + "FinalPowerCellPoints").text(data.BlueScoreSummary.PowerCellPoints);
$("#" + blueSide + "FinalControlPanelPoints").text(data.BlueScoreSummary.ControlPanelPoints);
$("#" + blueSide + "FinalEndgamePoints").text(data.BlueScoreSummary.EndgamePoints);
$("#" + blueSide + "FinalFoulPoints").text(data.BlueScoreSummary.FoulPoints);
$("#" + blueSide + "FinalCompleteRocket").html(data.BlueScoreSummary.CompleteRocket ? "&#x2714;" : "&#x2718;");
$("#" + blueSide + "FinalCompleteRocket").attr("data-checked", data.BlueScoreSummary.CompleteRocket);
$("#" + blueSide + "FinalHabDocking").html(data.BlueScoreSummary.HabDocking ? "&#x2714;" : "&#x2718;");
$("#" + blueSide + "FinalHabDocking").attr("data-checked", data.BlueScoreSummary.HabDocking);
$("#" + blueSide + "FinalControlPanelRankingPoint").html(data.BlueScoreSummary.ControlPanelRankingPoint ? "&#x2714;" : "&#x2718;");
$("#" + blueSide + "FinalControlPanelRankingPoint").attr("data-checked", data.BlueScoreSummary.ControlPanelRankingPoint);
$("#" + blueSide + "FinalEndgameRankingPoint").html(data.BlueScoreSummary.EndgameRankingPoint ? "&#x2714;" : "&#x2718;");
$("#" + blueSide + "FinalEndgameRankingPoint").attr("data-checked", data.BlueScoreSummary.EndgameRankingPoint);
$("#finalSeriesStatus").text(data.SeriesStatus);
$("#finalSeriesStatus").attr("data-leader", data.SeriesLeader);
$("#finalMatchName").text(data.MatchType + " " + data.Match.DisplayName);
@@ -181,10 +188,13 @@ var transitionIntroToInMatch = function(callback) {
$(".avatars").transition({queue: false, opacity: 0}, 500, "ease", function() {
$(".avatars").hide();
});
$(".score-fields").css("display", "flex");
$(".score-fields").transition({queue: false, width: scoreFieldsOut}, 500, "ease");
$("#logo").transition({queue: false, top: logoUp}, 500, "ease");
$(".score").transition({queue: false, width: scoreOut}, 500, "ease", function() {
$(".score-number").transition({queue: false, opacity: 1}, 750, "ease");
$("#matchTime").transition({queue: false, opacity: 1}, 750, "ease", callback);
$(".score-fields").transition({queue: false, opacity: 1}, 750, "ease");
});
};
@@ -203,21 +213,27 @@ var transitionIntroToBlank = function(callback) {
var transitionBlankToInMatch = function(callback) {
$("#overlayCentering").transition(overlayCenteringShowParams, 500, "ease", function() {
$(".teams").css("display", "flex");
$(".score-fields").css("display", "flex");
$(".score-fields").transition({queue: false, width: scoreFieldsOut}, 500, "ease");
$("#logo").transition({queue: false, top: logoUp}, 500, "ease");
$(".score").transition({queue: false, width: scoreOut}, 500, "ease", function() {
$("#eventMatchInfo").css("display", "flex");
$("#eventMatchInfo").transition({queue: false, height: eventMatchInfoDown}, 500, "ease", callback);
$(".score-number").transition({queue: false, opacity: 1}, 750, "ease");
$("#matchTime").transition({queue: false, opacity: 1}, 750, "ease");
$(".score-fields").transition({queue: false, opacity: 1}, 750, "ease");
});
});
};
var transitionInMatchToIntro = function(callback) {
$(".score-number").transition({queue: false, opacity: 0}, 300, "linear");
$(".score-fields").transition({queue: false, opacity: 0}, 300, "ease");
$("#matchTime").transition({queue: false, opacity: 0}, 300, "linear", function() {
$(".score-fields").transition({queue: false, width: 0}, 500, "ease");
$("#logo").transition({queue: false, top: logoDown}, 500, "ease");
$(".score").transition({queue: false, width: scoreMid}, 500, "ease", function() {
$(".score-fields").hide();
$(".avatars").css("display", "flex");
$(".avatars").transition({queue: false, opacity: 1}, 500, "ease", callback);
});
@@ -227,11 +243,14 @@ var transitionInMatchToIntro = function(callback) {
var transitionInMatchToBlank = function(callback) {
$("#eventMatchInfo").transition({queue: false, height: eventMatchInfoUp}, 500, "ease");
$("#matchTime").transition({queue: false, opacity: 0}, 300, "linear");
$(".score-fields").transition({queue: false, opacity: 0}, 300, "ease");
$(".score-number").transition({queue: false, opacity: 0}, 300, "linear", function() {
$("#eventMatchInfo").hide();
$(".score-fields").transition({queue: false, width: 0}, 500, "ease");
$("#logo").transition({queue: false, top: logoDown}, 500, "ease");
$(".score").transition({queue: false, width: scoreIn}, 500, "ease", function() {
$(".teams").hide();
$(".score-fields").hide();
$("#overlayCentering").transition(overlayCenteringHideParams, 1000, "ease", callback);
});
});
@@ -453,6 +472,20 @@ var getAvatarUrl = function(teamId) {
return "/api/teams/" + teamId + "/avatar";
};
// Populates the given element on the overlay to represent the given power cell stage.
var setPowerCellText = function(element, scoreSummary, stage) {
var text = "&nbsp;";
var opacity = 1;
if (scoreSummary.StagesActivated[stage]) {
text = "I".repeat(stage + 1);
opacity = 0.4;
} else if (stage === 0 || scoreSummary.StagesActivated[stage - 1]) {
text = scoreSummary.StagePowerCellsRemaining[stage];
}
element.html(text);
element.css("opacity", opacity);
};
$(function() {
// Read the configuration for this display from the URL query string.
var urlParams = new URLSearchParams(window.location.search);

View File

@@ -97,7 +97,7 @@
{{"{{#each fouls}}"}}
<div class="row">
<div class="col-lg-3 col-lg-offset-1">
{{"{{#if IsTechnical}}"}}Tech {{"{{/if}}"}}Foul{{"{{#if IsRankingPoint}}"}}+RP{{"{{/if}}"}}
{{"{{#if IsRankingPoint}}"}}Free RP{{"{{else}}"}}{{"{{#if IsTechnical}}"}}Tech {{"{{/if}}"}}Foul{{"{{/if}}"}}
</div>
<div class="col-lg-3">Team {{"{{TeamId}}"}}</div>
<div class="col-lg-3" data-toggle="tooltip" title="{{"{{Description}}"}}">{{"{{RuleNumber}}"}}</div>

View File

@@ -28,12 +28,20 @@
<img class="avatar" id="leftTeam2Avatar" src="" />
<img class="avatar" id="leftTeam3Avatar" src="" />
</div>
<div class="score-fields">
<div id="leftStage1"></div>
<div id="leftStage2"></div>
<div id="leftStage3"></div>
</div>
<div class="score-number" id="leftScoreNumber"></div>
<div class="dummy"></div>
</div>
<div class="score reversible-right">
<div class="dummy"></div>
<div class="score score-right reversible-right">
<div class="score-number" id="rightScoreNumber"></div>
<div class="score-fields">
<div id="rightStage1"></div>
<div id="rightStage2"></div>
<div id="rightStage3"></div>
</div>
<div class="avatars">
<img class="avatar" id="rightTeam1Avatar" src="" />
<img class="avatar" id="rightTeam2Avatar" src="" />
@@ -81,29 +89,30 @@
</div>
<div class="final-breakdown" id="leftFinalBreakdown">
<span class="valign-cell">
<span id="leftFinalSandstormBonusPoints"></span><br />
<span id="leftFinalHatchPanelPoints"></span><br />
<span id="leftFinalCargoPoints"></span><br />
<span id="leftFinalHabClimbPoints"></span><br />
<span id="leftFinalInitiationLinePoints"></span><br />
<span id="leftFinalPowerCellPoints"></span><br />
<span id="leftFinalControlPanelPoints"></span><br />
<span id="leftFinalEndgamePoints"></span><br />
<span id="leftFinalFoulPoints"></span><br />
<span id="leftFinalCompleteRocket"></span><br />
<span id="leftFinalHabDocking"></span><br />
<span id="leftFinalControlPanelRankingPoint"></span><br />
<span id="leftFinalEndgameRankingPoint"></span><br />
</span>
</div>
<div class="final-breakdown" id="centerFinalBreakdown">
<span class="valign-cell">
Sandstorm Bonus<br />Hatch Panel<br />Cargo<br />Hab Climb<br />Foul<br />Complete Rocket<br />Hab Docking
Initiation Line<br />Power Cell<br />Control Panel<br />Endgame<br />Foul<br />
Shield Energized<br />Shield Operational
</span>
</div>
<div class="final-breakdown" id="rightFinalBreakdown">
<span class="valign-cell">
<span id="rightFinalSandstormBonusPoints"></span><br />
<span id="rightFinalHatchPanelPoints"></span><br />
<span id="rightFinalCargoPoints"></span><br />
<span id="rightFinalHabClimbPoints"></span><br />
<span id="rightFinalInitiationLinePoints"></span><br />
<span id="rightFinalPowerCellPoints"></span><br />
<span id="rightFinalControlPanelPoints"></span><br />
<span id="rightFinalEndgamePoints"></span><br />
<span id="rightFinalFoulPoints"></span><br />
<span id="rightFinalCompleteRocket"></span><br />
<span id="rightFinalHabDocking"></span><br />
<span id="rightFinalControlPanelRankingPoint"></span><br />
<span id="rightFinalEndgameRankingPoint"></span><br />
</span>
</div>
<div id="finalEventMatchInfo">

View File

@@ -121,7 +121,7 @@
<select class="form-control" name="{{"{{../alliance}}"}}Foul{{"{{@index}}"}}RuleId">
{{range $rule := .Rules}}
<option value="{{$rule.Id}}">{{$rule.RuleNumber}}
[{{if $rule.IsTechnical}}Tech {{end}}Foul{{if $rule.IsRankingPoint}}+RP{{end}}]:
[{{if $rule.IsRankingPoint}}Free RP{{else}}{{if $rule.IsTechnical}}Tech {{end}}Foul{{end}}]:
{{$rule.Description}}
</option>
{{end}}