mirror of https://github.com/stijndcl/didier
Merge pull request #108 from stijndcl/compbio_commands
Add commands to track compbio leaderboardspull/136/head
commit
635560dcd0
|
@ -5,6 +5,7 @@ files/stats.json
|
|||
files/lost.json
|
||||
files/locked.json
|
||||
files/ufora_notifications.json
|
||||
files/compbio_benchmarks_2.json
|
||||
.idea/
|
||||
__pycache__
|
||||
.env
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import json
|
||||
|
||||
from discord import SlashCommandGroup
|
||||
from discord.ext import commands
|
||||
from discord.commands import slash_command, ApplicationContext, Option, AutocompleteContext
|
||||
|
||||
|
@ -5,6 +8,7 @@ from data import schedule
|
|||
from data.courses import load_courses, find_course_from_name
|
||||
from data.embeds.food import Menu
|
||||
from data.embeds.deadlines import Deadlines
|
||||
from data.menus import leaderboards
|
||||
from functions import les, config
|
||||
from functions.stringFormatters import capitalize
|
||||
from functions.timeFormatters import skip_weekends
|
||||
|
@ -83,6 +87,30 @@ class SchoolSlash(commands.Cog):
|
|||
year = 2018 + int(config.get("year"))
|
||||
return await ctx.respond(f"https://studiekiezer.ugent.be/studiefiche/nl/{course.code}/{year}")
|
||||
|
||||
_compbio_group = SlashCommandGroup("compbio", "Commands voor compbio opdrachten")
|
||||
|
||||
@_compbio_group.command(name="leaderboard", description="Gesorteerd en ingevuld leaderboard")
|
||||
async def _compbio_lb_slash(self, ctx: ApplicationContext):
|
||||
lb = leaderboards.CompbioLeaderboard(ctx)
|
||||
await lb.respond()
|
||||
|
||||
@_compbio_group.command(name="submit", description="Link een Dodona-submission aan jouw username")
|
||||
async def _compbio_submit_slash(self, ctx: ApplicationContext,
|
||||
submission: Option(int, description="Id van je Dodona indiening.", required=True)):
|
||||
with open("files/compbio_benchmarks_2.json", "r") as fp:
|
||||
file = json.load(fp)
|
||||
|
||||
submission = str(submission)
|
||||
|
||||
if submission in file:
|
||||
return await ctx.respond("❌ Deze submission is al aan iemand gelinkt.", ephemeral=True)
|
||||
|
||||
with open("files/compbio_benchmarks_2.json", "w") as fp:
|
||||
file[submission] = ctx.user.id
|
||||
json.dump(file, fp)
|
||||
|
||||
return await ctx.respond(f"✅ Submission **{submission}** is aan jouw naam gelinkt.", ephemeral=True)
|
||||
|
||||
|
||||
def setup(client: Didier):
|
||||
client.add_cog(SchoolSlash(client))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
import math
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass, field
|
||||
|
@ -8,11 +9,12 @@ import requests
|
|||
from discord import ApplicationContext
|
||||
from discord.ext.commands import Context
|
||||
|
||||
import settings
|
||||
from data.menus.paginated import Paginated
|
||||
from enums.numbers import Numbers
|
||||
from functions import xp
|
||||
from functions.database import currency, stats, poke, muttn
|
||||
from functions.utils import get_display_name
|
||||
from functions.utils import get_display_name, get_mention
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -21,6 +23,7 @@ class Leaderboard(Paginated, ABC):
|
|||
colour: discord.Colour = discord.Colour.blue()
|
||||
fetch_names: bool = True
|
||||
ignore_non_pos: bool = True
|
||||
reverse: bool = True
|
||||
|
||||
def __post_init__(self):
|
||||
self.data = self.process_data(self.get_data())
|
||||
|
@ -31,7 +34,7 @@ class Leaderboard(Paginated, ABC):
|
|||
|
||||
def process_data(self, entries: list[tuple]) -> Optional[list[tuple]]:
|
||||
data = []
|
||||
for i, v in enumerate(sorted(entries, key=self.get_value, reverse=True)):
|
||||
for i, v in enumerate(sorted(entries, key=self.get_value, reverse=self.reverse)):
|
||||
entry_data = self.get_value(v)
|
||||
|
||||
# Leaderboard is empty
|
||||
|
@ -90,13 +93,13 @@ class Leaderboard(Paginated, ABC):
|
|||
return await ctx.reply(embed=embed, **kwargs)
|
||||
|
||||
async def respond(self, **kwargs) -> discord.Message:
|
||||
if self.data is None:
|
||||
if self.data is None or not self.data:
|
||||
return await self.empty_leaderboard(self.ctx, **kwargs)
|
||||
|
||||
return await super().respond(**kwargs)
|
||||
|
||||
async def send(self, **kwargs) -> discord.Message:
|
||||
if self.data is None:
|
||||
if self.data is None or not self.data:
|
||||
return await self.empty_leaderboard(self.ctx, **kwargs)
|
||||
|
||||
return await super().send(**kwargs)
|
||||
|
@ -117,6 +120,56 @@ class BitcoinLeaderboard(Leaderboard):
|
|||
return "Er zijn nog geen personen met Bitcoins."
|
||||
|
||||
|
||||
@dataclass
|
||||
class CompbioLeaderboard(Leaderboard):
|
||||
colour: discord.Colour = field(default=discord.Colour.green())
|
||||
title: str = field(default="Leaderboard Computationele Biologie #2")
|
||||
reverse: bool = False
|
||||
|
||||
def get_submission_user(self, submission_id: str) -> str:
|
||||
with open("files/compbio_benchmarks_2.json", "r") as fp:
|
||||
file = json.load(fp)
|
||||
|
||||
if submission_id in file:
|
||||
user_id = file[submission_id]
|
||||
return get_mention(self.ctx, user_id)
|
||||
|
||||
return f"[# {submission_id}]"
|
||||
|
||||
def get_data(self) -> list[tuple]:
|
||||
headers = {"Authorization": f"token {settings.UGENT_GH_TOKEN}"}
|
||||
result = requests.get(f"https://github.ugent.be/raw/computationele-biologie/benchmarks-2022/main/reconstruction/J02459.1.50mers.md", headers=headers).text
|
||||
# Remove table headers
|
||||
result = result.split("\n")[2:]
|
||||
data = []
|
||||
|
||||
for line in result:
|
||||
try:
|
||||
cells = line.split("|")
|
||||
submission_id = cells[1].strip()
|
||||
mean = float(cells[2].strip().split(" ")[0])
|
||||
except IndexError:
|
||||
# Other lines because of markdown formatting
|
||||
continue
|
||||
|
||||
data.append((submission_id, mean, ))
|
||||
|
||||
return data
|
||||
|
||||
def _should_highlight(self, data) -> bool:
|
||||
# TODO maybe find a fix for this?
|
||||
return False
|
||||
|
||||
def format_entry(self, index: int, data: tuple) -> str:
|
||||
return f"{index + 1}: {self.get_submission_user(data[0])} ({self.format_entry_data(data)})"
|
||||
|
||||
def format_entry_data(self, data: tuple) -> str:
|
||||
return f"{str(data[1])} ms"
|
||||
|
||||
def get_value(self, data: tuple):
|
||||
return data[1]
|
||||
|
||||
|
||||
@dataclass
|
||||
class CoronaLeaderboard(Leaderboard):
|
||||
colour: discord.Colour = field(default=discord.Colour.red())
|
||||
|
|
|
@ -45,7 +45,7 @@ def format_command_usage(ctx: Context) -> str:
|
|||
def format_slash_command_usage(interaction: Interaction) -> str:
|
||||
# Create a string with the options used
|
||||
options = " ".join(list(map(
|
||||
lambda o: f"{o['name']}: \"{o['value']}\"",
|
||||
lambda o: f"{o['name']}: \"{o['value']}\"" if "value" in o else o["name"],
|
||||
interaction.data.get("options", [])
|
||||
)))
|
||||
|
||||
|
|
|
@ -4,34 +4,55 @@ import discord
|
|||
from discord import ApplicationContext
|
||||
from discord.ext.commands import Context
|
||||
|
||||
from data import constants
|
||||
import settings
|
||||
|
||||
|
||||
def get_display_name(ctx: Union[ApplicationContext, Context], user_id: int) -> str:
|
||||
def get_member_or_user(ctx: Union[ApplicationContext, Context], user_id: int) -> Optional[Union[discord.Member, discord.User]]:
|
||||
"""Get a COC Member instance of a user if they are in the server,
|
||||
otherwise the regular User instance
|
||||
"""
|
||||
author = ctx.author if isinstance(ctx, Context) else ctx.user
|
||||
|
||||
# Check if this is a DM, or the user is not in the guild
|
||||
if ctx.guild is None or ctx.guild.get_member(user_id) is None:
|
||||
# User is the author, no need to fetch their name
|
||||
if user_id == author.id:
|
||||
return author.display_name
|
||||
return author
|
||||
|
||||
# Get member instance from CoC
|
||||
COC = ctx.bot.get_guild(int(constants.DeZandbak))
|
||||
COC = ctx.bot.get_guild(settings.COC_ID)
|
||||
member = COC.get_member(user_id)
|
||||
if member is not None:
|
||||
return member.display_name
|
||||
return member
|
||||
|
||||
# Try to fetch the user
|
||||
user = ctx.bot.get_user(user_id)
|
||||
if user is not None:
|
||||
return user.name
|
||||
return ctx.bot.get_user(user_id)
|
||||
|
||||
# User couldn't be found
|
||||
# Guild exists, use that instead
|
||||
return ctx.guild.get_member(user_id)
|
||||
|
||||
|
||||
def get_display_name(ctx: Union[ApplicationContext, Context], user_id: int) -> str:
|
||||
member = get_member_or_user(ctx, user_id)
|
||||
|
||||
# Nothing found
|
||||
if member is None:
|
||||
return f"[? | {user_id}]"
|
||||
|
||||
mem = ctx.guild.get_member(user_id)
|
||||
return mem.display_name
|
||||
if isinstance(member, discord.Member):
|
||||
return member.display_name
|
||||
|
||||
return member.name
|
||||
|
||||
|
||||
def get_mention(ctx: Union[ApplicationContext, Context], user_id: int) -> str:
|
||||
member = get_member_or_user(ctx, user_id)
|
||||
|
||||
# Nothing found
|
||||
if member is None:
|
||||
return f"[? | {user_id}]"
|
||||
|
||||
return member.mention
|
||||
|
||||
|
||||
async def reply_to_reference(ctx: Context, content: Optional[str] = None, embed: Optional[discord.Embed] = None, always_mention=False):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Beta version of Discord.py fork
|
||||
py-cord==2.0.0b1
|
||||
py-cord==2.0.0b5
|
||||
|
||||
python-dotenv==0.14.0
|
||||
beautifulsoup4==4.9.1
|
||||
|
|
|
@ -41,3 +41,6 @@ COC_ID: int = int(os.getenv("COC_ID", "626699611192688641"))
|
|||
# Ex: 123,456,789
|
||||
_guilds = os.getenv("SLASHTESTGUILDS", "").replace(" ", "")
|
||||
SLASH_TEST_GUILDS: List[int] = list(map(lambda x: int(x), _guilds.split(","))) if _guilds else None
|
||||
|
||||
# GitHub token (UGent)
|
||||
UGENT_GH_TOKEN = os.getenv("UGENTGHTOKEN", "")
|
||||
|
|
Loading…
Reference in New Issue