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 psycopg2.extras
|
||||||
|
|
||||||
import hanabi.hanab_game
|
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]):
|
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):
|
for turn, action in enumerate(actions):
|
||||||
vals.append((game_id, turn, action.type.value, action.target, action.value or 0))
|
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(
|
psycopg2.extras.execute_values(
|
||||||
cur,
|
cur,
|
||||||
"INSERT INTO game_actions (game_id, turn, type, target, value) "
|
"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):
|
for index, card in enumerate(deck):
|
||||||
vals.append((seed, index, card.suitIndex, card.rank))
|
vals.append((seed, index, card.suitIndex, card.rank))
|
||||||
|
|
||||||
conn = conn_manager.get_connection()
|
|
||||||
cur = conn.cursor()
|
|
||||||
psycopg2.extras.execute_values(
|
psycopg2.extras.execute_values(
|
||||||
cur,
|
cur,
|
||||||
"INSERT INTO seeds (seed, card_index, suit_index, rank) "
|
"INSERT INTO decks (seed, deck_index, suit_index, rank) "
|
||||||
"VALUES %s "
|
"VALUES %s "
|
||||||
"ON CONFLICT (seed, card_index) "
|
"ON CONFLICT (seed, deck_index) DO UPDATE SET "
|
||||||
"DO NOTHING",
|
"(suit_index, rank) = (excluded.suit_index, excluded.rank)",
|
||||||
vals
|
vals
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
|
||||||
def load_actions(game_id: int) -> List[hanabi.hanab_game.Action]:
|
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 "
|
cur.execute("SELECT type, target, value FROM game_actions "
|
||||||
"WHERE game_id = %s "
|
"WHERE game_id = %s "
|
||||||
"ORDER BY turn ASC",
|
"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]:
|
def load_deck(seed: str) -> List[hanabi.hanab_game.DeckCard]:
|
||||||
cur = conn_manager.get_new_cursor()
|
cur.execute("SELECT deck_index, suit_index, rank FROM decks "
|
||||||
cur.execute("SELECT card_index, suit_index, rank FROM seeds "
|
|
||||||
"WHERE seed = %s "
|
"WHERE seed = %s "
|
||||||
"ORDER BY card_index ASC",
|
"ORDER BY deck_index ASC",
|
||||||
(seed,)
|
(seed,)
|
||||||
)
|
)
|
||||||
deck = []
|
deck = []
|
||||||
|
@ -79,15 +77,17 @@ def load_deck(seed: str) -> List[hanabi.hanab_game.DeckCard]:
|
||||||
return deck
|
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
|
Loads information on game from database
|
||||||
@param game_id: ID of game
|
@param game_id: ID of game
|
||||||
@return: Instance (i.e. deck + settings) of game, list of actions, variant name
|
@return: Instance (i.e. deck + settings) of game, list of actions, variant name
|
||||||
"""
|
"""
|
||||||
cur = conn_manager.get_new_cursor()
|
|
||||||
cur.execute(
|
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 "
|
"FROM games "
|
||||||
"INNER JOIN variants"
|
"INNER JOIN variants"
|
||||||
" ON games.variant_id = variants.id "
|
" 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)
|
raise ValueError(err_msg)
|
||||||
|
|
||||||
# Unpack results now
|
# 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)
|
actions = load_actions(game_id)
|
||||||
deck = load_deck(seed)
|
deck = load_deck(seed)
|
||||||
|
|
||||||
instance = hanabi.hanab_game.HanabiInstance(deck, num_players, clue_starved=clue_starved)
|
instance = hanabi.live.hanab_live.HanabLiveInstance(
|
||||||
return instance, actions, variant_name
|
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]:
|
def load_game(game_id: int) -> hanabi.live.hanab_live.HanabLiveGameState:
|
||||||
instance, actions, variant_name = load_game_parts(game_id)
|
instance, actions = load_game_parts(game_id)
|
||||||
game = hanabi.hanab_game.GameState(instance)
|
game = hanabi.live.hanab_live.HanabLiveGameState(instance)
|
||||||
for action in actions:
|
for action in actions:
|
||||||
game.make_action(action)
|
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.live import compress
|
||||||
from hanabi.solvers import sat
|
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
|
# 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:
|
# 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]:
|
def check_game(game_id: int) -> Tuple[int, hanab_game.GameState]:
|
||||||
logger.debug("Analysing game {}".format(game_id))
|
logger.debug("Analysing game {}".format(game_id))
|
||||||
with database.conn.cursor() as cur:
|
with database.conn.cursor() as cur:
|
||||||
cur.execute("SELECT games.num_players, deck, actions, score, games.variant_id, starting_player FROM games "
|
cur.execute("SELECT games.num_players, score, games.variant_id, starting_player FROM games "
|
||||||
"INNER JOIN seeds ON seeds.seed = games.seed "
|
|
||||||
"WHERE games.id = (%s)",
|
"WHERE games.id = (%s)",
|
||||||
(game_id,)
|
(game_id,)
|
||||||
)
|
)
|
||||||
res = cur.fetchone()
|
res = cur.fetchone()
|
||||||
if res is None:
|
if res is None:
|
||||||
raise ValueError("No game associated with id {} in database.".format(game_id))
|
raise ValueError("No game associated with id {} in database.".format(game_id))
|
||||||
(num_players, compressed_deck, compressed_actions, score, variant_id, starting_player) = res
|
(num_players, score, variant_id, starting_player) = res
|
||||||
deck = compress.decompress_deck(compressed_deck)
|
instance, actions = games_db_interface.load_game_parts(game_id)
|
||||||
actions = compress.decompress_actions(compressed_actions)
|
|
||||||
|
|
||||||
instance = hanab_live.HanabLiveInstance(
|
|
||||||
deck,
|
|
||||||
num_players,
|
|
||||||
variant_id=variant_id,
|
|
||||||
starting_player=starting_player
|
|
||||||
)
|
|
||||||
|
|
||||||
# check if the instance is already won
|
# check if the instance is already won
|
||||||
if instance.max_score == score:
|
if instance.max_score == score:
|
||||||
|
|
|
@ -11,10 +11,11 @@ from hanabi import constants
|
||||||
from hanabi import logger
|
from hanabi import logger
|
||||||
from hanabi import database
|
from hanabi import database
|
||||||
from hanabi.live import site_api
|
from hanabi.live import site_api
|
||||||
from hanabi.live import compress
|
|
||||||
from hanabi.live import variants
|
from hanabi.live import variants
|
||||||
from hanabi.live import hanab_live
|
from hanabi.live import hanab_live
|
||||||
|
|
||||||
|
from hanabi.database import games_db_interface
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class GameExportError(ValueError):
|
class GameExportError(ValueError):
|
||||||
|
@ -172,18 +173,7 @@ def detailed_export_game(
|
||||||
)
|
)
|
||||||
logger.debug("New seed {} imported.".format(seed))
|
logger.debug("New seed {} imported.".format(seed))
|
||||||
|
|
||||||
values = []
|
games_db_interface.store_deck_for_seed(seed, deck)
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
database.cur.execute(
|
database.cur.execute(
|
||||||
"INSERT INTO games ("
|
"INSERT INTO games ("
|
||||||
|
@ -219,18 +209,7 @@ def detailed_export_game(
|
||||||
game_participant_values
|
game_participant_values
|
||||||
)
|
)
|
||||||
|
|
||||||
# Insert actions into database
|
games_db_interface.store_actions(game_id, actions)
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.debug("Imported game {}".format(game_id))
|
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")
|
database.cur.execute("ROLLBACK TO seed_insert")
|
||||||
detailed_export_game(game_id, score=score, var_id=var_id)
|
detailed_export_game(game_id, score=score, var_id=var_id)
|
||||||
database.cur.execute("RELEASE seed_insert")
|
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))
|
logger.debug("Imported game {}".format(game_id))
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue