mirror of
https://github.com/Team254/cheesy-arena-lite.git
synced 2026-03-09 21:56:50 -04:00
Refactor alliance storage to use a single object per alliance instead of one per alliance-team association.
This commit is contained in:
@@ -89,16 +89,19 @@ func DeleteAward(database *model.Database, awardId int) error {
|
||||
|
||||
// Generates awards and lower thirds for the tournament winners and finalists.
|
||||
func CreateOrUpdateWinnerAndFinalistAwards(database *model.Database, winnerAllianceId, finalistAllianceId int) error {
|
||||
var winnerAllianceTeams, finalistAllianceTeams []model.AllianceTeam
|
||||
var winnerAlliance, finalistAlliance *model.Alliance
|
||||
var err error
|
||||
if winnerAllianceTeams, err = database.GetTeamsByAlliance(winnerAllianceId); err != nil {
|
||||
if winnerAlliance, err = database.GetAllianceById(winnerAllianceId); err != nil {
|
||||
return err
|
||||
}
|
||||
if finalistAllianceTeams, err = database.GetTeamsByAlliance(finalistAllianceId); err != nil {
|
||||
if finalistAlliance, err = database.GetAllianceById(finalistAllianceId); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(winnerAllianceTeams) == 0 || len(finalistAllianceTeams) == 0 {
|
||||
return fmt.Errorf("Input alliances do not contain any teams.")
|
||||
if winnerAlliance == nil || finalistAlliance == nil {
|
||||
return fmt.Errorf("Winner and/or finalist alliances do not exist.")
|
||||
}
|
||||
if len(winnerAlliance.TeamIds) == 0 || len(finalistAlliance.TeamIds) == 0 {
|
||||
return fmt.Errorf("Winner and/or finalist alliances do not contain teams.")
|
||||
}
|
||||
|
||||
// Clear out any awards that may exist if the final match was scored more than once.
|
||||
@@ -117,28 +120,34 @@ func CreateOrUpdateWinnerAndFinalistAwards(database *model.Database, winnerAllia
|
||||
}
|
||||
|
||||
// Create the finalist awards first since they're usually presented first.
|
||||
finalistAward := model.Award{AwardName: "Finalist", Type: model.FinalistAward,
|
||||
TeamId: finalistAllianceTeams[0].TeamId}
|
||||
finalistAward := model.Award{
|
||||
AwardName: "Finalist",
|
||||
Type: model.FinalistAward,
|
||||
TeamId: finalistAlliance.TeamIds[0],
|
||||
}
|
||||
if err = CreateOrUpdateAward(database, &finalistAward, true); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, allianceTeam := range finalistAllianceTeams[1:] {
|
||||
for _, allianceTeamId := range finalistAlliance.TeamIds[1:] {
|
||||
finalistAward.Id = 0
|
||||
finalistAward.TeamId = allianceTeam.TeamId
|
||||
finalistAward.TeamId = allianceTeamId
|
||||
if err = CreateOrUpdateAward(database, &finalistAward, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create the winner awards.
|
||||
winnerAward := model.Award{AwardName: "Winner", Type: model.WinnerAward,
|
||||
TeamId: winnerAllianceTeams[0].TeamId}
|
||||
winnerAward := model.Award{
|
||||
AwardName: "Winner",
|
||||
Type: model.WinnerAward,
|
||||
TeamId: winnerAlliance.TeamIds[0],
|
||||
}
|
||||
if err = CreateOrUpdateAward(database, &winnerAward, true); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, allianceTeam := range winnerAllianceTeams[1:] {
|
||||
for _, allianceTeamId := range winnerAlliance.TeamIds[1:] {
|
||||
winnerAward.Id = 0
|
||||
winnerAward.TeamId = allianceTeam.TeamId
|
||||
winnerAward.TeamId = allianceTeamId
|
||||
if err = CreateOrUpdateAward(database, &winnerAward, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -91,56 +91,62 @@ func TestCreateOrUpdateAwardWithoutIntro(t *testing.T) {
|
||||
func TestCreateOrUpdateWinnerAndFinalistAwards(t *testing.T) {
|
||||
database := setupTestDb(t)
|
||||
CreateTestAlliances(database, 2)
|
||||
database.CreateTeam(&model.Team{Id: 1})
|
||||
database.CreateTeam(&model.Team{Id: 10})
|
||||
database.CreateTeam(&model.Team{Id: 100})
|
||||
database.CreateTeam(&model.Team{Id: 2})
|
||||
database.CreateTeam(&model.Team{Id: 20})
|
||||
database.CreateTeam(&model.Team{Id: 200})
|
||||
database.CreateTeam(&model.Team{Id: 101})
|
||||
database.CreateTeam(&model.Team{Id: 102})
|
||||
database.CreateTeam(&model.Team{Id: 103})
|
||||
database.CreateTeam(&model.Team{Id: 104})
|
||||
database.CreateTeam(&model.Team{Id: 201})
|
||||
database.CreateTeam(&model.Team{Id: 202})
|
||||
database.CreateTeam(&model.Team{Id: 203})
|
||||
database.CreateTeam(&model.Team{Id: 204})
|
||||
|
||||
err := CreateOrUpdateWinnerAndFinalistAwards(database, 2, 1)
|
||||
assert.Nil(t, err)
|
||||
awards, _ := database.GetAllAwards()
|
||||
if assert.Equal(t, 6, len(awards)) {
|
||||
assert.Equal(t, model.Award{1, model.FinalistAward, "Finalist", 1, ""}, awards[0])
|
||||
assert.Equal(t, model.Award{2, model.FinalistAward, "Finalist", 10, ""}, awards[1])
|
||||
assert.Equal(t, model.Award{3, model.FinalistAward, "Finalist", 100, ""}, awards[2])
|
||||
assert.Equal(t, model.Award{4, model.WinnerAward, "Winner", 2, ""}, awards[3])
|
||||
assert.Equal(t, model.Award{5, model.WinnerAward, "Winner", 20, ""}, awards[4])
|
||||
assert.Equal(t, model.Award{6, model.WinnerAward, "Winner", 200, ""}, awards[5])
|
||||
if assert.Equal(t, 8, len(awards)) {
|
||||
assert.Equal(t, model.Award{1, model.FinalistAward, "Finalist", 101, ""}, awards[0])
|
||||
assert.Equal(t, model.Award{2, model.FinalistAward, "Finalist", 102, ""}, awards[1])
|
||||
assert.Equal(t, model.Award{3, model.FinalistAward, "Finalist", 103, ""}, awards[2])
|
||||
assert.Equal(t, model.Award{4, model.FinalistAward, "Finalist", 104, ""}, awards[3])
|
||||
assert.Equal(t, model.Award{5, model.WinnerAward, "Winner", 201, ""}, awards[4])
|
||||
assert.Equal(t, model.Award{6, model.WinnerAward, "Winner", 202, ""}, awards[5])
|
||||
assert.Equal(t, model.Award{7, model.WinnerAward, "Winner", 203, ""}, awards[6])
|
||||
assert.Equal(t, model.Award{8, model.WinnerAward, "Winner", 204, ""}, awards[7])
|
||||
}
|
||||
lowerThirds, _ := database.GetAllLowerThirds()
|
||||
if assert.Equal(t, 8, len(lowerThirds)) {
|
||||
if assert.Equal(t, 10, len(lowerThirds)) {
|
||||
assert.Equal(t, "Finalist", lowerThirds[0].TopText)
|
||||
assert.Equal(t, "", lowerThirds[0].BottomText)
|
||||
assert.Equal(t, "Finalist", lowerThirds[1].TopText)
|
||||
assert.Equal(t, "Team 1, ", lowerThirds[1].BottomText)
|
||||
assert.Equal(t, "Winner", lowerThirds[4].TopText)
|
||||
assert.Equal(t, "", lowerThirds[4].BottomText)
|
||||
assert.Equal(t, "Team 101, ", lowerThirds[1].BottomText)
|
||||
assert.Equal(t, "Winner", lowerThirds[5].TopText)
|
||||
assert.Equal(t, "Team 2, ", lowerThirds[5].BottomText)
|
||||
assert.Equal(t, "", lowerThirds[5].BottomText)
|
||||
assert.Equal(t, "Winner", lowerThirds[6].TopText)
|
||||
assert.Equal(t, "Team 201, ", lowerThirds[6].BottomText)
|
||||
}
|
||||
|
||||
err = CreateOrUpdateWinnerAndFinalistAwards(database, 1, 2)
|
||||
assert.Nil(t, err)
|
||||
awards, _ = database.GetAllAwards()
|
||||
if assert.Equal(t, 6, len(awards)) {
|
||||
assert.Equal(t, model.Award{7, model.FinalistAward, "Finalist", 2, ""}, awards[0])
|
||||
assert.Equal(t, model.Award{8, model.FinalistAward, "Finalist", 20, ""}, awards[1])
|
||||
assert.Equal(t, model.Award{9, model.FinalistAward, "Finalist", 200, ""}, awards[2])
|
||||
assert.Equal(t, model.Award{10, model.WinnerAward, "Winner", 1, ""}, awards[3])
|
||||
assert.Equal(t, model.Award{11, model.WinnerAward, "Winner", 10, ""}, awards[4])
|
||||
assert.Equal(t, model.Award{12, model.WinnerAward, "Winner", 100, ""}, awards[5])
|
||||
if assert.Equal(t, 8, len(awards)) {
|
||||
assert.Equal(t, model.Award{9, model.FinalistAward, "Finalist", 201, ""}, awards[0])
|
||||
assert.Equal(t, model.Award{10, model.FinalistAward, "Finalist", 202, ""}, awards[1])
|
||||
assert.Equal(t, model.Award{11, model.FinalistAward, "Finalist", 203, ""}, awards[2])
|
||||
assert.Equal(t, model.Award{12, model.FinalistAward, "Finalist", 204, ""}, awards[3])
|
||||
assert.Equal(t, model.Award{13, model.WinnerAward, "Winner", 101, ""}, awards[4])
|
||||
assert.Equal(t, model.Award{14, model.WinnerAward, "Winner", 102, ""}, awards[5])
|
||||
assert.Equal(t, model.Award{15, model.WinnerAward, "Winner", 103, ""}, awards[6])
|
||||
assert.Equal(t, model.Award{16, model.WinnerAward, "Winner", 104, ""}, awards[7])
|
||||
}
|
||||
lowerThirds, _ = database.GetAllLowerThirds()
|
||||
if assert.Equal(t, 8, len(lowerThirds)) {
|
||||
if assert.Equal(t, 10, len(lowerThirds)) {
|
||||
assert.Equal(t, "Finalist", lowerThirds[0].TopText)
|
||||
assert.Equal(t, "", lowerThirds[0].BottomText)
|
||||
assert.Equal(t, "Finalist", lowerThirds[1].TopText)
|
||||
assert.Equal(t, "Team 2, ", lowerThirds[1].BottomText)
|
||||
assert.Equal(t, "Winner", lowerThirds[4].TopText)
|
||||
assert.Equal(t, "", lowerThirds[4].BottomText)
|
||||
assert.Equal(t, "Team 201, ", lowerThirds[1].BottomText)
|
||||
assert.Equal(t, "Winner", lowerThirds[5].TopText)
|
||||
assert.Equal(t, "Team 1, ", lowerThirds[5].BottomText)
|
||||
assert.Equal(t, "", lowerThirds[5].BottomText)
|
||||
assert.Equal(t, "Winner", lowerThirds[6].TopText)
|
||||
assert.Equal(t, "Team 101, ", lowerThirds[6].BottomText)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,54 +43,60 @@ func UpdateEliminationSchedule(database *model.Database, startTime time.Time) (b
|
||||
matchIndex++
|
||||
}
|
||||
|
||||
return len(winner) > 0, err
|
||||
return winner != nil, err
|
||||
}
|
||||
|
||||
// Updates the alliance, if necessary, to include whoever played in the match, in case there was a substitute.
|
||||
func UpdateAlliance(database *model.Database, matchTeamIds [3]int, allianceId int) error {
|
||||
allianceTeams, err := database.GetTeamsByAlliance(allianceId)
|
||||
alliance, err := database.GetAllianceById(allianceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
changed := false
|
||||
if matchTeamIds != alliance.Lineup {
|
||||
alliance.Lineup = matchTeamIds
|
||||
changed = true
|
||||
}
|
||||
|
||||
for _, teamId := range matchTeamIds {
|
||||
found := false
|
||||
for _, allianceTeam := range allianceTeams {
|
||||
if teamId == allianceTeam.TeamId {
|
||||
for _, allianceTeamId := range alliance.TeamIds {
|
||||
if teamId == allianceTeamId {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
newAllianceTeam := model.AllianceTeam{AllianceId: allianceId, PickPosition: len(allianceTeams),
|
||||
TeamId: teamId}
|
||||
allianceTeams = append(allianceTeams, newAllianceTeam)
|
||||
if err := database.CreateAllianceTeam(&newAllianceTeam); err != nil {
|
||||
return err
|
||||
}
|
||||
alliance.TeamIds = append(alliance.TeamIds, teamId)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
if changed {
|
||||
return database.UpdateAlliance(alliance)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Recursively traverses the elimination bracket downwards, creating matches as necessary. Returns the winner
|
||||
// of the given round if known.
|
||||
func buildEliminationMatchSet(database *model.Database, round int, group int,
|
||||
numAlliances int) ([]model.AllianceTeam, error) {
|
||||
func buildEliminationMatchSet(
|
||||
database *model.Database, round int, group int, numAlliances int,
|
||||
) (*model.Alliance, error) {
|
||||
if numAlliances < 2 {
|
||||
return []model.AllianceTeam{}, fmt.Errorf("Must have at least 2 alliances")
|
||||
return nil, fmt.Errorf("Must have at least 2 alliances")
|
||||
}
|
||||
roundName, ok := model.ElimRoundNames[round]
|
||||
if !ok {
|
||||
return []model.AllianceTeam{}, fmt.Errorf("Round of depth %d is not supported", round*2)
|
||||
return nil, fmt.Errorf("Round of depth %d is not supported", round*2)
|
||||
}
|
||||
if round != 1 {
|
||||
roundName += strconv.Itoa(group)
|
||||
}
|
||||
|
||||
// Recurse to figure out who the involved alliances are.
|
||||
var redAlliance, blueAlliance []model.AllianceTeam
|
||||
var redAlliance, blueAlliance *model.Alliance
|
||||
var err error
|
||||
if numAlliances < 4*round {
|
||||
// This is the first round for some or all alliances and will be at least partially populated from the
|
||||
@@ -102,47 +108,37 @@ func buildEliminationMatchSet(database *model.Database, round int, group int,
|
||||
numDirectAlliances := 4*round - numAlliances
|
||||
if redAllianceNumber <= numDirectAlliances {
|
||||
// The red alliance has a bye or the number of alliances is a power of 2; get from alliance selection.
|
||||
redAlliance, err = database.GetTeamsByAlliance(redAllianceNumber)
|
||||
redAlliance, err = database.GetAllianceById(redAllianceNumber)
|
||||
if err != nil {
|
||||
return []model.AllianceTeam{}, err
|
||||
}
|
||||
|
||||
if len(redAlliance) >= 3 {
|
||||
// Swap the teams around to match the positions dictated by the rules.
|
||||
redAlliance[0], redAlliance[1], redAlliance[2] = redAlliance[1], redAlliance[0], redAlliance[2]
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if blueAllianceNumber <= numDirectAlliances {
|
||||
// The blue alliance has a bye or the number of alliances is a power of 2; get from alliance selection.
|
||||
blueAlliance, err = database.GetTeamsByAlliance(blueAllianceNumber)
|
||||
blueAlliance, err = database.GetAllianceById(blueAllianceNumber)
|
||||
if err != nil {
|
||||
return []model.AllianceTeam{}, err
|
||||
}
|
||||
|
||||
if len(blueAlliance) >= 3 {
|
||||
// Swap the teams around to match the positions dictated by the rules.
|
||||
blueAlliance[0], blueAlliance[1], blueAlliance[2] = blueAlliance[1], blueAlliance[0], blueAlliance[2]
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the alliances aren't known yet, get them from one round down in the bracket.
|
||||
if len(redAlliance) == 0 {
|
||||
if redAlliance == nil {
|
||||
redAlliance, err = buildEliminationMatchSet(database, round*2, group*2-1, numAlliances)
|
||||
if err != nil {
|
||||
return []model.AllianceTeam{}, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if len(blueAlliance) == 0 {
|
||||
if blueAlliance == nil {
|
||||
blueAlliance, err = buildEliminationMatchSet(database, round*2, group*2, numAlliances)
|
||||
if err != nil {
|
||||
return []model.AllianceTeam{}, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Bail if the rounds below are not yet complete and we don't know either alliance competing this round.
|
||||
if len(redAlliance) == 0 && len(blueAlliance) == 0 {
|
||||
return []model.AllianceTeam{}, nil
|
||||
if redAlliance == nil && blueAlliance == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Check if the match set exists already and if it has been won.
|
||||
@@ -150,24 +146,24 @@ func buildEliminationMatchSet(database *model.Database, round int, group int,
|
||||
var ties []model.Match
|
||||
matches, err := database.GetMatchesByElimRoundGroup(round, group)
|
||||
if err != nil {
|
||||
return []model.AllianceTeam{}, err
|
||||
return nil, err
|
||||
}
|
||||
var unplayedMatches []model.Match
|
||||
for _, match := range matches {
|
||||
if !match.IsComplete() {
|
||||
// Update the teams in the match if they are not yet set or are incorrect.
|
||||
if len(redAlliance) != 0 && !(match.Red1 == redAlliance[0].TeamId && match.Red2 == redAlliance[1].TeamId &&
|
||||
match.Red3 == redAlliance[2].TeamId) {
|
||||
if redAlliance != nil && !(match.Red1 == redAlliance.Lineup[0] && match.Red2 == redAlliance.Lineup[1] &&
|
||||
match.Red3 == redAlliance.Lineup[2]) {
|
||||
positionRedTeams(&match, redAlliance)
|
||||
match.ElimRedAlliance = redAlliance[0].AllianceId
|
||||
match.ElimRedAlliance = redAlliance.Id
|
||||
if err = database.UpdateMatch(&match); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if len(blueAlliance) != 0 && !(match.Blue1 == blueAlliance[0].TeamId &&
|
||||
match.Blue2 == blueAlliance[1].TeamId && match.Blue3 == blueAlliance[2].TeamId) {
|
||||
if blueAlliance != nil && !(match.Blue1 == blueAlliance.Lineup[0] &&
|
||||
match.Blue2 == blueAlliance.Lineup[1] && match.Blue3 == blueAlliance.Lineup[2]) {
|
||||
positionBlueTeams(&match, blueAlliance)
|
||||
match.ElimBlueAlliance = blueAlliance[0].AllianceId
|
||||
match.ElimBlueAlliance = blueAlliance.Id
|
||||
if err = database.UpdateMatch(&match); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -178,16 +174,6 @@ func buildEliminationMatchSet(database *model.Database, round int, group int,
|
||||
continue
|
||||
}
|
||||
|
||||
// Reorder the teams based on the last complete match, so that new and unplayed matches use the same positions.
|
||||
err = reorderTeams(match.Red1, match.Red2, match.Red3, redAlliance)
|
||||
if err != nil {
|
||||
return []model.AllianceTeam{}, err
|
||||
}
|
||||
err = reorderTeams(match.Blue1, match.Blue2, match.Blue3, blueAlliance)
|
||||
if err != nil {
|
||||
return []model.AllianceTeam{}, err
|
||||
}
|
||||
|
||||
// Check who won.
|
||||
switch match.Status {
|
||||
case model.RedWonMatch:
|
||||
@@ -197,8 +183,7 @@ func buildEliminationMatchSet(database *model.Database, round int, group int,
|
||||
case model.TieMatch:
|
||||
ties = append(ties, match)
|
||||
default:
|
||||
return []model.AllianceTeam{}, fmt.Errorf("Completed match %d has invalid winner '%s'", match.Id,
|
||||
match.Status)
|
||||
return nil, fmt.Errorf("Completed match %d has invalid winner '%s'", match.Id, match.Status)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +192,7 @@ func buildEliminationMatchSet(database *model.Database, round int, group int,
|
||||
for _, match := range unplayedMatches {
|
||||
err = database.DeleteMatch(match.Id)
|
||||
if err != nil {
|
||||
return []model.AllianceTeam{}, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,32 +207,26 @@ func buildEliminationMatchSet(database *model.Database, round int, group int,
|
||||
// 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 = []model.AllianceTeam{{}, {}, {}}
|
||||
} else if len(blueAlliance) == 0 {
|
||||
blueAlliance = []model.AllianceTeam{{}, {}, {}}
|
||||
}
|
||||
if len(redAlliance) < 3 || len(blueAlliance) < 3 {
|
||||
if redAlliance != nil && len(redAlliance.TeamIds) < 3 || blueAlliance != nil && len(blueAlliance.TeamIds) < 3 {
|
||||
// Raise an error if the alliance selection process gave us less than 3 teams per alliance.
|
||||
return []model.AllianceTeam{}, fmt.Errorf("Alliances must consist of at least 3 teams")
|
||||
return nil, fmt.Errorf("Alliances must consist of at least 3 teams")
|
||||
}
|
||||
if len(matches) < 1 {
|
||||
err = database.CreateMatch(createMatch(roundName, round, group, 1, redAlliance, blueAlliance))
|
||||
if err != nil {
|
||||
return []model.AllianceTeam{}, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if len(matches) < 2 {
|
||||
err = database.CreateMatch(createMatch(roundName, round, group, 2, redAlliance, blueAlliance))
|
||||
if err != nil {
|
||||
return []model.AllianceTeam{}, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if len(matches) < 3 {
|
||||
err = database.CreateMatch(createMatch(roundName, round, group, 3, redAlliance, blueAlliance))
|
||||
if err != nil {
|
||||
return []model.AllianceTeam{}, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -258,54 +237,51 @@ func buildEliminationMatchSet(database *model.Database, round int, group int,
|
||||
err = database.CreateMatch(createMatch(roundName, round, group, len(matches)+index+1, redAlliance,
|
||||
blueAlliance))
|
||||
if err != nil {
|
||||
return []model.AllianceTeam{}, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return []model.AllianceTeam{}, nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Creates a match at the given point in the elimination bracket and populates the teams.
|
||||
func createMatch(roundName string, round int, group int, instance int, redAlliance,
|
||||
blueAlliance []model.AllianceTeam) *model.Match {
|
||||
match := model.Match{Type: "elimination", DisplayName: fmt.Sprintf("%s-%d", roundName, instance),
|
||||
ElimRound: round, ElimGroup: group, ElimInstance: instance, ElimRedAlliance: redAlliance[0].AllianceId,
|
||||
ElimBlueAlliance: blueAlliance[0].AllianceId}
|
||||
positionRedTeams(&match, redAlliance)
|
||||
positionBlueTeams(&match, blueAlliance)
|
||||
func createMatch(
|
||||
roundName string,
|
||||
round int,
|
||||
group int,
|
||||
instance int,
|
||||
redAlliance,
|
||||
blueAlliance *model.Alliance,
|
||||
) *model.Match {
|
||||
match := model.Match{
|
||||
Type: "elimination",
|
||||
DisplayName: fmt.Sprintf("%s-%d", roundName, instance),
|
||||
ElimRound: round,
|
||||
ElimGroup: group,
|
||||
ElimInstance: instance,
|
||||
}
|
||||
if redAlliance != nil {
|
||||
match.ElimRedAlliance = redAlliance.Id
|
||||
positionRedTeams(&match, redAlliance)
|
||||
}
|
||||
if blueAlliance != nil {
|
||||
match.ElimBlueAlliance = blueAlliance.Id
|
||||
positionBlueTeams(&match, blueAlliance)
|
||||
}
|
||||
return &match
|
||||
}
|
||||
|
||||
// Assigns the first three teams from the alliance into the red team slots for the match.
|
||||
func positionRedTeams(match *model.Match, alliance []model.AllianceTeam) {
|
||||
match.Red1 = alliance[0].TeamId
|
||||
match.Red2 = alliance[1].TeamId
|
||||
match.Red3 = alliance[2].TeamId
|
||||
// Assigns the lineup from the alliance into the red team slots for the match.
|
||||
func positionRedTeams(match *model.Match, alliance *model.Alliance) {
|
||||
match.Red1 = alliance.Lineup[0]
|
||||
match.Red2 = alliance.Lineup[1]
|
||||
match.Red3 = alliance.Lineup[2]
|
||||
}
|
||||
|
||||
// Assigns the first three teams from the alliance into the blue team slots for the match.
|
||||
func positionBlueTeams(match *model.Match, alliance []model.AllianceTeam) {
|
||||
match.Blue1 = alliance[0].TeamId
|
||||
match.Blue2 = alliance[1].TeamId
|
||||
match.Blue3 = alliance[2].TeamId
|
||||
}
|
||||
|
||||
// Swaps the order of teams in the alliance to match the match positioning.
|
||||
func reorderTeams(team1, team2, team3 int, alliance []model.AllianceTeam) error {
|
||||
for i, team := range []int{team1, team2, team3} {
|
||||
found := false
|
||||
for j, oldTeam := range alliance {
|
||||
if team == oldTeam.TeamId {
|
||||
alliance[i], alliance[j] = alliance[j], alliance[i]
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("Team %d not found in alliance %v", team, alliance)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
// Assigns the lineup from the alliance into the blue team slots for the match.
|
||||
func positionBlueTeams(match *model.Match, alliance *model.Alliance) {
|
||||
match.Blue1 = alliance.Lineup[0]
|
||||
match.Blue2 = alliance.Lineup[1]
|
||||
match.Blue3 = alliance.Lineup[2]
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[1], "F-2", 1, 2)
|
||||
assertMatch(t, matches[2], "F-3", 1, 2)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 3)
|
||||
@@ -39,7 +39,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[4], "F-2", 1, 0)
|
||||
assertMatch(t, matches[5], "F-3", 1, 0)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 4)
|
||||
@@ -55,7 +55,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[4], "SF1-3", 1, 4)
|
||||
assertMatch(t, matches[5], "SF2-3", 2, 3)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 5)
|
||||
@@ -74,7 +74,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[7], "SF1-3", 1, 0)
|
||||
assertMatch(t, matches[8], "SF2-3", 2, 3)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 6)
|
||||
@@ -96,7 +96,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[10], "SF1-3", 1, 0)
|
||||
assertMatch(t, matches[11], "SF2-3", 2, 0)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 7)
|
||||
@@ -118,7 +118,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[10], "SF1-2", 1, 0)
|
||||
assertMatch(t, matches[11], "SF1-3", 1, 0)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 8)
|
||||
@@ -140,7 +140,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[10], "QF3-3", 2, 7)
|
||||
assertMatch(t, matches[11], "QF4-3", 3, 6)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 9)
|
||||
@@ -165,7 +165,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[13], "QF3-3", 2, 7)
|
||||
assertMatch(t, matches[14], "QF4-3", 3, 6)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 10)
|
||||
@@ -193,7 +193,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[16], "QF3-3", 2, 0)
|
||||
assertMatch(t, matches[17], "QF4-3", 3, 6)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 11)
|
||||
@@ -224,7 +224,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[19], "QF3-3", 2, 0)
|
||||
assertMatch(t, matches[20], "QF4-3", 3, 0)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 12)
|
||||
@@ -258,7 +258,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[22], "QF3-3", 2, 0)
|
||||
assertMatch(t, matches[23], "QF4-3", 3, 0)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 13)
|
||||
@@ -292,7 +292,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[22], "QF3-3", 2, 0)
|
||||
assertMatch(t, matches[23], "QF4-3", 3, 0)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 14)
|
||||
@@ -326,7 +326,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[22], "QF1-3", 1, 0)
|
||||
assertMatch(t, matches[23], "QF3-3", 2, 0)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 15)
|
||||
@@ -360,7 +360,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[22], "QF1-2", 1, 0)
|
||||
assertMatch(t, matches[23], "QF1-3", 1, 0)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
|
||||
CreateTestAlliances(database, 16)
|
||||
@@ -394,7 +394,7 @@ func TestEliminationScheduleInitial(t *testing.T) {
|
||||
assertMatch(t, matches[22], "EF7-3", 3, 14)
|
||||
assertMatch(t, matches[23], "EF8-3", 6, 11)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
}
|
||||
|
||||
@@ -406,24 +406,22 @@ func TestEliminationScheduleErrors(t *testing.T) {
|
||||
if assert.NotNil(t, err) {
|
||||
assert.Equal(t, "Must have at least 2 alliances", err.Error())
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
|
||||
CreateTestAlliances(database, 17)
|
||||
_, err = UpdateEliminationSchedule(database, time.Unix(0, 0))
|
||||
if assert.NotNil(t, err) {
|
||||
assert.Equal(t, "Round of depth 32 is not supported", err.Error())
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
|
||||
database.CreateAllianceTeam(&model.AllianceTeam{0, 1, 0, 1})
|
||||
database.CreateAllianceTeam(&model.AllianceTeam{0, 1, 1, 2})
|
||||
database.CreateAllianceTeam(&model.AllianceTeam{0, 2, 0, 3})
|
||||
database.CreateAllianceTeam(&model.AllianceTeam{0, 2, 1, 4})
|
||||
database.CreateAlliance(&model.Alliance{Id: 1, TeamIds: []int{1, 2}})
|
||||
database.CreateAlliance(&model.Alliance{Id: 2, TeamIds: []int{3, 4}})
|
||||
_, err = UpdateEliminationSchedule(database, time.Unix(0, 0))
|
||||
if assert.NotNil(t, err) {
|
||||
assert.Equal(t, "Alliances must consist of at least 3 teams", err.Error())
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
}
|
||||
|
||||
func TestEliminationSchedulePopulatePartialMatch(t *testing.T) {
|
||||
@@ -443,7 +441,7 @@ func TestEliminationSchedulePopulatePartialMatch(t *testing.T) {
|
||||
assertMatch(t, matches[3], "F-2", 1, 3)
|
||||
assertMatch(t, matches[4], "F-3", 1, 3)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
database.TruncateMatchResults()
|
||||
|
||||
@@ -472,7 +470,7 @@ func TestEliminationSchedulePopulatePartialMatch(t *testing.T) {
|
||||
assertMatch(t, matches[5], "F-2", 1, 2)
|
||||
assertMatch(t, matches[6], "F-3", 1, 2)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
database.TruncateMatchResults()
|
||||
}
|
||||
@@ -533,7 +531,7 @@ func TestEliminationScheduleDetermineWinner(t *testing.T) {
|
||||
}
|
||||
matches, _ = database.GetMatchesByType("elimination")
|
||||
assert.Equal(t, 3, len(matches))
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
database.TruncateMatchResults()
|
||||
|
||||
@@ -568,7 +566,7 @@ func TestEliminationScheduleDetermineWinner(t *testing.T) {
|
||||
if assert.Nil(t, err) {
|
||||
assert.True(t, won)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
database.TruncateMatchResults()
|
||||
|
||||
@@ -600,7 +598,7 @@ func TestEliminationScheduleDetermineWinner(t *testing.T) {
|
||||
if assert.Nil(t, err) {
|
||||
assert.True(t, won)
|
||||
}
|
||||
database.TruncateAllianceTeams()
|
||||
database.TruncateAlliances()
|
||||
database.TruncateMatches()
|
||||
database.TruncateMatchResults()
|
||||
|
||||
@@ -737,20 +735,22 @@ func TestEliminationScheduleTeamPositions(t *testing.T) {
|
||||
matches, _ := database.GetMatchesByType("elimination")
|
||||
match1 := matches[0]
|
||||
match2 := matches[1]
|
||||
assert.Equal(t, 10, match1.Red1)
|
||||
assert.Equal(t, 1, match1.Red2)
|
||||
assert.Equal(t, 100, match1.Red3)
|
||||
assert.Equal(t, 30, match2.Blue1)
|
||||
assert.Equal(t, 3, match2.Blue2)
|
||||
assert.Equal(t, 300, match2.Blue3)
|
||||
assert.Equal(t, 102, match1.Red1)
|
||||
assert.Equal(t, 101, match1.Red2)
|
||||
assert.Equal(t, 103, match1.Red3)
|
||||
assert.Equal(t, 302, match2.Blue1)
|
||||
assert.Equal(t, 301, match2.Blue2)
|
||||
assert.Equal(t, 303, match2.Blue3)
|
||||
|
||||
// Shuffle the team positions and check that the subsequent matches in the same round have the same ones.
|
||||
match1.Red1, match1.Red2 = match1.Red2, match1.Red1
|
||||
match2.Blue1, match2.Blue3 = match2.Blue3, match2.Blue1
|
||||
match1.Red1, match1.Red2 = match1.Red2, 104
|
||||
match2.Blue1, match2.Blue3 = 305, match2.Blue1
|
||||
database.UpdateMatch(&match1)
|
||||
database.UpdateMatch(&match2)
|
||||
scoreMatch(database, "SF1-1", model.RedWonMatch)
|
||||
scoreMatch(database, "SF2-1", model.BlueWonMatch)
|
||||
assert.Nil(t, UpdateAlliance(database, [3]int{match1.Red1, match1.Red2, match1.Red3}, 1))
|
||||
assert.Nil(t, UpdateAlliance(database, [3]int{match2.Blue1, match2.Blue2, match2.Blue3}, 3))
|
||||
UpdateEliminationSchedule(database, time.Unix(1000, 0))
|
||||
matches, _ = database.GetMatchesByType("elimination")
|
||||
if assert.Equal(t, 6, len(matches)) {
|
||||
@@ -783,10 +783,28 @@ func TestEliminationScheduleTeamPositions(t *testing.T) {
|
||||
|
||||
func assertMatch(t *testing.T, match model.Match, displayName string, redAlliance int, blueAlliance int) {
|
||||
assert.Equal(t, displayName, match.DisplayName)
|
||||
assert.Equal(t, redAlliance, match.Red2)
|
||||
assert.Equal(t, redAlliance, match.ElimRedAlliance)
|
||||
assert.Equal(t, blueAlliance, match.Blue2)
|
||||
assert.Equal(t, blueAlliance, match.ElimBlueAlliance)
|
||||
|
||||
if redAlliance > 0 {
|
||||
assert.Equal(t, 100*redAlliance+2, match.Red1)
|
||||
assert.Equal(t, 100*redAlliance+1, match.Red2)
|
||||
assert.Equal(t, 100*redAlliance+3, match.Red3)
|
||||
} else {
|
||||
assert.Equal(t, 0, match.Red1)
|
||||
assert.Equal(t, 0, match.Red2)
|
||||
assert.Equal(t, 0, match.Red3)
|
||||
}
|
||||
|
||||
if blueAlliance > 0 {
|
||||
assert.Equal(t, 100*blueAlliance+2, match.Blue1)
|
||||
assert.Equal(t, 100*blueAlliance+1, match.Blue2)
|
||||
assert.Equal(t, 100*blueAlliance+3, match.Blue3)
|
||||
} else {
|
||||
assert.Equal(t, 0, match.Blue1)
|
||||
assert.Equal(t, 0, match.Blue2)
|
||||
assert.Equal(t, 0, match.Blue3)
|
||||
}
|
||||
}
|
||||
|
||||
func scoreMatch(database *model.Database, displayName string, winner model.MatchStatus) {
|
||||
|
||||
@@ -12,9 +12,12 @@ import (
|
||||
|
||||
func CreateTestAlliances(database *model.Database, allianceCount int) {
|
||||
for i := 1; i <= allianceCount; i++ {
|
||||
database.CreateAllianceTeam(&model.AllianceTeam{0, i, 0, i})
|
||||
database.CreateAllianceTeam(&model.AllianceTeam{0, i, 1, 10 * i})
|
||||
database.CreateAllianceTeam(&model.AllianceTeam{0, i, 2, 100 * i})
|
||||
alliance := model.Alliance{
|
||||
Id: i,
|
||||
TeamIds: []int{100*i + 1, 100*i + 2, 100*i + 3, 100*i + 4},
|
||||
Lineup: [3]int{100*i + 2, 100*i + 1, 100*i + 3},
|
||||
}
|
||||
database.CreateAlliance(&alliance)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user