Adjust games_db_interface to database format
Also adjust the check_game method to use new interface.
This commit is contained in:
parent
6651ef9145
commit
1c656de615
3 changed files with 54 additions and 58 deletions
|
@ -3,6 +3,10 @@ from typing import List, Tuple
|
|||
import psycopg2.extras
|
||||
|
||||
import hanabi.hanab_game
|
||||
import hanabi.live.hanab_live
|
||||
from hanabi import logger
|
||||
|
||||
from hanabi.database import conn, cur
|
||||
|
||||
|
||||
def store_actions(game_id: int, actions: List[hanabi.hanab_game.Action]):
|
||||
|
@ -10,8 +14,6 @@ def store_actions(game_id: int, actions: List[hanabi.hanab_game.Action]):
|
|||
for turn, action in enumerate(actions):
|
||||
vals.append((game_id, turn, action.type.value, action.target, action.value or 0))
|
||||
|
||||
conn = conn_manager.get_connection()
|
||||
cur = conn.cursor()
|
||||
psycopg2.extras.execute_values(
|
||||
cur,
|
||||
"INSERT INTO game_actions (game_id, turn, type, target, value) "
|
||||
|
@ -28,21 +30,18 @@ def store_deck_for_seed(seed: str, deck: List[hanabi.hanab_game.DeckCard]):
|
|||
for index, card in enumerate(deck):
|
||||
vals.append((seed, index, card.suitIndex, card.rank))
|
||||
|
||||
conn = conn_manager.get_connection()
|
||||
cur = conn.cursor()
|
||||
psycopg2.extras.execute_values(
|
||||
cur,
|
||||
"INSERT INTO seeds (seed, card_index, suit_index, rank) "
|
||||
"INSERT INTO decks (seed, deck_index, suit_index, rank) "
|
||||
"VALUES %s "
|
||||
"ON CONFLICT (seed, card_index) "
|
||||
"DO NOTHING",
|
||||
"ON CONFLICT (seed, deck_index) DO UPDATE SET "
|
||||
"(suit_index, rank) = (excluded.suit_index, excluded.rank)",
|
||||
vals
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
|
||||
def load_actions(game_id: int) -> List[hanabi.hanab_game.Action]:
|
||||
cur = conn_manager.get_new_cursor()
|
||||
cur.execute("SELECT type, target, value FROM game_actions "
|
||||
"WHERE game_id = %s "
|
||||
"ORDER BY turn ASC",
|
||||
|
@ -60,10 +59,9 @@ def load_actions(game_id: int) -> List[hanabi.hanab_game.Action]:
|
|||
|
||||
|
||||
def load_deck(seed: str) -> List[hanabi.hanab_game.DeckCard]:
|
||||
cur = conn_manager.get_new_cursor()
|
||||
cur.execute("SELECT card_index, suit_index, rank FROM seeds "
|
||||
cur.execute("SELECT deck_index, suit_index, rank FROM decks "
|
||||
"WHERE seed = %s "
|
||||
"ORDER BY card_index ASC",
|
||||
"ORDER BY deck_index ASC",
|
||||
(seed,)
|
||||
)
|
||||
deck = []
|
||||
|
@ -79,15 +77,17 @@ def load_deck(seed: str) -> List[hanabi.hanab_game.DeckCard]:
|
|||
return deck
|
||||
|
||||
|
||||
def load_game_parts(game_id: int) -> Tuple[hanabi.hanab_game.HanabiInstance, List[hanabi.hanab_game.Action], str]:
|
||||
def load_game_parts(game_id: int) -> Tuple[hanabi.live.hanab_live.HanabLiveInstance, List[hanabi.hanab_game.Action]]:
|
||||
"""
|
||||
Loads information on game from database
|
||||
@param game_id: ID of game
|
||||
@return: Instance (i.e. deck + settings) of game, list of actions, variant name
|
||||
"""
|
||||
cur = conn_manager.get_new_cursor()
|
||||
cur.execute(
|
||||
"SELECT games.num_players, games.seed, variants.clue_starved, variants.name "
|
||||
"SELECT "
|
||||
"games.num_players, games.seed, games.one_extra_card, games.one_less_card, games.deck_plays, "
|
||||
"games.all_or_nothing,"
|
||||
"variants.clue_starved, variants.name, variants.id, variants.throw_it_in_a_hole "
|
||||
"FROM games "
|
||||
"INNER JOIN variants"
|
||||
" ON games.variant_id = variants.id "
|
||||
|
@ -101,19 +101,29 @@ def load_game_parts(game_id: int) -> Tuple[hanabi.hanab_game.HanabiInstance, Lis
|
|||
raise ValueError(err_msg)
|
||||
|
||||
# Unpack results now
|
||||
(num_players, seed, clue_starved, variant_name) = res
|
||||
(num_players, seed, one_extra_card, one_less_card, deck_plays, all_or_nothing, clue_starved, variant_name, variant_id, throw_it_in_a_hole) = res
|
||||
|
||||
actions = load_actions(game_id)
|
||||
deck = load_deck(seed)
|
||||
|
||||
instance = hanabi.hanab_game.HanabiInstance(deck, num_players, clue_starved=clue_starved)
|
||||
return instance, actions, variant_name
|
||||
instance = hanabi.live.hanab_live.HanabLiveInstance(
|
||||
deck=deck,
|
||||
num_players=num_players,
|
||||
variant_id=variant_id,
|
||||
one_extra_card=one_extra_card,
|
||||
one_less_card=one_less_card,
|
||||
fives_give_clue=not throw_it_in_a_hole,
|
||||
deck_plays=deck_plays,
|
||||
all_or_nothing=all_or_nothing,
|
||||
clue_starved=clue_starved
|
||||
)
|
||||
return instance, actions
|
||||
|
||||
|
||||
def load_game(game_id: int) -> Tuple[hanabi.hanab_game.GameState, str]:
|
||||
instance, actions, variant_name = load_game_parts(game_id)
|
||||
game = hanabi.hanab_game.GameState(instance)
|
||||
def load_game(game_id: int) -> hanabi.live.hanab_live.HanabLiveGameState:
|
||||
instance, actions = load_game_parts(game_id)
|
||||
game = hanabi.live.hanab_live.HanabLiveGameState(instance)
|
||||
for action in actions:
|
||||
game.make_action(action)
|
||||
return game, variant_name
|
||||
return game
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ from hanabi.live import hanab_live
|
|||
from hanabi.live import compress
|
||||
from hanabi.solvers import sat
|
||||
|
||||
from hanabi.database import games_db_interface
|
||||
|
||||
|
||||
# returns minimal number T of turns (from game) after which instance was infeasible
|
||||
# and a replay achieving maximum score while following the replay for the first (T-1) turns:
|
||||
|
@ -19,24 +21,15 @@ from hanabi.solvers import sat
|
|||
def check_game(game_id: int) -> Tuple[int, hanab_game.GameState]:
|
||||
logger.debug("Analysing game {}".format(game_id))
|
||||
with database.conn.cursor() as cur:
|
||||
cur.execute("SELECT games.num_players, deck, actions, score, games.variant_id, starting_player FROM games "
|
||||
"INNER JOIN seeds ON seeds.seed = games.seed "
|
||||
cur.execute("SELECT games.num_players, score, games.variant_id, starting_player FROM games "
|
||||
"WHERE games.id = (%s)",
|
||||
(game_id,)
|
||||
)
|
||||
res = cur.fetchone()
|
||||
if res is None:
|
||||
raise ValueError("No game associated with id {} in database.".format(game_id))
|
||||
(num_players, compressed_deck, compressed_actions, score, variant_id, starting_player) = res
|
||||
deck = compress.decompress_deck(compressed_deck)
|
||||
actions = compress.decompress_actions(compressed_actions)
|
||||
|
||||
instance = hanab_live.HanabLiveInstance(
|
||||
deck,
|
||||
num_players,
|
||||
variant_id=variant_id,
|
||||
starting_player=starting_player
|
||||
)
|
||||
(num_players, score, variant_id, starting_player) = res
|
||||
instance, actions = games_db_interface.load_game_parts(game_id)
|
||||
|
||||
# check if the instance is already won
|
||||
if instance.max_score == score:
|
||||
|
|
|
@ -11,10 +11,11 @@ from hanabi import constants
|
|||
from hanabi import logger
|
||||
from hanabi import database
|
||||
from hanabi.live import site_api
|
||||
from hanabi.live import compress
|
||||
from hanabi.live import variants
|
||||
from hanabi.live import hanab_live
|
||||
|
||||
from hanabi.database import games_db_interface
|
||||
|
||||
|
||||
|
||||
class GameExportError(ValueError):
|
||||
|
@ -172,18 +173,7 @@ def detailed_export_game(
|
|||
)
|
||||
logger.debug("New seed {} imported.".format(seed))
|
||||
|
||||
values = []
|
||||
for index, card in enumerate(deck):
|
||||
values.append((seed, index, card.suitIndex, card.rank))
|
||||
|
||||
psycopg2.extras.execute_values(
|
||||
database.cur,
|
||||
"INSERT INTO decks (seed, deck_index, suit_index, rank)"
|
||||
"VALUES %s "
|
||||
"ON CONFLICT (seed, deck_index) DO UPDATE SET "
|
||||
"(suit_index, rank) = (excluded.suit_index, excluded.rank)",
|
||||
values
|
||||
)
|
||||
games_db_interface.store_deck_for_seed(seed, deck)
|
||||
|
||||
database.cur.execute(
|
||||
"INSERT INTO games ("
|
||||
|
@ -219,18 +209,7 @@ def detailed_export_game(
|
|||
game_participant_values
|
||||
)
|
||||
|
||||
# Insert actions into database
|
||||
action_values = []
|
||||
for turn, action in enumerate(actions):
|
||||
action: hanab_game.Action
|
||||
action_values.append((game_id, turn, action.type.value, action.target, action.value or 0))
|
||||
|
||||
psycopg2.extras.execute_values(
|
||||
database.cur,
|
||||
"INSERT INTO game_actions (game_id, turn, type, target, value) "
|
||||
"VALUES %s",
|
||||
action_values
|
||||
)
|
||||
games_db_interface.store_actions(game_id, actions)
|
||||
|
||||
logger.debug("Imported game {}".format(game_id))
|
||||
|
||||
|
@ -277,6 +256,20 @@ def _process_game_row(game: Dict, var_id, export_all_games: bool = False):
|
|||
database.cur.execute("ROLLBACK TO seed_insert")
|
||||
detailed_export_game(game_id, score=score, var_id=var_id)
|
||||
database.cur.execute("RELEASE seed_insert")
|
||||
|
||||
# Insert participants into database
|
||||
ids = ensure_users_in_db_and_get_ids(users)
|
||||
game_participant_values = []
|
||||
for index, user_id in enumerate(ids):
|
||||
game_participant_values.append((game_id, user_id, index))
|
||||
psycopg2.extras.execute_values(
|
||||
database.cur,
|
||||
"INSERT INTO game_participants (game_id, user_id, seat) VALUES %s "
|
||||
"ON CONFLICT (game_id, user_id) DO UPDATE SET seat = excluded.seat",
|
||||
game_participant_values
|
||||
)
|
||||
|
||||
|
||||
logger.debug("Imported game {}".format(game_id))
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue