diff --git a/web/queueing_display.go b/web/queueing_display.go index 37ec790..66c8eb7 100644 --- a/web/queueing_display.go +++ b/web/queueing_display.go @@ -13,8 +13,11 @@ import ( "time" ) -const numMatchesToShow = 5 -const maxGapMin = 20 +const ( + earlyLateThresholdMin = 2 + maxGapMin = 20 + numMatchesToShow = 5 +) // Renders the queueing display that shows upcoming matches and timing information. func (web *Web) queueingDisplayHandler(w http.ResponseWriter, r *http.Request) { @@ -54,7 +57,8 @@ func (web *Web) queueingDisplayHandler(w http.ResponseWriter, r *http.Request) { MatchTypePrefix string Matches []model.Match StatusMessage string - }{web.arena.EventSettings, web.arena.CurrentMatch.TypePrefix(), upcomingMatches, generateEventStatusMessage(matches)} + }{web.arena.EventSettings, web.arena.CurrentMatch.TypePrefix(), upcomingMatches, + generateEventStatusMessage(web.arena.CurrentMatch.Type, matches)} err = template.ExecuteTemplate(w, "queueing_display.html", data) if err != nil { handleWebErr(w, err) @@ -84,22 +88,31 @@ func (web *Web) queueingDisplayWebsocketHandler(w http.ResponseWriter, r *http.R } // Returns a message indicating how early or late the event is running. -func generateEventStatusMessage(matches []model.Match) string { +func generateEventStatusMessage(matchType string, matches []model.Match) string { + if matchType != "practice" && matchType != "qualification" { + // Only practice and qualification matches have a strict schedule. + return "" + } + if len(matches) == 0 || matches[len(matches)-1].Status == "complete" { + // All matches of the current type are complete. + return "" + } + for i := len(matches) - 1; i >= 0; i-- { match := matches[i] if match.Status == "complete" { - minutesLate := match.StartedAt.Sub(match.Time).Minutes() - if minutesLate > 2 { - return fmt.Sprintf("Event is running %d minutes late", int(minutesLate)) - } else if minutesLate < -2 { - return fmt.Sprintf("Event is running %d minutes early", int(-minutesLate)) + if i+1 < len(matches) && matches[i+1].Time.Sub(match.Time) > maxGapMin*time.Minute { + break + } else { + minutesLate := match.StartedAt.Sub(match.Time).Minutes() + 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)) + } } } } - if len(matches) > 0 { - return "Event is running on schedule" - } else { - return "" - } + return "Event is running on schedule" } diff --git a/web/queueing_display_test.go b/web/queueing_display_test.go index 4d17a8a..70c3d84 100644 --- a/web/queueing_display_test.go +++ b/web/queueing_display_test.go @@ -1,4 +1,4 @@ -// Copyright 2014 Team 254. All Rights Reserved. +// Copyright 2018 Team 254. All Rights Reserved. // Author: pat@patfairbank.com (Patrick Fairbank) package web @@ -38,42 +38,51 @@ func TestQueueingDisplayWebsocket(t *testing.T) { } func TestQueueingStatusMessage(t *testing.T) { - assert.Equal(t, "", generateEventStatusMessage([]model.Match{})) + assert.Equal(t, "", generateEventStatusMessage("practice", []model.Match{})) matches := make([]model.Match, 3) - assert.Equal(t, "Event is running on schedule", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running on schedule", generateEventStatusMessage("practice", matches)) // Check within threshold considered to be on time. setMatchLateness(&matches[1], 0) - assert.Equal(t, "Event is running on schedule", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running on schedule", generateEventStatusMessage("qualification", matches)) setMatchLateness(&matches[1], 60) - assert.Equal(t, "Event is running on schedule", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running on schedule", generateEventStatusMessage("practice", matches)) setMatchLateness(&matches[1], -60) - assert.Equal(t, "Event is running on schedule", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running on schedule", generateEventStatusMessage("qualification", matches)) setMatchLateness(&matches[1], 90) - assert.Equal(t, "Event is running on schedule", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running on schedule", generateEventStatusMessage("qualification", matches)) setMatchLateness(&matches[1], -90) - assert.Equal(t, "Event is running on schedule", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running on schedule", generateEventStatusMessage("qualification", matches)) setMatchLateness(&matches[1], 110) - assert.Equal(t, "Event is running on schedule", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running on schedule", generateEventStatusMessage("practice", matches)) setMatchLateness(&matches[1], -110) - assert.Equal(t, "Event is running on schedule", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running on schedule", generateEventStatusMessage("qualification", matches)) // Check lateness. setMatchLateness(&matches[1], 130) - assert.Equal(t, "Event is running 2 minutes late", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running 2 minutes late", generateEventStatusMessage("practice", matches)) setMatchLateness(&matches[1], 3601) - assert.Equal(t, "Event is running 60 minutes late", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running 60 minutes late", generateEventStatusMessage("qualification", matches)) // Check earliness. setMatchLateness(&matches[1], -130) - assert.Equal(t, "Event is running 2 minutes early", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running 2 minutes early", generateEventStatusMessage("qualification", matches)) setMatchLateness(&matches[1], -3601) - assert.Equal(t, "Event is running 60 minutes early", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running 60 minutes early", generateEventStatusMessage("practice", matches)) + + // Check other match types. + assert.Equal(t, "", generateEventStatusMessage("test", matches)) + assert.Equal(t, "", generateEventStatusMessage("elimination", matches)) // Check that later matches supersede earlier ones. + matches = append(matches, model.Match{}) setMatchLateness(&matches[2], 180) - assert.Equal(t, "Event is running 3 minutes late", generateEventStatusMessage(matches)) + assert.Equal(t, "Event is running 3 minutes late", generateEventStatusMessage("qualification", matches)) + + // Check that a lateness before a large gap is ignored. + matches[3].Time = time.Now().Add(time.Minute * 25) + assert.Equal(t, "Event is running on schedule", generateEventStatusMessage("qualification", matches)) } func setMatchLateness(match *model.Match, secondsLate int) {