diff --git a/game/score.go b/game/score.go index 8184817..ddfb9d7 100644 --- a/game/score.go +++ b/game/score.go @@ -190,7 +190,7 @@ func (score *Score) CellCountingStage(teleopStarted bool) Stage { } // Returns true if the preconditions are satisfied for the given Stage to be activated. -func (score *Score) stageAtCapacity(stage Stage, teleopStarted bool) bool { +func (score *Score) StageAtCapacity(stage Stage, teleopStarted bool) bool { if stage > Stage1 && !score.stageActivated(stage-1, teleopStarted) { return false } @@ -202,7 +202,7 @@ func (score *Score) stageAtCapacity(stage Stage, teleopStarted bool) bool { // Returns true if the given Stage has been activated. func (score *Score) stageActivated(stage Stage, teleopStarted bool) bool { - if score.stageAtCapacity(stage, teleopStarted) { + if score.StageAtCapacity(stage, teleopStarted) { switch stage { case Stage1: return teleopStarted diff --git a/static/css/scoring_panel.css b/static/css/scoring_panel.css index b41c9bc..dd968a8 100644 --- a/static/css/scoring_panel.css +++ b/static/css/scoring_panel.css @@ -12,27 +12,45 @@ body { background-color: #222; } .container { + padding-top: 2vw; width: 100%; height: 100%; display: flex; flex-direction: column; + justify-content: flex-start; align-items: center; } +#alliance { + width: 90%; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; + border-radius: 25px; + border: 1px solid #333; +} +#alliance[data-alliance="red"] { + background-color: #322; +} +#alliance[data-alliance="blue"] { + background-color: #223; +} #matchName { font-size: 2vw; } -#robots { +.scoring-section { margin-bottom: 0.5vw; display: flex; font-size: 1.5vw; color: #ccc; } -#robotHeader { - margin-right: 1vw; +.scoring-header>div{ + height: 2.5vw; + margin: 0.4vw 1vw 0.4vw 0.2vw; color: #666; } .robot-field { - min-width: 12vw; + width: 17vw; height: 2.5vw; display: flex; justify-content: space-between; @@ -42,180 +60,91 @@ body { .team { display: flex; justify-content: center; + font-weight: bold; } -.robot-start-level[data-value="0"] { - background-color: #633; -} -.robot-start-level[data-value="1"] { - background-color: #236; -} -.robot-start-level[data-value="2"] { - background-color: #263; -} -.robot-start-level[data-value="3"] { - background-color: #850; -} -.sandstorm-bonus[data-value="false"] { +.boolean[data-value="false"] { background-color: #333; } -.sandstorm-bonus[data-value="true"] { +.boolean[data-value="true"] { background-color: #263; } -.robot-end-level[data-value="0"] { +.endgame-status[data-value="0"] { background-color: #333; } -.robot-end-level[data-value="1"] { +.endgame-status[data-value="1"] { background-color: #236; } -.robot-end-level[data-value="2"] { - background-color: #224d4d; -} -.robot-end-level[data-value="3"] { +.endgame-status[data-value="2"] { background-color: #263; } -.robot-shortcut { - width: 2vw; +.control-panel[data-value="disabled"] { + background-color: #333; +} +.control-panel[data-value="false"] { + background-color: #236; +} +.control-panel[data-value="true"] { + background-color: #263; +} +.shortcut { margin: 0 0.2vw; font-size: 1vw; align-self: flex-start; } -.team { - font-weight: bold; -} -#scoringElements { +#elements { width: 100%; - height: 100%; + display: flex; + justify-content: space-evenly; + align-items: center; +} +.goal-header { + height: 5vw; + margin: 0.4vw 0vw; + color: #666; + display: flex; + flex-direction: column; + justify-content: center; +} +.goal-period { + text-align: center; + color: #666; +} +.goal { + width: 13vw; + height: 5vw; + margin: 0.4vw 3vw; display: flex; justify-content: space-between; -} -.rocket { - display: flex; - align-items: flex-end; -} -.rocket-outline { - display: flex; - align-items: flex-end; - padding: 5vw 2vw 1vw 2vw; - border: 1px solid #222; - border-radius: 40% 40% 0% 0%; -} -.alliance-color[data-alliance="red"] { - background-color: #633; -} -.alliance-color[data-alliance="blue"] { - background-color: #236; -} -.outer-rocket { - height: 26vw; - margin: 0.2vw; -} -.inner-rocket { - margin: 0.2vw; -} -#centerColumn { - display: flex; - flex-direction: column; align-items: center; } -#cargoShipContainer { - display: flex; - flex-direction: column; - align-items: center; -} -#cargoShip { - display: flex; - flex-direction: column; - align-items: center; - padding: 1vw; - border: 1px solid #222; - border-radius: 10%; -} -.cargo-ship-side { - width: 25vw; +.number-button { + width: 4vw; + height: 4vw; display: flex; justify-content: space-between; + align-items: center; + border: 1px solid #666; + border-radius: 0.5vw; + font-size: 3vw; } -.cargo-ship-front { - display: flex; +.plus { + background: #263; } -.bay { - position: relative; - width: 7vw; - height: 7vw; - margin: 0.2vw; - border: 1px solid #222; - background-color: #666; - border-radius: 10%; -} -.bay[data-value="0"] .hatch-panel { - display: none; -} -.bay[data-value="1"] .hatch-panel { - display: flex; -} -.bay[data-value="2"] .hatch-panel { - display: flex; -} -.bay[data-value="3"] .hatch-panel { - display: none; -} -.bay[data-value="0"] .cargo { - display: none; -} -.bay[data-value="1"] .cargo { - display: none; -} -.bay[data-value="2"] .cargo { - display: flex; -} -.bay[data-value="3"] .cargo { - display: flex; -} -.shortcut { - position: absolute; - left: 0.3vw; - top: -0.1vw; - font-size: 1.2vw; - color: #fff -} -.hatch-panel { - width: 6vw; - height: 6vw; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - display: none; - margin: auto auto; - border: 1vw solid #c80; - border-radius: 50%; -} -.cargo { - width: 3vw; - height: 3vw; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - display: none; - margin: auto auto; - background-color: #c50; - border-radius: 50%; +.minus { + background: #633; } #instructions { margin-top: 0.3vw; } -#preMatchMessage, #postMatchMessage { - height: 100%; +#postMatchMessage { + height: 5vw; display: none; align-items: center; font-size: 1.5vw; color: #c90; } #commitMatchScore { - height: 100%; + height: 5vw; display: none; align-items: center; } diff --git a/static/js/scoring_panel.js b/static/js/scoring_panel.js index 0a65c03..1c47076 100644 --- a/static/js/scoring_panel.js +++ b/static/js/scoring_panel.js @@ -29,31 +29,44 @@ var handleRealtimeScore = function(data) { realtimeScore = data.Blue; } var score = realtimeScore.Score; + var summary = realtimeScore.ScoreSummary; for (var i = 0; i < 3; i++) { var i1 = i + 1; - $("#robotStartLevel" + i1 + ">.value").text(getRobotStartLevelText(score.RobotStartLevels[i])); - $("#robotStartLevel" + i1).attr("data-value", score.RobotStartLevels[i]); - $("#sandstormBonus" + i1 + ">.value").text(score.SandstormBonuses[i] ? "Yes" : "No"); - $("#sandstormBonus" + i1).attr("data-value", score.SandstormBonuses[i]); - $("#robotEndLevel" + i1 + ">.value").text(getRobotEndLevelText(score.RobotEndLevels[i])); - $("#robotEndLevel" + i1).attr("data-value", score.RobotEndLevels[i]); - getBay("rocketNearLeft", i).attr("data-value", score.RocketNearLeftBays[i]); - getBay("rocketNearRight", i).attr("data-value", score.RocketNearRightBays[i]); - getBay("rocketFarLeft", i).attr("data-value", score.RocketFarLeftBays[i]); - getBay("rocketFarRight", i).attr("data-value", score.RocketFarRightBays[i]); - } - for (var i = 0; i < 8; i++) { - getBay("cargoShip", i).attr("data-value", score.CargoBays[i]); + $("#exitedInitiationLine" + i1 + ">.value").text(score.ExitedInitiationLine[i] ? "Yes" : "No"); + $("#exitedInitiationLine" + i1).attr("data-value", score.ExitedInitiationLine[i]); + $("#endgameStatus" + i1 + ">.value").text(getEndgameStatusText(score.EndgameStatuses[i])); + $("#endgameStatus" + i1).attr("data-value", score.EndgameStatuses[i]); + setGoalValue($("#autoCellsInner"), score.AutoCellsInner); + setGoalValue($("#autoCellsOuter"), score.AutoCellsOuter); + setGoalValue($("#autoCellsBottom"), score.AutoCellsBottom); + setGoalValue($("#teleopCellsInner"), score.TeleopCellsInner); + setGoalValue($("#teleopCellsOuter"), score.TeleopCellsOuter); + setGoalValue($("#teleopCellsBottom"), score.TeleopCellsBottom); } - if (matchStates[data.MatchState] === "PRE_MATCH") { - if (realtimeScore.IsPreMatchScoreReady) { - $("#preMatchMessage").hide(); - } else { - $("#preMatchMessage").css("display", "flex"); - } + if (score.ControlPanelStatus >= 1) { + $("#rotationControl>.value").text("Yes"); + $("#rotationControl").attr("data-value", true); + } else if (summary.StagePowerCellsRemaining[1] === 0) { + $("#rotationControl>.value").text("Unlocked"); + $("#rotationControl").attr("data-value", false); + } else { + $("#rotationControl>.value").text("Disabled (" + summary.StagePowerCellsRemaining[1] + " left)"); + $("#rotationControl").attr("data-value", "disabled"); } + if (score.ControlPanelStatus === 2) { + $("#positionControl>.value").text("Yes"); + $("#positionControl").attr("data-value", true); + } else if (summary.StagePowerCellsRemaining[2] === 0) { + $("#positionControl>.value").text("Unlocked"); + $("#positionControl").attr("data-value", false); + } else { + $("#positionControl>.value").text("Disabled (" + summary.StagePowerCellsRemaining[2] + " left)"); + $("#positionControl").attr("data-value", "disabled"); + } + $("#rungIsLevel>.value").text(score.RungIsLevel ? "Yes" : "No"); + $("#rungIsLevel").attr("data-value", score.RungIsLevel); }; // Handles a websocket message to update the match status. @@ -93,42 +106,30 @@ var commitMatchScore = function() { $("#commitMatchScore").hide(); }; -// Returns the display text corresponding to the given integer start level value. -var getRobotStartLevelText = function(level) { +// Returns the display text corresponding to the given integer endgame status value. +var getEndgameStatusText = function(level) { switch (level) { case 1: - return "1"; + return "Park"; case 2: - return "2"; - case 3: - return "No-Show"; + return "Hang"; default: - return " "; + return "None"; } }; -// Returns the display text corresponding to the given integer end level value. -var getRobotEndLevelText = function(level) { - switch (level) { - case 1: - return "1"; - case 2: - return "2"; - case 3: - return "3"; - default: - return "Not On"; - } +// Updates the power cell count for a goal, given the element and score values. +var setGoalValue = function(element, powerCells) { + var total = 0; + $.each(powerCells, function(k, v) { + total += v; + }); + element.text(total); }; -// Returns the bay element matching the given parameters. -var getBay = function(type, index) { - return $("#bay" + bayMappings[type][index]); -} - $(function() { alliance = window.location.href.split("/").slice(-1)[0]; - $(".alliance-color").attr("data-alliance", alliance); + $("#alliance").attr("data-alliance", alliance); // Set up the websocket back to the server. websocket = new CheesyWebsocket("/panels/scoring/" + alliance + "/websocket", { diff --git a/templates/scoring_panel.html b/templates/scoring_panel.html index a436b87..f5728ae 100644 --- a/templates/scoring_panel.html +++ b/templates/scoring_panel.html @@ -7,74 +7,85 @@ {{define "title"}}Scoring Panel{{end}} {{define "body"}}
 
-
-
-
 
-
Start Hab Level
-
Sandstorm Bonus?
-
End Hab Level
+
+
+
+
 
+
Exited Initiation Line?
+
Endgame Status
+
+ {{range $i := seq 3}} +
+
+
+
{{$i}}
+
+
+
+
+
{{add $i 3}}
+
+
+
+
+ {{end}}
- {{range $i := seq 3}} -
-
-
-
{{$i}}
-
-
+ {{if eq .EventSettings.PlcAddress ""}} +
+
+
+
 
+
Inner
+
Outer
+
Lower
+
+
+
Auto
+ {{template "goal" dict "period" "auto" "level" "Inner" "plus" "W" "minus" "Q"}} + {{template "goal" dict "period" "auto" "level" "Outer" "plus" "S" "minus" "A"}} + {{template "goal" dict "period" "auto" "level" "Bottom" "plus" "X" "minus" "Z"}} +
+
+
Teleop
+ {{template "goal" dict "period" "teleop" "level" "Inner" "plus" "R" "minus" "E"}} + {{template "goal" dict "period" "teleop" "level" "Outer" "plus" "F" "minus" "D"}} + {{template "goal" dict "period" "teleop" "level" "Bottom" "plus" "V" "minus" "C"}} +
-
-
{{add $i 3}}
-
-
-
-
-
{{add $i 6}}
-
-
+
+
+
Rotation Control
+
Position Control
+
Rung Is Level
+
+
+
+
O
+
+
+
+
+
P
+
+
+
+
+
L
+
+
+
+
{{end}}
-
-
-
-
{{template "rocketHalf" dict "startBayId" 0 "vars" $}}
-
{{template "rocketHalf" dict "startBayId" 3 "vars" $}}
-
-
-
-
-
-
- {{template "bay" dict "id" 6 "vars" $}}{{template "bay" dict "id" 13 "vars" $}} -
-
- {{template "bay" dict "id" 7 "vars" $}}{{template "bay" dict "id" 12 "vars" $}} -
-
- {{template "bay" dict "id" 8 "vars" $}}{{template "bay" dict "id" 11 "vars" $}} -
-
- {{template "bay" dict "id" 9 "vars" $}}{{template "bay" dict "id" 10 "vars" $}} -
-
-
-
Click or use the labeled keyboard shortcuts to toggle each element
-
Set pre-match state of robots and cargo ship
-
- -
-
Waiting for the next match...
-
-
-
-
{{template "rocketHalf" dict "startBayId" 14 "vars" $}}
-
{{template "rocketHalf" dict "startBayId" 17 "vars" $}}
-
-
+
Click or use the labeled keyboard shortcuts to toggle each element
+
+
+
Waiting for the next match...
{{end}} {{define "head"}} @@ -82,27 +93,15 @@ {{define "script"}} - {{end}} -{{define "rocketHalf"}} - {{template "bay" dict "id" .startBayId "vars" .vars}} - {{template "bay" dict "id" (add .startBayId 1) "vars" .vars}} - {{template "bay" dict "id" (add .startBayId 2) "vars" .vars}} -{{end}} -{{define "bay"}} -
-
{{(index .vars.BayMappings .id).Shortcut}}
-
-
+{{define "goal"}} +
+
+
{{.minus}}
-
{{.minus}}
+
+
+
{{.plus}}
+
{{.plus}}
+
+
{{end}} diff --git a/web/scoring_panel.go b/web/scoring_panel.go index 7f860b0..37315d5 100644 --- a/web/scoring_panel.go +++ b/web/scoring_panel.go @@ -8,6 +8,7 @@ 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" @@ -15,41 +16,9 @@ import ( "log" "net/http" "strconv" + "strings" ) -// Maps a numbered bay on the scoring panel to the field that it represents in the Score model. -type bayMapping struct { - BayId int - Shortcut string - RedElement string - RedIndex int - BlueElement string - BlueIndex int -} - -var bayMappings = []*bayMapping{ - {0, "q", "rocketNearRight", 2, "rocketFarRight", 2}, - {1, "a", "rocketNearRight", 1, "rocketFarRight", 1}, - {2, "z", "rocketNearRight", 0, "rocketFarRight", 0}, - {3, "w", "rocketNearLeft", 2, "rocketFarLeft", 2}, - {4, "s", "rocketNearLeft", 1, "rocketFarLeft", 1}, - {5, "x", "rocketNearLeft", 0, "rocketFarLeft", 0}, - {6, "e", "cargoShip", 0, "cargoShip", 7}, - {7, "d", "cargoShip", 1, "cargoShip", 6}, - {8, "c", "cargoShip", 2, "cargoShip", 5}, - {9, "v", "cargoShip", 3, "cargoShip", 4}, - {10, "b", "cargoShip", 4, "cargoShip", 3}, - {11, "n", "cargoShip", 5, "cargoShip", 2}, - {12, "j", "cargoShip", 6, "cargoShip", 1}, - {13, "i", "cargoShip", 7, "cargoShip", 0}, - {14, "o", "rocketFarRight", 2, "rocketNearRight", 2}, - {15, "k", "rocketFarRight", 1, "rocketNearRight", 1}, - {16, "m", "rocketFarRight", 0, "rocketNearRight", 0}, - {17, "p", "rocketFarLeft", 2, "rocketNearLeft", 2}, - {18, "l", "rocketFarLeft", 1, "rocketNearLeft", 1}, - {19, ",", "rocketFarLeft", 0, "rocketNearLeft", 0}, -} - // Renders the scoring interface which enables input of scores in real-time. func (web *Web) scoringPanelHandler(w http.ResponseWriter, r *http.Request) { if !web.userIsAdmin(w, r) { @@ -70,9 +39,8 @@ func (web *Web) scoringPanelHandler(w http.ResponseWriter, r *http.Request) { } data := struct { *model.EventSettings - Alliance string - BayMappings []*bayMapping - }{web.arena.EventSettings, alliance, bayMappings} + Alliance string + }{web.arena.EventSettings, alliance} err = template.ExecuteTemplate(w, "base_no_navbar", data) if err != nil { handleWebErr(w, err) @@ -92,15 +60,13 @@ func (web *Web) scoringPanelWebsocketHandler(w http.ResponseWriter, r *http.Requ handleWebErr(w, fmt.Errorf("Invalid alliance '%s'.", alliance)) return } - // TODO(pat): Update for 2020. - /* - var realtimeScore **field.RealtimeScore - if alliance == "red" { - realtimeScore = &web.arena.RedRealtimeScore - } else { - realtimeScore = &web.arena.BlueRealtimeScore - } - */ + + 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 { @@ -129,8 +95,7 @@ func (web *Web) scoringPanelWebsocketHandler(w http.ResponseWriter, r *http.Requ return } - // TODO(pat): Update for 2020. - //score := &(*realtimeScore).CurrentScore + score := &(*realtimeScore).CurrentScore scoreChanged := false if command == "commitMatch" { @@ -141,62 +106,99 @@ 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 { - // 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 - } - */ - } else { - // Handle cargo bays. - var bayMapping *bayMapping - for _, mapping := range bayMappings { - if mapping.Shortcut == command { - bayMapping = mapping - break + } else if number, err := strconv.Atoi(command); err == nil && number >= 1 && number <= 6 { + // Handle per-robot scoring fields. + if number <= 3 { + index := number - 1 + score.ExitedInitiationLine[index] = !score.ExitedInitiationLine[index] + scoreChanged = true + } else { + index := number - 4 + score.EndgameStatuses[index]++ + if score.EndgameStatuses[index] == 3 { + score.EndgameStatuses[index] = 0 } + scoreChanged = true } - if bayMapping != nil { - // 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]) - } - */ + } else { + switch strings.ToUpper(command) { + case "Q": + if decrementGoal(score.AutoCellsInner[:], + score.CellCountingStage(web.arena.MatchState >= field.TeleopPeriod)) { + scoreChanged = true + } + case "A": + if decrementGoal(score.AutoCellsOuter[:], + score.CellCountingStage(web.arena.MatchState >= field.TeleopPeriod)) { + scoreChanged = true + } + case "Z": + if decrementGoal(score.AutoCellsBottom[:], + score.CellCountingStage(web.arena.MatchState >= field.TeleopPeriod)) { + scoreChanged = true + } + case "W": + if incrementGoal(score.AutoCellsInner[:], + score.CellCountingStage(web.arena.MatchState >= field.TeleopPeriod)) { + scoreChanged = true + } + case "S": + if incrementGoal(score.AutoCellsOuter[:], + score.CellCountingStage(web.arena.MatchState >= field.TeleopPeriod)) { + scoreChanged = true + } + case "X": + if incrementGoal(score.AutoCellsBottom[:], + score.CellCountingStage(web.arena.MatchState >= field.TeleopPeriod)) { + scoreChanged = true + } + case "E": + if decrementGoal(score.TeleopCellsInner[:], + score.CellCountingStage(web.arena.MatchState >= field.TeleopPeriod)) { + scoreChanged = true + } + case "D": + if decrementGoal(score.TeleopCellsOuter[:], + score.CellCountingStage(web.arena.MatchState >= field.TeleopPeriod)) { + scoreChanged = true + } + case "C": + if decrementGoal(score.TeleopCellsBottom[:], + score.CellCountingStage(web.arena.MatchState >= field.TeleopPeriod)) { + scoreChanged = true + } + case "R": + if incrementGoal(score.TeleopCellsInner[:], + score.CellCountingStage(web.arena.MatchState >= field.TeleopPeriod)) { + scoreChanged = true + } + case "F": + if incrementGoal(score.TeleopCellsOuter[:], + score.CellCountingStage(web.arena.MatchState >= field.TeleopPeriod)) { + scoreChanged = true + } + case "V": + if incrementGoal(score.TeleopCellsBottom[:], + score.CellCountingStage(web.arena.MatchState >= field.TeleopPeriod)) { + scoreChanged = true + } + case "O": + if score.ControlPanelStatus >= game.ControlPanelRotation { + score.ControlPanelStatus = game.ControlPanelNone + } else if score.StageAtCapacity(game.Stage2, true) { + score.ControlPanelStatus = game.ControlPanelRotation + } + scoreChanged = true + case "P": + if score.ControlPanelStatus == game.ControlPanelPosition { + score.ControlPanelStatus = game.ControlPanelRotation + } else if score.StageAtCapacity(game.Stage3, true) { + score.ControlPanelStatus = game.ControlPanelPosition + } + scoreChanged = true + case "L": + score.RungIsLevel = !score.RungIsLevel + scoreChanged = true } } @@ -206,48 +208,20 @@ func (web *Web) scoringPanelWebsocketHandler(w http.ResponseWriter, r *http.Requ } } -// 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 { - // Only the side bays can be preloaded. - return false - } - - if web.arena.MatchState == field.PreMatch { - *bay++ - if *bay == game.BayHatchCargo { - // Skip the hatch+cargo state pre-match as it is invalid. - *bay = game.BayCargo - } else if *bay > game.BayCargo { - *bay = game.BayEmpty - } - } else { - if *bay == game.BayCargo { - // If the bay was pre-loaded with cargo, go immediately to hatch+cargo during first toggle. - *bay = game.BayHatchCargo - } else { - *bay++ - if *bay == game.BayCargo { - // Skip the cargo-only state during the match as it can't stay in on its own. - *bay = game.BayEmpty - } - } - } - return true -} - -// Advances the given rocket bay through the states applicable to the current status of the field. -func (web *Web) toggleRocketBay(bay *game.BayStatus) bool { - if web.arena.MatchState != field.PreMatch { - *bay++ - if *bay == game.BayCargo { - // Skip the cargo-only state as it's not applicable to rocket bays. - *bay = game.BayEmpty - } +// Increments the power cell count for the given goal, if the preconditions are met. +func incrementGoal(goal []int, currentStage game.Stage) bool { + if int(currentStage) < len(goal) { + goal[currentStage]++ + return true + } + return false +} + +// Decrements the power cell count for the given goal, if the preconditions are met. +func decrementGoal(goal []int, currentStage game.Stage) bool { + if int(currentStage) < len(goal) && goal[currentStage] > 0 { + goal[currentStage]-- return true } return false } -*/ diff --git a/web/web.go b/web/web.go index eb9982e..7b145a6 100644 --- a/web/web.go +++ b/web/web.go @@ -189,6 +189,7 @@ func (web *Web) newHandler() http.Handler { // Writes the given error out as plain text with a status code of 500. func handleWebErr(w http.ResponseWriter, err error) { + log.Printf("HTTP request error: %v", err) http.Error(w, "Internal server error: "+err.Error(), 500) }