Check for correct number of players earlier. Add CLI for downloading

games
This commit is contained in:
Maximilian Keßler 2023-07-05 16:44:22 +02:00
parent 3c2c73d00b
commit f8ff2411a0
Signed by: max
GPG key ID: BCC5A619923C0BA5
2 changed files with 31 additions and 20 deletions

View file

@ -1,6 +1,5 @@
#! /usr/bin/python3
import argparse import argparse
from typing import Optional
import verboselogs import verboselogs
@ -52,6 +51,14 @@ def subcommand_init(force: bool, populate: bool):
logger.info("Successfully initialized database tables") logger.info("Successfully initialized database tables")
if populate: if populate:
init_database.populate_static_tables() init_database.populate_static_tables()
logger.info("Successfully populated tables with variants and suits from hanab.live")
def subcommand_download(game_id: Optional[int], variant_id: Optional[int], export_all_games):
if game_id is not None:
download_data.detailed_export_game(game_id)
if variant_id is not None:
download_data.download_games(variant_id, export_all_games)
def add_init_subparser(subparsers): def add_init_subparser(subparsers):
@ -60,17 +67,20 @@ def add_init_subparser(subparsers):
help='Init database tables, retrieve variant and suit information from hanab.live' help='Init database tables, retrieve variant and suit information from hanab.live'
) )
parser.add_argument('--force', '-f', help='Force initialization (Drops existing tables)', action='store_true') parser.add_argument('--force', '-f', help='Force initialization (Drops existing tables)', action='store_true')
parser.add_argument('--no-populate-tables', '-n', parser.add_argument(
'--no-populate-tables', '-n',
help='Do not download variant and suit information from hanab.live', help='Do not download variant and suit information from hanab.live',
action='store_true', action='store_false',
dest='populate') dest='populate'
)
def add_download_subparser(subparsers): def add_download_subparser(subparsers):
parser = subparsers.add_parser('download', help='Download games from hanab.live') parser = subparsers.add_parser('download', help='Download games from hanab.live')
group = parser.add_mutually_exclusive_group(required=True) group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--var', '-v', type=int) group.add_argument('--var', '--variant', '-v', type=int, dest='variant_id')
group.add_argument('--id', '-i', type=int) group.add_argument('--id', '-i', type=int, dest='game_id')
parser.add_argument('--all-games', '-a', action='store_true', dest='export_all_games')
def add_analyze_subparser(subparsers): def add_analyze_subparser(subparsers):
@ -98,7 +108,8 @@ def hanabi_cli():
args = main_parser().parse_args() args = main_parser().parse_args()
switcher = { switcher = {
'analyze': subcommand_analyze, 'analyze': subcommand_analyze,
'init': subcommand_init 'init': subcommand_init,
'download': subcommand_download
} }
if args.verbose: if args.verbose:
logger_manager.set_console_level(verboselogs.VERBOSE) logger_manager.set_console_level(verboselogs.VERBOSE)

View file

@ -41,16 +41,16 @@ class GameExportInvalidFormatError(GameExportError):
class GameExportInvalidNumberOfPlayersError(GameExportInvalidFormatError): class GameExportInvalidNumberOfPlayersError(GameExportInvalidFormatError):
def __init__(self, game_id, expected, received): def __init__(self, game_id, expected, received):
super().__init__(game_id, "Received invalid list of players: Expected {}, got {}".format(expected, received)) super().__init__(
game_id,
pass "Received invalid list of players: Expected {} many, got {}".format(expected, received)
)
# #
def detailed_export_game( def detailed_export_game(
game_id: int game_id: int
, score: Optional[int] = None , score: Optional[int] = None
, num_players: Optional[int] = None
, var_id: Optional[int] = None , var_id: Optional[int] = None
, seed_exists: bool = False , seed_exists: bool = False
) -> None: ) -> None:
@ -59,10 +59,8 @@ def detailed_export_game(
If seed is already present, it is left as is If seed is already present, it is left as is
If game is already present, game details will be updated If game is already present, game details will be updated
:param game_id: Id of game to export :param game_id: id of game to export
:param score: If given, this will be inserted as score of the game. If not given, score is calculated :param score: If given, this will be inserted as score of the game. If not given, score is calculated
:param num_players: If given, the number of players reported by the site is checked against this. If inconsistent,
InvalidNumberOfPlayersError is raised
:param var_id: If given, this will be inserted as variant id of the game. If not given, this is looked up :param var_id: If given, this will be inserted as variant id of the game. If not given, this is looked up
:param seed_exists: If specified and true, assumes that the seed is already present in database. :param seed_exists: If specified and true, assumes that the seed is already present in database.
If this is not the case, call will raise a DB insertion error If this is not the case, call will raise a DB insertion error
@ -84,8 +82,6 @@ def detailed_export_game(
)) ))
players = game_json.get('players', []) players = game_json.get('players', [])
if num_players is not None and len(players) != num_players:
raise GameExportInvalidNumberOfPlayersError(game_id, num_players, game_json.get('players', []))
num_players = len(players) num_players = len(players)
if num_players < 2: if num_players < 2:
raise GameExportInvalidNumberOfPlayersError(game_id, "≥2", num_players) raise GameExportInvalidNumberOfPlayersError(game_id, "≥2", num_players)
@ -174,13 +170,17 @@ def _process_game_row(game: Dict, var_id, export_all_games: bool = False):
game_id = game.get('id', None) game_id = game.get('id', None)
seed = game.get('seed', None) seed = game.get('seed', None)
num_players = game.get('num_players', None) num_players = game.get('num_players', None)
users = game.get('users', "").split(", ")
score = game.get('score', None) score = game.get('score', None)
if any(v is None for v in [game_id, seed, num_players, score]): if any(v is None for v in [game_id, seed, num_players, score]):
raise ValueError("Unknown response format on hanab.live") raise ValueError("Unknown response format on hanab.live")
if len(users) != num_players:
raise GameExportInvalidNumberOfPlayersError(game_id, num_players, users)
if export_all_games: if export_all_games:
detailed_export_game(game_id, score=score, num_players=num_players, var_id=var_id) detailed_export_game(game_id, score=score, var_id=var_id)
logger.debug("Imported game {}".format(game_id)) logger.debug("Imported game {}".format(game_id))
return return
@ -197,7 +197,7 @@ def _process_game_row(game: Dict, var_id, export_all_games: bool = False):
# Sometimes, seed is not present in the database yet, then we will have to query the full game details # Sometimes, seed is not present in the database yet, then we will have to query the full game details
# (including the seed) to export it accordingly # (including the seed) to export it accordingly
database.cur.execute("ROLLBACK TO seed_insert") database.cur.execute("ROLLBACK TO seed_insert")
detailed_export_game(game_id, score=score, num_players=num_players, 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")
logger.debug("Imported game {}".format(game_id)) logger.debug("Imported game {}".format(game_id))