Store actions and deck to database

This commit is contained in:
Maximilian Keßler 2023-11-23 13:18:38 +01:00
parent 07aba5fefb
commit 7fdee4bae0
Signed by: max
GPG key ID: BCC5A619923C0BA5
3 changed files with 60 additions and 8 deletions

View file

@ -9,6 +9,7 @@ import hanabi.live.hanab_live
import hanabi.hanab_game
import constants
import games_db_interface
import database
import utils
from database import conn_manager
@ -181,7 +182,12 @@ def store_new_games(games: Dict[int, GameInfo]):
conn.commit()
def detailed_fetch_game(game_id: int):
def detailed_fetch_game(game_id: int) -> bool:
"""
Fetches full game details from the server and stores it in local DB if this game is a league game.
@param game_id: Game ID from hanab.live
@return: Whether the processed game was accepted as a league game, i.e. inserted into the DB
"""
url = "https://hanab.live/export/{}".format(game_id)
response = session.get(url)
if not response.status_code == 200:
@ -191,8 +197,6 @@ def detailed_fetch_game(game_id: int):
game_json = json.loads(response.text)
instance, actions = hanabi.live.hanab_live.parse_json_game(game_json, False)
print(instance, actions, instance.deck)
print(game_json)
game_id = game_json["id"]
players = game_json["players"]
@ -202,15 +206,15 @@ def detailed_fetch_game(game_id: int):
var_name = game_options.get("variant", "No Variant")
if not utils.are_game_options_allowed(game_id, game_options):
return
return False
if not utils.is_player_count_allowed(game_id, num_players):
return
return False
var_id = database.get_variant_id(var_name)
if var_id is None:
logger.debug("Rejected game {} due to invalid variant id {}".format(game_id, var_id))
return
return False
# All game options are ok, now check if the number of players is okay.
normalized_usernames = [utils.normalize_username(username) for username in players]
@ -218,11 +222,12 @@ def detailed_fetch_game(game_id: int):
# The return value here is a str if there was an unregistered participant
if type(user_ids) is str:
logger.debug("Rejected game {} due to unregistered participant {}".format(game_id, user_ids))
return
return False
# Now, we can start to actually process the game details
instance, actions = hanabi.live.hanab_live.parse_json_game(game_json, False)
game = hanabi.hanab_game.GameState(instance)
# In order to figure out the score, we will need to play the game once
for action in actions:
game.make_action(action)
@ -256,3 +261,8 @@ def detailed_fetch_game(game_id: int):
)
# DB is now in a consistent state again: We made sure the game and its participants are added.
conn.commit()
# It remains to store the seed and action data for this game
games_db_interface.store_deck_for_seed(seed, instance.deck)
games_db_interface.store_actions(game_id, actions)
return True

42
games_db_interface.py Normal file
View file

@ -0,0 +1,42 @@
from typing import List
import psycopg2.extras
from database import conn_manager
import hanabi.hanab_game
def store_actions(game_id: int, actions: List[hanabi.hanab_game.Action]):
vals = []
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) "
"VALUES %s "
"ON CONFLICT (game_id, turn) "
"DO NOTHING",
vals
)
conn.commit()
def store_deck_for_seed(seed: str, deck: List[hanabi.hanab_game.DeckCard]):
vals = []
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) "
"VALUES %s "
"ON CONFLICT (seed, card_index) "
"DO NOTHING",
vals
)
conn.commit()

View file

@ -225,7 +225,7 @@ CREATE TABLE seeds (
card_index SMALLINT NOT NULL,
suit_index SMALLINT NOT NULL,
rank SMALLINT NOT NULL,
CONSTRAINT cards_unique UNIQUE (seed, card_index)
PRIMARY KEY (seed, card_index)
);