diff --git a/displays.go b/displays.go index e6e0175..700f84f 100644 --- a/displays.go +++ b/displays.go @@ -335,9 +335,23 @@ func ScoringDisplayWebsocketHandler(w http.ResponseWriter, r *http.Request) { if !(*score).AutoCommitted { (*score).AutoCommitted = true } else if !(*score).TeleopCommitted { - if (*score).CurrentCycle.ScoredLow || (*score).CurrentCycle.ScoredHigh || + if (*score).CurrentCycle.ScoredHigh || (*score).CurrentCycle.ScoredLow || (*score).CurrentCycle.DeadBall { - (*score).CurrentScore.Cycles = append((*score).CurrentScore.Cycles, (*score).CurrentCycle) + // Check whether this is a leftover ball from autonomous. + if ((*score).AutoPreloadedBalls - (*score).CurrentScore.AutoHighHot - + (*score).CurrentScore.AutoHigh - (*score).CurrentScore.AutoLowHot - + (*score).CurrentScore.AutoLow - (*score).CurrentScore.AutoClearHigh - + (*score).CurrentScore.AutoClearLow - (*score).CurrentScore.AutoClearDead) > 0 { + if (*score).CurrentCycle.ScoredHigh { + (*score).CurrentScore.AutoClearHigh += 1 + } else if (*score).CurrentCycle.ScoredLow { + (*score).CurrentScore.AutoClearLow += 1 + } else { + (*score).CurrentScore.AutoClearDead += 1 + } + } else { + (*score).CurrentScore.Cycles = append((*score).CurrentScore.Cycles, (*score).CurrentCycle) + } (*score).CurrentCycle = Cycle{} (*score).undoCycles = []Cycle{} } diff --git a/displays_test.go b/displays_test.go index a05b694..e448b3d 100644 --- a/displays_test.go +++ b/displays_test.go @@ -68,3 +68,144 @@ func TestAnnouncerDisplayWebsocket(t *testing.T) { mainArena.Update() readWebsocketType(t, ws, "matchTime") } + +func TestScoringDisplay(t *testing.T) { + clearDb() + defer clearDb() + var err error + db, err = OpenDatabase(testDbPath) + assert.Nil(t, err) + defer db.Close() + eventSettings, _ = db.GetEventSettings() + mainArena.Setup() + + recorder := getHttpResponse("/displays/scoring/invalidalliance") + assert.Equal(t, 500, recorder.Code) + assert.Contains(t, recorder.Body.String(), "Invalid alliance") + recorder = getHttpResponse("/displays/scoring/red") + assert.Equal(t, 200, recorder.Code) + recorder = getHttpResponse("/displays/scoring/blue") + assert.Equal(t, 200, recorder.Code) + assert.Contains(t, recorder.Body.String(), "Scoring - Untitled Event - Cheesy Arena") +} + +func TestScoringDisplayWebsocket(t *testing.T) { + clearDb() + defer clearDb() + var err error + db, err = OpenDatabase(testDbPath) + assert.Nil(t, err) + defer db.Close() + mainArena.Setup() + + server, wsUrl := startTestServer() + defer server.Close() + _, _, err = websocket.DefaultDialer.Dial(wsUrl+"/displays/scoring/blorpy/websocket", nil) + assert.NotNil(t, err) + redConn, _, err := websocket.DefaultDialer.Dial(wsUrl+"/displays/scoring/red/websocket", nil) + assert.Nil(t, err) + defer redConn.Close() + redWs := &Websocket{redConn} + blueConn, _, err := websocket.DefaultDialer.Dial(wsUrl+"/displays/scoring/blue/websocket", nil) + assert.Nil(t, err) + defer blueConn.Close() + blueWs := &Websocket{blueConn} + + // Should a score update right after connection. + readWebsocketType(t, redWs, "score") + readWebsocketType(t, blueWs, "score") + + // Send a match worth of scoring commands in. + redWs.Write("preload", "3") + blueWs.Write("preload", "3") + redWs.Write("mobility", nil) + blueWs.Write("mobility", nil) + blueWs.Write("mobility", nil) + blueWs.Write("mobility", nil) + blueWs.Write("scoredHighHot", nil) + blueWs.Write("scoredHigh", nil) + blueWs.Write("scoredLowHot", nil) + blueWs.Write("scoredLow", nil) + blueWs.Write("undo", nil) + redWs.Write("commit", nil) + blueWs.Write("commit", nil) + redWs.Write("deadBall", nil) + redWs.Write("commit", nil) + redWs.Write("scoredLow", nil) + redWs.Write("commit", nil) + redWs.Write("scoredHigh", nil) + redWs.Write("commit", nil) + redWs.Write("assist", nil) + blueWs.Write("assist", nil) + blueWs.Write("assist", nil) + blueWs.Write("assist", nil) + blueWs.Write("assist", nil) + blueWs.Write("scoredLow", nil) + blueWs.Write("scoredHigh", nil) + blueWs.Write("commit", nil) + blueWs.Write("assist", nil) + blueWs.Write("assist", nil) + blueWs.Write("truss", nil) + blueWs.Write("catch", nil) + blueWs.Write("undo", nil) + blueWs.Write("scoredLow", nil) + blueWs.Write("commit", nil) + redWs.Write("commitMatch", nil) + for i := 0; i < 10; i++ { + readWebsocketType(t, redWs, "score") + } + for i := 0; i < 24; i++ { + readWebsocketType(t, blueWs, "score") + } + + assert.Equal(t, 1, mainArena.redRealtimeScore.CurrentScore.AutoMobilityBonuses) + assert.Equal(t, 0, mainArena.redRealtimeScore.CurrentScore.AutoHighHot) + assert.Equal(t, 0, mainArena.redRealtimeScore.CurrentScore.AutoHigh) + assert.Equal(t, 0, mainArena.redRealtimeScore.CurrentScore.AutoLowHot) + assert.Equal(t, 0, mainArena.redRealtimeScore.CurrentScore.AutoLow) + assert.Equal(t, 1, mainArena.redRealtimeScore.CurrentScore.AutoClearHigh) + assert.Equal(t, 1, mainArena.redRealtimeScore.CurrentScore.AutoClearLow) + assert.Equal(t, 1, mainArena.redRealtimeScore.CurrentScore.AutoClearDead) + if assert.Equal(t, 1, len(mainArena.redRealtimeScore.CurrentScore.Cycles)) { + assert.Equal(t, 1, mainArena.redRealtimeScore.CurrentScore.Cycles[0].Assists) + assert.False(t, mainArena.redRealtimeScore.CurrentScore.Cycles[0].Truss) + assert.False(t, mainArena.redRealtimeScore.CurrentScore.Cycles[0].Catch) + assert.False(t, mainArena.redRealtimeScore.CurrentScore.Cycles[0].ScoredHigh) + assert.False(t, mainArena.redRealtimeScore.CurrentScore.Cycles[0].ScoredLow) + assert.False(t, mainArena.redRealtimeScore.CurrentScore.Cycles[0].DeadBall) + } + assert.True(t, mainArena.redRealtimeScore.AutoCommitted) + assert.True(t, mainArena.redRealtimeScore.TeleopCommitted) + + assert.Equal(t, 3, mainArena.blueRealtimeScore.CurrentScore.AutoMobilityBonuses) + assert.Equal(t, 1, mainArena.blueRealtimeScore.CurrentScore.AutoHighHot) + assert.Equal(t, 1, mainArena.blueRealtimeScore.CurrentScore.AutoHigh) + assert.Equal(t, 1, mainArena.blueRealtimeScore.CurrentScore.AutoLowHot) + assert.Equal(t, 0, mainArena.blueRealtimeScore.CurrentScore.AutoLow) + assert.Equal(t, 0, mainArena.blueRealtimeScore.CurrentScore.AutoClearHigh) + assert.Equal(t, 0, mainArena.blueRealtimeScore.CurrentScore.AutoClearLow) + assert.Equal(t, 0, mainArena.blueRealtimeScore.CurrentScore.AutoClearDead) + if assert.Equal(t, 2, len(mainArena.blueRealtimeScore.CurrentScore.Cycles)) { + assert.Equal(t, 3, mainArena.blueRealtimeScore.CurrentScore.Cycles[0].Assists) + assert.False(t, mainArena.blueRealtimeScore.CurrentScore.Cycles[0].Truss) + assert.False(t, mainArena.blueRealtimeScore.CurrentScore.Cycles[0].Catch) + assert.True(t, mainArena.blueRealtimeScore.CurrentScore.Cycles[0].ScoredHigh) + assert.False(t, mainArena.blueRealtimeScore.CurrentScore.Cycles[0].ScoredLow) + assert.False(t, mainArena.blueRealtimeScore.CurrentScore.Cycles[0].DeadBall) + assert.Equal(t, 2, mainArena.blueRealtimeScore.CurrentScore.Cycles[1].Assists) + assert.True(t, mainArena.blueRealtimeScore.CurrentScore.Cycles[1].Truss) + assert.False(t, mainArena.blueRealtimeScore.CurrentScore.Cycles[1].Catch) + assert.False(t, mainArena.blueRealtimeScore.CurrentScore.Cycles[1].ScoredHigh) + assert.True(t, mainArena.blueRealtimeScore.CurrentScore.Cycles[1].ScoredLow) + assert.False(t, mainArena.blueRealtimeScore.CurrentScore.Cycles[1].DeadBall) + } + assert.True(t, mainArena.blueRealtimeScore.AutoCommitted) + assert.False(t, mainArena.blueRealtimeScore.TeleopCommitted) + + // Load another match to reset the results. + mainArena.LoadTestMatch() + readWebsocketType(t, redWs, "score") + readWebsocketType(t, blueWs, "score") + assert.Equal(t, RealtimeScore{}, *mainArena.redRealtimeScore) + assert.Equal(t, RealtimeScore{}, *mainArena.blueRealtimeScore) +} diff --git a/match_result.go b/match_result.go index 7eea2fa..838ee7c 100644 --- a/match_result.go +++ b/match_result.go @@ -39,6 +39,7 @@ type Score struct { AutoLow int AutoClearHigh int AutoClearLow int + AutoClearDead int Cycles []Cycle } diff --git a/match_result_test.go b/match_result_test.go index 1e19785..b1a81df 100644 --- a/match_result_test.go +++ b/match_result_test.go @@ -153,8 +153,8 @@ func buildTestMatchResult(matchId int, playNumber int) MatchResult { cycle3 := Cycle{1, true, false, false, false, true} fouls := []Foul{Foul{25, "G22", 25.2, false}, Foul{25, "G18", 150, false}, Foul{1868, "G20", 0, true}} matchResult := MatchResult{MatchId: matchId, PlayNumber: playNumber} - matchResult.RedScore = Score{1, 2, 3, 4, 5, 6, 7, []Cycle{cycle1, cycle2, cycle3}} - matchResult.BlueScore = Score{7, 6, 5, 4, 3, 2, 1, []Cycle{cycle3, cycle1, cycle1, cycle1}} + matchResult.RedScore = Score{1, 2, 3, 4, 5, 6, 7, 8, []Cycle{cycle1, cycle2, cycle3}} + matchResult.BlueScore = Score{7, 6, 5, 4, 3, 2, 1, 0, []Cycle{cycle3, cycle1, cycle1, cycle1}} matchResult.RedFouls = fouls matchResult.BlueFouls = []Foul{} matchResult.Cards = Cards{[]int{1868}, []int{}}