From 48d10883d8fa1c3b190275c42fd67fc7ed97083f Mon Sep 17 00:00:00 2001 From: Patrick Fairbank Date: Fri, 5 Sep 2014 23:40:02 -0700 Subject: [PATCH] Remove elimination rubber matches when they are not needed. --- elimination_schedule.go | 56 ++++++++++++++++++++++----------- elimination_schedule_test.go | 60 ++++++++++++++++++++++++++---------- 2 files changed, 81 insertions(+), 35 deletions(-) diff --git a/elimination_schedule.go b/elimination_schedule.go index bfff3fa..90f7955 100644 --- a/elimination_schedule.go +++ b/elimination_schedule.go @@ -111,6 +111,7 @@ func (database *Database) buildEliminationMatchSet(round int, group int, numAlli if err != nil { return []AllianceTeam{}, err } + var unplayedMatches []*Match for _, match := range matches { // Update the teams in the match if they are not yet set. if match.Red1 == 0 && len(redAlliance) != 0 { @@ -122,6 +123,7 @@ func (database *Database) buildEliminationMatchSet(round int, group int, numAlli } if match.Status != "complete" { + unplayedMatches = append(unplayedMatches, &match) numIncomplete += 1 continue } @@ -139,8 +141,27 @@ func (database *Database) buildEliminationMatchSet(round int, group int, numAlli } } - if len(matches) == 0 { - // Create the initial set of matches, filling in zeroes if only one alliance is known. + // Delete any superfluous matches if the round is won. + if redWins == 2 || blueWins == 2 { + for _, match := range unplayedMatches { + err = database.DeleteMatch(match) + if err != nil { + return []AllianceTeam{}, err + } + } + + // Bail out and announce the winner of this round. + if redWins == 2 { + return redAlliance, nil + } else { + return blueAlliance, nil + } + } + + // Create initial set of matches or recreate any superfluous matches that were deleted but now are needed + // due to a revision in who won. + if len(matches) == 0 || len(ties) == 0 && numIncomplete == 0 { + // Fill in zeroes if only one alliance is known. if len(redAlliance) == 0 { redAlliance = []AllianceTeam{AllianceTeam{}, AllianceTeam{}, AllianceTeam{}} } else if len(blueAlliance) == 0 { @@ -150,27 +171,26 @@ func (database *Database) buildEliminationMatchSet(round int, group int, numAlli // Raise an error if the alliance selection process gave us less than 3 teams per alliance. return []AllianceTeam{}, fmt.Errorf("Alliances must consist of at least 3 teams") } - err = database.CreateMatch(createMatch(roundName, round, group, 1, redAlliance, blueAlliance)) - if err != nil { - return []AllianceTeam{}, err + if len(matches) < 1 { + err = database.CreateMatch(createMatch(roundName, round, group, 1, redAlliance, blueAlliance)) + if err != nil { + return []AllianceTeam{}, err + } } - err = database.CreateMatch(createMatch(roundName, round, group, 2, redAlliance, blueAlliance)) - if err != nil { - return []AllianceTeam{}, err + if len(matches) < 2 { + err = database.CreateMatch(createMatch(roundName, round, group, 2, redAlliance, blueAlliance)) + if err != nil { + return []AllianceTeam{}, err + } } - err = database.CreateMatch(createMatch(roundName, round, group, 3, redAlliance, blueAlliance)) - if err != nil { - return []AllianceTeam{}, err + if len(matches) < 3 { + err = database.CreateMatch(createMatch(roundName, round, group, 3, redAlliance, blueAlliance)) + if err != nil { + return []AllianceTeam{}, err + } } } - // Bail out and announce the winner of this round if there is one. - if redWins == 2 { - return redAlliance, nil - } else if blueWins == 2 { - return blueAlliance, nil - } - // Duplicate any ties if we have run out of matches. Don't reshuffle the team positions, so queueing // personnel can reuse any tied matches without having to print new schedules. if numIncomplete == 0 { diff --git a/elimination_schedule_test.go b/elimination_schedule_test.go index bee4782..9fb44ae 100644 --- a/elimination_schedule_test.go +++ b/elimination_schedule_test.go @@ -449,10 +449,10 @@ func TestEliminationSchedulePopulatePartialMatch(t *testing.T) { assert.Nil(t, err) matches, err := db.GetMatchesByType("elimination") assert.Nil(t, err) - if assert.Equal(t, 6, len(matches)) { - assertMatch(t, matches[3], "F-1", 1, 3) - assertMatch(t, matches[4], "F-2", 1, 3) - assertMatch(t, matches[5], "F-3", 1, 3) + if assert.Equal(t, 5, len(matches)) { + assertMatch(t, matches[2], "F-1", 1, 3) + assertMatch(t, matches[3], "F-2", 1, 3) + assertMatch(t, matches[4], "F-3", 1, 3) } db.TruncateAllianceTeams() db.TruncateMatches() @@ -467,10 +467,10 @@ func TestEliminationSchedulePopulatePartialMatch(t *testing.T) { assert.Nil(t, err) matches, err = db.GetMatchesByType("elimination") assert.Nil(t, err) - if assert.Equal(t, 9, len(matches)) { - assertMatch(t, matches[6], "F-1", 0, 2) - assertMatch(t, matches[7], "F-2", 0, 2) - assertMatch(t, matches[8], "F-3", 0, 2) + if assert.Equal(t, 8, len(matches)) { + assertMatch(t, matches[5], "F-1", 0, 2) + assertMatch(t, matches[6], "F-2", 0, 2) + assertMatch(t, matches[7], "F-3", 0, 2) } scoreMatch(db, "SF1-1", "R") scoreMatch(db, "SF1-2", "R") @@ -478,10 +478,10 @@ func TestEliminationSchedulePopulatePartialMatch(t *testing.T) { assert.Nil(t, err) matches, err = db.GetMatchesByType("elimination") assert.Nil(t, err) - if assert.Equal(t, 9, len(matches)) { - assertMatch(t, matches[6], "F-1", 1, 2) - assertMatch(t, matches[7], "F-2", 1, 2) - assertMatch(t, matches[8], "F-3", 1, 2) + if assert.Equal(t, 7, len(matches)) { + assertMatch(t, matches[4], "F-1", 1, 2) + assertMatch(t, matches[5], "F-2", 1, 2) + assertMatch(t, matches[6], "F-3", 1, 2) } db.TruncateAllianceTeams() db.TruncateMatches() @@ -511,15 +511,15 @@ func TestEliminationScheduleCreateNextRound(t *testing.T) { _, err = db.UpdateEliminationSchedule(time.Unix(0, 0)) assert.Nil(t, err) matches, _ = db.GetMatchesByType("elimination") - assert.Equal(t, 9, len(matches)) + assert.Equal(t, 8, len(matches)) scoreMatch(db, "SF2-2", "B") _, err = db.UpdateEliminationSchedule(time.Unix(0, 0)) assert.Nil(t, err) matches, _ = db.GetMatchesByType("elimination") - if assert.Equal(t, 9, len(matches)) { - assertMatch(t, matches[6], "F-1", 4, 3) - assertMatch(t, matches[7], "F-2", 4, 3) - assertMatch(t, matches[8], "F-3", 4, 3) + if assert.Equal(t, 7, len(matches)) { + assertMatch(t, matches[4], "F-1", 4, 3) + assertMatch(t, matches[5], "F-2", 4, 3) + assertMatch(t, matches[6], "F-3", 4, 3) } } @@ -654,6 +654,32 @@ func TestEliminationScheduleDetermineWinner(t *testing.T) { db.TruncateMatchResults() } +func TestEliminationScheduleRemoveUnneededMatches(t *testing.T) { + clearDb() + defer clearDb() + db, err := OpenDatabase(testDbPath) + assert.Nil(t, err) + defer db.Close() + + createTestAlliances(db, 2) + db.UpdateEliminationSchedule(time.Unix(0, 0)) + scoreMatch(db, "F-1", "R") + scoreMatch(db, "F-2", "R") + _, err = db.UpdateEliminationSchedule(time.Unix(0, 0)) + assert.Nil(t, err) + matches, _ := db.GetMatchesByType("elimination") + assert.Equal(t, 2, len(matches)) + + // Check that the deleted match is recreated if the score is changed. + scoreMatch(db, "F-2", "B") + _, err = db.UpdateEliminationSchedule(time.Unix(0, 0)) + assert.Nil(t, err) + matches, _ = db.GetMatchesByType("elimination") + if assert.Equal(t, 3, len(matches)) { + assert.Equal(t, "F-3", matches[2].DisplayName) + } +} + func TestEliminationScheduleUnscoredMatch(t *testing.T) { clearDb() defer clearDb()