""" 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 MAX_LINE_LENGTH, 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() # get the longest string longest_str: int = scores.UserName.map(len).max() for i, row in scores.iterrows(): str_list.append( format_score_string( row["UserName"], row["Score"], longest_str, category.IsTimeRecord, i + 1, MAX_LINE_LENGTH ) ) 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" message_str += "```" 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) )