Skip to content

Commit a772367

Browse files
authored
Merge pull request #164 from onerandomusername/qt/aoc-12
update aoc to support 12 stars this year rather than all 25
2 parents 091484e + d51d388 commit a772367

File tree

4 files changed

+37
-21
lines changed

4 files changed

+37
-21
lines changed

bot/exts/advent_of_code/_cog.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ async def cog_load(self) -> None:
8282
@tasks.loop(minutes=10.0)
8383
async def completionist_task(self) -> None:
8484
"""
85-
Give members who have completed all 50 AoC stars the completionist role.
85+
Give members who have completed all AoC stars for this year the completionist role.
8686
8787
Runs on a schedule, as defined in the task.loop decorator.
8888
"""
@@ -107,8 +107,8 @@ async def completionist_task(self) -> None:
107107
placement_leaderboard = json.loads(leaderboard["placement_leaderboard"])
108108

109109
for member_aoc_info in placement_leaderboard.values():
110-
if member_aoc_info["stars"] != 50:
111-
# Only give the role to people who have completed all 50 stars
110+
if member_aoc_info["stars"] < _helpers.STARS_THIS_YEAR:
111+
# Only give the role to people who have completed all stars for this year
112112
continue
113113

114114
aoc_name = member_aoc_info["name"] or f"Anonymous #{member_aoc_info['id']}"

bot/exts/advent_of_code/_helpers.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@
5656
# for each star to compute the rank score.
5757
StarResult = collections.namedtuple("StarResult", "member_id completion_time")
5858

59+
# In 2025, AOC was changed to be held from Dec 1 to 12, with 12 days rather than 25.
60+
# This implementation is done in such a way that any arbitary number of days can be supported.
61+
def days_in_year(year: int | None = None) -> int:
62+
"""Return the number of days in the current Advent of Code year."""
63+
if year is None:
64+
year = AdventOfCode.year
65+
return 25 if year < 2025 else 12
66+
67+
DAYS_THIS_YEAR = days_in_year()
68+
STARS_THIS_YEAR = DAYS_THIS_YEAR * 2
5969

6070
class UnexpectedRedirect(aiohttp.ClientError):
6171
"""Raised when an unexpected redirect was detected."""
@@ -156,7 +166,7 @@ def _parse_raw_leaderboard_data(raw_leaderboard_data: dict) -> dict:
156166

157167
# Create summary stats for the stars completed for each day of the event.
158168
daily_stats = {}
159-
for day in range(1, 26):
169+
for day in range(1, DAYS_THIS_YEAR + 1):
160170
day = str(day)
161171
star_one = len(star_results.get((day, "1"), []))
162172
star_two = len(star_results.get((day, "2"), []))
@@ -455,13 +465,15 @@ async def get_public_join_code(author: discord.Member) -> str | None:
455465

456466
def is_in_advent() -> bool:
457467
"""
458-
Check if we're currently on an Advent of Code day, excluding 25 December.
468+
Check if we're currently on an Advent of Code day, excluding the final day of AOC for that year.
459469
460470
This helper function is used to check whether or not a feature that prepares
461471
something for the next Advent of Code challenge should run. As the puzzle
462-
published on the 25th is the last puzzle, this check excludes that date.
472+
published on the final day is the last puzzle, this check excludes that date.
463473
"""
464-
return arrow.now(EST).day in range(1, 25) and arrow.now(EST).month == 12
474+
# Advent of Code always begins on December 1st, and runs for one month
475+
now = arrow.now(EST)
476+
return now.month == 12 and now.day in range(1, DAYS_THIS_YEAR)
465477

466478

467479
def time_left_to_est_midnight() -> tuple[datetime.datetime, datetime.timedelta]:
@@ -499,7 +511,7 @@ async def countdown_status(bot: SirRobin) -> None:
499511
# sleeping for the entire year, it will only wait in the currently
500512
# configured year. This means that the task will only start hibernating once
501513
# we start preparing the next event by changing environment variables.
502-
last_challenge = arrow.get(datetime.datetime(AdventOfCode.year, 12, 25, tzinfo=datetime.UTC), EST)
514+
last_challenge = arrow.get(datetime.datetime(AdventOfCode.year, 12, DAYS_THIS_YEAR, tzinfo=datetime.UTC), EST)
503515
end = last_challenge + datetime.timedelta(hours=1)
504516

505517
while arrow.now(EST) < end:
@@ -544,9 +556,8 @@ async def new_puzzle_notification(bot: SirRobin) -> None:
544556
log.error("Could not find the AoC role to announce the daily puzzle")
545557
return
546558

547-
# The last event day is 25 December, so we only have to schedule
548-
# a reminder if the current day is before 25 December.
549-
end = arrow.get(datetime.datetime(AdventOfCode.year, 12, 25, tzinfo=datetime.UTC), EST)
559+
# Only schedule a reminder if the current day is before the final day December.
560+
end = arrow.get(datetime.datetime(AdventOfCode.year, 12, DAYS_THIS_YEAR, tzinfo=datetime.UTC), EST)
550561
while arrow.now(EST) < end:
551562
log.trace("Started puzzle notification loop.")
552563
tomorrow, time_left = time_left_to_est_midnight()

bot/exts/advent_of_code/views/dayandstarview.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import discord
44

5+
from bot.exts.advent_of_code._helpers import DAYS_THIS_YEAR
6+
57
AOC_DAY_AND_STAR_TEMPLATE = "{rank: >4} | {name:25.25} | {completion_time: >10}"
68

79

@@ -52,7 +54,7 @@ async def interaction_check(self, interaction: discord.Interaction) -> bool:
5254

5355
@discord.ui.select(
5456
placeholder="Day",
55-
options=[discord.SelectOption(label=str(i)) for i in range(1, 26)],
57+
options=[discord.SelectOption(label=str(i)) for i in range(1, DAYS_THIS_YEAR + 1)],
5658
custom_id="day_select",
5759
)
5860
async def day_select(self, interaction: discord.Interaction, select: discord.ui.Select) -> None:

bot/exts/summer_aoc.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111

1212
from bot.bot import SirRobin
1313
from bot.constants import Bot, Channels, Roles
14+
from bot.exts.advent_of_code._helpers import days_in_year
1415
from bot.utils.time import time_until
1516

1617
log = logging.get_logger(__name__)
1718

19+
# TODO: Add support for different years in accordance with AOC changes
1820
AOC_URL = "https://adventofcode.com/{year}/day/{day}"
19-
LAST_DAY = 25
2021
FIRST_YEAR = 2015
2122
LAST_YEAR = arrow.get().year - 1
2223
PUBLIC_NAME = "Revival of Code"
@@ -63,8 +64,9 @@ def __init__(self, bot: SirRobin):
6364
self.wait_task: asyncio.Task | None = None
6465
self.loop_task: tasks.Loop | None = None
6566

66-
self.is_running = False
67+
self.is_running: bool = False
6768
self.year: int | None = None
69+
self.days_this_year: int | None = None
6870
self.current_day: int | None = None
6971
self.day_interval: int | None = None
7072
self.post_time = 0
@@ -145,6 +147,7 @@ async def start(self, ctx: commands.Context, year: int, day_interval: int, post_
145147

146148
self.is_running = True
147149
self.year = year
150+
self.days_this_year = days_in_year(year)
148151
self.current_day = 1
149152
self.day_interval = day_interval
150153
self.post_time = post_time
@@ -174,8 +177,8 @@ async def force_day(self, ctx: commands.Context, day: int, now: Literal["now"] |
174177
await ctx.send(embed=embed)
175178
return
176179

177-
if not 1 <= day <= LAST_DAY:
178-
raise commands.BadArgument(f"Start day must be between 1 and {LAST_DAY}, inclusive")
180+
if not 1 <= day <= self.days_this_year:
181+
raise commands.BadArgument(f"Start day must be between 1 and {self.days_this_year}, inclusive")
179182

180183
log.info(f"Setting the current day of Summer AoC to {day}")
181184
await self.stop_event()
@@ -187,7 +190,7 @@ async def force_day(self, ctx: commands.Context, day: int, now: Literal["now"] |
187190

188191
embed = self.get_info_embed()
189192
if now:
190-
if self.current_day > LAST_DAY:
193+
if self.current_day > self.days_this_year:
191194
title = "Puzzle posted and event is now ending"
192195
else:
193196
title = "Puzzle posted and event is now running"
@@ -197,7 +200,7 @@ async def force_day(self, ctx: commands.Context, day: int, now: Literal["now"] |
197200
embed.title = title
198201
embed.color = discord.Color.green()
199202
await ctx.send(embed=embed)
200-
if self.current_day <= LAST_DAY:
203+
if self.current_day <= self.days_this_year:
201204
await self.start_event()
202205

203206
@summer_aoc_group.command(name="stop")
@@ -290,7 +293,7 @@ async def stop_event(self) -> bool:
290293

291294
async def post_puzzle(self) -> None:
292295
"""Create a thread for the current day's puzzle."""
293-
if self.current_day > LAST_DAY:
296+
if self.current_day > self.days_this_year:
294297
log.error("Attempted to post puzzle after last day, stopping event")
295298
await self.stop_event()
296299
return
@@ -306,7 +309,7 @@ async def post_puzzle(self) -> None:
306309

307310
self.current_day += 1
308311
await self.save_event_state()
309-
if self.current_day > LAST_DAY:
312+
if self.current_day > self.days_this_year:
310313
await self.stop_event()
311314

312315
def get_info_embed(self) -> discord.Embed:
@@ -326,7 +329,7 @@ def get_info_embed(self) -> discord.Embed:
326329

327330
def get_puzzle_embed(self) -> discord.Embed:
328331
"""Generate an embed for the day's puzzle post."""
329-
if self.current_day == LAST_DAY:
332+
if self.current_day == self.days_this_year:
330333
next_puzzle_text = LAST_PUZZLE_TEXT.format(timestamp=int(arrow.get(REAL_AOC_START).timestamp()))
331334
else:
332335
next_puzzle_text = NEXT_PUZZLE_TEXT.format(

0 commit comments

Comments
 (0)