diff --git a/cogs/commands/__init__.py b/cogs/commands/__init__.py index 05bb85d..21a0f0c 100644 --- a/cogs/commands/__init__.py +++ b/cogs/commands/__init__.py @@ -10,6 +10,7 @@ from .help import HelpCog from .refresh import RefreshCog from .set import SetCog from .update import UpdateCog +from .view import ViewCog # This function will be called when this extension is loaded. @@ -24,3 +25,4 @@ def setup(bot: commands.Bot): bot.add_cog(RefreshCog(bot)) bot.add_cog(SetCog()) bot.add_cog(UpdateCog(bot)) + bot.add_cog(ViewCog()) diff --git a/cogs/commands/view.py b/cogs/commands/view.py index 949fe2b..1be4000 100644 --- a/cogs/commands/view.py +++ b/cogs/commands/view.py @@ -1,3 +1,107 @@ """ -_summary_ -""" \ No newline at end of file +View command heirarchy. +""" + +import nextcord +import pandas as pd +from nextcord.ext import commands +from sqlalchemy import select +from sqlalchemy.orm import Session + +# pylint: disable=import-error +from utilities.sql_data_classes import Category, CategoryGroup, Score, engine +from utilities.utils import autofill_categories, autofill_groups, format_score_string + + +class ViewCog(commands.Cog, name="View Command"): + """ + Class holds commands for viewing data. + """ + + def __init__(self) -> None: + """ + Default constructor for ViewCog class. Does nothing. + """ + + @nextcord.slash_command() + async def view(self, interaction: nextcord.Interaction): + """ + Parent slash command for view. Never called. + """ + + @view.subcommand(description="Lists all scores for a given category.") + async def leaderboard( + self, + interaction: nextcord.Interaction, + group_id: str = nextcord.SlashOption( + name="group", description="Group to show leaderboard from.", required=True + ), + category_id: str = nextcord.SlashOption( + name="category", description="Category to show leaderboard.", required=True + ), + ): + """ + Gathers all users that have a submission in the group/category combo and returns a message with them + in ranked order. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + group_id (str): String representation of Group id to search from. Is SlashOption. + category_id (str): String representation of Category id to show leaderboard. Is SlashOption. + """ + str_list: "list[str]" = [] + + # get group, category, and all scores sorted correctly. + with Session(engine) as session: + stmt = select(CategoryGroup).where(CategoryGroup.GroupId == int(group_id)) + group = session.scalar(stmt) + + stmt = select(Category).where(Category.CategoryId == int(category_id)) + category = session.scalar(stmt) + + d_f = pd.read_sql_query( + sql=session.query(Score).where(Score.CategoryId == category_id).statement, con=engine + ) + + scores = d_f.sort_values("Score", ascending=category.IsAscending).reset_index() + + for i, row in scores.iterrows(): + str_list.append( + format_score_string( + row["UserName"], row["Score"], group.UsernameLength, category.IsTimeRecord, i + 1, group.PadLength + ) + ) + + message_str: str = f"**{group.GroupName} {category.CategoryName} Leaderboard!**\n" + if len(str_list) == 0: + message_str += "No Submissions!" + else: + for line in str_list: + message_str += f"{line}\n" + + await interaction.response.send_message(content=message_str) + + @leaderboard.on_autocomplete("group_id") + async def group_autocomplete(self, interaction: nextcord.Interaction, group_id: str): + """ + Autocomplete function for table names. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + group_id (str): String to be autocompleted with Group name. + """ + await interaction.response.send_autocomplete(autofill_groups(interaction.guild_id, group_id)) + + @leaderboard.on_autocomplete("category_id") + async def category_autocomplete(self, interaction: nextcord.Interaction, category_id: str, group_id: str): + """ + Autocomplete function for category names. + + Args: + interaction (nextcord.Interaction): Interaction that invoked the command. + category_id (str): String to be autocompleted with Category name. + group_id (str): Group to find Category from. + """ + await interaction.response.send_autocomplete( + autofill_categories(interaction.guild_id, int(group_id), category_id) + )