@@ -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+
8391def _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
162170def _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