Account for the cadence in all the messages
This commit is contained in:
parent
2ad7ed2ff2
commit
7491a4d2f8
5 changed files with 109 additions and 40 deletions
|
@ -92,8 +92,8 @@ class MatcherCog(commands.Cog):
|
|||
msg += "\n" + strings.paused_matchees(mentions) + "\n"
|
||||
|
||||
tasks = state.State.get_channel_match_tasks(interaction.channel.id)
|
||||
for (day, hour, min) in tasks:
|
||||
next_run = util.get_next_datetime(day, hour)
|
||||
for (day, hour, min, cadence, cadence_start) in tasks:
|
||||
next_run = util.get_next_datetime_with_cadence(day, hour, datetime.now(), cadence, cadence_start)
|
||||
msg += "\n" + strings.scheduled(next_run, min)
|
||||
|
||||
if not msg:
|
||||
|
@ -132,19 +132,19 @@ class MatcherCog(commands.Cog):
|
|||
return
|
||||
|
||||
# Add the scheduled task and save
|
||||
state.State.set_channel_match_task(
|
||||
channel_id, members_min, weekday, hour, cadence)
|
||||
(_, _, _, _, cadence_start) = state.State.set_channel_match_task(
|
||||
channel_id, members_min, weekday, hour, cadence)
|
||||
|
||||
# Let the user know what happened
|
||||
logger.info("Scheduled new match task in %s with min %s weekday %s hour %s and cadence %s",
|
||||
channel_id, members_min, weekday, hour, cadence)
|
||||
next_run = util.get_next_datetime(weekday, hour)
|
||||
next_run = util.get_next_datetime_with_cadence(weekday, hour, datetime.now(), cadence, cadence_start)
|
||||
|
||||
view = discord.ui.View(timeout=None)
|
||||
view.add_item(ScheduleButton())
|
||||
|
||||
await interaction.response.send_message(
|
||||
strings.scheduled_success(next_run),
|
||||
strings.scheduled_success(next_run, cadence),
|
||||
ephemeral=True, silent=True, view=view)
|
||||
|
||||
@app_commands.command(description="Cancel all scheduled matches in this channel")
|
||||
|
@ -307,8 +307,8 @@ class ScheduleButton(discord.ui.Button):
|
|||
msg += strings.scheduled_matches()
|
||||
|
||||
if tasks:
|
||||
for (day, hour, min) in tasks:
|
||||
next_run = util.get_next_datetime(day, hour)
|
||||
for (day, hour, min, cadence, cadence_start) in tasks:
|
||||
next_run = util.get_next_datetime(day, hour, datetime.now(), cadence, cadence_start)
|
||||
msg += strings.scheduled(next_run, min)
|
||||
|
||||
await interaction.channel.send(msg)
|
||||
|
|
|
@ -85,11 +85,11 @@ def need_matcher_scope(): return [
|
|||
|
||||
|
||||
@randomised
|
||||
def scheduled_success(d): return [
|
||||
f"Done :) Next run will be at {datetime_as_discord_time(d)}",
|
||||
f"Woohoo! Scheduled for {datetime_as_discord_time(d)}",
|
||||
f"Yessir, will do a matcho at {datetime_as_discord_time(d)}",
|
||||
f"Arf Arf! Bork bork bark {datetime_as_discord_time(d)}",
|
||||
def scheduled_success(d, cadence): return [
|
||||
f"Done :) Next run will be at {datetime_as_discord_time(d)} and every {cadence} week(s) after",
|
||||
f"Woohoo! Scheduled for {datetime_as_discord_time(d)} plus each {cadence} week(s) after",
|
||||
f"Yessir, will do a matcho every {cadence} week(s), first one is {datetime_as_discord_time(d)}",
|
||||
f"Arf Arf! Bork bork bark {datetime_as_discord_time(d)} berk {cadence} week(s) arf",
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -358,7 +358,7 @@ class _State():
|
|||
)
|
||||
for tasks in all_tasks:
|
||||
for task in tasks:
|
||||
yield (task[_Key.WEEKDAY], task[_Key.HOUR], task[_Key.MEMBERS_MIN])
|
||||
yield _task_to_tuple(task)
|
||||
|
||||
@safe_write
|
||||
def set_channel_match_task(self, channel_id: str, members_min: int, weekday: int, hour: int, cadence: int):
|
||||
|
@ -366,28 +366,27 @@ class _State():
|
|||
channel = self._tasks.setdefault(str(channel_id), {})
|
||||
matches = channel.setdefault(_Key.MATCH_TASKS, [])
|
||||
|
||||
found = False
|
||||
for match in matches:
|
||||
for match_task in matches:
|
||||
# Specifically check for the combination of weekday and hour
|
||||
if match[_Key.WEEKDAY] == weekday and match[_Key.HOUR] == hour:
|
||||
found = True
|
||||
match[_Key.MEMBERS_MIN] = members_min
|
||||
if match_task[_Key.WEEKDAY] == weekday and match_task[_Key.HOUR] == hour:
|
||||
match_task[_Key.MEMBERS_MIN] = members_min
|
||||
# If the cadence has changed, update it and reset the start
|
||||
if cadence != match[_Key.CADENCE]:
|
||||
match[_Key.CADENCE] = cadence
|
||||
match[_Key.CADENCE_START] = datetime_to_ts(datetime.now())
|
||||
# Return true as we've successfully changed the data in place
|
||||
return True
|
||||
if cadence != match_task[_Key.CADENCE]:
|
||||
match_task[_Key.CADENCE] = cadence
|
||||
match_task[_Key.CADENCE_START] = datetime_to_ts(datetime.now())
|
||||
# Return as we've successfully changed the data in place
|
||||
return _task_to_tuple(match_task)
|
||||
|
||||
# If we didn't find it, add it to the schedule
|
||||
if not found:
|
||||
matches.append({
|
||||
_Key.MEMBERS_MIN: members_min,
|
||||
_Key.WEEKDAY: weekday,
|
||||
_Key.HOUR: hour,
|
||||
_Key.CADENCE: cadence,
|
||||
_Key.CADENCE_START: datetime_to_ts(datetime.now())
|
||||
})
|
||||
match_task = {
|
||||
_Key.MEMBERS_MIN: members_min,
|
||||
_Key.WEEKDAY: weekday,
|
||||
_Key.HOUR: hour,
|
||||
_Key.CADENCE: cadence,
|
||||
_Key.CADENCE_START: datetime_to_ts(datetime.now())
|
||||
}
|
||||
matches.append(match_task)
|
||||
return _task_to_tuple(match_task)
|
||||
|
||||
@safe_write
|
||||
def remove_channel_match_tasks(self, channel_id: str):
|
||||
|
@ -405,6 +404,14 @@ class _State():
|
|||
return self._dict[_Key.TASKS]
|
||||
|
||||
|
||||
def _task_to_tuple(task):
|
||||
return (task[_Key.WEEKDAY],
|
||||
task[_Key.HOUR],
|
||||
task[_Key.MEMBERS_MIN],
|
||||
task[_Key.CADENCE],
|
||||
ts_to_datetime(task[_Key.CADENCE_START]))
|
||||
|
||||
|
||||
def load_from_file(file: str) -> _State:
|
||||
"""
|
||||
Load the state from a files
|
||||
|
|
|
@ -18,20 +18,32 @@ def format_list(list: list) -> str:
|
|||
return list[0] if list else ''
|
||||
|
||||
|
||||
def get_next_datetime(weekday, hour) -> datetime:
|
||||
def get_next_datetime(weekday: int, hour: int, start: datetime) -> datetime:
|
||||
"""Get the next datetime for the given weekday and hour"""
|
||||
now = datetime.now()
|
||||
days_until_next_week = (weekday - now.weekday() + 7) % 7
|
||||
|
||||
days_until_next_week_run = (weekday - start.weekday() + 7) % 7
|
||||
|
||||
# Account for when we're already beyond the time now
|
||||
if days_until_next_week == 0 and now.hour >= hour:
|
||||
days_until_next_week = 7
|
||||
if days_until_next_week_run == 0 and start.hour >= hour:
|
||||
days_until_next_week_run = 7
|
||||
|
||||
# Calculate the next datetime
|
||||
next_date = now + timedelta(days=days_until_next_week)
|
||||
next_date = next_date.replace(hour=hour, minute=0, second=0, microsecond=0)
|
||||
next_date = start + timedelta(days=days_until_next_week_run)
|
||||
|
||||
return next_date
|
||||
return next_date.replace(hour=hour, minute=0, second=0, microsecond=0)
|
||||
|
||||
|
||||
def get_next_datetime_with_cadence(weekday: int, hour: int, start: datetime, cadence: int, cadence_start: datetime):
|
||||
"""Get the next datetime for given weekday, hour and cadence values"""
|
||||
|
||||
# Get the first run based on the cadence
|
||||
next_time = get_next_datetime(weekday, hour, cadence_start)
|
||||
|
||||
# Walk forwards until we get the actual time
|
||||
while next_time < start:
|
||||
next_time += timedelta(weeks=cadence)
|
||||
|
||||
return next_time
|
||||
|
||||
|
||||
def datetime_as_discord_time(time: datetime) -> str:
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import matchy.util as util
|
||||
from datetime import datetime, timedelta
|
||||
import pytest
|
||||
|
||||
|
||||
def test_iterate_all_shifts():
|
||||
|
@ -50,3 +52,51 @@ def test_randomized():
|
|||
|
||||
assert util.randomised(string)() == "foo"
|
||||
assert util.randomised(list)() in list()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"weekday, hour, start, expected",
|
||||
[
|
||||
pytest.param(
|
||||
0, 0, datetime(2024, 9, 22),
|
||||
datetime(2024, 9, 23), id="tomorrow"
|
||||
),
|
||||
pytest.param(
|
||||
4, 16, datetime(2024, 9, 22),
|
||||
datetime(2024, 9, 27, 16), id="complicated"
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_get_next_datetime(weekday, hour, start, expected):
|
||||
value = util.get_next_datetime(weekday, hour, start)
|
||||
assert value == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"weekday, hour, start, cadence, cadence_start, expected",
|
||||
[
|
||||
pytest.param(
|
||||
0, 0, datetime(2024, 9, 22),
|
||||
1, datetime(2024, 9, 22),
|
||||
datetime(2024, 9, 23), id="tomorrow"
|
||||
),
|
||||
pytest.param(
|
||||
0, 0, datetime(2024, 9, 22),
|
||||
2, datetime(2024, 9, 22),
|
||||
datetime(2024, 9, 23), id="every-other"
|
||||
),
|
||||
pytest.param(
|
||||
0, 0, datetime(2024, 9, 22),
|
||||
2, datetime(2024, 9, 14),
|
||||
datetime(2024, 9, 30), id="every-other-before"
|
||||
),
|
||||
pytest.param(
|
||||
0, 0, datetime(2024, 9, 22),
|
||||
3, datetime(2024, 9, 14),
|
||||
datetime(2024, 10, 7), id="every-third"
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_get_next_datetime_with_cadence(weekday, hour, start, expected, cadence, cadence_start):
|
||||
value = util.get_next_datetime_with_cadence(weekday, hour, start, cadence, cadence_start)
|
||||
assert value == expected
|
||||
|
|
Loading…
Add table
Reference in a new issue