From 8ca77d93b36cd43517657a1933e5ecf186b55ea1 Mon Sep 17 00:00:00 2001 From: alwayscompiling Date: Tue, 2 Aug 2022 16:13:08 -0400 Subject: [PATCH] Update highscores_data to be an overarching class for all data. --- data/category.py | 6 + data/highscores_data.py | 318 ++++++---------------------------------- 2 files changed, 53 insertions(+), 271 deletions(-) diff --git a/data/category.py b/data/category.py index e0d6f55..e01ef73 100644 --- a/data/category.py +++ b/data/category.py @@ -111,6 +111,12 @@ class Category: sorted(self._scores_map.items(), key=lambda x: x[1].value, reverse=not self.ascending) ) + def clear(self) -> None: + """ + Clears all Scores tracked in score map. This is a test function and shouldn't really be used. + """ + self._scores_map.clear() + def get_user_score(self, user: str) -> Score: """ Gets a user's score. Returns None if user is not found. diff --git a/data/highscores_data.py b/data/highscores_data.py index 071245d..be12e28 100644 --- a/data/highscores_data.py +++ b/data/highscores_data.py @@ -3,302 +3,78 @@ import os import json -HIGHSCORES_CONFIG_FILE = "highscores_config.json" -HIGHSCORES_DATA_FILE = "highscores_data.json" +from data.guild import Guild # 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: - self._config = open_highscores_config() - self._data = open_highscores_data() - - def add_new_server(self, guild_id: int): """ - Creates new skeleton data dict and adds to self for new guild. - - @param guild_id: guild_id to add. + Default constructor for Highscores Data. Opens up known highscores data on creation. """ - # create the dict - skeleton = { - "highscore_channel_id": -1, - "verification_channel_id": -1, - "username_length": 12, - } - config: dict = open_highscores_config() - skeleton["tables"] = {} - for boss, categories in config["tables"].items(): - skeleton["tables"][boss] = {"message_id": 0} - boss_categories = {} - for category in categories: - scores_list = {} - boss_categories[category] = scores_list - skeleton["tables"][boss]["categories"] = boss_categories + self._guild_map: dict = {} + 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._data[str(guild_id)] = skeleton - - def add_score( - self, guild_id: int, boss_name: str, category: str, user: str, score: str - ) -> None: + def add_guild(self, guild_id: int) -> None: """ - Adds a new score to guilds highscore data. - Ensures that there is no user duplicate and then sorts the scores + Creates a new Guild and adds to Guild map. - @param guild_id: guild id to retrieve from. - @param boss_name: boss to add score to. - @param category: category to add score to. - @param user: user that submitted score. - @param score: score to add. + Args: + guild_id (int): Guild Id to add """ - scores: "list[tuple]" = self._data[str(guild_id)]["tables"][boss_name]["categories"][ - category - ] - ascending: bool = self._config["categories"][category]["ascending"] - time_record: bool = self._config["categories"][category]["is_time_record"] + guild: Guild = Guild(guild_id) + self._guild_map[guild_id] = guild - # create score tuple for either time or int - # define sort index - if time_record: - if score.find(":") == -1: - score_seconds = float(score) - else: - minutes = score.split(":")[0] - seconds = score.split(":")[1] - score_seconds = int(minutes) * 60 + float(seconds) - score_list = [score, score_seconds] - sort_index = 1 - else: - score_list = [int(score)] - sort_index = 0 - - # Will not ensure new score is better than old one. Allows for correcting mistakes. - - scores[user] = score_list - - scores = dict(sorted(scores.items(), key=lambda x: x[1][sort_index], reverse=not ascending)) - - self._data[str(guild_id)]["tables"][boss_name]["categories"][category] = scores - save_highscores_data(self._data) - - def get_categories_data(self, guild_id: int, table: str) -> "list[tuple]": - """ - Returns categories data in a list of tuples. Calls dict function items(). - - @param guild_id: guild's id to retrieve from. - @param table: table to get category data from - @returns: list of tuples containing all category and relative score data. - """ - return self._data[str(guild_id)]["tables"][table]["categories"].items() - - def get_config_highscore_size(self) -> int: - """ - Gets the defined size of highscore for config. - - @returns: int highscore size - """ - return self._config["highscore_size"] - - def get_config_time_record(self, category: str) -> bool: - """ - Tells if the category is a time record - - @param category: category name to retrieve from. - @returns: bool indicating time record or not. - """ - return self._config["categories"][category]["is_time_record"] - - def get_guilds(self) -> "list[int]": - """ - Gets a list of guilds tracked by data - - @returns: list of ints representing guild ids - """ - guilds: "list[int]" = [] - - for guild, data in self._data.items(): # pylint: disable=unused-variable - guilds.append(int(guild)) - - return guilds - - def get_guild_highscores_channel(self, guild_id: int) -> int: - """ - Returns the channel id to post highscore messages to. - - @param guild_id: guild id to retrieve from. - @returns: channel id of highscores channel. - """ - return self._data[str(guild_id)]["highscore_channel_id"] - - def get_guild_submission_channel(self, guild_id: int) -> int: - """ - Returns the channel id to post submission messages to. - - @param guild_id: guild id to retrieve from. - @returns: channel id of submission channel. - """ - return self._data[str(guild_id)]["submission_channel_id"] - - def get_guild_username_length(self, guild_id: int) -> int: - """ - Returns username length as set by each guild. - - @param guild_id: guild id to retrieve from. - @returns: int of username length. - """ - return self._data[str(guild_id)]["username_length"] - - def get_guild_verification_channel(self, guild_id: int) -> int: - """ - Returns the channel id to post verification messages to. - - @param guild_id: guild id to retrieve from. - @returns: channel id of verification channel. - """ - return self._data[str(guild_id)]["verification_channel_id"] - - def get_table_categories(self, guild_id: int, table: str) -> "list[str]": - """ - Returns list of categories for a guild's table - - @param guild_id: guild id to retrieve from. - @param table: the table to retreive from. - @returns: string list of categories in given table. - """ - categories: "list[str]" = [] - - for category, data in self._data[str(guild_id)][ # pylint: disable=unused-variable - "tables" - ][table]["categories"].items(): - categories.append(category) - - return categories - - def get_table_message_id(self, guild_id: int, table: str) -> int: - """ - Returns the message id for given guild's table. - - @param guild_id: guild id to retrieve from. - @param table: the table to retrieve from. - @returns: int id of message for table's highscores. - """ - return self._data[str(guild_id)]["tables"][table]["message_id"] - - def get_table_names(self, guild_id) -> "list[str]": - """ - Returns a list of table names. - - @param guild_id: guild id to retrieve from. - @returns: list of table names - """ - tables: "list[str]" = [] - - for table, data in self._data[str(guild_id)][ # pylint: disable=unused-variable - "tables" - ].items(): - tables.append(table) - - return tables - - def remove_guild(self, guild_id: int, guild_name: str) -> None: + def remove_guild(self, guild_id: int) -> None: """ Removes a guild's data from object. Saves backup. - @param guild_id: guild id to remove. - @param guild_name: name of guild for backup. + Args: + guild_id (int): guild id to remove """ - old_data = self._data.pop(str(guild_id)) - save_highscores_data(self._data) + self._guild_map.pop(guild_id) - if not os.path.exists("deleted_backups"): - os.mkdir("deleted_backups") + os.rename( + f"{HIGHSCORES_DATA_DIR}/{guild_id}.json", f"{HIGHSCORES_BACKUP_DIR}/{guild_id}.json" + ) - with open(f"deleted_backups/{guild_name}_backup.json", encoding="utf-8", mode="w") as file: - file.write(json.dumps(old_data, indent=4)) - - def reset_guild_data(self, guild_id: int) -> None: + def open_highscores_config(self, config: str) -> dict: """ - Resets highscore data for a guild. Should only be used for development really... + Opens the highscores config file and returns in dictionary format. + Will be replaced when config class is created. - @param guild_id: guild id to reset data for + Args: + config (str): Name of config to load. + + Returns: + dict: dict of highscores config """ - guild_data: dict = self._data[str(guild_id)] + with open(f"{HIGHSCORES_CONFIG_DIR}/{config}.json", encoding="utf-8", mode="r") as file: + return json.load(file) - for boss, boss_data in guild_data["tables"].items(): - for category, category_data in boss_data["categories"].items(): - category_data = [] - boss_data["categories"][category] = category_data - guild_data["tables"][boss] = boss_data - self._data[str(guild_id)] = guild_data - save_highscores_data(self._data) - - def set_guild_highscore_channel(self, guild_id: int, channel_id: int) -> None: + def open_highscores_data(self): """ - Sets the guild's highscores channel. - - @param guild_id: guild id to set to. - @param channel_id: channel id to set. + Opens all saved highscores data in the HIGHSCORES_DATA_DIR dir. Creates a Guild object from + each file and adds to guild map. """ - self._data[str(guild_id)]["highscore_channel_id"] = channel_id + for data_file in os.listdir(HIGHSCORES_DATA_DIR): + with open(f"{HIGHSCORES_DATA_DIR}/{data_file}", encoding="utf-8", mode="r") as file: + guild_obj: Guild = Guild.from_dict(json.load(file)) + self._guild_map[guild_obj.guild_id] = guild_obj - def set_guild_submission_channel(self, guild_id: int, channel_id: int) -> None: + def save_highscores_data(self): """ - Sets the guild's submission channel. - - @param guild_id: guild id to set to. - @param channel_id: channel id to set. + Saves each Guild object into its own json data file. """ - self._data[str(guild_id)]["submission_channel_id"] = channel_id - - def set_guild_verification_channel(self, guild_id: int, channel_id: int) -> None: - """ - Sets the guild's verification channel. - - @param guild_id: guild id to set to. - @param channel_id: channel id to set. - """ - self._data[str(guild_id)]["verification_channel_id"] = channel_id - - def set_table_message_id(self, guild_id: int, table: str, message_id: int) -> None: - """ - Sets the message id for given guild's table. - Saves highscores data. - - @param guild_id: guild id to set to. - @param table: the table to set to. - @param message_id: message id to set. - """ - self._data[str(guild_id)]["tables"][table]["message_id"] = message_id - save_highscores_data(self._data) - - -def open_highscores_config(): - """ - Opens the highscores config file and returns. - @return: dict of highscores config. - """ - # Load bot config - with open(HIGHSCORES_CONFIG_FILE, encoding="utf-8", mode="r") as file: - return json.load(file) - - -def open_highscores_data(): - """ - Opens a highscores_data.json file if one exists, otherwise returns empty dict. - @return: dict of highscores data. - """ - if os.path.exists(HIGHSCORES_DATA_FILE): - with open(HIGHSCORES_DATA_FILE, encoding="utf-8", mode="r") as file: - data = json.load(file) - else: - data = {} - return data - - -def save_highscores_data(data: dict): - """ - Saves the highscores data dict into a json file. - @param data: dict of highscores data. - """ - with open(HIGHSCORES_DATA_FILE, encoding="utf-8", mode="w") as file: - file.write(json.dumps(data, indent=4)) + for guild_id, guild_obj in self._guild_map.items(): + with open(f"{HIGHSCORES_DATA_DIR}/{guild_id}.json", encoding="utf-8", mode="w") as file: + file.write(guild_obj) # should use str function