From 5b31314f02dd98d863753f5a5466bb0b7345d0dd Mon Sep 17 00:00:00 2001 From: alwayscompiling Date: Wed, 27 Jul 2022 22:15:06 -0400 Subject: [PATCH] Fill out HighscoreData class with access functions for utils.py. --- utilities/highscores_data.py | 126 ++++++++++++++++++++++++++++++++--- utilities/utils.py | 87 +++++------------------- 2 files changed, 132 insertions(+), 81 deletions(-) diff --git a/utilities/highscores_data.py b/utilities/highscores_data.py index 7f50b5a..e0c1fbc 100644 --- a/utilities/highscores_data.py +++ b/utilities/highscores_data.py @@ -38,23 +38,127 @@ class HighscoresData: self._data[str(guild_id)] = skeleton - def get_guild_data(self, guild_id: int) -> dict: + def add_score( + self, guild_id: int, boss_name: str, category: str, user: str, score: str + ) -> None: """ - Gets guild data from the guild id. + Adds a new score to guilds highscore data. + Ensures that there is no user duplicate and then sorts the scores - @param guild_id: guild id to retrieve data for - @returns: dict of guild's highscore data + @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. """ - return self._data[str(guild_id)] + 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"] - def set_guild_data(self, guild_id: int, data: dict) -> None: - """ - Sets guild data for given guild id, saves data. + # 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_tuple = (user, score, score_seconds) + sort_index = 2 + else: + score_tuple = (user, int(score)) + sort_index = 1 - @param guild_id: guild id to save data for - @param data: data to set and save + # if user is in an existing tuple, delete it. + users_scores: "list[tuple]" = [score_tuple] + for tup in scores: + if user == tup[0]: + # Add tup to users_scores, remove from scores + users_scores.append(tup) + + # sort users_scores + users_scores.sort( + key=lambda x: x[sort_index], + reverse=not ascending, + ) + + for index, tup in enumerate(users_scores): + if index == 0: + # first score is the best score. + if tup not in scores: + scores.append(tup) + else: + # discard all other scores from scores list. + if tup in scores: + scores.remove(tup) + + # sort scores. + scores.sort( + key=lambda x: x[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]": """ - self._data[str(guild_id)] = data + 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)][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_guild_channel_id(self, guild_id: int) -> int: + """ + Returns the channel id to post highscore messages to. + + @param guild_id: guild id to retrieve from + """ + return self._data[str(guild_id)]["highscore_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_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 retreive from. + @returns: int id of message for table's highscores. + """ + return self._data[str(guild_id)]["tables"][table]["message_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 retrieve from. + @param table: the table to retreive from. + @param message_id: message id to set. + """ + self._data[str(guild_id)]["tables"][table]["message_id"] = message_id save_highscores_data(self._data) diff --git a/utilities/utils.py b/utilities/utils.py index a8daf23..3131e2f 100644 --- a/utilities/utils.py +++ b/utilities/utils.py @@ -3,10 +3,8 @@ Contains various utlity functions for highscores bot """ import nextcord -from highscores import highscores_config # pylint: disable=import-error from highscores import highscores_data # pylint: disable=import-error from highscores import highscores_message_map # pylint: disable=import-error -from utilities.highscores_data import save_highscores_data # pylint: disable=import-error def create_message_map(data: dict): @@ -28,36 +26,37 @@ def create_message_map(data: dict): return message_map -def format_highscore_message(boss_name: str, guild_data: dict): +def format_highscore_message(boss_name: str, guild_id: int): """ returns a formatted string for a boss's highscore @param boss: the dictionary object for the boss - @param guild_data: the guild's highscore data + @param guild_id: the guild id the message is for @return the formatted string """ ret_string = f"**{boss_name}**\n```" - boss_data = guild_data["tables"][boss_name] # Gather all categories and add to string - for key, value in boss_data["categories"].items(): + for key, value in highscores_data.get_categories_data(guild_id, boss_name): ret_string += f"{key}".ljust(26, " ") ret_string += "\n" - highscore_size = highscores_config["highscore_size"] + highscore_size = highscores_data.get_config_highscore_size() # list rankings in a single line. Start with first place for each category and then continue for i in range(highscore_size): - for key, value in boss_data["categories"].items(): + for key, value in highscores_data.get_categories_data(guild_id, boss_name): if len(value) > i: score_pair = value[i] # pad username to max length. - username: str = score_pair[0].ljust(guild_data["username_length"], " ") + username: str = score_pair[0].ljust( + highscores_data.get_guild_username_length(guild_id), " " + ) score: str = str(score_pair[1]) # pad score to correct length # MM:SS.ms is 7 characters long - if highscores_config["categories"][key]["is_time_record"]: + if highscores_data.get_config_is_category_time_record(key): # if there are single digit minutes, add a space for formatting. if score.find(":") and len(score.split(":", maxsplit=1)[0]) < 2: score = " " + score @@ -73,19 +72,19 @@ def format_highscore_message(boss_name: str, guild_data: dict): async def send_highscore_message( - channel: nextcord.TextChannel, boss_name: str, guild_data: dict + channel: nextcord.TextChannel, boss_name: str, guild_id: int ) -> nextcord.Message: """ Function takes care of checking if a message exists for a boss, then creating and sending/editing the message @param channel: the channel to send the message in/search for message id @param boss: the boss to send the message about - @param guild_data: the guild's highscore data + @param guild_id: the guild id to send message to @return: The nextcord message """ - highscore_string = format_highscore_message(boss_name, guild_data) + highscore_string = format_highscore_message(boss_name, guild_id) - message_id = guild_data["tables"][boss_name]["message_id"] + message_id = highscores_data.get_table_message_id(guild_id, boss_name) try: message: nextcord.Message = await channel.fetch_message(message_id) await message.edit(content=highscore_string) @@ -93,7 +92,7 @@ async def send_highscore_message( # message doesn't exist. message: nextcord.Message = await channel.send(highscore_string) message_id = message.id - guild_data["tables"][boss_name]["message_id"] = message_id + highscores_data.set_table_message_id(guild_id, boss_name, message_id) # save message -> boss_name in message_map # get guild id from channel # channel should come from the guild that is requesting this highscores message anyways. @@ -116,58 +115,10 @@ async def submit_score( @param score: score to add """ - boss_category_config = highscores_config["categories"][category] - guild_data = highscores_data[str(interaction.guild.id)] - - # create score tuple for either time or int - # define sort index - if boss_category_config["is_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_tuple = (user, score, score_seconds) - sort_index = 2 - - else: - score_tuple = (user, int(score)) - sort_index = 1 - - scores: "list[tuple]" = guild_data["tables"][boss_name]["categories"][category] - - # if user is in an existing tuple, delete it. - users_scores: "list[tuple]" = [score_tuple] - for tup in scores: - if user == tup[0]: - # Add tup to users_scores, remove from scores - users_scores.append(tup) - - # sort users_scores - users_scores.sort( - key=lambda x: x[sort_index], - reverse=not boss_category_config["ascending"], - ) - - for index, tup in enumerate(users_scores): - if index == 0: - # first score is the best score. - if tup not in scores: - scores.append(tup) - else: - # discard all other scores from scores list. - if tup in scores: - scores.remove(tup) - - # sort scores. - scores.sort( - key=lambda x: x[sort_index], - reverse=not boss_category_config["ascending"], - ) + highscores_data.add_score(interaction.guild_id, boss_name, category, user, score) # edit message - highscore_channel_id = guild_data["highscore_channel_id"] + highscore_channel_id = highscores_data.get_guild_channel_id(interaction.guild_id) print(f"Editting message {highscore_channel_id}") channel = interaction.guild.get_channel(highscore_channel_id) @@ -175,8 +126,4 @@ async def submit_score( error_response += 'Register with "?register" command.' assert channel is not None, await interaction.send(error_response, ephemeral=True) - await send_highscore_message(channel, boss_name, guild_data) - - # save data - highscores_data[str(interaction.guild.id)] = guild_data - save_highscores_data(highscores_data) + await send_highscore_message(channel, boss_name, interaction.guild_id)