"""Class and functions for storing and retrieving highscores data.""" import os import json from data.guild import Guild # pylint: disable=import-error from data.table import Table # pylint: disable=import-error from data.category import Category # pylint: disable=import-error HIGHSCORES_BACKUP_DIR = "deleted_backups" HIGHSCORES_CONFIG_DIR = "examples" HIGHSCORES_DATA_DIR = "highscores_data" class HighscoresData: """Class for storing and retrieving highscores data.""" def __init__(self) -> None: """ Default constructor for Highscores Data. Opens up known highscores data on creation. """ self._guild_map: dict = {} # Ensure that data directories exist. if not os.path.exists(HIGHSCORES_BACKUP_DIR): os.mkdir(HIGHSCORES_BACKUP_DIR) if not os.path.exists(HIGHSCORES_DATA_DIR): os.mkdir(HIGHSCORES_DATA_DIR) self.open_highscores_data() def __str__(self) -> str: """ Returns Highscores class as a string for printing. Returns: str: Highscores class as a string """ data: dict = {} for guild_id, guild_obj in self._guild_map.items(): data[guild_id] = guild_obj.to_dict() return "Highscores Data\n" + json.dumps(data, indent=4) @property def guilds(self) -> "list[Guild]": """ Getter for Guilds list. Returns: list[Guild]: List of Guilds tracked by Highscores Bot """ return self._guild_map.values() def add_configuration(self, guild_id: int, config_str: str) -> None: """ Adds an example configuration to a Guild. Uses guild id to know which guild and config name to open a file in example_config. Args: guild_id (int): Guild id to add config to config_str (str): Config name to add """ config = self._open_highscores_config(config_str) guild = self.get_guild(guild_id) for table_name, categorys in config["tables"].items(): table_obj = Table(table_name) table_obj.size = config["table_size"] for category_name in categorys: category = Category(category_name) category.ascending = config["categories"][category]["ascending"] category.time_record = config["categories"][category]["is_time_record"] table_obj.add_category(category) guild.add_table(table_obj) def add_guild(self, guild_id: int) -> None: """ Creates a new Guild and adds to Guild map. Args: guild_id (int): Guild Id to add """ guild: Guild = Guild(guild_id) self._guild_map[guild_id] = guild def get_guild(self, guild_id: int) -> Guild: """ Getter for Guild object that corresponds with the guild_id. Args: guild_id (int): id of Guild to retrieve. Returns: Guild: Guild object for guild_id """ return self._guild_map[guild_id] def remove_guild(self, guild_id: int) -> None: """ Removes a guild's data from object. Saves backup. Args: guild_id (int): guild id to remove """ self._guild_map.pop(guild_id) os.rename( f"{HIGHSCORES_DATA_DIR}/{guild_id}.json", f"{HIGHSCORES_BACKUP_DIR}/{guild_id}.json" ) def _open_highscores_config(self, config: str) -> dict: """ Opens the highscores config file and returns in dictionary format. Will be replaced when config class is created. Args: config (str): Name of config to load. Returns: dict: dict of highscores config """ with open(f"{HIGHSCORES_CONFIG_DIR}/{config}.json", encoding="utf-8", mode="r") as file: return json.load(file) def open_highscores_data(self): """ Opens all saved highscores data in the HIGHSCORES_DATA_DIR dir. Creates a Guild object from each file and adds to guild map. """ for data_file in os.listdir(HIGHSCORES_DATA_DIR): guild_id: int = int(data_file.split(".", maxsplit=1)[0]) with open(f"{HIGHSCORES_DATA_DIR}/{data_file}", encoding="utf-8", mode="r") as file: guild_obj: Guild = Guild.from_dict(guild_id, json.load(file)) self._guild_map[guild_obj.guild_id] = guild_obj def save_all_data(self) -> None: """ Calls save_guild_data for each guild tracked in guild map. """ for guild in self.guilds: self.save_guild_data(guild) def save_guild_data(self, guild: Guild) -> None: """ Saves a guild to its own json file. Args: guild (Guild): Guild to save """ with open( f"{HIGHSCORES_DATA_DIR}/{guild.guild_id}.json", encoding="utf-8", mode="w" ) as file: file.write(guild.to_str()) # should use str function