aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/exts/events/advent_of_code/_cog.py72
-rw-r--r--bot/exts/events/advent_of_code/_helpers.py25
2 files changed, 66 insertions, 31 deletions
diff --git a/bot/exts/events/advent_of_code/_cog.py b/bot/exts/events/advent_of_code/_cog.py
index 2c1f4541..7f35c306 100644
--- a/bot/exts/events/advent_of_code/_cog.py
+++ b/bot/exts/events/advent_of_code/_cog.py
@@ -180,24 +180,18 @@ class AdventOfCode(commands.Cog):
@in_month(Month.DECEMBER)
@adventofcode_group.command(
- name="leaderboard",
- aliases=("board", "lb"),
- brief="Get a snapshot of the PyDis private AoC leaderboard",
+ name="dayandstar",
+ aliases=("daynstar", "daystar"),
+ brief="Get a view that lets you filter the leaderboard by day and star",
)
@whitelist_override(channels=AOC_WHITELIST_RESTRICTED)
- async def aoc_leaderboard(
+ async def aoc_day_and_star_leaderboard(
self,
ctx: commands.Context,
- day_and_star: Optional[bool] = False,
- maximum_scorers: Optional[int] = 10
+ maximum_scorers_day_and_star: Optional[int] = 10
) -> None:
- """
- Get the current top scorers of the Python Discord Leaderboard.
-
- Additionally, you can provide an argument `day_and_star` (Boolean) to have the bot send a View
- that will let you filter by day and star.
- """
- if maximum_scorers > AocConfig.max_day_and_star_results or maximum_scorers <= 0:
+ """Have the bot send a View that will let you filter the leaderboard by day and star."""
+ if maximum_scorers_day_and_star > AocConfig.max_day_and_star_results or maximum_scorers_day_and_star <= 0:
raise commands.BadArgument(
f"The maximum number of results you can query is {AocConfig.max_day_and_star_results}"
)
@@ -207,25 +201,12 @@ class AdventOfCode(commands.Cog):
except _helpers.FetchingLeaderboardFailedError:
await ctx.send(":x: Unable to fetch leaderboard!")
return
- if not day_and_star:
-
- number_of_participants = leaderboard["number_of_participants"]
-
- top_count = min(AocConfig.leaderboard_displayed_members, number_of_participants)
- header = f"Here's our current top {top_count}! {Emojis.christmas_tree * 3}"
-
- table = f"```\n{leaderboard['top_leaderboard']}\n```"
- info_embed = _helpers.get_summary_embed(leaderboard)
-
- await ctx.send(content=f"{header}\n\n{table}", embed=info_embed)
- return
-
# This is a dictionary that contains solvers in respect of day, and star.
# e.g. 1-1 means the solvers of the first star of the first day and their completion time
per_day_and_star = json.loads(leaderboard['leaderboard_per_day_and_star'])
view = AoCDropdownView(
day_and_star_data=per_day_and_star,
- maximum_scorers=maximum_scorers,
+ maximum_scorers=maximum_scorers_day_and_star,
original_author=ctx.author
)
message = await ctx.send(
@@ -237,6 +218,43 @@ class AdventOfCode(commands.Cog):
@in_month(Month.DECEMBER)
@adventofcode_group.command(
+ name="leaderboard",
+ aliases=("board", "lb"),
+ brief="Get a snapshot of the PyDis private AoC leaderboard",
+ )
+ @whitelist_override(channels=AOC_WHITELIST_RESTRICTED)
+ async def aoc_leaderboard(
+ self,
+ ctx: commands.Context,
+ self_placement_name: Optional[str] = None,
+ ) -> None:
+ """
+ Get the current top scorers of the Python Discord Leaderboard.
+
+ Additionaly you can specify a `self_placement_name`
+ that will append the specified profile's personal stats to the top of the leaderboard
+ """
+ async with ctx.typing():
+ try:
+ leaderboard = await _helpers.fetch_leaderboard(self_placement_name=self_placement_name)
+ except _helpers.FetchingLeaderboardFailedError:
+ await ctx.send(":x: Unable to fetch leaderboard!")
+ return
+
+ number_of_participants = leaderboard["number_of_participants"]
+
+ top_count = min(AocConfig.leaderboard_displayed_members, number_of_participants)
+ self_placement_header = "(and your personal stats compared to the top 10)" if self_placement_name else ""
+ header = f"Here's our current top {top_count}{self_placement_header}! {Emojis.christmas_tree * 3}"
+
+ table = f"```\n{leaderboard['top_leaderboard']}\n```"
+ info_embed = _helpers.get_summary_embed(leaderboard)
+
+ await ctx.send(content=f"{header}\n\n{table}", embed=info_embed)
+ return
+
+ @in_month(Month.DECEMBER)
+ @adventofcode_group.command(
name="global",
aliases=("globalboard", "gb"),
brief="Get a link to the global leaderboard",
diff --git a/bot/exts/events/advent_of_code/_helpers.py b/bot/exts/events/advent_of_code/_helpers.py
index af64bc81..58fc3054 100644
--- a/bot/exts/events/advent_of_code/_helpers.py
+++ b/bot/exts/events/advent_of_code/_helpers.py
@@ -10,6 +10,7 @@ from typing import Any, Optional
import aiohttp
import arrow
import discord
+from discord.ext import commands
from bot.bot import Bot
from bot.constants import AdventOfCode, Channels, Colours
@@ -160,10 +161,23 @@ def _parse_raw_leaderboard_data(raw_leaderboard_data: dict) -> dict:
return {"daily_stats": daily_stats, "leaderboard": sorted_leaderboard, 'per_day_and_star': per_day_star_stats}
-def _format_leaderboard(leaderboard: dict[str, dict]) -> str:
+def _format_leaderboard(leaderboard: dict[str, dict], self_placement_name: str = None) -> str:
"""Format the leaderboard using the AOC_TABLE_TEMPLATE."""
leaderboard_lines = [HEADER]
+ self_placement_exists = False
for rank, data in enumerate(leaderboard.values(), start=1):
+ if self_placement_name and data["name"].lower() == self_placement_name.lower():
+ leaderboard_lines.insert(
+ 1,
+ AOC_TABLE_TEMPLATE.format(
+ rank=rank,
+ name=f"(You) {data['name']}",
+ score=str(data["score"]),
+ stars=f"({data['star_1']}, {data['star_2']})"
+ )
+ )
+ self_placement_exists = True
+ continue
leaderboard_lines.append(
AOC_TABLE_TEMPLATE.format(
rank=rank,
@@ -172,7 +186,10 @@ def _format_leaderboard(leaderboard: dict[str, dict]) -> str:
stars=f"({data['star_1']}, {data['star_2']})"
)
)
-
+ if self_placement_name and not self_placement_exists:
+ raise commands.BadArgument(
+ "Sorry, your profile does not exist in this leaderboard."
+ )
return "\n".join(leaderboard_lines)
@@ -260,7 +277,7 @@ def _get_top_leaderboard(full_leaderboard: str) -> str:
@_caches.leaderboard_cache.atomic_transaction
-async def fetch_leaderboard(invalidate_cache: bool = False) -> dict:
+async def fetch_leaderboard(invalidate_cache: bool = False, self_placement_name: str = None) -> dict:
"""
Get the current Python Discord combined leaderboard.
@@ -284,7 +301,7 @@ async def fetch_leaderboard(invalidate_cache: bool = False) -> dict:
leaderboard = parsed_leaderboard_data["leaderboard"]
number_of_participants = len(leaderboard)
- formatted_leaderboard = _format_leaderboard(leaderboard)
+ formatted_leaderboard = _format_leaderboard(leaderboard, self_placement_name)
full_leaderboard_url = await _upload_leaderboard(formatted_leaderboard)
leaderboard_fetched_at = datetime.datetime.utcnow().isoformat()