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
from typing import Dict
import yaml
import platformdirs
from pathlib import Path
from datetime import datetime, timezone
import dateutil.parser
import constants
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))
else:
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.
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_USER = 'hanabi-league'
@ -27,3 +28,4 @@ DB_TABLE_NAMES = [
DATABASE_SCHEMA_PATH = 'install/database_schema.sql'
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():
config.create_db_config()
config.create_config()
def get_parser() -> argparse.ArgumentParser:

View file

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