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)
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)
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)
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))
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])