Ejemplo n.º 1
0
    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
Ejemplo n.º 2
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)
Ejemplo n.º 3
0
    def messages(self, gamedb: Database) -> List[SMSEventMessage]:
        player_messages = []
        count_players = gamedb.count_players(
            from_tribe=gamedb.tribe_from_id(self.winning_player.tribe_id))
        # TODO(brandon): unclear why this can't be done in a single bulk message.
        for player in self.losing_players:
            options_map = messages.players_as_formatted_options_map(
                players=self.losing_players, exclude_player=player)
            # NOTE(brandon): we perform this synchronously to guarantee that ballots are
            # created in the DB before SMS messages go out to users.
            gamedb.ballot(player_id=player.id,
                          options=options_map.options,
                          challenge_id=None)
            player_messages.append(
                SMSEventMessage(
                    content=messages.
                    NOTIFY_SINGLE_TEAM_COUNCIL_EVENT_LOSING_MSG_FMT.format(
                        header=messages.game_sms_header(gamedb=gamedb),
                        winner=messages.format_tiktok_username(
                            self.winning_player.tiktok),
                        players=count_players,
                        time=self.game_options.game_schedule.
                        localized_time_string(self.game_options.game_schedule.
                                              daily_challenge_end_time),
                        options=options_map.formatted_string),
                    recipient_phone_numbers=[player.phone_number]))

        options_map = messages.players_as_formatted_options_map(
            players=self.losing_players, exclude_player=self.winning_player)
        gamedb.ballot(player_id=self.winning_player.id,
                      options=options_map.options,
                      challenge_id=None)
        player_messages.append(
            SMSEventMessage(
                content=messages.
                NOTIFY_SINGLE_TEAM_COUNCIL_EVENT_WINNING_MSG_FMT.format(
                    header=messages.game_sms_header(gamedb=gamedb),
                    players=count_players,
                    time=self.game_options.game_schedule.localized_time_string(
                        self.game_options.game_schedule.
                        daily_challenge_end_time),
                    options=options_map.formatted_string),
                recipient_phone_numbers=[self.winning_player.phone_number]))

        return player_messages
Ejemplo n.º 4
0
    def messages(self, gamedb: Database) -> List[SMSEventMessage]:
        player_messages = []
        count_players = gamedb.count_players(
            from_tribe=gamedb.tribe_from_id(self.winning_player.tribe_id))
        for player in self.losing_players:
            player_messages.append(
                SMSEventMessage(
                    content=messages.NOTIFY_SINGLE_TEAM_COUNCIL_EVENT_LOSING_MSG_FMT.format(
                        header=messages.VIR_US_SMS_HEADER,
                        winner=messages.format_tiktok_username(
                            self.winning_player.tiktok),
                        players=count_players,
                        time=self.game_options.game_schedule.localized_time_string(
                            self.game_options.game_schedule.daily_challenge_end_time),
                        options=messages.players_as_formatted_options_list(
                            players=self.losing_players, exclude_player=player)
                    ),
                    recipient_phone_numbers=player.phone_number
                )
            )

        player_messages.append(
            SMSEventMessage(
                content=messages.NOTIFY_SINGLE_TEAM_COUNCIL_EVENT_WINNING_MSG_FMT.format(
                    header=messages.VIR_US_SMS_HEADER,
                    players=count_players,
                    time=self.game_options.game_schedule.localized_time_string(
                        self.game_options.game_schedule.daily_challenge_end_time),
                    options=messages.players_as_formatted_options_list(
                        players=self.losing_players)
                ),
                recipient_phone_numbers=self.winning_player.phone_number
            )
        )

        return player_messages