2023-05-14 19:11:51 +02:00
|
|
|
import argparse
|
2023-07-05 16:44:22 +02:00
|
|
|
from typing import Optional
|
2023-05-20 14:32:42 +02:00
|
|
|
|
|
|
|
import verboselogs
|
2023-05-14 19:11:51 +02:00
|
|
|
|
2023-07-04 20:06:06 +02:00
|
|
|
from hanabi import logger, logger_manager
|
2023-07-05 18:48:33 +02:00
|
|
|
from hanabi.live import variants
|
2023-07-04 20:06:06 +02:00
|
|
|
from hanabi.live import check_game
|
|
|
|
from hanabi.live import download_data
|
|
|
|
from hanabi.live import compress
|
2023-07-05 09:33:55 +02:00
|
|
|
from hanabi.database import init_database
|
2023-05-14 19:11:51 +02:00
|
|
|
|
|
|
|
"""
|
|
|
|
init db + populate tables
|
|
|
|
download games of variant
|
|
|
|
download single game
|
|
|
|
analyze single game
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
2023-07-05 09:33:55 +02:00
|
|
|
def subcommand_analyze(game_id: int, download: bool = False):
|
|
|
|
if download:
|
|
|
|
download_data.detailed_export_game(game_id)
|
|
|
|
logger.info('Analyzing game {}'.format(game_id))
|
|
|
|
turn, sol = check_game.check_game(game_id)
|
|
|
|
if turn == 0:
|
|
|
|
logger.info('Instance is unfeasible')
|
|
|
|
else:
|
|
|
|
logger.info('Game was first lost after {} turns.'.format(turn))
|
|
|
|
logger.info(
|
|
|
|
'A replay achieving perfect score from the previous turn onwards is: {}#{}'
|
|
|
|
.format(compress.link(sol), turn)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def subcommand_init(force: bool, populate: bool):
|
|
|
|
tables = init_database.get_existing_tables()
|
|
|
|
if len(tables) > 0 and not force:
|
|
|
|
logger.info(
|
|
|
|
'Database tables "{}" exist already, aborting. To force re-initialization, use the --force options'
|
|
|
|
.format(", ".join(tables))
|
|
|
|
)
|
|
|
|
return
|
|
|
|
if len(tables) > 0:
|
|
|
|
logger.info(
|
|
|
|
"WARNING: This will drop all existing tables from the database and re-initialize them."
|
|
|
|
)
|
|
|
|
response = input("Do you wish to continue? [y/N] ")
|
|
|
|
if response not in ["y", "Y", "yes"]:
|
|
|
|
return
|
|
|
|
init_database.init_database_tables()
|
|
|
|
logger.info("Successfully initialized database tables")
|
|
|
|
if populate:
|
|
|
|
init_database.populate_static_tables()
|
2023-07-05 16:44:22 +02:00
|
|
|
logger.info("Successfully populated tables with variants and suits from hanab.live")
|
|
|
|
|
|
|
|
|
2023-07-05 18:48:33 +02:00
|
|
|
def subcommand_download(
|
|
|
|
game_id: Optional[int]
|
|
|
|
, variant_id: Optional[int]
|
|
|
|
, export_all: bool = False
|
|
|
|
, all_variants: bool = False
|
|
|
|
):
|
2023-07-05 16:44:22 +02:00
|
|
|
if game_id is not None:
|
|
|
|
download_data.detailed_export_game(game_id)
|
2023-07-05 18:48:33 +02:00
|
|
|
logger.info("Successfully exported game ")
|
2023-07-05 16:44:22 +02:00
|
|
|
if variant_id is not None:
|
2023-07-05 18:48:33 +02:00
|
|
|
download_data.download_games(variant_id, export_all)
|
|
|
|
logger.info("Successfully exported games for variant id {}".format(variant_id))
|
|
|
|
if all_variants:
|
|
|
|
for variant in variants.get_all_variant_ids():
|
|
|
|
download_data.download_games(variant, export_all)
|
|
|
|
logger.info("Successfully exported games for all variants")
|
2023-07-05 09:33:55 +02:00
|
|
|
|
|
|
|
|
2023-05-14 19:11:51 +02:00
|
|
|
def add_init_subparser(subparsers):
|
|
|
|
parser = subparsers.add_parser(
|
|
|
|
'init',
|
|
|
|
help='Init database tables, retrieve variant and suit information from hanab.live'
|
|
|
|
)
|
2023-07-05 09:33:55 +02:00
|
|
|
parser.add_argument('--force', '-f', help='Force initialization (Drops existing tables)', action='store_true')
|
2023-07-05 16:44:22 +02:00
|
|
|
parser.add_argument(
|
|
|
|
'--no-populate-tables', '-n',
|
|
|
|
help='Do not download variant and suit information from hanab.live',
|
|
|
|
action='store_false',
|
|
|
|
dest='populate'
|
|
|
|
)
|
2023-05-14 19:11:51 +02:00
|
|
|
|
|
|
|
|
|
|
|
def add_download_subparser(subparsers):
|
|
|
|
parser = subparsers.add_parser('download', help='Download games from hanab.live')
|
|
|
|
group = parser.add_mutually_exclusive_group(required=True)
|
2023-07-05 18:48:33 +02:00
|
|
|
group.add_argument(
|
|
|
|
'--var', '--variant', '-v',
|
|
|
|
type=int,
|
|
|
|
dest='variant_id',
|
|
|
|
help='Download information on all games given variant id (but not necessarily export all of them)'
|
|
|
|
)
|
|
|
|
group.add_argument('--id', '-i', type=int, dest='game_id', help='Download single game given id')
|
|
|
|
group.add_argument(
|
|
|
|
'--all-variants', '-a',
|
|
|
|
action='store_true',
|
|
|
|
dest='all_variants',
|
|
|
|
help='Download information from games on all variants (but not necessarily export all of them)'
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
'--export-all', '-e',
|
|
|
|
action='store_true',
|
|
|
|
dest='export_all',
|
|
|
|
help='Export all games specified in full detail (i.e. also actions and game options)'
|
|
|
|
)
|
2023-05-14 19:11:51 +02:00
|
|
|
|
|
|
|
|
|
|
|
def add_analyze_subparser(subparsers):
|
|
|
|
parser = subparsers.add_parser('analyze', help='Analyze a game and find the last winning state')
|
|
|
|
parser.add_argument('game_id', type=int)
|
|
|
|
parser.add_argument('--download', '-d', help='Download game if not in database', action='store_true')
|
|
|
|
|
|
|
|
|
|
|
|
def main_parser() -> argparse.ArgumentParser:
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
prog='hanabi_suite',
|
|
|
|
description='High-level interface for analysis of hanabi instances.'
|
|
|
|
)
|
2023-05-20 14:38:38 +02:00
|
|
|
parser.add_argument('--verbose', '-v', help='Enable verbose logging to console', action='store_true')
|
2023-05-14 19:11:51 +02:00
|
|
|
subparsers = parser.add_subparsers(dest='command', required=True, help='select subcommand')
|
|
|
|
|
|
|
|
add_init_subparser(subparsers)
|
|
|
|
add_analyze_subparser(subparsers)
|
|
|
|
add_download_subparser(subparsers)
|
|
|
|
|
|
|
|
return parser
|
|
|
|
|
2023-07-04 22:19:13 +02:00
|
|
|
|
2023-07-04 20:06:06 +02:00
|
|
|
def hanabi_cli():
|
2023-05-14 19:11:51 +02:00
|
|
|
args = main_parser().parse_args()
|
|
|
|
switcher = {
|
2023-07-05 09:33:55 +02:00
|
|
|
'analyze': subcommand_analyze,
|
2023-07-05 16:44:22 +02:00
|
|
|
'init': subcommand_init,
|
|
|
|
'download': subcommand_download
|
2023-05-14 19:11:51 +02:00
|
|
|
}
|
2023-05-20 14:38:38 +02:00
|
|
|
if args.verbose:
|
|
|
|
logger_manager.set_console_level(verboselogs.VERBOSE)
|
2023-05-14 19:11:51 +02:00
|
|
|
method_args = dict(vars(args))
|
|
|
|
method_args.pop('command')
|
2023-05-20 14:38:38 +02:00
|
|
|
method_args.pop('verbose')
|
2023-05-14 19:11:51 +02:00
|
|
|
switcher[args.command](**method_args)
|
2023-07-04 20:06:06 +02:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2023-07-04 22:19:13 +02:00
|
|
|
hanabi_cli()
|