Updated referee display and optimized for iPad.

This commit is contained in:
Patrick Fairbank
2015-08-30 22:52:03 -07:00
parent 2e16998bb8
commit 4ea0ced315
7 changed files with 64 additions and 41 deletions

View File

@@ -46,7 +46,6 @@ type MatchTiming struct {
type RealtimeScore struct {
CurrentScore Score
Fouls []Foul
Cards map[string]string
AutoCommitted bool
TeleopCommitted bool

View File

@@ -200,6 +200,9 @@ func scoreSummary(score *Score) *ScoreSummary {
summary.FoulPoints = 6 * len(score.Fouls)
summary.Score = summary.AutoPoints + summary.StackPoints + summary.CoopertitionPoints - summary.FoulPoints
if summary.Score < 0 {
summary.Score = 0
}
return summary
}

View File

@@ -74,8 +74,8 @@ func RefereeDisplayHandler(w http.ResponseWriter, r *http.Request) {
Rules []string
EntryEnabled bool
}{eventSettings, matchType, match.DisplayName, red1, red2, red3, blue1, blue2, blue3,
mainArena.redRealtimeScore.Fouls, mainArena.blueRealtimeScore.Fouls, mainArena.redRealtimeScore.Cards,
mainArena.blueRealtimeScore.Cards, rules,
mainArena.redRealtimeScore.CurrentScore.Fouls, mainArena.blueRealtimeScore.CurrentScore.Fouls,
mainArena.redRealtimeScore.Cards, mainArena.blueRealtimeScore.Cards, rules,
!(mainArena.redRealtimeScore.FoulsCommitted && mainArena.blueRealtimeScore.FoulsCommitted)}
err = template.ExecuteTemplate(w, "referee_display.html", data)
if err != nil {
@@ -157,9 +157,11 @@ func RefereeDisplayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
// Add the foul to the correct alliance's list.
foul := Foul{TeamId: args.TeamId, Rule: args.Rule, TimeInMatchSec: mainArena.MatchTimeSec()}
if args.Alliance == "red" {
mainArena.redRealtimeScore.Fouls = append(mainArena.redRealtimeScore.Fouls, foul)
mainArena.redRealtimeScore.CurrentScore.Fouls =
append(mainArena.redRealtimeScore.CurrentScore.Fouls, foul)
} else {
mainArena.blueRealtimeScore.Fouls = append(mainArena.blueRealtimeScore.Fouls, foul)
mainArena.blueRealtimeScore.CurrentScore.Fouls =
append(mainArena.blueRealtimeScore.CurrentScore.Fouls, foul)
}
mainArena.realtimeScoreNotifier.Notify(nil)
case "deleteFoul":
@@ -180,9 +182,9 @@ func RefereeDisplayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
deleteFoul := Foul{TeamId: args.TeamId, Rule: args.Rule, TimeInMatchSec: args.TimeInMatchSec}
var fouls *[]Foul
if args.Alliance == "red" {
fouls = &mainArena.redRealtimeScore.Fouls
fouls = &mainArena.redRealtimeScore.CurrentScore.Fouls
} else {
fouls = &mainArena.blueRealtimeScore.Fouls
fouls = &mainArena.blueRealtimeScore.CurrentScore.Fouls
}
for i, foul := range *fouls {
if foul == deleteFoul {

View File

@@ -60,17 +60,17 @@ func TestRefereeDisplayWebsocket(t *testing.T) {
readWebsocketType(t, ws, "reload")
readWebsocketType(t, ws, "reload")
readWebsocketType(t, ws, "reload")
if assert.Equal(t, 2, len(mainArena.redRealtimeScore.Fouls)) {
assert.Equal(t, 256, mainArena.redRealtimeScore.Fouls[0].TeamId)
assert.Equal(t, "G22", mainArena.redRealtimeScore.Fouls[0].Rule)
assert.Equal(t, 0.0, mainArena.redRealtimeScore.Fouls[0].TimeInMatchSec)
assert.Equal(t, 359, mainArena.redRealtimeScore.Fouls[1].TeamId)
assert.Equal(t, "G22", mainArena.redRealtimeScore.Fouls[1].Rule)
if assert.Equal(t, 2, len(mainArena.redRealtimeScore.CurrentScore.Fouls)) {
assert.Equal(t, 256, mainArena.redRealtimeScore.CurrentScore.Fouls[0].TeamId)
assert.Equal(t, "G22", mainArena.redRealtimeScore.CurrentScore.Fouls[0].Rule)
assert.Equal(t, 0.0, mainArena.redRealtimeScore.CurrentScore.Fouls[0].TimeInMatchSec)
assert.Equal(t, 359, mainArena.redRealtimeScore.CurrentScore.Fouls[1].TeamId)
assert.Equal(t, "G22", mainArena.redRealtimeScore.CurrentScore.Fouls[1].Rule)
}
if assert.Equal(t, 1, len(mainArena.blueRealtimeScore.Fouls)) {
assert.Equal(t, 1680, mainArena.blueRealtimeScore.Fouls[0].TeamId)
assert.Equal(t, "G22", mainArena.blueRealtimeScore.Fouls[0].Rule)
assert.Equal(t, 0.0, mainArena.blueRealtimeScore.Fouls[0].TimeInMatchSec)
if assert.Equal(t, 1, len(mainArena.blueRealtimeScore.CurrentScore.Fouls)) {
assert.Equal(t, 1680, mainArena.blueRealtimeScore.CurrentScore.Fouls[0].TeamId)
assert.Equal(t, "G22", mainArena.blueRealtimeScore.CurrentScore.Fouls[0].Rule)
assert.Equal(t, 0.0, mainArena.blueRealtimeScore.CurrentScore.Fouls[0].TimeInMatchSec)
}
assert.False(t, mainArena.redRealtimeScore.FoulsCommitted)
assert.False(t, mainArena.blueRealtimeScore.FoulsCommitted)
@@ -78,17 +78,17 @@ func TestRefereeDisplayWebsocket(t *testing.T) {
// Test foul deletion.
ws.Write("deleteFoul", foulData)
readWebsocketType(t, ws, "reload")
assert.Equal(t, 0, len(mainArena.blueRealtimeScore.Fouls))
assert.Equal(t, 0, len(mainArena.blueRealtimeScore.CurrentScore.Fouls))
foulData.Alliance = "red"
foulData.TeamId = 359
foulData.TimeInMatchSec = 29 // Make it not match.
ws.Write("deleteFoul", foulData)
readWebsocketType(t, ws, "reload")
assert.Equal(t, 2, len(mainArena.redRealtimeScore.Fouls))
assert.Equal(t, 2, len(mainArena.redRealtimeScore.CurrentScore.Fouls))
foulData.TimeInMatchSec = 0
ws.Write("deleteFoul", foulData)
readWebsocketType(t, ws, "reload")
assert.Equal(t, 1, len(mainArena.redRealtimeScore.Fouls))
assert.Equal(t, 1, len(mainArena.redRealtimeScore.CurrentScore.Fouls))
// Test card setting.
cardData := struct {

View File

@@ -17,15 +17,15 @@ h3, h4 {
color: #fff;
}
.btn-referee {
width: 120px;
width: 100px;
margin: 5px 5px;
font-size: 30px;
font-size: 25px;
cursor: default;
}
.btn-referee-wide {
width: 254px;
margin: 5px 5px;
font-size: 30px;
font-size: 25px;
}
.btn {
cursor: default;

View File

@@ -4,21 +4,29 @@
// Client-side logic for the referee interface.
var websocket;
var foulAlliance;
var foulTeam;
var foulRule;
var foulTeamButton;
var foulRuleButton;
// Handles a click on a team button.
var setFoulTeam = function(teamButton) {
foulAlliance = $(teamButton).attr("data-alliance");
foulTeam = $(teamButton).attr("data-team");
setSelections();
if (foulTeamButton) {
foulTeamButton.attr("data-selected", false);
}
foulTeamButton = $(teamButton);
foulTeamButton.attr("data-selected", true);
$("#commit").prop("disabled", !(foulTeamButton && foulRuleButton));
};
// Handles a click on a rule button.
var setFoulRule = function(ruleButton) {
foulRule = $(ruleButton).attr("data-rule");
setSelections();
if (foulRuleButton) {
foulRuleButton.attr("data-selected", false);
}
foulRuleButton = $(ruleButton);
foulRuleButton.attr("data-selected", true);
$("#commit").prop("disabled", !(foulTeamButton && foulRuleButton));
};
// Sets button styles to match the selection cached in the global variables.
@@ -30,20 +38,25 @@ var setSelections = function() {
$("[data-rule]").each(function(i, ruleButton) {
$(ruleButton).attr("data-selected", $(ruleButton).attr("data-rule") == foulRule);
});
$("#commit").prop("disabled", (foulTeam == "" || foulRule == ""));
};
// Resets the buttons to their default selections.
var clearFoul = function() {
foulTeam = "";
foulRule = "";
setSelections();
if (foulTeamButton) {
foulTeamButton.attr("data-selected", false);
foulTeamButton = null;
}
if (foulRuleButton) {
foulRuleButton.attr("data-selected", false);
foulRuleButton = null;
}
$("#commit").prop("disabled", true);
};
// Sends the foul to the server to add it to the list.
var commitFoul = function() {
websocket.send("addFoul", {Alliance: foulAlliance, TeamId: parseInt(foulTeam), Rule: foulRule});
websocket.send("addFoul", {Alliance: foulTeamButton.attr("data-alliance"),
TeamId: parseInt(foulTeamButton.attr("data-team")), Rule: foulRuleButton.attr("data-rule")});
};
// Removes the foul with the given parameters from the list.

View File

@@ -10,6 +10,7 @@
<title>Referee Display - {{.EventSettings.Name}} - Cheesy Arena</title>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="format-detection" content="telephone=no">
<link rel="shortcut icon" href="/static/img/favicon.png">
<link rel="apple-touch-icon" href="/static/img/apple-icon.png">
<link href="/static/css/lib/bootstrap.min.css" rel="stylesheet">
@@ -22,7 +23,7 @@
{{if .EntryEnabled}}
<h3 style="margin-top: 0">{{.MatchType}} Match {{.MatchDisplayName}}</h3>
<div class="row">
<div class="col-lg-3">
<div class="col-xs-3">
<h4>Fouls</h4>
<table class="table">
{{range $foul := .RedFouls}}
@@ -40,7 +41,7 @@
{{template "card" dict "team" .Blue2 "alliance" "blue" "cards" .BlueCards}}
{{template "card" dict "team" .Blue3 "alliance" "blue" "cards" .BlueCards}}
</div>
<div class="col-lg-9">
<div class="col-xs-9">
<h4>Add Foul</h4>
<div class="row">
<a class="btn btn-lg btn-primary btn-referee" data-alliance="red" data-team="{{.Red1.Id}}"
@@ -62,6 +63,7 @@
onclick="setFoulRule(this);">{{$rule}}</a>
{{end}}
</div>
<br />
<div class="row text-center">
<a class="btn btn-lg btn-default btn-referee btn-referee-wide" onclick="clearFoul();">Clear Foul</a>
<button type="button" class="btn btn-lg btn-success btn-referee btn-referee-wide" id="commit"
@@ -73,6 +75,11 @@
<a class="btn btn-lg btn-info btn-referee btn-referee-wide"
onclick="commitMatch();">Commit Match</a>
</div>
<br />
<div class="row text-center">
<a class="btn btn-lg btn-danger btn-referee btn-referee-wide"
onclick="location.reload();">Refresh</a>
</div>
</div>
</div>
{{else}}
@@ -83,7 +90,6 @@
<script src="/static/js/lib/jquery.min.js"></script>
<script src="/static/js/lib/jquery.json-2.4.min.js"></script>
<script src="/static/js/lib/jquery.websocket-0.0.1.js"></script>
<script src="/static/js/lib/bootstrap.min.js"></script>
<script src="/static/js/cheesy-websocket.js"></script>
<script src="/static/js/referee_display.js"></script>
</body>
@@ -97,7 +103,7 @@
</tr>
{{end}}
{{define "card"}}
<a class="btn btn-lg btn-card" data-old-yellow-card="{{.team.YellowCard}}" data-alliance="{{.alliance}}"
<a class="btn btn-md btn-card" data-old-yellow-card="{{.team.YellowCard}}" data-alliance="{{.alliance}}"
data-card-team="{{.team.Id}}" data-card="{{index .cards (print .team.Id)}}"
onclick="cycleCard(this);">{{.team.Id}}</a><br />
{{end}}