def _score_entries_top_k_players(self, team: Team, challenge: Challenge, gamedb: Database, engine: Engine) -> List[Player]: player_scores = {} top_scores = list() losing_players = list() entries = gamedb.stream_entries( from_team=team, from_challenge=challenge) with ThreadPoolExecutor(max_workers=self._options.engine_worker_thread_count) as executor: executor.submit(self._score_entries_top_k_players_fn, entries=entries, challenge=challenge, score_dict=player_scores, gamedb=gamedb, engine=engine) for player_id, score in player_scores.items(): heapq.heappush(top_scores, (score, player_id)) # note that the default python heap pops in ascending order, # so the rank here is actually worst to best. num_scores = len(top_scores) if num_scores == 1: raise GameError( "Unable to rank losing players with team size = 1.") else: for rank in range(num_scores): score, player_id = heapq.heappop(top_scores) log_message("Player {} rank {} with score {}.".format( player_id, rank, score)) # all but the highest scorer lose if rank < (num_scores - 1): losing_players.append(gamedb.player_from_id(player_id)) return losing_players
def _score_entries_tribe_aggregate(self, tribe: Tribe, challenge: Challenge, gamedb: Database, engine: Engine): score_dict = {'score': 0} players = gamedb.count_players(from_tribe=tribe) entries = gamedb.stream_entries(from_tribe=tribe, from_challenge=challenge) with ThreadPoolExecutor(max_workers=self._options. engine_worker_thread_count) as executor: executor.submit(self._score_entries_tribe_aggregate_fn, entries=entries, challenge=challenge, score_dict=score_dict, gamedb=gamedb, engine=engine) # tribe score = avg score of all tribe members log_message(message="_score_entries_tribe_agg = {}.".format( score_dict['score']), game_id=self._game_id) if players > 0: return score_dict['score'] / players return 0
def _score_entries_top_k_teams( self, k: float, tribe: Tribe, challenge: Challenge, gamedb: Database, engine: Engine) -> Tuple[List[Team], List[Team]]: team_scores = {} top_scores = list() winning_teams = list() losing_teams = list() entries = gamedb.stream_entries(from_tribe=tribe, from_challenge=challenge) with ThreadPoolExecutor(max_workers=self._options. engine_worker_thread_count) as executor: executor.submit(self._score_entries_top_k_teams_fn, entries=entries, challenge=challenge, score_dict=team_scores, gamedb=gamedb, engine=engine) for team_id, score in team_scores.items(): heapq.heappush( top_scores, (score / gamedb.count_players(from_team=gamedb.team_from_id(team_id)), team_id)) rank_threshold = float(k * len(top_scores)) log_message(message="Rank threshold = {}".format(rank_threshold), game_id=self._game_id) # note that the default python heap pops in ascending order, # so the rank here is actually worst to best. num_scores = len(top_scores) if num_scores == 1: score, team_id = heapq.heappop(top_scores) log_message(message="Winner {}.".format(team_id), game_id=self._game_id) winning_teams = [gamedb.team_from_id(team_id)] else: for rank in range(num_scores): score, team_id = heapq.heappop(top_scores) log_message(message="Team {} rank {} with score {}.".format( team_id, rank, score), game_id=self._game_id) if rank >= rank_threshold: log_message(message="Winner {}.".format(team_id), game_id=self._game_id) winning_teams.append(gamedb.team_from_id(team_id)) else: log_message(message="Loser {}.".format(team_id), game_id=self._game_id) losing_teams.append(gamedb.team_from_id(team_id)) return (winning_teams, losing_teams)