Skip to content

Commit e92a666

Browse files
fix: sort the user into the leaderboard if in the top x values, and show the full top users even when a user is provided
if a user is linked and provided, we add an additional line to allow viewing the top 10 PLUS the user if the user is in the top ten, we don't want this additional line closes #107
1 parent 3f02057 commit e92a666

File tree

2 files changed

+37
-9
lines changed

2 files changed

+37
-9
lines changed

bot/exts/advent_of_code/_cog.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ async def aoc_leaderboard(self, ctx: commands.Context, *, aoc_name: str | None =
398398
number_of_participants = leaderboard["number_of_participants"]
399399

400400
top_count = min(AocConfig.leaderboard_displayed_members, number_of_participants)
401-
self_placement_header = " (and your personal stats compared to the top 10)" if aoc_name else ""
401+
self_placement_header = f" (and your personal stats compared to the top {top_count})" if aoc_name else ""
402402
header = f"Here's our current top {top_count}{self_placement_header}! {Emojis.christmas_tree * 3}"
403403
table = (
404404
"```\n"

bot/exts/advent_of_code/_helpers.py

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ def leaderboard_sorting_function(entry: tuple[str, dict]) -> tuple[int, int]:
8080
return result["score"], result["star_2"] + result["star_1"]
8181

8282

83+
def _get_user_placement(user_name: str, leaderboard: dict[int, dict]) -> int | None:
84+
"""Get the placement of a specific user in the leaderboard."""
85+
for rank, data in enumerate(leaderboard.values(), start=1):
86+
if data["name"] == user_name:
87+
return rank
88+
return None
89+
90+
8391
def _parse_raw_leaderboard_data(raw_leaderboard_data: dict) -> dict:
8492
"""
8593
Parse the leaderboard data received from the AoC website.
@@ -160,22 +168,29 @@ def _parse_raw_leaderboard_data(raw_leaderboard_data: dict) -> dict:
160168

161169

162170
def _format_leaderboard(leaderboard: dict[str, dict], self_placement_name: str | None = None) -> str:
163-
"""Format the leaderboard using the AOC_TABLE_TEMPLATE."""
171+
"""
172+
Format the leaderboard using the AOC_TABLE_TEMPLATE.
173+
174+
If the rank of self_placement_name is within AdventOfCode.leader_displayed_members, it is placed
175+
in the correct position; otherwise, it is placed just below the header.
176+
"""
164177
leaderboard_lines = [HEADER]
165178
self_placement_exists = False
166179
for rank, data in enumerate(leaderboard.values(), start=1):
167180
if self_placement_name and data["name"].lower() == self_placement_name.lower():
168181
leaderboard_lines.insert(
169-
1,
182+
# Plus one to account for the user being one rank outside of the shown users
183+
rank if rank <= AdventOfCode.leaderboard_displayed_members + 1 else 1,
170184
AOC_TABLE_TEMPLATE.format(
171185
rank=rank,
172186
name=f"(You) {data['name']}",
173187
score=str(data["score"]),
174-
stars=f"({data['star_1']}, {data['star_2']})"
175-
)
188+
stars=f"({data['star_1']}, {data['star_2']})",
189+
),
176190
)
177191
self_placement_exists = True
178192
continue
193+
179194
leaderboard_lines.append(
180195
AOC_TABLE_TEMPLATE.format(
181196
rank=rank,
@@ -279,9 +294,16 @@ async def _upload_leaderboard(leaderboard: str) -> str:
279294
return paste.link
280295

281296

282-
def _get_top_leaderboard(full_leaderboard: str) -> str:
283-
"""Get the leaderboard up to the maximum specified entries."""
284-
return "\n".join(full_leaderboard.splitlines()[:TOP_LEADERBOARD_LINES])
297+
def _get_top_leaderboard(full_leaderboard: str, *, include_self: bool = False) -> str:
298+
"""
299+
Get the leaderboard up to the maximum specified entries.
300+
301+
Include_self specifies whether to include an extra line for the user's placement.
302+
If the user is within the top entries, include_self should be False to avoid an additional entry.
303+
"""
304+
return "\n".join(
305+
full_leaderboard.splitlines()[: TOP_LEADERBOARD_LINES + (1 if include_self else 0)]
306+
) # +1 if including self placement
285307

286308

287309
@_caches.leaderboard_cache.atomic_transaction
@@ -336,8 +358,14 @@ async def fetch_leaderboard(invalidate_cache: bool = False, self_placement_name:
336358
formatted_placement_leaderboard = _parse_raw_leaderboard_data(
337359
json.loads(cached_leaderboard["placement_leaderboard"])
338360
)["leaderboard"]
361+
full_formatted_leaderboard = _format_leaderboard(
362+
formatted_placement_leaderboard, self_placement_name=self_placement_name
363+
)
364+
user_placement = _get_user_placement(self_placement_name, formatted_placement_leaderboard)
365+
include_self = bool(user_placement and user_placement > AdventOfCode.leaderboard_displayed_members)
339366
cached_leaderboard["placement_leaderboard"] = _get_top_leaderboard(
340-
_format_leaderboard(formatted_placement_leaderboard, self_placement_name=self_placement_name)
367+
full_formatted_leaderboard,
368+
include_self=include_self
341369
)
342370
return cached_leaderboard
343371

0 commit comments

Comments
 (0)