mirror of
https://github.com/Team254/cheesy-arena-lite.git
synced 2026-03-09 13:46:44 -04:00
Refactor event status to include cycle time calculation.
This commit is contained in:
@@ -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"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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{} {
|
||||||
|
|||||||
@@ -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
107
field/event_status.go
Normal 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
126
field/event_status_test.go
Normal 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)
|
||||||
|
}
|
||||||
@@ -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";
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user