def _test_match_generation(self, teams, multiplier=1): """Test even-numbered round-robin match generation (actual code).""" meetings = multiplier * 2 scheduler = RoundRobinScheduler(teams, meetings=meetings) expected = list(itertools.permutations(scheduler.teams, 2)) * multiplier matches = scheduler.generate_matches() self.assertCountEqual(expected, matches, ('Incorrect matches generated for even-numbered ' 'round-robin schedule with {} meetings for ' '{} teams.').format(meetings, teams))
def _test_match_generation(self, teams, evens=0, known_home_teams=None): """Test odd-numbered round-robin match generation.""" meetings = 2 * evens + 1 team_list = list(range(1, teams + 1)) scheduler = RoundRobinScheduler(teams, meetings=meetings) self.assertSequenceEqual(scheduler.home_teams, (), 'Default home teams not returned.') matches = scheduler.generate_matches(home_teams=known_home_teams) if known_home_teams: self.assertSequenceEqual(known_home_teams, scheduler.home_teams, 'Home teams not stored.') homes = [match[0] for match in matches] aways = [match[1] for match in matches] home_teams = 0 away_teams = 0 odd_teams = teams % 2 == 1 if odd_teams: teams += 1 team_list.append(None) more_matches = evens * (teams - 1) + int(teams / 2) less_matches = more_matches - 1 home_match_counts = collections.Counter(homes) away_match_counts = collections.Counter(aways) for team in team_list: home_count = home_match_counts[team] away_count = away_match_counts[team] self.assertTrue( (home_count == more_matches or home_count == less_matches), 'Team has an illegal number of home matches.') self.assertTrue( (away_count == more_matches or away_count == less_matches), 'Team has an illegal number of away matches.') if home_count == more_matches: if known_home_teams: self.assertIn(team, known_home_teams, 'Home team designation violated.') self.assertEqual(away_count, less_matches, 'Wrong number of away matches.') home_teams += 1 else: if known_home_teams: self.assertNotIn(team, known_home_teams, 'Away team designation violated.') self.assertEqual(away_count, more_matches, 'Wrong number of away matches.') away_teams += 1 self.assertEqual(home_teams, away_teams, 'Home and away team counts not balanced.')
def _test_match_generation(self, teams, evens=0, known_home_teams=None): """Test odd-numbered round-robin match generation.""" meetings = 2 * evens + 1 team_list = list(range(1, teams + 1)) scheduler = RoundRobinScheduler(teams, meetings=meetings) self.assertSequenceEqual(scheduler.home_teams, (), 'Default home teams not returned.') matches = scheduler.generate_matches(home_teams=known_home_teams) if known_home_teams: self.assertSequenceEqual(known_home_teams, scheduler.home_teams, 'Home teams not stored.') homes = [match[0] for match in matches] aways = [match[1] for match in matches] home_teams = 0 away_teams = 0 odd_teams = teams % 2 == 1 if odd_teams: teams += 1 team_list.append(None) more_matches = evens * (teams - 1) + int(teams / 2) less_matches = more_matches - 1 home_match_counts = collections.Counter(homes) away_match_counts = collections.Counter(aways) for team in team_list: home_count = home_match_counts[team] away_count = away_match_counts[team] self.assertTrue((home_count == more_matches or home_count == less_matches), 'Team has an illegal number of home matches.') self.assertTrue((away_count == more_matches or away_count == less_matches), 'Team has an illegal number of away matches.') if home_count == more_matches: if known_home_teams: self.assertIn(team, known_home_teams, 'Home team designation violated.') self.assertEqual(away_count, less_matches, 'Wrong number of away matches.') home_teams += 1 else: if known_home_teams: self.assertNotIn(team, known_home_teams, 'Away team designation violated.') self.assertEqual(away_count, more_matches, 'Wrong number of away matches.') away_teams += 1 self.assertEqual(home_teams, away_teams, 'Home and away team counts not balanced.')
def _test_matrix_generation(self, meetings, teams, known_home_teams=None): """Test odd-numbered round-robin matrix generation.""" scheduler = RoundRobinScheduler(teams, meetings=meetings) self.assertSequenceEqual(scheduler.home_teams, (), 'Default home teams not returned.') matrix = scheduler.generate_matrix(home_teams=known_home_teams) if known_home_teams: self.assertSequenceEqual(known_home_teams, scheduler.home_teams, 'Home teams not stored.') home_teams = 0 away_teams = 0 odd_teams = teams % 2 == 1 if odd_teams: teams += 1 for x in range(teams): self.assertIsNone(matrix[x][x], 'Match against self not None.') opponents = matrix[x] home_count = opponents.count(True) away_count = opponents.count(False) if home_count > away_count: home_teams += 1 if known_home_teams: self.assertIn(scheduler.teams[x], known_home_teams, 'Home team designation violated.') self.assertEqual(home_count, away_count + 1, 'Team has too many home opponents.') if odd_teams and x != teams - 1: self.assertTrue(opponents[-1], 'Home excess not balanced by bye round.') else: away_teams += 1 if known_home_teams: self.assertNotIn(scheduler.teams[x], known_home_teams, 'Away team designation violated.') self.assertEqual(away_count, home_count + 1, 'Team has too many away opponents.') if odd_teams and x != teams - 1: self.assertFalse(opponents[-1], 'Away excess not balanced by bye round.') self.assertEqual(home_teams, away_teams, 'Home and away team counts not balanced.')
def test_wrappers(self): """Test that named RoundRobinScheduler wrappers are equivalent.""" wrappers = [ SingleRoundRobinScheduler, DoubleRoundRobinScheduler, TripleRoundRobinScheduler, QuadrupleRoundRobinScheduler ] for i in range(4): meetings = i + 1 wrapper = wrappers[i] direct_scheduler = RoundRobinScheduler(4, meetings=meetings) wrapped_scheduler = wrapper(4) self.assertTrue( issubclass(wrapped_scheduler.__class__, direct_scheduler.__class__), 'Wrapper class is not a subclass of base class.') self.assertEqual( direct_scheduler.find_unique_match, wrapped_scheduler.find_unique_match, 'find_unique_match different in base and wrapper.') self.assertEqual(direct_scheduler.matches_share_opponents, wrapped_scheduler.matches_share_opponents, ('matches_share_opponents different in base and ' 'wrapper.')) self.assertEqual( direct_scheduler.generate_matches.__func__, wrapped_scheduler.generate_matches.__func__, 'generate_matches different in base and wrapper.') self.assertEqual(direct_scheduler.generate_matrix.__func__, wrapped_scheduler.generate_matrix.__func__, 'generate_matrix different in base and wrapper.') self.assertEqual(direct_scheduler.generate_round.__func__, wrapped_scheduler.generate_round.__func__, 'generate_round different in base and wrapper.') self.assertEqual( direct_scheduler.generate_schedule.__func__, wrapped_scheduler.generate_schedule.__func__, 'generate_schedule different in base and wrapper.')
def test_schedule_generation(self): """Test sextuple round-robin schedule generation.""" scheduler = RoundRobinScheduler(6, meetings=6) # Failed attempt random.seed(35) self.assertRaises(ScheduleGenerationFailed, scheduler.generate_schedule, try_once=True) # Successful attempt random.seed(1) if PY2: expected_schedule = [[(6, 4), (3, 1), (2, 5)], [(3, 1), (6, 5), (4, 2)], [(6, 1), (2, 3), (5, 4)], [(5, 1), (2, 6), (3, 4)], [(1, 6), (2, 5), (3, 4)], [(5, 6), (4, 3), (2, 1)], [(2, 6), (3, 5), (4, 1)], [(3, 1), (2, 5), (4, 6)], [(1, 4), (3, 5), (6, 2)], [(1, 2), (5, 4), (6, 3)], [(5, 2), (6, 4), (1, 3)], [(1, 3), (4, 2), (6, 5)], [(5, 3), (2, 6), (4, 1)], [(5, 1), (4, 6), (3, 2)], [(3, 2), (1, 6), (4, 5)], [(1, 3), (4, 6), (5, 2)], [(3, 6), (4, 5), (2, 1)], [(2, 3), (4, 5), (1, 6)], [(1, 2), (5, 3), (6, 4)], [(4, 1), (3, 2), (6, 5)], [(1, 4), (6, 3), (5, 2)], [(1, 5), (3, 6), (4, 2)], [(5, 1), (2, 4), (6, 3)], [(1, 2), (3, 6), (5, 4)], [(5, 6), (1, 4), (2, 3)], [(5, 3), (6, 1), (2, 4)], [(4, 3), (1, 5), (6, 2)], [(2, 1), (3, 4), (5, 6)], [(6, 1), (2, 4), (3, 5)], [(1, 5), (6, 2), (4, 3)]] elif PY3: expected_schedule = [[(6, 4), (2, 3), (5, 1)], [(4, 5), (1, 2), (3, 6)], [(3, 4), (1, 2), (6, 5)], [(2, 6), (5, 3), (4, 1)], [(6, 3), (1, 5), (2, 4)], [(5, 6), (3, 2), (1, 4)], [(6, 1), (4, 2), (5, 3)], [(1, 3), (6, 4), (5, 2)], [(5, 1), (3, 4), (6, 2)], [(4, 1), (5, 6), (3, 2)], [(4, 5), (6, 1), (2, 3)], [(2, 1), (5, 4), (3, 6)], [(6, 2), (4, 5), (3, 1)], [(1, 5), (2, 4), (3, 6)], [(2, 6), (1, 5), (4, 3)], [(4, 6), (2, 1), (5, 3)], [(3, 1), (2, 5), (6, 4)], [(1, 6), (4, 2), (3, 5)], [(6, 1), (2, 3), (5, 4)], [(1, 4), (6, 2), (3, 5)], [(5, 2), (1, 4), (6, 3)], [(5, 6), (2, 4), (3, 1)], [(3, 4), (6, 5), (1, 2)], [(2, 5), (4, 1), (6, 3)], [(4, 3), (5, 1), (2, 6)], [(2, 5), (4, 6), (1, 3)], [(1, 3), (5, 2), (4, 6)], [(1, 6), (5, 4), (3, 2)], [(2, 1), (4, 3), (6, 5)], [(3, 5), (1, 6), (4, 2)]] schedule = scheduler.generate_schedule(try_once=True) self.assertListEqual(expected_schedule, schedule, ('Wrong schedule created for ' 'sextuple round-robin competition'))
def test_schedule_generation(self): """Test sextuple round-robin schedule generation.""" scheduler = RoundRobinScheduler(6, meetings=6) # Failed attempt random.seed(35) self.assertRaises(ScheduleGenerationFailed, scheduler.generate_schedule, try_once=True) # Successful attempt random.seed(1) if PY2: expected_schedule = [ [(6, 4), (3, 1), (2, 5)], [(3, 1), (6, 5), (4, 2)], [(6, 1), (2, 3), (5, 4)], [(5, 1), (2, 6), (3, 4)], [(1, 6), (2, 5), (3, 4)], [(5, 6), (4, 3), (2, 1)], [(2, 6), (3, 5), (4, 1)], [(3, 1), (2, 5), (4, 6)], [(1, 4), (3, 5), (6, 2)], [(1, 2), (5, 4), (6, 3)], [(5, 2), (6, 4), (1, 3)], [(1, 3), (4, 2), (6, 5)], [(5, 3), (2, 6), (4, 1)], [(5, 1), (4, 6), (3, 2)], [(3, 2), (1, 6), (4, 5)], [(1, 3), (4, 6), (5, 2)], [(3, 6), (4, 5), (2, 1)], [(2, 3), (4, 5), (1, 6)], [(1, 2), (5, 3), (6, 4)], [(4, 1), (3, 2), (6, 5)], [(1, 4), (6, 3), (5, 2)], [(1, 5), (3, 6), (4, 2)], [(5, 1), (2, 4), (6, 3)], [(1, 2), (3, 6), (5, 4)], [(5, 6), (1, 4), (2, 3)], [(5, 3), (6, 1), (2, 4)], [(4, 3), (1, 5), (6, 2)], [(2, 1), (3, 4), (5, 6)], [(6, 1), (2, 4), (3, 5)], [(1, 5), (6, 2), (4, 3)] ] elif PY3: expected_schedule = [ [(6, 4), (2, 3), (5, 1)], [(4, 5), (1, 2), (3, 6)], [(3, 4), (1, 2), (6, 5)], [(2, 6), (5, 3), (4, 1)], [(6, 3), (1, 5), (2, 4)], [(5, 6), (3, 2), (1, 4)], [(6, 1), (4, 2), (5, 3)], [(1, 3), (6, 4), (5, 2)], [(5, 1), (3, 4), (6, 2)], [(4, 1), (5, 6), (3, 2)], [(4, 5), (6, 1), (2, 3)], [(2, 1), (5, 4), (3, 6)], [(6, 2), (4, 5), (3, 1)], [(1, 5), (2, 4), (3, 6)], [(2, 6), (1, 5), (4, 3)], [(4, 6), (2, 1), (5, 3)], [(3, 1), (2, 5), (6, 4)], [(1, 6), (4, 2), (3, 5)], [(6, 1), (2, 3), (5, 4)], [(1, 4), (6, 2), (3, 5)], [(5, 2), (1, 4), (6, 3)], [(5, 6), (2, 4), (3, 1)], [(3, 4), (6, 5), (1, 2)], [(2, 5), (4, 1), (6, 3)], [(4, 3), (5, 1), (2, 6)], [(2, 5), (4, 6), (1, 3)], [(1, 3), (5, 2), (4, 6)], [(1, 6), (5, 4), (3, 2)], [(2, 1), (4, 3), (6, 5)], [(3, 5), (1, 6), (4, 2)] ] schedule = scheduler.generate_schedule(try_once=True) self.assertListEqual(expected_schedule, schedule, ('Wrong schedule created for ' 'sextuple round-robin competition'))