mirror of
https://github.com/Team254/cheesy-arena-lite.git
synced 2026-03-09 13:46:44 -04:00
Added publishing to The Blue Alliance.
This commit is contained in:
@@ -16,6 +16,7 @@ func TestAssignTeam(t *testing.T) {
|
||||
db, err = OpenDatabase(testDbPath)
|
||||
assert.Nil(t, err)
|
||||
defer db.Close()
|
||||
eventSettings, _ = db.GetEventSettings()
|
||||
team := Team{Id: 254}
|
||||
err = db.CreateTeam(&team)
|
||||
assert.Nil(t, err)
|
||||
|
||||
@@ -12,9 +12,11 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const elimMatchSpacingSec = 600
|
||||
|
||||
// Incrementally creates any elimination matches that can be created, based on the results of alliance
|
||||
// selection or prior elimination rounds. Returns the winning alliance once it has been determined.
|
||||
func (database *Database) UpdateEliminationSchedule(startTime time.Time, matchSpacingSec int) ([]AllianceTeam, error) {
|
||||
func (database *Database) UpdateEliminationSchedule(startTime time.Time) ([]AllianceTeam, error) {
|
||||
alliances, err := database.GetAllAlliances()
|
||||
if err != nil {
|
||||
return []AllianceTeam{}, err
|
||||
@@ -34,7 +36,7 @@ func (database *Database) UpdateEliminationSchedule(startTime time.Time, matchSp
|
||||
if match.Status == "complete" {
|
||||
continue
|
||||
}
|
||||
match.Time = startTime.Add(time.Duration(matchIndex*matchSpacingSec) * time.Second)
|
||||
match.Time = startTime.Add(time.Duration(matchIndex*elimMatchSpacingSec) * time.Second)
|
||||
database.SaveMatch(&match)
|
||||
matchIndex++
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
createTestAlliances(db, 2)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err := db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -30,7 +30,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 3)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -46,7 +46,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 4)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -62,7 +62,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 5)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -81,7 +81,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 6)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -103,7 +103,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 7)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -125,7 +125,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 8)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -147,7 +147,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 9)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -172,7 +172,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 10)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -200,7 +200,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 11)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -231,7 +231,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 12)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -265,7 +265,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 13)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -299,7 +299,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 14)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -333,7 +333,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 15)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -367,7 +367,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
db.TruncateMatches()
|
||||
|
||||
createTestAlliances(db, 16)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -409,14 +409,14 @@ func TestEliminationScheduleErrors(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
createTestAlliances(db, 1)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
if assert.NotNil(t, err) {
|
||||
assert.Equal(t, "Must have at least 2 alliances", err.Error())
|
||||
}
|
||||
db.TruncateAllianceTeams()
|
||||
|
||||
createTestAlliances(db, 17)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
if assert.NotNil(t, err) {
|
||||
assert.Equal(t, "Round of depth 32 is not supported", err.Error())
|
||||
}
|
||||
@@ -426,7 +426,7 @@ func TestEliminationScheduleErrors(t *testing.T) {
|
||||
db.CreateAllianceTeam(&AllianceTeam{0, 1, 1, 2})
|
||||
db.CreateAllianceTeam(&AllianceTeam{0, 2, 0, 3})
|
||||
db.CreateAllianceTeam(&AllianceTeam{0, 2, 1, 4})
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
if assert.NotNil(t, err) {
|
||||
assert.Equal(t, "Alliances must consist of at least 3 teams", err.Error())
|
||||
}
|
||||
@@ -442,10 +442,10 @@ func TestEliminationSchedulePopulatePartialMatch(t *testing.T) {
|
||||
|
||||
// Final should be updated after semifinal is concluded.
|
||||
createTestAlliances(db, 3)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
scoreMatch(db, "SF2-1", "B")
|
||||
scoreMatch(db, "SF2-2", "B")
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err := db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -460,10 +460,10 @@ func TestEliminationSchedulePopulatePartialMatch(t *testing.T) {
|
||||
|
||||
// Final should be generated and populated as both semifinals conclude.
|
||||
createTestAlliances(db, 4)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
scoreMatch(db, "SF2-1", "R")
|
||||
scoreMatch(db, "SF2-2", "R")
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -474,7 +474,7 @@ func TestEliminationSchedulePopulatePartialMatch(t *testing.T) {
|
||||
}
|
||||
scoreMatch(db, "SF1-1", "R")
|
||||
scoreMatch(db, "SF1-2", "R")
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
@@ -496,24 +496,24 @@ func TestEliminationScheduleCreateNextRound(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
createTestAlliances(db, 4)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
scoreMatch(db, "SF1-1", "B")
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, _ := db.GetMatchesByType("elimination")
|
||||
assert.Equal(t, 6, len(matches))
|
||||
scoreMatch(db, "SF2-1", "B")
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, _ = db.GetMatchesByType("elimination")
|
||||
assert.Equal(t, 6, len(matches))
|
||||
scoreMatch(db, "SF1-2", "B")
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, _ = db.GetMatchesByType("elimination")
|
||||
assert.Equal(t, 9, len(matches))
|
||||
scoreMatch(db, "SF2-2", "B")
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
matches, _ = db.GetMatchesByType("elimination")
|
||||
if assert.Equal(t, 9, len(matches)) {
|
||||
@@ -532,21 +532,21 @@ func TestEliminationScheduleDetermineWinner(t *testing.T) {
|
||||
|
||||
// Round with one tie and a sweep.
|
||||
createTestAlliances(db, 2)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
scoreMatch(db, "F-1", "T")
|
||||
winner, err := db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err := db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
assert.Empty(t, winner)
|
||||
matches, _ := db.GetMatchesByType("elimination")
|
||||
assert.Equal(t, 3, len(matches))
|
||||
scoreMatch(db, "F-2", "B")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
assert.Empty(t, winner)
|
||||
matches, _ = db.GetMatchesByType("elimination")
|
||||
assert.Equal(t, 3, len(matches))
|
||||
scoreMatch(db, "F-3", "B")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
if assert.Nil(t, err) {
|
||||
if assert.Equal(t, 3, len(winner)) {
|
||||
assert.Equal(t, 2, winner[0].TeamId)
|
||||
@@ -560,32 +560,32 @@ func TestEliminationScheduleDetermineWinner(t *testing.T) {
|
||||
|
||||
// Round with one tie and a split.
|
||||
createTestAlliances(db, 2)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
scoreMatch(db, "F-1", "R")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
assert.Empty(t, winner)
|
||||
matches, _ = db.GetMatchesByType("elimination")
|
||||
assert.Equal(t, 3, len(matches))
|
||||
scoreMatch(db, "F-2", "T")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
assert.Empty(t, winner)
|
||||
matches, _ = db.GetMatchesByType("elimination")
|
||||
assert.Equal(t, 3, len(matches))
|
||||
scoreMatch(db, "F-3", "B")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
assert.Empty(t, winner)
|
||||
matches, _ = db.GetMatchesByType("elimination")
|
||||
assert.Equal(t, 4, len(matches))
|
||||
assert.Equal(t, "F-4", matches[3].DisplayName)
|
||||
scoreMatch(db, "F-4", "T")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
assert.Empty(t, winner)
|
||||
scoreMatch(db, "F-5", "R")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
if assert.Nil(t, err) {
|
||||
if assert.Equal(t, 3, len(winner)) {
|
||||
assert.Equal(t, 1, winner[0].TeamId)
|
||||
@@ -597,21 +597,21 @@ func TestEliminationScheduleDetermineWinner(t *testing.T) {
|
||||
|
||||
// Round with two ties.
|
||||
createTestAlliances(db, 2)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
scoreMatch(db, "F-1", "T")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
assert.Empty(t, winner)
|
||||
matches, _ = db.GetMatchesByType("elimination")
|
||||
assert.Equal(t, 3, len(matches))
|
||||
scoreMatch(db, "F-2", "B")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
assert.Empty(t, winner)
|
||||
matches, _ = db.GetMatchesByType("elimination")
|
||||
assert.Equal(t, 3, len(matches))
|
||||
scoreMatch(db, "F-3", "T")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
assert.Nil(t, err)
|
||||
assert.Empty(t, winner)
|
||||
matches, _ = db.GetMatchesByType("elimination")
|
||||
@@ -619,7 +619,7 @@ func TestEliminationScheduleDetermineWinner(t *testing.T) {
|
||||
assert.Equal(t, "F-4", matches[3].DisplayName)
|
||||
assert.Equal(t, "F-5", matches[4].DisplayName)
|
||||
scoreMatch(db, "F-4", "B")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
if assert.Nil(t, err) {
|
||||
if assert.Equal(t, 3, len(winner)) {
|
||||
assert.Equal(t, 2, winner[0].TeamId)
|
||||
@@ -631,19 +631,19 @@ func TestEliminationScheduleDetermineWinner(t *testing.T) {
|
||||
|
||||
// Round with repeated ties.
|
||||
createTestAlliances(db, 2)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
scoreMatch(db, "F-1", "T")
|
||||
scoreMatch(db, "F-2", "T")
|
||||
scoreMatch(db, "F-3", "T")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
scoreMatch(db, "F-4", "T")
|
||||
scoreMatch(db, "F-5", "T")
|
||||
scoreMatch(db, "F-6", "T")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
scoreMatch(db, "F-7", "R")
|
||||
scoreMatch(db, "F-8", "B")
|
||||
scoreMatch(db, "F-9", "R")
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
winner, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
if assert.Nil(t, err) {
|
||||
if assert.Equal(t, 3, len(winner)) {
|
||||
assert.Equal(t, 1, winner[0].TeamId)
|
||||
@@ -662,9 +662,9 @@ func TestEliminationScheduleUnscoredMatch(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
createTestAlliances(db, 2)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
scoreMatch(db, "F-1", "blorpy")
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0), 0)
|
||||
_, err = db.UpdateEliminationSchedule(time.Unix(0, 0))
|
||||
if assert.NotNil(t, err) {
|
||||
assert.Equal(t, "Completed match 1 has invalid winner 'blorpy'", err.Error())
|
||||
}
|
||||
@@ -678,7 +678,7 @@ func TestEliminationScheduleTiming(t *testing.T) {
|
||||
defer db.Close()
|
||||
|
||||
createTestAlliances(db, 4)
|
||||
db.UpdateEliminationSchedule(time.Unix(1000, 0), 600)
|
||||
db.UpdateEliminationSchedule(time.Unix(1000, 0))
|
||||
matches, err := db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
if assert.Equal(t, 6, len(matches)) {
|
||||
@@ -691,16 +691,16 @@ func TestEliminationScheduleTiming(t *testing.T) {
|
||||
}
|
||||
scoreMatch(db, "SF1-1", "R")
|
||||
scoreMatch(db, "SF1-3", "B")
|
||||
db.UpdateEliminationSchedule(time.Unix(5000, 0), 1000)
|
||||
db.UpdateEliminationSchedule(time.Unix(5000, 0))
|
||||
matches, err = db.GetMatchesByType("elimination")
|
||||
assert.Nil(t, err)
|
||||
if assert.Equal(t, 6, len(matches)) {
|
||||
assert.True(t, time.Unix(1000, 0).Equal(matches[0].Time))
|
||||
assert.True(t, time.Unix(5000, 0).Equal(matches[1].Time))
|
||||
assert.True(t, time.Unix(6000, 0).Equal(matches[2].Time))
|
||||
assert.True(t, time.Unix(7000, 0).Equal(matches[3].Time))
|
||||
assert.True(t, time.Unix(5600, 0).Equal(matches[2].Time))
|
||||
assert.True(t, time.Unix(6200, 0).Equal(matches[3].Time))
|
||||
assert.True(t, time.Unix(3400, 0).Equal(matches[4].Time))
|
||||
assert.True(t, time.Unix(8000, 0).Equal(matches[5].Time))
|
||||
assert.True(t, time.Unix(6800, 0).Equal(matches[5].Time))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"text/template"
|
||||
"time"
|
||||
)
|
||||
|
||||
type MatchPlayListItem struct {
|
||||
@@ -344,10 +345,36 @@ func CommitMatchScore(match *Match, matchResult *MatchResult) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Recalculate all the rankings.
|
||||
err = db.CalculateRankings()
|
||||
if err != nil {
|
||||
return err
|
||||
if match.Type == "qualification" {
|
||||
// Recalculate all the rankings.
|
||||
err = db.CalculateRankings()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if match.Type == "elimination" {
|
||||
// Generate any subsequent elimination matches.
|
||||
_, err = db.UpdateEliminationSchedule(time.Now().Add(time.Second * elimMatchSpacingSec))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if eventSettings.TbaPublishingEnabled && match.Type != "practice" {
|
||||
// Publish asynchronously to The Blue Alliance.
|
||||
go func() {
|
||||
err = PublishMatches()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
if match.Type == "qualification" {
|
||||
err = PublishRankings()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -53,6 +53,7 @@ func TestMatchReviewEditExistingResult(t *testing.T) {
|
||||
db.CreateMatch(&match)
|
||||
matchResult := buildTestMatchResult(match.Id, 1)
|
||||
db.CreateMatchResult(&matchResult)
|
||||
createTestAlliances(db, 2)
|
||||
|
||||
recorder := getHttpResponse("/match_review")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
@@ -96,6 +97,7 @@ func TestMatchReviewCreateNewResult(t *testing.T) {
|
||||
match := Match{Type: "elimination", DisplayName: "QF4-3", Status: "complete", Winner: "R", Red1: 101,
|
||||
Red2: 102, Red3: 103, Blue1: 104, Blue2: 105, Blue3: 106}
|
||||
db.CreateMatch(&match)
|
||||
createTestAlliances(db, 2)
|
||||
|
||||
recorder := getHttpResponse("/match_review")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
|
||||
@@ -137,11 +137,6 @@ func AllianceSelectionFinalizeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
renderAllianceSelection(w, r, "Must specify a valid start time for the elimination rounds.")
|
||||
return
|
||||
}
|
||||
matchSpacingSec, err := strconv.Atoi(r.PostFormValue("matchSpacingSec"))
|
||||
if err != nil || matchSpacingSec <= 0 {
|
||||
renderAllianceSelection(w, r, "Must specify a valid match spacing for the elimination rounds.")
|
||||
return
|
||||
}
|
||||
|
||||
// Check that all spots are filled.
|
||||
for _, alliance := range cachedAlliances {
|
||||
@@ -165,12 +160,26 @@ func AllianceSelectionFinalizeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Generate the first round of elimination matches.
|
||||
_, err = db.UpdateEliminationSchedule(startTime, matchSpacingSec)
|
||||
_, err = db.UpdateEliminationSchedule(startTime)
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
if eventSettings.TbaPublishingEnabled {
|
||||
// Publish alliances and schedule to The Blue Alliance.
|
||||
err = PublishAlliances()
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
err = PublishMatches()
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/setup/alliance_selection", 302)
|
||||
}
|
||||
|
||||
|
||||
@@ -79,8 +79,7 @@ func TestSetupAllianceSelection(t *testing.T) {
|
||||
assert.Contains(t, recorder.Body.String(), ">110<")
|
||||
|
||||
// Finalize alliance selection.
|
||||
recorder = postHttpResponse("/setup/alliance_selection/finalize",
|
||||
"startTime=2014-01-01 01:00:00 PM&matchSpacingSec=360")
|
||||
recorder = postHttpResponse("/setup/alliance_selection/finalize", "startTime=2014-01-01 01:00:00 PM")
|
||||
assert.Equal(t, 302, recorder.Code)
|
||||
alliances, err := db.GetAllAlliances()
|
||||
assert.Nil(t, err)
|
||||
@@ -135,19 +134,15 @@ func TestSetupAllianceSelectionErrors(t *testing.T) {
|
||||
recorder = postHttpResponse("/setup/alliance_selection", "selection0_0=101&selection0_1=102&"+
|
||||
"selection0_2=103&selection1_0=104&selection1_1=105&selection1_2=106")
|
||||
assert.Equal(t, 302, recorder.Code)
|
||||
recorder = postHttpResponse("/setup/alliance_selection/finalize", "startTime=asdf&matchSpacingSec=100")
|
||||
recorder = postHttpResponse("/setup/alliance_selection/finalize", "startTime=asdf")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Contains(t, recorder.Body.String(), "valid start time")
|
||||
recorder = postHttpResponse("/setup/alliance_selection/finalize", "startTime=2014-01-01 01:00:00 PM")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Contains(t, recorder.Body.String(), "valid match spacing")
|
||||
recorder = postHttpResponse("/setup/alliance_selection/finalize",
|
||||
"startTime=2014-01-01 01:00:00 PM&matchSpacingSec=360")
|
||||
"startTime=2014-01-01 01:00:00 PM")
|
||||
assert.Equal(t, 302, recorder.Code)
|
||||
|
||||
// Do other things after finalization.
|
||||
recorder = postHttpResponse("/setup/alliance_selection/finalize",
|
||||
"startTime=2014-01-01 01:00:00 PM&matchSpacingSec=360")
|
||||
recorder = postHttpResponse("/setup/alliance_selection/finalize", "startTime=2014-01-01 01:00:00 PM")
|
||||
assert.Equal(t, 200, recorder.Code)
|
||||
assert.Contains(t, recorder.Body.String(), "already been finalized")
|
||||
recorder = postHttpResponse("/setup/alliance_selection/reset", "")
|
||||
|
||||
@@ -106,6 +106,16 @@ func ScheduleSavePostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if eventSettings.TbaPublishingEnabled && cachedMatchType != "practice" {
|
||||
// Publish schedule to The Blue Alliance.
|
||||
err = PublishMatches()
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/setup/schedule", 302)
|
||||
}
|
||||
|
||||
|
||||
@@ -157,6 +157,16 @@ func TeamDeletePostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/setup/teams", 302)
|
||||
}
|
||||
|
||||
// Publishes the team list to the web.
|
||||
func TeamsPublishHandler(w http.ResponseWriter, r *http.Request) {
|
||||
err := PublishTeams()
|
||||
if err != nil {
|
||||
handleWebErr(w, err)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/setup/teams", 302)
|
||||
}
|
||||
|
||||
func renderTeams(w http.ResponseWriter, r *http.Request, showErrorMessage bool) {
|
||||
teams, err := db.GetAllTeams()
|
||||
if err != nil {
|
||||
|
||||
204
tba.go
Normal file
204
tba.go
Normal file
@@ -0,0 +1,204 @@
|
||||
// Copyright 2014 Team 254. All Rights Reserved.
|
||||
// Author: pat@patfairbank.com (Patrick Fairbank)
|
||||
//
|
||||
// Methods for publishing data to and retrieving data from The Blue Alliance.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var tbaBaseUrl = "http://tbatv-dev-efang.appspot.com"
|
||||
|
||||
type TbaMatch struct {
|
||||
CompLevel string `json:"comp_level"`
|
||||
SetNumber int `json:"set_number"`
|
||||
MatchNumber int `json:"match_number"`
|
||||
Alliances map[string]interface{} `json:"alliances"`
|
||||
TimeString string `json:"time_string"`
|
||||
}
|
||||
|
||||
type TbaRanking struct {
|
||||
TeamKey string `json:"team_key"`
|
||||
Rank int `json:"rank"`
|
||||
Wins int `json:"wins"`
|
||||
Losses int `json:"losses"`
|
||||
Ties int `json:"ties"`
|
||||
Played int `json:"played"`
|
||||
Dqs int `json:"dqs"`
|
||||
QS int
|
||||
Assist int
|
||||
Auto int
|
||||
TrussCatch int `json:"T&C"`
|
||||
GoalFoul int `json:"G&F"`
|
||||
}
|
||||
|
||||
// Uploads the event team list to The Blue Alliance.
|
||||
func PublishTeams() error {
|
||||
teams, err := db.GetAllTeams()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Build a JSON array of TBA-format team keys (e.g. "frc254").
|
||||
teamKeys := make([]string, len(teams))
|
||||
for i, team := range teams {
|
||||
teamKeys[i] = getTbaTeam(team.Id)
|
||||
}
|
||||
jsonBody, err := json.Marshal(teamKeys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := http.PostForm(getTbaPostUrl("team_list"), getTbaPostBody("team_list", string(jsonBody)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
defer resp.Body.Close()
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
return fmt.Errorf("Got status code %d from TBA: %s", resp.StatusCode, body)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Uploads the qualification and elimination match schedule and results to The Blue Alliance.
|
||||
func PublishMatches() error {
|
||||
qualMatches, err := db.GetMatchesByType("qualification")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elimMatches, err := db.GetMatchesByType("elimination")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
matches := append(qualMatches, elimMatches...)
|
||||
tbaMatches := make([]TbaMatch, len(matches))
|
||||
|
||||
// Build a JSON array of TBA-format matches.
|
||||
for i, match := range matches {
|
||||
matchNumber, _ := strconv.Atoi(match.DisplayName)
|
||||
redAlliance := map[string]interface{}{"teams": []string{getTbaTeam(match.Red1), getTbaTeam(match.Red2),
|
||||
getTbaTeam(match.Red3)}, "score": nil}
|
||||
blueAlliance := map[string]interface{}{"teams": []string{getTbaTeam(match.Blue1), getTbaTeam(match.Blue2),
|
||||
getTbaTeam(match.Blue3)}, "score": nil}
|
||||
|
||||
// Fill in scores if the match has been played.
|
||||
if match.Status == "complete" {
|
||||
matchResult, err := db.GetMatchResultForMatch(match.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if matchResult != nil {
|
||||
redAlliance["score"] = matchResult.RedScoreSummary().Score
|
||||
blueAlliance["score"] = matchResult.BlueScoreSummary().Score
|
||||
}
|
||||
}
|
||||
|
||||
tbaMatches[i] = TbaMatch{"qm", 0, matchNumber, map[string]interface{}{"red": redAlliance,
|
||||
"blue": blueAlliance}, match.Time.Local().Format("3:04 PM")}
|
||||
if match.Type == "elimination" {
|
||||
tbaMatches[i].CompLevel = map[int]string{1: "f", 2: "sf", 4: "qf", 8: "ef"}[match.ElimRound]
|
||||
tbaMatches[i].SetNumber = match.ElimGroup
|
||||
tbaMatches[i].MatchNumber = match.ElimInstance
|
||||
}
|
||||
}
|
||||
jsonBody, err := json.Marshal(tbaMatches)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := http.PostForm(getTbaPostUrl("matches"), getTbaPostBody("matches", string(jsonBody)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
defer resp.Body.Close()
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
return fmt.Errorf("Got status code %d from TBA: %s", resp.StatusCode, body)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Uploads the team standings to The Blue Alliance.
|
||||
func PublishRankings() error {
|
||||
rankings, err := db.GetAllRankings()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Build a JSON object of TBA-format rankings.
|
||||
breakdowns := []string{"QS", "Assist", "Auto", "T&C", "G&F"}
|
||||
tbaRankings := make([]TbaRanking, len(rankings))
|
||||
for i, ranking := range rankings {
|
||||
tbaRankings[i] = TbaRanking{getTbaTeam(ranking.TeamId), ranking.Rank, ranking.Wins, ranking.Losses,
|
||||
ranking.Ties, ranking.Played, ranking.Disqualifications, ranking.QualificationScore,
|
||||
ranking.AssistPoints, ranking.AutoPoints, ranking.TrussCatchPoints, ranking.GoalFoulPoints}
|
||||
}
|
||||
jsonBody, err := json.Marshal(map[string]interface{}{"breakdowns": breakdowns, "rankings": tbaRankings})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := http.PostForm(getTbaPostUrl("rankings"), getTbaPostBody("rankings", string(jsonBody)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
defer resp.Body.Close()
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
return fmt.Errorf("Got status code %d from TBA: %s", resp.StatusCode, body)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Uploads the alliances selection results to The Blue Alliance.
|
||||
func PublishAlliances() error {
|
||||
alliances, err := db.GetAllAlliances()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Build a JSON object of TBA-format alliances.
|
||||
tbaAlliances := make([][]string, len(alliances))
|
||||
for i, alliance := range alliances {
|
||||
for _, team := range alliance {
|
||||
tbaAlliances[i] = append(tbaAlliances[i], getTbaTeam(team.TeamId))
|
||||
}
|
||||
}
|
||||
jsonBody, err := json.Marshal(tbaAlliances)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := http.PostForm(getTbaPostUrl("alliance_selections"), getTbaPostBody("alliances", string(jsonBody)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
defer resp.Body.Close()
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
return fmt.Errorf("Got status code %d from TBA: %s", resp.StatusCode, body)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getTbaPostUrl(resource string) string {
|
||||
return fmt.Sprintf("%s/api/trusted/v1/event/%s/%s/update", tbaBaseUrl, eventSettings.TbaEventCode,
|
||||
resource)
|
||||
}
|
||||
|
||||
func getTbaPostBody(key string, value string) url.Values {
|
||||
return url.Values{"secret-id": {eventSettings.TbaSecretId}, "secret": {eventSettings.TbaSecret}, key: {value}}
|
||||
}
|
||||
|
||||
// Converts an integer team number into the "frcXXXX" format TBA expects.
|
||||
func getTbaTeam(team int) string {
|
||||
return fmt.Sprintf("frc%d", team)
|
||||
}
|
||||
@@ -134,12 +134,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-lg-6 control-label">Elimination Round Cycle Time (sec)</label>
|
||||
<div class="col-lg-6">
|
||||
<input type="text" class="form-control input-sm" name="matchSpacingSec" value="480" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
|
||||
@@ -24,6 +24,13 @@
|
||||
Clear Team List
|
||||
</button>
|
||||
</div>
|
||||
{{if .EventSettings.TbaPublishingEnabled}}
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn btn-info" onclick="$('#confirmPublishTeams').modal('show');">
|
||||
Publish Team List to TBA
|
||||
</button>
|
||||
</div>
|
||||
{{end}}
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
@@ -87,5 +94,25 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="confirmPublishTeams" class="modal" style="top: 20%;">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Confirm</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Are you sure you want to publish the team list to The Blue Alliance? This will overwrite any
|
||||
existing team list data.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<form class="form-horizontal" action="/setup/teams/publish" method="POST">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Publish Team List</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{define "script"}}{{end}}
|
||||
|
||||
1
web.go
1
web.go
@@ -111,6 +111,7 @@ func newHandler() http.Handler {
|
||||
router.HandleFunc("/setup/teams/{id}/edit", TeamEditGetHandler).Methods("GET")
|
||||
router.HandleFunc("/setup/teams/{id}/edit", TeamEditPostHandler).Methods("POST")
|
||||
router.HandleFunc("/setup/teams/{id}/delete", TeamDeletePostHandler).Methods("POST")
|
||||
router.HandleFunc("/setup/teams/publish", TeamsPublishHandler).Methods("POST")
|
||||
router.HandleFunc("/setup/schedule", ScheduleGetHandler).Methods("GET")
|
||||
router.HandleFunc("/setup/schedule/generate", ScheduleGeneratePostHandler).Methods("POST")
|
||||
router.HandleFunc("/setup/schedule/save", ScheduleSavePostHandler).Methods("POST")
|
||||
|
||||
Reference in New Issue
Block a user