mirror of
https://github.com/Team254/cheesy-arena-lite.git
synced 2026-03-09 13:46:44 -04:00
Add FTA variant of field monitor with ability to save notes (closes #58).
This commit is contained in:
@@ -8,12 +8,19 @@ package web
|
||||
import (
|
||||
"github.com/Team254/cheesy-arena/model"
|
||||
"github.com/Team254/cheesy-arena/websocket"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Renders the field monitor display.
|
||||
func (web *Web) fieldMonitorDisplayHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if !web.enforceDisplayConfiguration(w, r, map[string]string{"reversed": "false"}) {
|
||||
if r.URL.Query().Get("fta") == "true" && !web.userIsAdmin(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
if !web.enforceDisplayConfiguration(w, r, map[string]string{"reversed": "false", "fta": "false"}) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -34,6 +41,11 @@ func (web *Web) fieldMonitorDisplayHandler(w http.ResponseWriter, r *http.Reques
|
||||
|
||||
// The websocket endpoint for the field monitor display client to receive status updates.
|
||||
func (web *Web) fieldMonitorDisplayWebsocketHandler(w http.ResponseWriter, r *http.Request) {
|
||||
isFta := r.URL.Query().Get("fta") == "true"
|
||||
if isFta && !web.userIsAdmin(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
display, err := web.registerDisplay(r)
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
@@ -48,7 +60,50 @@ func (web *Web) fieldMonitorDisplayWebsocketHandler(w http.ResponseWriter, r *ht
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
// Subscribe the websocket to the notifiers whose messages will be passed on to the client.
|
||||
ws.HandleNotifiers(display.Notifier, web.arena.ArenaStatusNotifier, web.arena.EventStatusNotifier,
|
||||
// Subscribe the websocket to the notifiers whose messages will be passed on to the client, in a separate goroutine.
|
||||
go ws.HandleNotifiers(display.Notifier, web.arena.ArenaStatusNotifier, web.arena.EventStatusNotifier,
|
||||
web.arena.ReloadDisplaysNotifier)
|
||||
|
||||
// Loop, waiting for commands and responding to them, until the client closes the connection.
|
||||
for {
|
||||
command, data, err := ws.Read()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
// Client has closed the connection; nothing to do here.
|
||||
return
|
||||
}
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if command == "updateTeamNotes" {
|
||||
if isFta {
|
||||
args := struct {
|
||||
Station string
|
||||
Notes string
|
||||
}{}
|
||||
err = mapstructure.Decode(data, &args)
|
||||
if err != nil {
|
||||
ws.WriteError(err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
if allianceStation, ok := web.arena.AllianceStations[args.Station]; ok {
|
||||
if allianceStation.Team != nil {
|
||||
allianceStation.Team.FtaNotes = args.Notes
|
||||
if err := web.arena.Database.SaveTeam(allianceStation.Team); err != nil {
|
||||
ws.WriteError(err.Error())
|
||||
}
|
||||
web.arena.ArenaStatusNotifier.Notify()
|
||||
} else {
|
||||
ws.WriteError("No team present")
|
||||
}
|
||||
} else {
|
||||
ws.WriteError("Invalid alliance station")
|
||||
}
|
||||
} else {
|
||||
ws.WriteError("Must be in FTA mode to update team notes")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,17 +13,19 @@ import (
|
||||
func TestFieldMonitorDisplay(t *testing.T) {
|
||||
web := setupTestWeb(t)
|
||||
|
||||
recorder := web.getHttpResponse("/displays/field_monitor?displayId=1&reversed=false")
|
||||
recorder := web.getHttpResponse("/displays/field_monitor?displayId=1&fta=true&reversed=false")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Contains(t, recorder.Body.String(), "Field Monitor - Untitled Event - Cheesy Arena")
|
||||
}
|
||||
|
||||
func TestFieldMonitorDisplayWebsocket(t *testing.T) {
|
||||
web := setupTestWeb(t)
|
||||
assert.Nil(t, web.arena.SubstituteTeam(254, "B1"))
|
||||
|
||||
server, wsUrl := web.startTestServer()
|
||||
defer server.Close()
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial(wsUrl+"/displays/field_monitor/websocket?displayId=1", nil)
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial(wsUrl+"/displays/field_monitor/websocket?displayId=1&fta=false",
|
||||
nil)
|
||||
assert.Nil(t, err)
|
||||
defer conn.Close()
|
||||
ws := websocket.NewTestWebsocket(conn)
|
||||
@@ -32,4 +34,38 @@ func TestFieldMonitorDisplayWebsocket(t *testing.T) {
|
||||
readWebsocketType(t, ws, "displayConfiguration")
|
||||
readWebsocketType(t, ws, "arenaStatus")
|
||||
readWebsocketType(t, ws, "eventStatus")
|
||||
|
||||
// Should not be able to update team notes.
|
||||
ws.Write("updateTeamNotes", map[string]interface{}{"station": "B1", "notes": "Bypassed in M1"})
|
||||
assert.Contains(t, readWebsocketError(t, ws), "Must be in FTA mode to update team notes")
|
||||
assert.Equal(t, "", web.arena.AllianceStations["B1"].Team.FtaNotes)
|
||||
}
|
||||
|
||||
func TestFieldMonitorFtaDisplayWebsocket(t *testing.T) {
|
||||
web := setupTestWeb(t)
|
||||
assert.Nil(t, web.arena.SubstituteTeam(254, "B1"))
|
||||
|
||||
server, wsUrl := web.startTestServer()
|
||||
defer server.Close()
|
||||
conn, _, err := gorillawebsocket.DefaultDialer.Dial(wsUrl+"/displays/field_monitor/websocket?displayId=1&fta=true",
|
||||
nil)
|
||||
assert.Nil(t, err)
|
||||
defer conn.Close()
|
||||
ws := websocket.NewTestWebsocket(conn)
|
||||
|
||||
// Should get a few status updates right after connection.
|
||||
readWebsocketType(t, ws, "displayConfiguration")
|
||||
readWebsocketType(t, ws, "arenaStatus")
|
||||
readWebsocketType(t, ws, "eventStatus")
|
||||
|
||||
// Should not be able to update team notes.
|
||||
ws.Write("updateTeamNotes", map[string]interface{}{"station": "B1", "notes": "Bypassed in M1"})
|
||||
readWebsocketType(t, ws, "arenaStatus")
|
||||
assert.Equal(t, "Bypassed in M1", web.arena.AllianceStations["B1"].Team.FtaNotes)
|
||||
|
||||
// Check error scenarios.
|
||||
ws.Write("updateTeamNotes", map[string]interface{}{"station": "N", "notes": "Bypassed in M2"})
|
||||
assert.Contains(t, readWebsocketError(t, ws), "Invalid alliance station")
|
||||
ws.Write("updateTeamNotes", map[string]interface{}{"station": "R3", "notes": "Bypassed in M3"})
|
||||
assert.Contains(t, readWebsocketError(t, ws), "No team present")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user