Refactor event status to include cycle time calculation.

This commit is contained in:
Patrick Fairbank
2020-03-29 18:40:11 -07:00
parent 6cef7112ae
commit 7c7b90f8cc
14 changed files with 256 additions and 177 deletions

View File

@@ -13,7 +13,6 @@ import (
"github.com/Team254/cheesy-arena/partner" "github.com/Team254/cheesy-arena/partner"
"github.com/Team254/cheesy-arena/plc" "github.com/Team254/cheesy-arena/plc"
"log" "log"
"math"
"time" "time"
) )
@@ -64,7 +63,7 @@ type Arena struct {
BlueRealtimeScore *RealtimeScore BlueRealtimeScore *RealtimeScore
lastDsPacketTime time.Time lastDsPacketTime time.Time
lastPeriodicTaskTime time.Time lastPeriodicTaskTime time.Time
EventStatusMessage string EventStatus EventStatus
FieldVolunteers bool FieldVolunteers bool
FieldReset bool FieldReset bool
AudienceDisplayMode string AudienceDisplayMode string
@@ -289,6 +288,7 @@ func (arena *Arena) StartMatch() error {
if arena.CurrentMatch.Type != "test" { if arena.CurrentMatch.Type != "test" {
arena.Database.SaveMatch(arena.CurrentMatch) arena.Database.SaveMatch(arena.CurrentMatch)
} }
arena.updateCycleTime(arena.CurrentMatch.StartedAt)
// Save the missed packet count to subtract it from the running count. // Save the missed packet count to subtract it from the running count.
for _, allianceStation := range arena.AllianceStations { 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. // Performs any actions that need to run at the interval specified by periodicTaskPeriodSec.
func (arena *Arena) runPeriodicTasks() { func (arena *Arena) runPeriodicTasks() {
// Check how early or late the event is running and publish an update to the displays that show it. arena.updateEarlyLateMessage()
newEventStatusMessage := arena.getEventStatusMessage()
if newEventStatusMessage != arena.EventStatusMessage {
arena.EventStatusMessage = newEventStatusMessage
arena.EventStatusNotifier.Notify()
}
// Clean up the list of displays.
arena.purgeDisconnectedDisplays() 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"
}

View File

@@ -113,7 +113,7 @@ func (arena *Arena) generateDisplayConfigurationMessage() interface{} {
} }
func (arena *Arena) generateEventStatusMessage() interface{} { func (arena *Arena) generateEventStatusMessage() interface{} {
return arena.EventStatusMessage return arena.EventStatus
} }
func (arena *Arena) generateLowerThirdMessage() interface{} { func (arena *Arena) generateLowerThirdMessage() interface{} {

View File

@@ -644,100 +644,3 @@ func TestSaveTeamHasConnected(t *testing.T) {
assert.Equal(t, "San Jose", teams[5].City) 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)
}

107
field/event_status.go Normal file
View File

@@ -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"
}

126
field/event_status_test.go Normal file
View File

@@ -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)
}

View File

@@ -75,7 +75,7 @@ body {
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
} }
#eventStatusMessage { #earlyLateMessage {
margin-top: 10px; margin-top: 10px;
font-size: 25px; font-size: 25px;
font-family: "FuturaLTBold"; font-family: "FuturaLTBold";

View File

@@ -54,7 +54,7 @@ h1 {
.avatars { .avatars {
line-height: 51px; line-height: 51px;
} }
#eventStatusMessage { #earlyLateMessage {
font-size: 25px; font-size: 25px;
font-family: "FuturaLTBold"; font-family: "FuturaLTBold";
color: #fff; color: #fff;

View File

@@ -227,7 +227,12 @@ var handleAllianceStationDisplayMode = function(data) {
// Handles a websocket message to update the event status message. // Handles a websocket message to update the event status message.
var handleEventStatus = function(data) { 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() { $(function() {

View File

@@ -81,7 +81,7 @@ var setHighestPlayedMatch = function(highestPlayedMatch) {
// Handles a websocket message to update the event status message. // Handles a websocket message to update the event status message.
var handleEventStatus = function(data) { var handleEventStatus = function(data) {
$("#eventStatusMessage").text(data); $("#earlyLateMessage").text(data.EarlyLateMessage);
}; };
$(function() { $(function() {

View File

@@ -30,7 +30,7 @@ var handleMatchTime = function(data) {
// Handles a websocket message to update the event status message. // Handles a websocket message to update the event status message.
var handleEventStatus = function(data) { var handleEventStatus = function(data) {
$("#eventStatusMessage").text(data); $("#earlyLateMessage").text(data.EarlyLateMessage);
}; };
$(function() { $(function() {

View File

@@ -217,7 +217,9 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div id="eventStatusMessage" class="col-lg-12"></div> <div id="cycleTimeMessage" class="col-lg-5 col-lg-offset-1"></div>
<div id="earlyLateMessage" class="col-lg-5 text-right"></div>
<div class="col-lg-1"></div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -46,7 +46,7 @@
<span id="highestPlayedMatch"></span> <span id="highestPlayedMatch"></span>
</div> </div>
</div> </div>
<div id="eventStatusMessage"></div> <div id="earlyLateMessage"></div>
</div> </div>
<script id="standingsTemplate" type="text/x-handlebars-template"> <script id="standingsTemplate" type="text/x-handlebars-template">
<tbody> <tbody>

View File

@@ -70,7 +70,7 @@
</div> </div>
</div> </div>
{{end}} {{end}}
<div id="eventStatusMessage" class="col-lg-10 col-lg-offset-1"></div> <div id="earlyLateMessage" class="col-lg-10 col-lg-offset-1"></div>
</body> </body>
<script src="/static/js/lib/jquery.min.js"></script> <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.json-2.4.min.js"></script>

View File

@@ -299,6 +299,7 @@ func TestMatchPlayWebsocketCommands(t *testing.T) {
web.arena.AllianceStations["B3"].Bypass = true web.arena.AllianceStations["B3"].Bypass = true
ws.Write("startMatch", nil) ws.Write("startMatch", nil)
readWebsocketType(t, ws, "arenaStatus") readWebsocketType(t, ws, "arenaStatus")
readWebsocketType(t, ws, "eventStatus")
assert.Equal(t, field.StartMatch, web.arena.MatchState) assert.Equal(t, field.StartMatch, web.arena.MatchState)
ws.Write("commitResults", nil) ws.Write("commitResults", nil)
assert.Contains(t, readWebsocketError(t, ws), "Cannot reset match") assert.Contains(t, readWebsocketError(t, ws), "Cannot reset match")
@@ -359,13 +360,15 @@ func TestMatchPlayWebsocketNotifications(t *testing.T) {
web.arena.AllianceStations["B3"].Bypass = true web.arena.AllianceStations["B3"].Bypass = true
assert.Nil(t, web.arena.StartMatch()) assert.Nil(t, web.arena.StartMatch())
web.arena.Update() web.arena.Update()
messages := readWebsocketMultiple(t, ws, 4) messages := readWebsocketMultiple(t, ws, 5)
_, ok := messages["matchTime"] _, ok := messages["matchTime"]
assert.True(t, ok) assert.True(t, ok)
_, ok = messages["audienceDisplayMode"] _, ok = messages["audienceDisplayMode"]
assert.True(t, ok) assert.True(t, ok)
_, ok = messages["allianceStationDisplayMode"] _, ok = messages["allianceStationDisplayMode"]
assert.True(t, ok) 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.MatchStartTime = time.Now().Add(-time.Duration(game.MatchTiming.WarmupDurationSec) * time.Second)
web.arena.Update() web.arena.Update()
messages = readWebsocketMultiple(t, ws, 2) messages = readWebsocketMultiple(t, ws, 2)