From 7c7b90f8cc4d0408713211af38eda08cd8fc560d Mon Sep 17 00:00:00 2001 From: Patrick Fairbank Date: Sun, 29 Mar 2020 18:40:11 -0700 Subject: [PATCH] Refactor event status to include cycle time calculation. --- field/arena.go | 73 +----------------- field/arena_notifiers.go | 2 +- field/arena_test.go | 97 ------------------------ field/event_status.go | 107 +++++++++++++++++++++++++++ field/event_status_test.go | 126 ++++++++++++++++++++++++++++++++ static/css/pit_display.css | 2 +- static/css/queueing_display.css | 2 +- static/js/match_play.js | 7 +- static/js/pit_display.js | 2 +- static/js/queueing_display.js | 2 +- templates/match_play.html | 4 +- templates/pit_display.html | 2 +- templates/queueing_display.html | 2 +- web/match_play_test.go | 5 +- 14 files changed, 256 insertions(+), 177 deletions(-) create mode 100644 field/event_status.go create mode 100644 field/event_status_test.go diff --git a/field/arena.go b/field/arena.go index 3978928..fd88c03 100644 --- a/field/arena.go +++ b/field/arena.go @@ -13,7 +13,6 @@ import ( "github.com/Team254/cheesy-arena/partner" "github.com/Team254/cheesy-arena/plc" "log" - "math" "time" ) @@ -64,7 +63,7 @@ type Arena struct { BlueRealtimeScore *RealtimeScore lastDsPacketTime time.Time lastPeriodicTaskTime time.Time - EventStatusMessage string + EventStatus EventStatus FieldVolunteers bool FieldReset bool AudienceDisplayMode string @@ -289,6 +288,7 @@ func (arena *Arena) StartMatch() error { if arena.CurrentMatch.Type != "test" { arena.Database.SaveMatch(arena.CurrentMatch) } + arena.updateCycleTime(arena.CurrentMatch.StartedAt) // Save the missed packet count to subtract it from the running count. for _, allianceStation := range arena.AllianceStations { @@ -867,73 +867,6 @@ func (arena *Arena) alliancePostMatchScoreReady(alliance string) bool { // Performs any actions that need to run at the interval specified by periodicTaskPeriodSec. func (arena *Arena) runPeriodicTasks() { - // Check how early or late the event is running and publish an update to the displays that show it. - newEventStatusMessage := arena.getEventStatusMessage() - if newEventStatusMessage != arena.EventStatusMessage { - arena.EventStatusMessage = newEventStatusMessage - arena.EventStatusNotifier.Notify() - } - - // Clean up the list of displays. + arena.updateEarlyLateMessage() arena.purgeDisconnectedDisplays() } - -// Updates the string that indicates how early or late the event is running. -func (arena *Arena) getEventStatusMessage() string { - currentMatch := arena.CurrentMatch - if currentMatch.Type != "practice" && currentMatch.Type != "qualification" { - // Only practice and qualification matches have a strict schedule. - return "" - } - if currentMatch.IsComplete() { - // This is a replay or otherwise unpredictable situation. - return "" - } - - var minutesLate float64 - if arena.MatchState > PreMatch && arena.MatchState < PostMatch { - // The match is in progress; simply calculate lateness from its start time. - minutesLate = currentMatch.StartedAt.Sub(currentMatch.Time).Minutes() - } else { - // We need to check the adjacent matches to accurately determine lateness. - matches, _ := arena.Database.GetMatchesByType(currentMatch.Type) - - previousMatchIndex := -1 - nextMatchIndex := len(matches) - for i, match := range matches { - if match.Id == currentMatch.Id { - previousMatchIndex = i - 1 - nextMatchIndex = i + 1 - break - } - } - - if arena.MatchState == PreMatch { - currentMinutesLate := time.Now().Sub(currentMatch.Time).Minutes() - if previousMatchIndex >= 0 && - currentMatch.Time.Sub(matches[previousMatchIndex].Time).Minutes() <= MaxMatchGapMin { - previousMatch := matches[previousMatchIndex] - previousMinutesLate := previousMatch.StartedAt.Sub(previousMatch.Time).Minutes() - minutesLate = math.Max(previousMinutesLate, currentMinutesLate) - } else { - minutesLate = math.Max(currentMinutesLate, 0) - } - } else if arena.MatchState == PostMatch { - currentMinutesLate := currentMatch.StartedAt.Sub(currentMatch.Time).Minutes() - if nextMatchIndex < len(matches) { - nextMatch := matches[nextMatchIndex] - nextMinutesLate := time.Now().Sub(nextMatch.Time).Minutes() - minutesLate = math.Max(currentMinutesLate, nextMinutesLate) - } else { - minutesLate = currentMinutesLate - } - } - } - - if minutesLate > earlyLateThresholdMin { - return fmt.Sprintf("Event is running %d minutes late", int(minutesLate)) - } else if minutesLate < -earlyLateThresholdMin { - return fmt.Sprintf("Event is running %d minutes early", int(-minutesLate)) - } - return "Event is running on schedule" -} diff --git a/field/arena_notifiers.go b/field/arena_notifiers.go index 5e530bb..950954f 100644 --- a/field/arena_notifiers.go +++ b/field/arena_notifiers.go @@ -113,7 +113,7 @@ func (arena *Arena) generateDisplayConfigurationMessage() interface{} { } func (arena *Arena) generateEventStatusMessage() interface{} { - return arena.EventStatusMessage + return arena.EventStatus } func (arena *Arena) generateLowerThirdMessage() interface{} { diff --git a/field/arena_test.go b/field/arena_test.go index 59c45d9..1567b8c 100644 --- a/field/arena_test.go +++ b/field/arena_test.go @@ -644,100 +644,3 @@ func TestSaveTeamHasConnected(t *testing.T) { assert.Equal(t, "San Jose", teams[5].City) } } - -func TestEventStatusMessage(t *testing.T) { - arena := setupTestArena(t) - - arena.LoadTestMatch() - assert.Equal(t, "", arena.getEventStatusMessage()) - - arena.Database.CreateMatch(&model.Match{Type: "qualification", DisplayName: "1"}) - arena.Database.CreateMatch(&model.Match{Type: "qualification", DisplayName: "2"}) - matches, _ := arena.Database.GetMatchesByType("qualification") - assert.Equal(t, 2, len(matches)) - - setMatch(arena.Database, &matches[0], time.Now().Add(300*time.Second), time.Time{}, false) - arena.CurrentMatch = &matches[0] - arena.MatchState = PreMatch - assert.Equal(t, "Event is running on schedule", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[0], time.Now().Add(60*time.Second), time.Time{}, false) - assert.Equal(t, "Event is running on schedule", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[0], time.Now().Add(-60*time.Second), time.Time{}, false) - assert.Equal(t, "Event is running on schedule", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[0], time.Now().Add(-120*time.Second), time.Time{}, false) - assert.Equal(t, "Event is running on schedule", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[0], time.Now().Add(-180*time.Second), time.Time{}, false) - assert.Equal(t, "Event is running 3 minutes late", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[0], time.Now().Add(181*time.Second), time.Now(), false) - arena.MatchState = AutoPeriod - assert.Equal(t, "Event is running 3 minutes early", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[0], time.Now().Add(-300*time.Second), time.Now().Add(-601*time.Second), false) - setMatch(arena.Database, &matches[1], time.Now().Add(481*time.Second), time.Time{}, false) - arena.MatchState = PostMatch - assert.Equal(t, "Event is running 5 minutes early", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[1], time.Now().Add(181*time.Second), time.Time{}, false) - assert.Equal(t, "Event is running 3 minutes early", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[1], time.Now().Add(-60*time.Second), time.Time{}, false) - assert.Equal(t, "Event is running on schedule", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[1], time.Now().Add(-180*time.Second), time.Time{}, false) - assert.Equal(t, "Event is running 3 minutes late", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[0], time.Now().Add(-300*time.Second), time.Now().Add(-601*time.Second), true) - assert.Equal(t, "", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[1], time.Now().Add(900*time.Second), time.Time{}, false) - arena.CurrentMatch = &matches[1] - arena.MatchState = PreMatch - assert.Equal(t, "Event is running on schedule", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[1], time.Now().Add(899*time.Second), time.Time{}, false) - assert.Equal(t, "Event is running 5 minutes early", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[1], time.Now().Add(60*time.Second), time.Time{}, false) - assert.Equal(t, "Event is running on schedule", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[1], time.Now().Add(-120*time.Second), time.Time{}, false) - assert.Equal(t, "Event is running on schedule", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[1], time.Now().Add(-180*time.Second), time.Time{}, false) - assert.Equal(t, "Event is running 3 minutes late", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[1], time.Now().Add(-180*time.Second), time.Now().Add(-541*time.Second), false) - arena.MatchState = TeleopPeriod - assert.Equal(t, "Event is running 6 minutes early", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[1], time.Now(), time.Now().Add(481*time.Second), false) - arena.MatchState = PostMatch - assert.Equal(t, "Event is running 8 minutes late", arena.getEventStatusMessage()) - - setMatch(arena.Database, &matches[1], time.Now(), time.Now().Add(481*time.Second), true) - assert.Equal(t, "", arena.getEventStatusMessage()) - - // Check other match types. - arena.MatchState = PreMatch - arena.CurrentMatch = &model.Match{Type: "practice", Time: time.Now().Add(-181 * time.Second)} - assert.Equal(t, "Event is running 3 minutes late", arena.getEventStatusMessage()) - - arena.CurrentMatch = &model.Match{Type: "elimination", Time: time.Now().Add(-181 * time.Second)} - assert.Equal(t, "", arena.getEventStatusMessage()) -} - -func setMatch(database *model.Database, match *model.Match, matchTime time.Time, startedAt time.Time, isComplete bool) { - match.Time = matchTime - match.StartedAt = startedAt - if isComplete { - match.Status = model.TieMatch - } else { - match.Status = model.MatchNotPlayed - } - _ = database.SaveMatch(match) -} diff --git a/field/event_status.go b/field/event_status.go new file mode 100644 index 0000000..78cdfcf --- /dev/null +++ b/field/event_status.go @@ -0,0 +1,107 @@ +// Copyright 2020 Team 254. All Rights Reserved. +// Author: pat@patfairbank.com (Patrick Fairbank) +// +// Model and functions for reporting on event status. + +package field + +import ( + "fmt" + "math" + "time" +) + +type EventStatus struct { + CycleTime string + EarlyLateMessage string + lastMatchStartTime time.Time +} + +// Calculates the last cycle time and publishes an update to the displays that show it. +func (arena *Arena) updateCycleTime(matchStartTime time.Time) { + if arena.EventStatus.lastMatchStartTime.IsZero() { + // We don't know when the previous match was started. + arena.EventStatus.CycleTime = "" + } else { + cycleTimeSec := int(matchStartTime.Sub(arena.EventStatus.lastMatchStartTime).Seconds()) + hours := cycleTimeSec / 3600 + minutes := cycleTimeSec % 3600 / 60 + seconds := cycleTimeSec % 60 + if hours > 0 { + arena.EventStatus.CycleTime = fmt.Sprintf("%d:%02d:%02d", hours, minutes, seconds) + } else { + arena.EventStatus.CycleTime = fmt.Sprintf("%d:%02d", minutes, seconds) + } + } + arena.EventStatus.lastMatchStartTime = matchStartTime + arena.EventStatusNotifier.Notify() +} + +// Checks how early or late the event is running and publishes an update to the displays that show it. +func (arena *Arena) updateEarlyLateMessage() { + newEarlyLateMessage := arena.getEarlyLateMessage() + if newEarlyLateMessage != arena.EventStatus.EarlyLateMessage { + arena.EventStatus.EarlyLateMessage = newEarlyLateMessage + arena.EventStatusNotifier.Notify() + } +} + +// Updates the string that indicates how early or late the event is running. +func (arena *Arena) getEarlyLateMessage() string { + currentMatch := arena.CurrentMatch + if currentMatch.Type != "practice" && currentMatch.Type != "qualification" { + // Only practice and qualification matches have a strict schedule. + return "" + } + if currentMatch.IsComplete() { + // This is a replay or otherwise unpredictable situation. + return "" + } + + var minutesLate float64 + if arena.MatchState > PreMatch && arena.MatchState < PostMatch { + // The match is in progress; simply calculate lateness from its start time. + minutesLate = currentMatch.StartedAt.Sub(currentMatch.Time).Minutes() + } else { + // We need to check the adjacent matches to accurately determine lateness. + matches, _ := arena.Database.GetMatchesByType(currentMatch.Type) + + previousMatchIndex := -1 + nextMatchIndex := len(matches) + for i, match := range matches { + if match.Id == currentMatch.Id { + previousMatchIndex = i - 1 + nextMatchIndex = i + 1 + break + } + } + + if arena.MatchState == PreMatch { + currentMinutesLate := time.Now().Sub(currentMatch.Time).Minutes() + if previousMatchIndex >= 0 && + currentMatch.Time.Sub(matches[previousMatchIndex].Time).Minutes() <= MaxMatchGapMin { + previousMatch := matches[previousMatchIndex] + previousMinutesLate := previousMatch.StartedAt.Sub(previousMatch.Time).Minutes() + minutesLate = math.Max(previousMinutesLate, currentMinutesLate) + } else { + minutesLate = math.Max(currentMinutesLate, 0) + } + } else if arena.MatchState == PostMatch { + currentMinutesLate := currentMatch.StartedAt.Sub(currentMatch.Time).Minutes() + if nextMatchIndex < len(matches) { + nextMatch := matches[nextMatchIndex] + nextMinutesLate := time.Now().Sub(nextMatch.Time).Minutes() + minutesLate = math.Max(currentMinutesLate, nextMinutesLate) + } else { + minutesLate = currentMinutesLate + } + } + } + + if minutesLate > earlyLateThresholdMin { + return fmt.Sprintf("Event is running %d minutes late", int(minutesLate)) + } else if minutesLate < -earlyLateThresholdMin { + return fmt.Sprintf("Event is running %d minutes early", int(-minutesLate)) + } + return "Event is running on schedule" +} diff --git a/field/event_status_test.go b/field/event_status_test.go new file mode 100644 index 0000000..a8e3f57 --- /dev/null +++ b/field/event_status_test.go @@ -0,0 +1,126 @@ +// Copyright 2020 Team 254. All Rights Reserved. +// Author: pat@patfairbank.com (Patrick Fairbank) + +package field + +import ( + "github.com/Team254/cheesy-arena/model" + "github.com/stretchr/testify/assert" + "testing" + "time" +) + +func TestCycleTime(t *testing.T) { + arena := setupTestArena(t) + + assert.Equal(t, "", arena.EventStatus.CycleTime) + arena.updateCycleTime(time.Time{}) + assert.Equal(t, "", arena.EventStatus.CycleTime) + arena.updateCycleTime(time.Now().Add(-125 * time.Second)) + assert.Equal(t, "", arena.EventStatus.CycleTime) + arena.updateCycleTime(time.Now()) + assert.Equal(t, "2:05", arena.EventStatus.CycleTime) + arena.updateCycleTime(time.Now().Add(3456 * time.Second)) + assert.Equal(t, "57:36", arena.EventStatus.CycleTime) + arena.updateCycleTime(time.Now().Add(5 * time.Hour)) + assert.Equal(t, "4:02:24", arena.EventStatus.CycleTime) + arena.updateCycleTime(time.Now().Add(123*time.Hour + 1256*time.Second)) + assert.Equal(t, "118:20:56", arena.EventStatus.CycleTime) +} + +func TestEarlyLateMessage(t *testing.T) { + arena := setupTestArena(t) + + arena.LoadTestMatch() + assert.Equal(t, "", arena.getEarlyLateMessage()) + + arena.Database.CreateMatch(&model.Match{Type: "qualification", DisplayName: "1"}) + arena.Database.CreateMatch(&model.Match{Type: "qualification", DisplayName: "2"}) + matches, _ := arena.Database.GetMatchesByType("qualification") + assert.Equal(t, 2, len(matches)) + + setMatch(arena.Database, &matches[0], time.Now().Add(300*time.Second), time.Time{}, false) + arena.CurrentMatch = &matches[0] + arena.MatchState = PreMatch + assert.Equal(t, "Event is running on schedule", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[0], time.Now().Add(60*time.Second), time.Time{}, false) + assert.Equal(t, "Event is running on schedule", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[0], time.Now().Add(-60*time.Second), time.Time{}, false) + assert.Equal(t, "Event is running on schedule", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[0], time.Now().Add(-120*time.Second), time.Time{}, false) + assert.Equal(t, "Event is running on schedule", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[0], time.Now().Add(-180*time.Second), time.Time{}, false) + assert.Equal(t, "Event is running 3 minutes late", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[0], time.Now().Add(181*time.Second), time.Now(), false) + arena.MatchState = AutoPeriod + assert.Equal(t, "Event is running 3 minutes early", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[0], time.Now().Add(-300*time.Second), time.Now().Add(-601*time.Second), false) + setMatch(arena.Database, &matches[1], time.Now().Add(481*time.Second), time.Time{}, false) + arena.MatchState = PostMatch + assert.Equal(t, "Event is running 5 minutes early", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[1], time.Now().Add(181*time.Second), time.Time{}, false) + assert.Equal(t, "Event is running 3 minutes early", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[1], time.Now().Add(-60*time.Second), time.Time{}, false) + assert.Equal(t, "Event is running on schedule", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[1], time.Now().Add(-180*time.Second), time.Time{}, false) + assert.Equal(t, "Event is running 3 minutes late", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[0], time.Now().Add(-300*time.Second), time.Now().Add(-601*time.Second), true) + assert.Equal(t, "", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[1], time.Now().Add(900*time.Second), time.Time{}, false) + arena.CurrentMatch = &matches[1] + arena.MatchState = PreMatch + assert.Equal(t, "Event is running on schedule", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[1], time.Now().Add(899*time.Second), time.Time{}, false) + assert.Equal(t, "Event is running 5 minutes early", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[1], time.Now().Add(60*time.Second), time.Time{}, false) + assert.Equal(t, "Event is running on schedule", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[1], time.Now().Add(-120*time.Second), time.Time{}, false) + assert.Equal(t, "Event is running on schedule", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[1], time.Now().Add(-180*time.Second), time.Time{}, false) + assert.Equal(t, "Event is running 3 minutes late", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[1], time.Now().Add(-180*time.Second), time.Now().Add(-541*time.Second), false) + arena.MatchState = TeleopPeriod + assert.Equal(t, "Event is running 6 minutes early", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[1], time.Now(), time.Now().Add(481*time.Second), false) + arena.MatchState = PostMatch + assert.Equal(t, "Event is running 8 minutes late", arena.getEarlyLateMessage()) + + setMatch(arena.Database, &matches[1], time.Now(), time.Now().Add(481*time.Second), true) + assert.Equal(t, "", arena.getEarlyLateMessage()) + + // Check other match types. + arena.MatchState = PreMatch + arena.CurrentMatch = &model.Match{Type: "practice", Time: time.Now().Add(-181 * time.Second)} + assert.Equal(t, "Event is running 3 minutes late", arena.getEarlyLateMessage()) + + arena.CurrentMatch = &model.Match{Type: "elimination", Time: time.Now().Add(-181 * time.Second)} + assert.Equal(t, "", arena.getEarlyLateMessage()) +} + +func setMatch(database *model.Database, match *model.Match, matchTime time.Time, startedAt time.Time, isComplete bool) { + match.Time = matchTime + match.StartedAt = startedAt + if isComplete { + match.Status = model.TieMatch + } else { + match.Status = model.MatchNotPlayed + } + _ = database.SaveMatch(match) +} diff --git a/static/css/pit_display.css b/static/css/pit_display.css index 1ea5e02..8c163ac 100644 --- a/static/css/pit_display.css +++ b/static/css/pit_display.css @@ -75,7 +75,7 @@ body { padding-left: 0; padding-right: 0; } -#eventStatusMessage { +#earlyLateMessage { margin-top: 10px; font-size: 25px; font-family: "FuturaLTBold"; diff --git a/static/css/queueing_display.css b/static/css/queueing_display.css index eb03139..4153e67 100644 --- a/static/css/queueing_display.css +++ b/static/css/queueing_display.css @@ -54,7 +54,7 @@ h1 { .avatars { line-height: 51px; } -#eventStatusMessage { +#earlyLateMessage { font-size: 25px; font-family: "FuturaLTBold"; color: #fff; diff --git a/static/js/match_play.js b/static/js/match_play.js index 38d487c..ff4f36e 100644 --- a/static/js/match_play.js +++ b/static/js/match_play.js @@ -227,7 +227,12 @@ var handleAllianceStationDisplayMode = function(data) { // Handles a websocket message to update the event status message. var handleEventStatus = function(data) { - $("#eventStatusMessage").text(data); + if (data.CycleTime === "") { + $("#cycleTimeMessage").text("Last cycle time: Unknown"); + } else { + $("#cycleTimeMessage").text("Last cycle time: " + data.CycleTime); + } + $("#earlyLateMessage").text(data.EarlyLateMessage); }; $(function() { diff --git a/static/js/pit_display.js b/static/js/pit_display.js index 49398b5..f82bd49 100644 --- a/static/js/pit_display.js +++ b/static/js/pit_display.js @@ -81,7 +81,7 @@ var setHighestPlayedMatch = function(highestPlayedMatch) { // Handles a websocket message to update the event status message. var handleEventStatus = function(data) { - $("#eventStatusMessage").text(data); + $("#earlyLateMessage").text(data.EarlyLateMessage); }; $(function() { diff --git a/static/js/queueing_display.js b/static/js/queueing_display.js index 2bb95fb..0932be6 100644 --- a/static/js/queueing_display.js +++ b/static/js/queueing_display.js @@ -30,7 +30,7 @@ var handleMatchTime = function(data) { // Handles a websocket message to update the event status message. var handleEventStatus = function(data) { - $("#eventStatusMessage").text(data); + $("#earlyLateMessage").text(data.EarlyLateMessage); }; $(function() { diff --git a/templates/match_play.html b/templates/match_play.html index a9db9e5..f0d40a3 100644 --- a/templates/match_play.html +++ b/templates/match_play.html @@ -217,7 +217,9 @@
-
+
+
+
diff --git a/templates/pit_display.html b/templates/pit_display.html index c30f991..fe3fdc9 100644 --- a/templates/pit_display.html +++ b/templates/pit_display.html @@ -46,7 +46,7 @@ -
+
diff --git a/web/match_play_test.go b/web/match_play_test.go index f6c8db3..78acfce 100644 --- a/web/match_play_test.go +++ b/web/match_play_test.go @@ -299,6 +299,7 @@ func TestMatchPlayWebsocketCommands(t *testing.T) { web.arena.AllianceStations["B3"].Bypass = true ws.Write("startMatch", nil) readWebsocketType(t, ws, "arenaStatus") + readWebsocketType(t, ws, "eventStatus") assert.Equal(t, field.StartMatch, web.arena.MatchState) ws.Write("commitResults", nil) assert.Contains(t, readWebsocketError(t, ws), "Cannot reset match") @@ -359,13 +360,15 @@ func TestMatchPlayWebsocketNotifications(t *testing.T) { web.arena.AllianceStations["B3"].Bypass = true assert.Nil(t, web.arena.StartMatch()) web.arena.Update() - messages := readWebsocketMultiple(t, ws, 4) + messages := readWebsocketMultiple(t, ws, 5) _, ok := messages["matchTime"] assert.True(t, ok) _, ok = messages["audienceDisplayMode"] assert.True(t, ok) _, ok = messages["allianceStationDisplayMode"] assert.True(t, ok) + _, ok = messages["eventStatus"] + assert.True(t, ok) web.arena.MatchStartTime = time.Now().Add(-time.Duration(game.MatchTiming.WarmupDurationSec) * time.Second) web.arena.Update() messages = readWebsocketMultiple(t, ws, 2)