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)
def messages(self, gamedb: Database) -> List[SMSEventMessage]: player_messages = [] team = gamedb.team_from_id(id=self.player.team_id) teammate_phone_numbers = [p.phone_number for p in gamedb.list_players( from_team=team) if p.id != self.player.id] player_messages.append( SMSEventMessage( content=messages.NOTIFY_PLAYER_VOTED_OUT_TEAM_MSG_FMT.format( header=messages.VIR_US_SMS_HEADER, player=messages.format_tiktok_username( self.player.tiktok), time=self.game_options.game_schedule.localized_time_string( self.game_options.game_schedule.daily_challenge_start_time )), recipient_phone_numbers=teammate_phone_numbers ) ) player_messages.append( SMSEventMessage( content=messages.NOTIFY_PLAYER_VOTED_OUT_MSG_FMT.format( header=messages.VIR_US_SMS_HEADER ), recipient_phone_numbers=[self.player.phone_number] ) ) return player_messages
def _team_count_players(team: Team, gamedb: Database) -> int: team = gamedb.team_from_id(team.id) return team.count_players