def test__generate_teams_returns_correct_number_of_teams(self): subject = schedule_generator.ScheduleGenerator() teams = subject._generate_teams() expected_num_teams = NUM_CONFERENCES * NUM_DIVISIONS_PER_CONFERENCE * NUM_TEAMS_PER_DIVISION self.assertEqual(expected_num_teams, len(teams))
def test_simulate_season(self): subject = league.League(num_players=10, schedule=schedule_generator.ScheduleGenerator( ).generate_schedule()) subject.simulate_season() num_still_alive = len([p for p in subject.PLAYERS if p.is_alive()]) self.assertTrue(num_still_alive < len(subject.PLAYERS)) self.assertEqual(subject._num_active_players(), num_still_alive)
def test_generate_schedule_returns_correct_number_of_weeks_with_correct_number_of_games( self): subject = schedule_generator.ScheduleGenerator() result = subject.generate_schedule().weeks self.assertEqual(len(result), NUM_WEEKS) for week in result: self.assertTrue( len(week.games) <= NUM_CONFERENCES * NUM_DIVISIONS_PER_CONFERENCE * NUM_TEAMS_PER_DIVISION / 2.0)
def test__num_active_players(self): subject = league.League(num_players=10, schedule=schedule_generator.ScheduleGenerator( ).generate_schedule()) self.assertEqual(subject._num_active_players(), len(subject.PLAYERS)) subject.PLAYERS[0].eliminate(0) self.assertEqual(subject._num_active_players(), len(subject.PLAYERS) - 1)
def test__choose_teams(self): subject = league.League(num_players=10, schedule=schedule_generator.ScheduleGenerator( ).generate_schedule()) with patch('survivor_league.player.Player.choose_team', return_value='winner'): choices = subject._choose_teams(subject.SCHEDULE.weeks[0].games) for player in subject.PLAYERS: self.assertTrue(player.name() in choices) self.assertEqual(choices[player.name()], 'winner')
def test__determine_game_winners(self): subject = league.League(num_players=10, schedule=schedule_generator.ScheduleGenerator( ).generate_schedule()) games = subject.SCHEDULE.weeks[0].games home_teams = [g.home_team for g in games] with patch('random.random', return_value=0): winners_names = subject._determine_game_winners( subject.SCHEDULE.weeks[0].games) self.assertEqual(len(home_teams), len(winners_names)) for t in home_teams: self.assertTrue(t.name in winners_names)
def test__eliminate_losers(self): subject = league.League(num_players=10, schedule=schedule_generator.ScheduleGenerator( ).generate_schedule()) choices = dict() for p in subject.PLAYERS: choices[p.name()] = 0 choices[subject.PLAYERS[0].name()] = 1 winning_team_names = [0] subject._eliminate_losers(choices, winning_team_names, 300) self.assertListEqual(subject._active_players(), subject.PLAYERS[1:]) self.assertFalse(subject.PLAYERS[0].is_alive()) self.assertEqual(subject.PLAYERS[0]._elimination_week_num, 300)
def test__simulate_week(self): subject = league.League(num_players=10, schedule=schedule_generator.ScheduleGenerator( ).generate_schedule()) week_to_simulate = subject.SCHEDULE.weeks[0] games = week_to_simulate.games home_teams = set() away_teams = set() for game in games: for player in subject.PLAYERS: self.assertFalse(player.have_chosen_team(game.home_team.name)) self.assertFalse(player.have_chosen_team(game.away_team.name)) home_teams.add(game.home_team) away_teams.add(game.away_team) # home team wins every game with patch('random.random', return_value=0): subject._simulate_week(week_to_simulate) alive_players = [ player for player in subject.PLAYERS if player.is_alive() ] eliminated_players = [ player for player in subject.PLAYERS if not player.is_alive() ] for player in alive_players: self.assertEqual( len([t for t in home_teams if player.have_chosen_team(t.name)]), 1) self.assertEqual( len([t for t in away_teams if player.have_chosen_team(t.name)]), 0) for player in eliminated_players: self.assertEqual( len([t for t in home_teams if player.have_chosen_team(t.name)]), 0) self.assertEqual( len([t for t in away_teams if player.have_chosen_team(t.name)]), 1)
def test_assign_games_randomly(self): subject = schedule_generator.ScheduleGenerator() result = subject.generate_schedule().weeks first_half_weeks = result[:int(len(result) / 2)] second_half_weeks = result[-int(len(result) / 2):] # Each week, there is a greater than 1 / (num_weeks / num_other_teams) chance one team plays another num_weeks = NUM_WEEKS - NUM_BYES num_teams = NUM_TEAMS_PER_DIVISION * NUM_DIVISIONS_PER_CONFERENCE * NUM_CONFERENCES expected_games = (num_weeks - 1) / (num_teams - 1) / 2 + 1 max_allowable_games = expected_games + 1 num_successes = 0 num_failures = 0 for early_week in first_half_weeks: for game in early_week.games: t1 = game.home_team t2 = game.away_team times_played = 1 for late_week in second_half_weeks: for late_game in late_week.games: if late_game.home_team in { t1, t2 } and late_game.away_team in {t1, t2}: times_played += 1 if times_played < max_allowable_games: num_successes += 1 else: num_failures += 1 minimum_valid_ratio = 900 / 25 if num_failures == 0: num_successes += minimum_valid_ratio num_failures += 1 self.assertTrue(num_successes / num_failures > minimum_valid_ratio)
def test__give_teams_byes_gives_the_right_number_of_teams_byes(self): # This test is by design intentionally slightly flaky. If you encounter an error with the assertions, # try running again. subject = schedule_generator.ScheduleGenerator() n_trials = 100 sum_num_non_bye_teams = 0 for i in range(n_trials): non_bye = subject._filter_bye_teams(subject._generate_teams()) self.assertTrue(len(non_bye) % 2 == 0) sum_num_non_bye_teams += len(non_bye) num_non_bye_teams = float(sum_num_non_bye_teams) / n_trials num_teams = NUM_CONFERENCES * NUM_DIVISIONS_PER_CONFERENCE * NUM_TEAMS_PER_DIVISION expected_avg_num_non_byes = num_teams - float( NUM_BYES) / NUM_WEEKS * num_teams allowable_num_bye_difference = 1 self.assertTrue(num_non_bye_teams > expected_avg_num_non_byes - allowable_num_bye_difference) self.assertTrue(num_non_bye_teams < expected_avg_num_non_byes + allowable_num_bye_difference)
def run_simulation(): strategy_victory_outcome_dict = dict() strategy_victory_dict = dict() strategy_elimination_week_dict = dict() strategy_end_result_dict = dict() strategy_cumulative_elimination_probability = dict() strategy_average_winnings_dict = dict() num_weeks = 0 num_winners = 0 for strategy in league.STRATEGIES: strategy_name = strategy().name strategy_victory_outcome_dict[strategy_name] = 0 strategy_victory_dict[strategy_name] = 0 strategy_elimination_week_dict[strategy_name] = dict() strategy_end_result_dict[strategy_name] = dict() strategy_average_winnings_dict[strategy_name] = 0 for _ in range(NUM_SIMULATIONS): schedule = schedule_generator.ScheduleGenerator().generate_schedule() lg = league.League(NUM_PLAYERS, schedule) lg.simulate_season() results = lg.PLAYERS was_tie = len([result for result in results if result.is_alive()]) == 0 simulation_weeks = 0 for result in results: if result.elimination_week() is None: continue simulation_weeks = max(simulation_weeks, result.elimination_week()) num_weeks += simulation_weeks simulation_winners = [result for result in results if result.is_alive() or (was_tie and result.elimination_week() == simulation_weeks)] num_winners += len(simulation_winners) for winner in simulation_winners: strategy_victory_dict[winner.strategy_name()] += 1 / len(simulation_winners) strategy_victory_outcome_dict[winner.strategy_name()] += 1 / (len(results) - len(simulation_winners) + 1) strategy_average_winnings_dict[winner.strategy_name()] += 1 strategy_player_count = dict() for result in results: if result.strategy_name() not in strategy_player_count: strategy_player_count[result.strategy_name()] = 0 strategy_player_count[result.strategy_name()] += 1 strategy_loser_count = dict() for result in results: if result.is_alive() or (was_tie and result.elimination_week() == simulation_weeks): continue if result.strategy_name() not in strategy_loser_count: strategy_loser_count[result.strategy_name()] = 0 strategy_loser_count[result.strategy_name()] += 1 for result in results: if result.is_alive() or (was_tie and result.elimination_week() == simulation_weeks): continue if result.elimination_week() not in strategy_elimination_week_dict[result.strategy_name()]: for week in range(result.elimination_week()): if week not in strategy_elimination_week_dict[result.strategy_name()]: strategy_elimination_week_dict[result.strategy_name()][week] = 0 strategy_end_result_dict[result.strategy_name()][week] = 0 strategy_elimination_week_dict[result.strategy_name()][result.elimination_week()] = 0 strategy_end_result_dict[result.strategy_name()][result.elimination_week()] = 0 strategy_elimination_week_dict[result.strategy_name()][result.elimination_week()] += \ 1 / strategy_loser_count[result.strategy_name()] strategy_end_result_dict[result.strategy_name()][result.elimination_week()] += \ 1 / strategy_player_count[result.strategy_name()] for k in strategy_victory_dict.keys(): strategy_victory_dict[k] /= NUM_SIMULATIONS for k in strategy_victory_outcome_dict.keys(): strategy_victory_outcome_dict[k] /= NUM_SIMULATIONS for s in strategy_elimination_week_dict.keys(): for w in strategy_elimination_week_dict[s]: strategy_elimination_week_dict[s][w] /= NUM_SIMULATIONS for s in strategy_end_result_dict.keys(): if s not in strategy_cumulative_elimination_probability: strategy_cumulative_elimination_probability[s] = {0: 0} for w in strategy_end_result_dict[s]: strategy_end_result_dict[s][w] /= NUM_SIMULATIONS strategy_cumulative_elimination_probability[s][w] = 0 for wn in range(w): strategy_cumulative_elimination_probability[s][w] += strategy_end_result_dict[s][wn] strategy_cumulative_elimination_probability[s][w] += strategy_end_result_dict[s][w] for s in league.STRATEGIES: strategy_name = s().name strategy_average_winnings_dict[strategy_name] = strategy_victory_dict[strategy_name] / \ strategy_average_winnings_dict[strategy_name] * NUM_SIMULATIONS * \ strategy_victory_outcome_dict[strategy_name] scale = 1 / sum([v for v in strategy_average_winnings_dict.values()]) for s in league.STRATEGIES: strategy_name = s().name strategy_average_winnings_dict[strategy_name] *= scale print("Average maximum simulation week number:") print(num_weeks / NUM_SIMULATIONS) print("Average number of winners:") print(num_winners / NUM_SIMULATIONS) print("Odds a strategy wins:") print(strategy_victory_dict) print("Odds of winning, by strategy:") print(strategy_victory_outcome_dict) print("Odds of being eliminated in a week, by strategy") for strategy, elimination_odds in strategy_end_result_dict.items(): print(strategy, elimination_odds) print("Elimination week distribution, by strategy:") for strategy, elimination_odds in strategy_elimination_week_dict.items(): print(strategy, elimination_odds) print("Cumulative elimination probability, by strategy") for strategy, elimination_odds in strategy_cumulative_elimination_probability.items(): print(strategy, elimination_odds) print("Average player winnings, by strategy") print(strategy_average_winnings_dict)
def test__generate_players(self): subject = league.League(num_players=10, schedule=schedule_generator.ScheduleGenerator( ).generate_schedule()) self.assertEqual(len(subject.PLAYERS), 10)