diff --git a/classes/category.py b/classes/category.py deleted file mode 100644 index cb00c5e..0000000 --- a/classes/category.py +++ /dev/null @@ -1,201 +0,0 @@ -"""File for Category class.""" - -import json - -from classes.score import Score, ScoreTime # pylint: disable=import-error - - -class Category: - """Stores a category's information and relative scores.""" - - def __init__(self, name: str) -> None: - """ - Default constructor for Category class. Creates empty category and populates with defaults. - - Args: - name (str): Category's name - """ - self._name: str = name - self._ascending: bool = False - self._time_record: bool = False - self._scores_map: dict = {} - - def __str__(self) -> str: - """ - Returns Category class as a string for printing. - - Returns: - str: Category class as a string - """ - return self.to_str() - - @classmethod - def from_dict(cls, name: str, data: dict): - """ - Creates a Category class from the passed data. - - Args: - name (str): Category name - data (dict): Rest of Category data in dictionary format - - Returns: - Category: Populated Category object - """ - category = cls(name) - category.ascending = data["ascending"] - category.time_record = data["time_record"] - for user, score in data["scores"].items(): - if category.time_record: - score_obj: ScoreTime = ScoreTime(user) - score_obj.value = float(score) - category.add_score(score_obj) - else: - score_obj: Score = Score(user) - score_obj.value = int(score) - category.add_score(score_obj) - - return category - - @property - def ascending(self) -> bool: - """ - Getter for is ascending. - - Returns: - bool: is ascending - """ - return self._ascending - - @ascending.setter - def ascending(self, ascending: bool) -> None: - """ - Setter for is ascending. - - Args: - ascending (bool): is ascending - """ - self._ascending = ascending - - @property - def name(self) -> str: - """ - Getter for name. - - Returns: - str: name - """ - return self._name - - @property - def time_record(self) -> bool: - """ - Getter for is time record. - - Returns: - bool: is time record - """ - return self._time_record - - @time_record.setter - def time_record(self, time_record: bool) -> None: - """ - Setter for is time record. - - Args: - time_record (bool): is time record - """ - self._time_record = time_record - - @property - def scores(self) -> "list[Score]": - """ - Getter for Scores list. - - Returns: - list[Score]: List of Scores in this Category - """ - return self._scores_map.values() - - def add_score(self, score: Score) -> None: - """ - Adds score to dictionary storage map. Sorts dictionary by score value. - - Args: - score (Score): Score to be added - """ - if score.user in self._scores_map: - self._scores_map[score.user].value = score.value - else: - self._scores_map[score.user] = score - - self._scores_map = dict(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_users(self) -> "list[str]": - """ - Returns list of users in this category. - - Returns: - list[str]: List of all users in category. - """ - return self._scores_map.keys() - - def get_user_score(self, user: str) -> Score: - """ - Gets a user's score. Returns None if user is not found. - - Args: - user (str): Name of score to find - - Returns: - Score: User's Score or None - """ - if user in self._scores_map: - return self._scores_map[user] - return None - - def remove_score(self, user: str) -> Score: - """ - Removes a user's score from dictionary storage. - - Args: - user (str): user whose score to remove - - Returns: - Score: User's Score or None - """ - if user in self._scores_map: - return self._scores_map.pop(user) - return None - - def to_dict(self) -> dict: - """ - Saves category data as a python dictionary. - Does not include category name. It should be the key of above data structure. - - Returns: - dict: Category class in dictionary format - """ - data = {} - data["ascending"] = self.ascending - data["time_record"] = self.time_record - data["scores"] = {} - for score in self.scores: - data["scores"][score.user] = score.value - - return data - - def to_str(self) -> str: - """ - Returns Category object as a string. - - Returns: - str: string of json representation of Category - """ - return json.dumps(self.to_dict(), indent=4) diff --git a/classes/guild.py b/classes/guild.py deleted file mode 100644 index bcdd4fe..0000000 --- a/classes/guild.py +++ /dev/null @@ -1,245 +0,0 @@ -"""File for Guild class.""" - -import json - -from classes.table import Table # pylint: disable=import-error - - -class Guild: - """Stores a guild's information.""" - - def __init__(self, guild_id: int) -> None: - """ - Default constructor for Guild class. Initializes channel ids as 0 as they won't be - registered yet. Sets default username length of 12. Default highscores size to 3. - - Args: - guild_id (int): Discord Guild id of new Guild - """ - self._category_pad_length: int = 26 - self._guild_id: int = guild_id - self._highscore_channel_id: int = 0 - self._submission_channel_id: int = 0 - self._table_map: dict = {} - self._username_length: int = 12 - self._verification_channel_id: int = 0 - - def __str__(self) -> str: - """ - Returns Guild class as a string for printing. - - Returns: - str: Guild class as a string - """ - return self.to_str() - - @classmethod - def from_dict(cls, guild_id: int, data: dict): - """ - Creates a Guild class from the passed data. - - Args: - guild_id (int): Guild's id - data (dict): Rest of Guild data in dictionary format - - Returns: - Guild: Populated Guild object - """ - guild = cls(guild_id) - guild.category_pad_length = data["category_pad_length"] - guild.highscore_channel = data["highscore_channel_id"] - guild.submission_channel = data["submission_channel_id"] - guild.username_length = data["username_length"] - guild.verification_channel = data["verification_channel_id"] - - for table_name, table_data in data["tables"].items(): - table = Table.from_dict(table_name, table_data) - guild.add_table(table) - - return guild - - @property - def category_pad_length(self) -> int: - """ - Getter for Category Pad Length. - - Returns: - int: Length to pad each category entry. - """ - return self._category_pad_length - - @category_pad_length.setter - def category_pad_length(self, length: int) -> None: - """ - Setter for Category Pad Length. - - Args: - length (int): New length to set. - """ - self._category_pad_length = length - - @property - def guild_id(self) -> int: - """ - Getter for Guild id. - - Returns: - int: Guild id - """ - return self._guild_id - - @property - def highscore_channel(self) -> int: - """ - Getter for highscore channel id. - - Returns: - int: highscore channel id - """ - return self._highscore_channel_id - - @highscore_channel.setter - def highscore_channel(self, channel: int) -> None: - """ - Setter for highscore channel id. - - Args: - channel (int): highscore channel id - """ - self._highscore_channel_id = channel - - @property - def submission_channel(self) -> int: - """ - Getter for submission channel id. - - Returns: - int: submission channel id - """ - return self._submission_channel_id - - @submission_channel.setter - def submission_channel(self, channel: id) -> None: - """ - Setter fro submission channel id. - - Args: - channel (id): submission channel id - """ - self._submission_channel_id = channel - - @property - def tables(self) -> "list[Table]": - """ - Getter for Tables list. - - Returns: - list[Table]: List of Tables in this Guild - """ - return self._table_map.values() - - @property - def username_length(self) -> int: - """ - Getter for username length. - - Returns: - int: username length - """ - return self._username_length - - @username_length.setter - def username_length(self, length: int) -> None: - """ - Setter for username length. - - Args: - length (int): username length - """ - self._username_length = length - - @property - def verification_channel(self) -> int: - """ - Getter for verification channel id. - - Returns: - int: verification channel id - """ - return self._verification_channel_id - - @verification_channel.setter - def verification_channel(self, channel: int) -> None: - """ - Setter for verification channel id - - Args: - channel (int): verification channel id - """ - self._verification_channel_id = channel - - def add_table(self, table: Table) -> None: - """ - Adds a Table to table map. Shouldn't exist already. - - Args: - table (Table): new Table to add - """ - if table.name not in self._table_map: - self._table_map[table.name] = table - - def get_table(self, table_name: str) -> Table: - """ - Getter for specific Table. Returns None if Table is not found. - - Args: - table_name (str): Name of Table to find - - Returns: - Table: Table corresponding to Name. None if not found. - """ - if table_name in self._table_map: - return self._table_map[table_name] - return None - - def get_tables(self) -> dict: - """ - Getter for dict of table names and tables. - - Returns: - dict: Dictionary consisting of the Table Names and the Table object itself. - """ - - # I don't know if this is const data. Don't want to allow data to be written as a result of this function. - return self._table_map - - def to_dict(self) -> dict: - """ - Creates python dictionary object from class data. - Does not include guild_id in dict, it should be the key of above data structure. - - Returns: - dict: Guild class in dictionary format - """ - data: dict = {} - - data["category_pad_length"] = self.category_pad_length - data["highscore_channel_id"] = self.highscore_channel - data["submission_channel_id"] = self.submission_channel - data["tables"] = {} - data["username_length"] = self.username_length - data["verification_channel_id"] = self.verification_channel - - for table in self.tables: - data["tables"][table.name] = table.to_dict() - - return data - - def to_str(self) -> str: - """ - Returns Guild object as a string. - - Returns: - str: string of json representation of Guild - """ - return json.dumps(self.to_dict(), indent=4) diff --git a/classes/highscores_data.py b/classes/highscores_data.py deleted file mode 100644 index 51ce5cf..0000000 --- a/classes/highscores_data.py +++ /dev/null @@ -1,153 +0,0 @@ -"""Class and functions for storing and retrieving highscores data.""" - -import os -import json - -from classes.guild import Guild # pylint: disable=import-error -from classes.table import Table # pylint: disable=import-error -from classes.category import Category # pylint: disable=import-error - - -HIGHSCORES_BACKUP_DIR = "deleted_backups" -HIGHSCORES_CONFIG_DIR = "example_config" -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.name]["ascending"] - category.time_record = config["categories"][category.name]["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 diff --git a/classes/score.py b/classes/score.py deleted file mode 100644 index c6f4344..0000000 --- a/classes/score.py +++ /dev/null @@ -1,154 +0,0 @@ -"""File for Score classes""" - -import time - - -class Score: - """Parent class for Scores. Stores common information for a Score.""" - - # no user setter, it should never change. - - def __init__(self, user: str) -> None: - """ - Default constructor for Score class. - - Args: - user (str): Score's user - value (int): Score's value - """ - self._user: str = user - self._value: int = -1 - - def __str__(self) -> str: - """ - Returns Score class as a string for printing. - - Returns: - str: Score class as a string - """ - return self.to_str() - - @property - def user(self) -> str: - """ - Getter for score user. - - Returns: - str: user - """ - return self._user - - @user.setter - def user(self, username: str) -> None: - """ - Setter for score's username. - - Args: - username (str): username to set to - """ - self._user = username - - @property - def value(self) -> int: - """ - Getter for score value. - - Returns: - int: value - """ - return self._value - - @value.setter - def value(self, value: int) -> None: - """ - Setter for score value. - - Args: - value (int): score value input - """ - self._value = value - - def get_str(self) -> str: - """ - Gets score's value as string. - - Returns: - str: Score's value - """ - return str(self._value) - - def set_value_str(self, value: str) -> None: - """ - Setter for score value from string. - - Args: - value (str): int as a string - """ - self._value = int(value) - - def to_str(self) -> str: - """ - Returns Score object as a string. - - Returns: - str: string of json representation of Score - """ - return f"{self.user}: {self.get_str()}" - - -class ScoreTime(Score): - """Class for a time based score. Inherits from Score.""" - - def __init__(self, user: str) -> None: # pylint: disable=super-init-not-called - """ - Default constructor for ScoreTime class. - - Args: - user (str): Score's user - score (float): Score's value - """ - # store time score as seconds. - self._user: str = user - self._score: float = -1.0 - - @property - def value(self) -> float: - """ - Getter for score value. - - Returns: - float: value - """ - return self._score - - @value.setter - def value(self, value: float) -> None: - """ - Setter for score value. - - Args: - value (float): value - """ - self._score = value - - def get_str(self) -> str: - """ - Gets score's value as string. Turns seconds into MM:SS.ms format. - - Returns: - str: value in time format. - """ - milliseconds = round((self.value - int(self.value)) * 10) - return time.strftime(f"%-M:%S.{milliseconds}", time.gmtime(self.value)) - - def set_value_str(self, value: str) -> None: - """ - Setter for score value from a string. - - Args: - value (str): string representation of time - """ - if value.find(":"): - self._score = int(value.split(":")[0]) * 60 + float(value.split(":")[1]) - else: - self._score = float(value) diff --git a/classes/table.py b/classes/table.py deleted file mode 100644 index e12224e..0000000 --- a/classes/table.py +++ /dev/null @@ -1,174 +0,0 @@ -"""File for Table class.""" - -import json - -from classes.category import Category # pylint: disable=import-error - - -class Table: - """Stores a table's information a list of categories.""" - - def __init__(self, name: str) -> None: - """ - Default constructor for Table class. - Creates object and fills out class variables with defaults. - - Args: - name (str): Table's name - """ - self._name: str = name - self._message_id: int = 0 - self._categories_map: dict = {} - self._size = 3 - - def __str__(self) -> str: - """ - Returns Table class as a string for printing. - - Returns: - str: Table class as a string - """ - return self.to_str() - - @classmethod - def from_dict(cls, table_name: str, data: dict): - """ - Creates a Table class from the passed data. - - Args: - table_name (str): Table name - data (dict): Rest of Table data in dictionary format - - Returns: - Table: Populated Table object - """ - table = cls(table_name) - - table.message_id = data["message_id"] - table.size = data["table_size"] - - for cat_name, cat in data["categories"].items(): - category = Category.from_dict(cat_name, cat) - table.add_category(category) - - return table - - @property - def categories(self) -> "list[Category]": - """ - Getter for Categories list. - - Returns: - list[Category]: List of Categories in this Table - """ - return self._categories_map.values() - - @property - def message_id(self) -> int: - """ - Getter for message id - - Returns: - int: message id - """ - return self._message_id - - @message_id.setter - def message_id(self, m_id: int) -> None: - """ - Setter for message id. - - Args: - m_id (int): message id - """ - self._message_id = m_id - - @property - def name(self) -> str: - """ - Getter for name. - - Returns: - str: name - """ - return self._name - - @property - def size(self) -> int: - """ - Getter for size of table. - - Returns: - int: Size of table - """ - return self._size - - @size.setter - def size(self, size: int) -> None: - """ - Setter for size of table. - - Args: - size (int): New size of table - """ - self._size = size - - def add_category(self, category: Category) -> None: - """ - Adds a Category to categories map. Shouldn't exist already. - - Args: - category (Category): New Category to add - """ - if category.name not in self._categories_map: - self._categories_map[category.name] = category - - def get_categories(self) -> dict: - """ - Getter for dict of category names and categories. - - Returns: - dict: Dictionary consisting of Category names and Category objects. - """ - # I don't know if this is const data. Don't want to allow data to be written as a result of this function. - return self._categories_map - - def get_category(self, category_name: str) -> Category: - """ - Getter for specific category. Returns None if not found. - - Args: - category_name (str): name of category to return - - Returns: - Category: Category corresponding to name. None if not found. - """ - if category_name in self._categories_map: - return self._categories_map[category_name] - return None - - def to_dict(self) -> dict: - """ - Saves Table as a python dictionary. - Does not include table name. It should be the key of above data structure. - - Returns: - dict: Table class in dictionary format - """ - data = {} - data["message_id"] = self.message_id - data["table_size"] = self.size - data["categories"] = {} - for category in self.categories: - data["categories"][category.name] = category.to_dict() - - return data - - def to_str(self) -> str: - """ - Returns Table object as a string. - - Returns: - str: string of json representation of Table - """ - return json.dumps(self.to_dict(), indent=4)