def test_throws_error_on_impossible_pairing(self): teams = [ get_team(1, past_pairings=[2], wins=2), get_team(2, past_pairings=[1]) ] matchups = [{"p": 1, "d": 2}] with self.assertRaises(Exception): resolve_impermissibles(matchups, teams, 2)
def test_prefers_larger_rank_sum(self): with self.subTest("6 teams"): teams = [ get_team(1), get_team(2), get_team(3, school=10), get_team(4, school=10), get_team(5), get_team(6) ] # Should swap 4 and 5 matchups = [ {"p": 1, "d": 2}, {"p": 4, "d": 3}, {"p": 5, "d": 6}, ] self.pairings = resolve_impermissibles(matchups, teams, 3) self.assertPairingExists(5, 3, enforce_sides=True) self.assertPairingExists(4, 6, enforce_sides=True) with self.subTest("8 teams"): teams = [ get_team(i) for i in range(1, 9) ] teams[4]['school'] = 13 # Team 5 teams[5]['school'] = 13 # Team 6 matchups = [ {"p": 1, "d": 2}, {"p": 4, "d": 3}, {"p": 5, "d": 6}, {"p": 8, "d": 7}, ] self.pairings = resolve_impermissibles(matchups, teams, 2) self.assertPairingExists(5, 7, enforce_sides=True) self.assertPairingExists(8, 6, enforce_sides=True)
def test_doesnt_pair_teams_twice(self): teams = [ get_team(1, past_pairings=[2]), get_team(2, past_pairings=[1]), get_team(3, past_pairings=[4]), get_team(4, past_pairings=[3]) ] matchups = [ {"p": 1, "d": 2}, {"p": 4, "d": 3} ] self.pairings = resolve_impermissibles(matchups, teams, 1) self.assertPairingExists(1, 3, enforce_sides=True) self.assertPairingExists(4, 2, enforce_sides=True)
def test_forbids_same_school_matchup(self): teams = [ get_team(1, school=1), get_team(2, school=1), get_team(3), get_team(4) ] matchups = [ {"p": 1, "d": 2}, {"p": 4, "d": 3} ] self.pairings = resolve_impermissibles(matchups, teams, 1) self.assertPairingExists(1, 3) self.assertPairingExists(2, 4)
def generate_round(round_num, teams, coin_flip: str, r3_coin_flip="Heads"): teams_copy = teams[:] random.shuffle(teams_copy) if (round_num > 1): teams_copy.sort(key=lambda team: -team.get("id") if coin_flip == "Heads" else team.get("id")) teams_copy.sort(key=get_order_info_for_team, reverse=True) [p_teams, d_teams] = separate_pl_and_def_teams(round_num, teams_copy, r3_coin_flip) pairings = [{"p": p, "d": d} for (p, d) in zip(p_teams, d_teams)] pairings = resolve_impermissibles(pairings, teams, round_num) return pairings
def test_prefers_small_ballot_diff(self): teams = [ get_team(1, wins=2, side=Side.PI), get_team(2, wins=1, side=Side.PI, past_pairings=[5]), get_team(3, wins=0, side=Side.PI), get_team(4, wins=1, ties=1, side=Side.DEF), get_team(5, wins=1, side=Side.DEF, past_pairings=[2]), get_team(6, side=Side.DEF) ] matchups = [ {"p": 1, "d": 4}, {"p": 2, "d": 5}, {"p": 3, "d": 6} ] self.pairings = resolve_impermissibles(matchups, teams, 2) self.assertPairingExists(1, 5, enforce_sides=True) self.assertPairingExists(2, 4, enforce_sides=True)
def test_switches_same_side_for_r2(self): teams = [ get_team(1), get_team(2, past_pairings=[5]), get_team(3), get_team(4), get_team(5, past_pairings=[2]), get_team(6) ] matchups = [ {"p": 1, "d": 4}, {"p": 2, "d": 5}, {"p": 3, "d": 6} ] self.pairings = resolve_impermissibles(matchups, teams, 2) self.assertPairingExists(2, 6, enforce_sides=True) self.assertPairingExists(3, 5, enforce_sides=True)
def test_looks_beyond_adjacent_neighbors_when_necessary(self): teams = [ get_team(1, past_pairings=[5]), get_team(2, school=12, past_pairings=[4]), get_team(3), get_team(4, past_pairings=[2]), get_team(5, school=12, past_pairings=[1]), get_team(6), ] # Should switch 4/5, then 1/2, then 5/6 matchups = [ {"p": 1, "d": 4}, {"p": 2, "d": 5}, {"p": 3, "d": 6}, ] self.pairings = resolve_impermissibles(matchups, teams, 2) self.assertPairingExists(2, 6, enforce_sides=True) self.assertPairingExists(1, 4, enforce_sides=True) self.assertPairingExists(3, 5, enforce_sides=True)
def test_doesnt_repeat_swap(self): teams = [ get_team(1), get_team(2), get_team(3, school=10), get_team(4, school=10), get_team(5, school=10), get_team(6) ] # Should swap 4 and 5, then 2 and 3 matchups = [ {"p": 1, "d": 2}, {"p": 4, "d": 3}, {"p": 5, "d": 6}, ] self.pairings = resolve_impermissibles(matchups, teams, 3) self.assertPairingExists(1, 3, enforce_sides=True) self.assertPairingExists(5, 2, enforce_sides=True) self.assertPairingExists(4, 6, enforce_sides=True)
def test_finds_deeper_impermissible(self): teams = [ get_team(1), get_team(2), get_team(3), get_team(4), get_team(5, past_pairings=[6]), get_team(6, past_pairings=[5]), get_team(7), get_team(8) ] matchups = [ {"p": 1, "d": 2}, {"p": 4, "d": 3}, {"p": 5, "d": 6}, {"p": 8, "d": 7}, ] self.pairings = resolve_impermissibles(matchups, teams, 1) self.assertPairingExists(5, 7, True) self.assertPairingExists(8, 6, True)
def test_prefers_swapping_def(self): """ Original grid: 1 ≠ 4 2 5 3 ≠ 6 If P swaps, this becomes 2 4 1 5 3 ≠ 6 Then, 5 and 6 swap, and 3 is matched against 5. If D is swapped, it becomes 1 5 2 4 3 ≠ 6 Then, 4 and 6 are swapped, and 3 is matched against 4 """ teams = [ get_team(1, wins=1, school=10), get_team(2, wins=1, past_pairings=[4]), get_team(3, school=19), get_team(4, wins=1, school=10, past_pairings=[2]), get_team(5, wins=1), get_team(6, wins=1, school=19), ] matchups = [ {"p": 1, "d": 4}, {"p": 2, "d": 5}, {"p": 3, "d": 6}, ] self.pairings = resolve_impermissibles(matchups, teams, 2) self.assertPairingExists(3, 4)