Add config file for hanabi league

This commit is contained in:
Maximilian Keßler 2023-11-22 17:13:44 +01:00
parent cc8dd2a90c
commit ab32fae4f2
Signed by: max
GPG Key ID: BCC5A619923C0BA5
5 changed files with 147 additions and 1 deletions

115
config.py
View File

@ -1,8 +1,11 @@
import shutil import shutil
from typing import Dict
import yaml import yaml
import platformdirs import platformdirs
from pathlib import Path from pathlib import Path
from datetime import datetime, timezone
import dateutil.parser
import constants import constants
from log_setup import logger from log_setup import logger
@ -71,3 +74,115 @@ def create_db_config() -> None:
logger.info("Created default DB config file at {}".format(config_path)) logger.info("Created default DB config file at {}".format(config_path))
else: else:
logger.info("DB config file at {} already exists".format(config_path)) logger.info("DB config file at {} already exists".format(config_path))
def check_config_attr(func):
def wrapper():
try:
func()
except KeyError as e:
logger.error("Missing config attribute:\n{}".format(e))
class Config:
def __init__(self, config: Dict):
self._config = config
@check_config_attr
def player_base_rating(self) -> int:
return self._config["player_base_rating"]
@check_config_attr
def min_player_count(self) -> int:
return self._config["min_player_count"]
@check_config_attr
def max_player_count(self) -> int:
return self._config["max_player_count"]
@check_config_attr
def min_suit_count(self) -> int:
return self._config["min_suit_count"]
@check_config_attr
def max_suit_count(self) -> int:
return self._config["max_suit_count"]
@check_config_attr
def starting_game_id(self) -> int:
return self._config["starting_game_id"]
@check_config_attr
def ending_game_id(self) -> int:
return self._config["ending_game_id"]
@check_config_attr
def starting_time(self):
time = self._config["starting_time"]
return dateutil.parser(time, tzinfos={'EST': 'US/Eastern'})
@check_config_attr
def ending_time(self):
time = self._config["ending_time"]
return dateutil.parser(time, tzinfos={'EST': 'US/Eastern'})
@check_config_attr
def variant_base_rating(self, variant_name: str, player_count: int) -> int:
global_base_rating = self._config["variant_base_rating"]
# We use different ways of specifying base ratings here:
# First, there is a (required) config setting for the variant base rating, which will be used as default.
# Then, for each variant, it is possible to either specify some base rating directly,
# or further specify a base rating for each player count.
# Parsing this is now quite easy: We just check if there is an entry for the specific variant and if so,
# read the base rating from there, where we will have to distinguish between a player-independent value
# and possibly player-specific entries. Whenever we don't find an explicit entry, we use the global fallback.
# This makes it possible to just specify the variant + player combinations that differ in their base rating
# from the globally specified one.
var_rating = self._config.get("variant_base_ratings", {}).get(variant_name, None)
if type(var_rating) == int:
return var_rating
elif type(var_rating) == dict:
return var_rating.get("{}p".format(player_count), global_base_rating)
elif var_rating is None:
return global_base_rating
logger.error("Unexpected config format for entry {} in 'variant_base_ratings'".format(variant_name))
def get_config_path():
config_dir = Path(platformdirs.user_config_dir(constants.APP_NAME, ensure_exists=True))
config_path = config_dir / constants.CONFIG_FILE_NAME
return config_path
def read_config() -> Config:
config_path = get_config_path()
logger.verbose("Hanabi League configuration read from file {}".format(config_path))
if config_path.exists():
with open(config_path, "r") as f:
config = yaml.safe_load(f)
return Config(config)
else:
logger.info("No hanabi league configuration found. Falling back to default file {}".format(
constants.DEFAULT_CONFIG_PATH))
logger.info(
"Note: To turn off this message, create a config file at {}".format(config_path)
)
with open(constants.DEFAULT_CONFIG_PATH, "r") as f:
config = yaml.safe_load(f)
return Config(config)
def create_config() -> None:
"""
Creates a default config file for the league at the config location
"""
config_path = get_config_path()
if not config_path.exists():
shutil.copy(constants.DEFAULT_CONFIG_PATH, config_path)
logger.info("Created default hanabi league config file at {}".format(config_path))
else:
logger.info("Hanabi league config file at {} already exists".format(config_path))

View File

@ -3,7 +3,8 @@
# It's not meant to include all string constants or anything, just the ones that are important for functioning. # It's not meant to include all string constants or anything, just the ones that are important for functioning.
APP_NAME = 'hanabi-league' APP_NAME = 'hanabi-league'
DB_CONFIG_FILE_NAME = 'config.yaml' DB_CONFIG_FILE_NAME = 'db_config.yaml'
CONFIG_FILE_NAME = 'config.yaml'
DEFAULT_DB_NAME = 'hanabi-league' DEFAULT_DB_NAME = 'hanabi-league'
DEFAULT_DB_USER = 'hanabi-league' DEFAULT_DB_USER = 'hanabi-league'
@ -27,3 +28,4 @@ DB_TABLE_NAMES = [
DATABASE_SCHEMA_PATH = 'install/database_schema.sql' DATABASE_SCHEMA_PATH = 'install/database_schema.sql'
DEFAULT_DB_CONFIG_PATH = 'install/default_db_config.yaml' DEFAULT_DB_CONFIG_PATH = 'install/default_db_config.yaml'
DEFAULT_CONFIG_PATH = 'install/default_config.yaml'

View File

@ -0,0 +1,27 @@
player_base_rating: 1500
variant_base_rating: 1500
variant_base_ratings:
No Variant:
3p: 1500
4p: 1500
5p: 1500
6 Suits:
3p: 1500
4p: 1500
5p: 1500
Clue Starved:
3p: 1500
4p: 1500
6p: 1700
Clue Starved (6 Suits):
3p: 1500
4p: 1500
6p: 1700
min_player_count: 3
max_player_count: 5
min_suits: 5
max_suits: 6
starting_game_id: 1000000
ending_game_id: 9999999
starting_time: "2023-10-10 00:00:00 EST"
ending_time: "2023-12-10 00:00:00 EST"

View File

@ -32,6 +32,7 @@ def subcommand_init(force: bool):
def subcommand_generate_config(): def subcommand_generate_config():
config.create_db_config() config.create_db_config()
config.create_config()
def get_parser() -> argparse.ArgumentParser: def get_parser() -> argparse.ArgumentParser:

View File

@ -2,3 +2,4 @@ psycopg2
platformdirs platformdirs
PyYAML PyYAML
verboselogs verboselogs
python-dateutil