示例#1
0
    def _get_voted_out_player(self, team: Team,
                              gamedb: Database) -> [Player, None]:
        high = 0
        candidates = []
        log_message(message="Counting votes from team {}.".format(team),
                    game_id=self._game_id)
        team_votes = gamedb.count_votes(from_team=team)
        log_message(message="Got votes {}.".format(pprint.pformat(team_votes)),
                    game_id=self._game_id)

        for _, votes in team_votes.items():
            if votes > high:
                high = votes

        for id, votes in team_votes.items():
            if votes == high:
                candidates.append(id)

        num_candidates = len(candidates)
        if num_candidates == 1:
            return gamedb.player_from_id(candidates[0])
        elif num_candidates > 1:
            return gamedb.player_from_id(candidates[random.randint(
                0, num_candidates - 1)])
        else:
            raise GameError("Unable to determine voted out player.")
示例#2
0
    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
示例#3
0
    def _run_finalist_tribe_council(self, finalists: List[Player], gamedb: Database, engine: Engine) -> Player:
        gamedb.clear_votes()

        engine.add_event(
            events.NotifyFinalTribalCouncilEvent(
                game_id=self._game_id, game_options=self._options, finalists=finalists))
        tribal_council_start_timestamp = _unixtime()

        # wait for votes
        while (((_unixtime() - tribal_council_start_timestamp)
                < self._options.final_tribal_council_time_sec) and not self._stop.is_set()):
            log_message("Waiting for tribal council to end.")
            time.sleep(self._options.game_wait_sleep_interval_sec)

        # count votes
        player_votes = gamedb.count_votes(is_for_win=True)
        max_votes = 0
        winner = None

        for player_id, votes in player_votes.items():
            if votes > max_votes:
                max_votes = votes
                winner = gamedb.player_from_id(id=player_id)

        # announce winner
        engine.add_event(events.NotifyWinnerAnnouncementEvent(
            game_id=self._game_id, game_options=self._options, winner=winner))
        return winner
示例#4
0
    def _score_entries_top_k_teams_fn(self, entries: Iterable,
                                      challenge: Challenge, score_dict: Dict,
                                      gamedb: Database, engine: Engine):
        entries_iter = iter(entries)
        while not self._stop_event.is_set():
            try:
                entry = next(entries_iter)
                log_message(message="Entry {}.".format(entry),
                            game_id=self._game_id)
                points = self._score_entry(entry=entry)
                player = gamedb.player_from_id(entry.player_id)
                engine.add_event(
                    events.NotifyPlayerScoreEvent(game_id=self._game_id,
                                                  game_options=self._options,
                                                  player=player,
                                                  challenge=challenge,
                                                  entry=entry,
                                                  points=points))

                if player.team_id not in score_dict:
                    score_dict[player.team_id] = points
                else:
                    score_dict[player.team_id] += points
            except StopIteration:
                break
示例#5
0
    def _run_finalist_tribe_council(self, finalists: List[Player],
                                    gamedb: Database,
                                    engine: Engine) -> Player:
        gamedb.clear_votes()
        self._wait_for_tribal_council_start_time()

        engine.add_event(
            events.NotifyFinalTribalCouncilEvent(game_id=self._game_id,
                                                 game_options=self._options,
                                                 finalists=finalists))
        self._wait_for_tribal_council_end_time()

        # count votes
        player_votes = gamedb.count_votes(is_for_win=True)
        max_votes = 0
        winner = None

        for player_id, votes in player_votes.items():
            if votes > max_votes:
                max_votes = votes
                winner = gamedb.player_from_id(id=player_id)

        for player in gamedb.stream_players(
                active_player_predicate_value=True):
            if player.id != winner.id:
                gamedb.deactivate_player(player=player)

        # announce winner
        engine.add_event(
            events.NotifyWinnerAnnouncementEvent(game_id=self._game_id,
                                                 game_options=self._options,
                                                 winner=winner))
        return winner
示例#6
0
    def _score_entries_tribe_aggregate_fn(self, entries: Iterable, challenge: Challenge, score_dict: Dict, gamedb: Database, engine: Engine):
        """Note that all built-ins are thread safe in python, meaning we can
        atomically increment the score int held in score_dict."""

        entries_iter = iter(entries)
        while not self._stop.is_set():
            try:
                entry = next(entries_iter)
                pprint.pprint(entry)
                points = entry.likes / entry.views
                player = gamedb.player_from_id(entry.player_id)
                engine.add_event(events.NotifyPlayerScoreEvent(
                    game_id=self._game_id, game_options=self._options,
                    player=player, challenge=challenge,
                    entry=entry, points=points))
                score_dict['score'] += points
            except StopIteration:
                break
示例#7
0
    def generate_tribes(cls, game_id: str, players: List[DocumentSnapshot],
                        game_options: GameOptions, gamedb: Database) -> dict:
        tribes = list()
        teams = list()
        count_players = len(players)
        if count_players < game_options.target_team_size:
            raise MatchMakerError("Insufficient players for given team size")
        if count_players < game_options.multi_tribe_min_tribe_size * 2:
            raise MatchMakerError("Insufficient players to make two tribes")
        # generate tribes
        for tribe_name in [
                _DEFAULT_TRIBE_NAMES[int(n)]
                for n in random.sample(range(0, len(_DEFAULT_TRIBE_NAMES)), 2)
        ]:
            tribe = database.Tribe(id=str(uuid.uuid4()),
                                   name="{}".format(tribe_name))
            tribes.append(tribe)

        # generate teams
        for n in range(
                0, math.floor(count_players / game_options.target_team_size)):
            team = database.Team(
                id=str(uuid.uuid4()),
                name="{}".format(n),
            )
            teams.append(team)

        count_tribes = len(tribes)
        count_teams = len(teams)
        team_to_tribe_map = {}

        # randomly assign team, tribe to each player
        set_of_mutable_players = set()
        set_of_mutable_users = set()
        for n, player in enumerate(players):
            mutable_user = gamedb.find_user(
                phone_number=player.get('phone_number'))
            mutable_user.game_id = game_id
            mutable_player = gamedb.player_from_id(player.id)
            tribe = tribes[n % count_tribes]
            team = teams[n % count_teams]
            if team.id not in team_to_tribe_map:
                team_to_tribe_map[team.id] = tribe
                tribe.count_teams += 1
            mutable_player.tribe_id = tribe.id
            mutable_player.team_id = team.id
            team.tribe_id = tribe.id
            tribe.count_players += 1
            team.count_players += 1
            set_of_mutable_players.add(mutable_player)
            set_of_mutable_users.add(mutable_user)

        # Save data
        game = gamedb.game_from_id(game_id)
        game.count_tribes = count_tribes
        game.count_teams = count_teams
        game.count_players = count_players
        gamedb.save(game)

        for tribe in tribes:
            gamedb.save(tribe)
        for team in teams:
            gamedb.save(team)
        for player in set_of_mutable_players:
            gamedb.save(player)
        for user in set_of_mutable_users:
            gamedb.save(user)

        d = {}
        d['players'] = players
        d['teams'] = teams
        d['tribes'] = tribes
        d['game'] = game
        return d