Ejemplo n.º 1
0
    def test00_calculate_level(self):
        score = 4112
        level1, score_next1, score_left1 = levels.calculate_level(score)
        self.assertTrue(score_left1 > 0)

        level2, score_next2, score_left2 = levels.calculate_level(score + score_left1)
        self.assertEquals(level2, level1 + 1)
        self.assertEquals(score_next2, score_left2)
Ejemplo n.º 2
0
    def test00_calculate_level(self):
        score = 4112
        level1, score_next1, score_left1 = levels.calculate_level(score)
        self.assertTrue(score_left1 > 0)

        level2, score_next2, score_left2 = levels.calculate_level(score +
                                                                  score_left1)
        self.assertEquals(level2, level1 + 1)
        self.assertEquals(score_next2, score_left2)
Ejemplo n.º 3
0
    def update_players_info(self, players_info, players_id_list):
        '''Add new player ids as key to players_info dict, from players_list'''
        # Python's DB-API doesn't support interpolating lists into SQL's "WHERE x IN (...)" statements,
        # so we have to generate the correct number of '?' placeholders programatically.
        format_strings = ','.join(['?'] * len(players_id_list))
        sql_statement = 'SELECT player_id, score FROM players WHERE player_id IN (%s)' % format_strings
        rows = yield self.db.runQuery(sql_statement, players_id_list)
        # Build up a dict of {player_id: player_level} key-value pairs.
        levels = {}
        for row in rows:
            level, _, _ = calculate_level(row[1])
            levels[row[0]] = level

        for player_id in players_id_list:
            if player_id not in players_info:
                info = {}
                if levels.has_key(player_id):
                    info['level'] = levels[player_id]
                try:
                    info['name'] = yield self.auth.get_player_name(player_id)
                    info['avatar_url'] = yield self.auth.get_player_avatar_url(player_id)
                except Exception as e:
                    raise CardstoriesException('Failed fetching player data (player_id=%s): %s' % (player_id, e))
                players_info[str(player_id)] = info

        defer.returnValue(players_info)
Ejemplo n.º 4
0
    def update_players_info(self, players_info, players_id_list):
        '''Add new player ids as key to players_info dict, from players_list'''
        # Python's DB-API doesn't support interpolating lists into SQL's "WHERE x IN (...)" statements,
        # so we have to generate the correct number of '?' placeholders programatically.
        format_strings = ','.join(['?'] * len(players_id_list))
        sql_statement = 'SELECT player_id, score FROM players WHERE player_id IN (%s)' % format_strings
        rows = yield self.db.runQuery(sql_statement, players_id_list)
        # Build up a dict of {player_id: player_level} key-value pairs.
        levels = {}
        for row in rows:
            level, _, _ = calculate_level(row[1])
            levels[row[0]] = level

        for player_id in players_id_list:
            if player_id not in players_info:
                info = {}
                if levels.has_key(player_id):
                    info['level'] = levels[player_id]
                try:
                    info['name'] = yield self.auth.get_player_name(player_id)
                    info['avatar_url'] = yield self.auth.get_player_avatar_url(
                        player_id)
                except Exception as e:
                    raise CardstoriesException(
                        'Failed fetching player data (player_id=%s): %s' %
                        (player_id, e))
                players_info[str(player_id)] = info

        defer.returnValue(players_info)
Ejemplo n.º 5
0
    def completeInteraction(self, transaction, game_id, owner_id):
        transaction.execute("SELECT picked FROM player2game WHERE game_id = ? AND player_id = ?", (game_id, owner_id))
        winner_card = transaction.fetchone()[0]
        transaction.execute("SELECT vote, picked, player_id FROM player2game WHERE game_id = ? AND player_id != ? AND vote IS NOT NULL", (game_id, owner_id))
        players_count = 0
        guessed = []
        failed = []
        score = {}
        player2vote = {}
        pick2player = {}
        for (vote, picked, player_id) in transaction.fetchall():
            players_count += 1
            player2vote[player_id] = vote
            pick2player[picked] = player_id
            if vote == winner_card:
                guessed.append(player_id)
            else:
                failed.append(player_id)

        if len(guessed) > 0 and len(guessed) < players_count:
            winners = guessed + [ owner_id ]
            score[owner_id] = self.POINTS_GM_WON
            for player_id in guessed:
                score[player_id] = self.POINTS_P_WON
            for player_id in failed:
                score[owner_id] += self.POINTS_GM_FAILED
                score[player_id] = self.POINTS_P_LOST
        else:
            winners = failed + guessed
            score[owner_id] = self.POINTS_GM_LOST
            for player_id in winners:
                score[player_id] = self.POINTS_P_WON

        # Also distribute points to players who fooled other players.
        for player_id in failed:
            vote = player2vote[player_id]
            try:
                candidate = pick2player[vote]
                try:
                    score[candidate] += self.POINTS_P_FAILED
                except KeyError:
                    score[candidate] = self.POINTS_P_FAILED
            except KeyError:
                pass

        transaction.execute("UPDATE player2game SET win = 'y' WHERE "
                            "  game_id = %d AND " % game_id +
                            "  player_id IN ( %s ) " % ','.join([ str(id) for id in winners ]))
        transaction.execute("UPDATE games SET completed = datetime('now'), state = 'complete' WHERE id = %d" % game_id)

        for player_id in score.keys():
            # Calculate if level needs to be bumped
            transaction.execute("SELECT score, levelups, earned_cards FROM players WHERE player_id = %s" % player_id)
            row = transaction.fetchone()
            if not row:
                continue
            score_prev, levelups, earned_cards = row

            level_prev, _, _ = calculate_level(score_prev)
            score_cur = score_prev + score[player_id]
            level_cur, _, _ = calculate_level(score_cur)

            if earned_cards:
                earned_cards = list(earned_cards)
            else:
                earned_cards = []
            earned_cards_cur = []

            # Only distribute new cards if the player has leveled up during
            # this game, AND he hasn't already earned a card for this level
            # (this last check will only fail if the level formula is tuned in
            # such a way that it becomes harder to level up).
            if level_prev < level_cur and levelups < level_cur - 1:
                deck = [chr(x) for x in range(self.NCARDS + 1, self.NCARDS_EARNED + 1)]
                # Take care not to distribute a card that the player already owns,
                # or a card that is marked for sell only.
                cards_to_remove = set(earned_cards) | set([chr(x) for x in self.CARDS_FOR_SELL])
                clean_deck = [c for c in deck if c not in cards_to_remove]

                # Distribute one card for each level since last levelup.
                for i in range(levelups, level_cur - 1):
                    if clean_deck:
                        card = random.choice(clean_deck)
                        clean_deck.remove(card)
                        earned_cards.append(card)
                        earned_cards_cur.append(card)
                        levelups += 1

            # Store it
            transaction.execute("UPDATE players SET "
                                "score_prev = score, "
                                "score = ?, "
                                "levelups = ?, "
                                "earned_cards = ?, "
                                "earned_cards_cur = ? "
                                "WHERE player_id = ?",
                                (score_cur,
                                 levelups,
                                 ''.join(earned_cards),
                                 ''.join(earned_cards_cur),
                                 player_id))
Ejemplo n.º 6
0
    def game(self, player_id):
        db = self.service.db
        game_id = self.get_id()
        rows = yield db.runQuery("SELECT owner_id, sentence, cards, board, state FROM games WHERE id = ?", [ game_id ])
        if not rows:
            raise CardstoriesWarning('GAME_DOES_NOT_EXIST', {'game_id': game_id, 'player_id': player_id})
        (owner_id, sentence, cards, board, state) = rows[0]
        if owner_id == player_id:
            cards = [ ord(c) for c in cards ]
            invited = list(self.invited)
        else:
            cards = None
            invited = None
        if owner_id != player_id and state in ('create', 'invitation'):
            board = None
        else:
            board = [ ord(c) for c in board ]
        sql = ("SELECT "
               "player2game.player_id, "
               "player2game.cards, "
               "player2game.picked, "
               "player2game.vote, "
               "player2game.win, "
               "players.score, "
               "players.score_prev, "
               "players.earned_cards, "
               "players.earned_cards_cur "
               "FROM player2game LEFT JOIN players "
               "ON player2game.player_id = players.player_id "
               "WHERE game_id = ? ORDER BY serial")
        rows = yield db.runQuery(sql, [ game_id ])
        picked_count = 0
        voted_count = 0
        players = []
        winner_card = None
        myself = None
        players_id_list = [] # Keep track of all players being referenced
        for player in rows:
            # player_id
            players_id_list.append(player[0])

            # player_cards
            if player[0] == player_id or owner_id == player_id:
                player_cards = [ ord(c) for c in player[1] ]
            else:
                player_cards = None

            # picked
            if player[2] != None:
                if (state == 'complete' or player[0] == player_id or owner_id == player_id):
                    picked = ord(player[2])
                else:
                    picked = ''
            else:
                picked = None
            if player[2] != None:
                picked_count += 1

            # self
            if player[0] == player_id:
                myself = [ self.ord(player[2]), self.ord(player[3]), player_cards ]

            # vote / winner_card
            if state == 'complete' or owner_id == player_id:
                if player[0] == owner_id and player[2]:
                    winner_card = ord(player[2])
                vote = self.ord(player[3])
            else:
                if player[0] == owner_id and player[2]:
                    winner_card = ''
                if player[3] != None:
                    vote = ''
                else:
                    vote = None
            if player[3] != None:
                voted_count += 1

            # win
            win = player[4]

            # Set score, level, and earned cards, but only for the requesting player.
            if player[0] == player_id:
                score = player[5]
                score_prev = player[6]
                level, score_next, score_left = calculate_level(score)
                level_prev, _, _ = calculate_level(score_prev)
                if player[7]:
                    earned_cards = [ord(c) for c in player[7]]
                else:
                    earned_cards = None
                if player[8]:
                    earned_cards_cur = [ord(c) for c in player[8]]
                else:
                    earned_cards_cur = None
            else:
                score = None
                level = None
                score_next = None
                score_left = None
                score_prev = None
                level_prev = None
                earned_cards = None
                earned_cards_cur = None

            # players
            players.append({'id': player[0],
                            'cards': player_cards,
                            'picked': picked,
                            'vote': vote,
                            'win': win,
                            'score': score,
                            'level': level,
                            'score_next': score_next,
                            'score_left': score_left,
                            'score_prev': score_prev,
                            'level_prev': level_prev,
                            'earned_cards': earned_cards,
                            'earned_cards_cur': earned_cards_cur})

        ready = None
        if state == 'invitation':
            ready = picked_count >= self.MIN_PICKED
        elif state == 'vote':
            ready = voted_count >= self.MIN_VOTED
        defer.returnValue([{'id': game_id,
                            'modified': self.get_modified(),
                            'sentence': sentence,
                            'winner_card': winner_card,
                            'cards': cards,
                            'board': board,
                            'state': state,
                            'ready': ready,
                            'countdown_finish': self.get_countdown_finish(),
                            'self': myself,
                            'owner': owner_id == player_id,
                            'owner_id': owner_id,
                            'players': players,
                            'invited': invited },
                            players_id_list])