From b86aaf70164023615c3426dadde89ab6f1783ccf Mon Sep 17 00:00:00 2001 From: Marc Di Luzio Date: Sun, 22 Sep 2024 11:57:44 +0100 Subject: [PATCH 1/3] Add cadence values to the matchy tasks cadence - Run this task every "x" weeks cadence - Unix seconds timestamp for the start of this cadence --- matchy/state.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/matchy/state.py b/matchy/state.py index d498af6..9fd16bb 100644 --- a/matchy/state.py +++ b/matchy/state.py @@ -16,7 +16,7 @@ logger = logging.getLogger("state") logger.setLevel(logging.INFO) # Warning: Changing any of the below needs proper thought to ensure backwards compatibility -_VERSION = 4 +_VERSION = 5 def _migrate_to_v1(d: dict): @@ -64,12 +64,24 @@ def _migrate_to_v4(d: dict): del d[_Key._HISTORY] +def _migrate_to_v5(d: dict): + """v5 added weekly cadence""" + tasks = d.get(_Key.TASKS, {}) + for tasks in tasks.values(): + match_tasks = tasks.get(_Key.MATCH_TASKS, []) + for match in match_tasks: + # All previous matches were every week starting from now + match[_Key.CADENCE] = 1 + match[_Key.CADENCE_START] = int(datetime.now().timestamp()) + + # Set of migration functions to apply _MIGRATIONS = [ _migrate_to_v1, _migrate_to_v2, _migrate_to_v3, _migrate_to_v4, + _migrate_to_v5 ] @@ -94,6 +106,8 @@ class _Key(str): MEMBERS_MIN = "members_min" WEEKDAY = "weekdays" HOUR = "hours" + CADENCE = "cadence" + CADENCE_START = "CADENCE_START" # Unused _MATCHEES = "matchees" @@ -139,6 +153,8 @@ _SCHEMA = Schema( _Key.MEMBERS_MIN: Use(int), _Key.WEEKDAY: Use(int), _Key.HOUR: Use(int), + _Key.CADENCE: Use(int), + _Key.CADENCE_START: Use(int), } ] } From e9cccefacbc1cd2d4c8630b616a6c5aa1e371198 Mon Sep 17 00:00:00 2001 From: Marc Di Luzio Date: Sun, 22 Sep 2024 12:09:59 +0100 Subject: [PATCH 2/3] Add cadence argument to the /schedule command This allows setting the cadence, or changing it. When changing the initial start time will be reset --- matchy/cogs/matcher.py | 11 +++++++---- matchy/state.py | 14 ++++++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/matchy/cogs/matcher.py b/matchy/cogs/matcher.py index 394fb79..10ed62b 100644 --- a/matchy/cogs/matcher.py +++ b/matchy/cogs/matcher.py @@ -110,7 +110,8 @@ class MatcherCog(commands.Cog): interaction: discord.Interaction, members_min: int | None = None, weekday: int | None = None, - hour: int | None = None): + hour: int | None = None, + cadence: int | None = None): """Schedule a match using the input parameters""" # Set all the defaults @@ -120,6 +121,8 @@ class MatcherCog(commands.Cog): weekday = 0 if hour is None: hour = 9 + if cadence is None: + cadence = 1 channel_id = str(interaction.channel.id) # Bail if not a matcher @@ -130,11 +133,11 @@ class MatcherCog(commands.Cog): # Add the scheduled task and save state.State.set_channel_match_task( - channel_id, members_min, weekday, hour) + 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", - channel_id, members_min, weekday, hour) + 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) view = discord.ui.View(timeout=None) diff --git a/matchy/state.py b/matchy/state.py index 9fd16bb..66cb1a2 100644 --- a/matchy/state.py +++ b/matchy/state.py @@ -72,7 +72,7 @@ def _migrate_to_v5(d: dict): for match in match_tasks: # All previous matches were every week starting from now match[_Key.CADENCE] = 1 - match[_Key.CADENCE_START] = int(datetime.now().timestamp()) + match[_Key.CADENCE_START] = datetime_to_ts(datetime.now()) # Set of migration functions to apply @@ -107,7 +107,7 @@ class _Key(str): WEEKDAY = "weekdays" HOUR = "hours" CADENCE = "cadence" - CADENCE_START = "CADENCE_START" + CADENCE_START = "cadence_start" # Unused _MATCHEES = "matchees" @@ -154,7 +154,7 @@ _SCHEMA = Schema( _Key.WEEKDAY: Use(int), _Key.HOUR: Use(int), _Key.CADENCE: Use(int), - _Key.CADENCE_START: Use(int), + _Key.CADENCE_START: Use(str), } ] } @@ -357,7 +357,7 @@ class _State(): yield (task[_Key.WEEKDAY], task[_Key.HOUR], task[_Key.MEMBERS_MIN]) @safe_write - def set_channel_match_task(self, channel_id: str, members_min: int, weekday: int, hour: int): + def set_channel_match_task(self, channel_id: str, members_min: int, weekday: int, hour: int, cadence: int): """Set up a match task on a channel""" channel = self._tasks.setdefault(str(channel_id), {}) matches = channel.setdefault(_Key.MATCH_TASKS, []) @@ -368,6 +368,10 @@ class _State(): if match[_Key.WEEKDAY] == weekday and match[_Key.HOUR] == hour: found = True match[_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 @@ -377,6 +381,8 @@ class _State(): _Key.MEMBERS_MIN: members_min, _Key.WEEKDAY: weekday, _Key.HOUR: hour, + _Key.CADENCE: cadence, + _Key.CADENCE_START: datetime_to_ts(datetime.now()) }) @safe_write From d83f933f1d262d11169cc123416870675574104b Mon Sep 17 00:00:00 2001 From: Marc Di Luzio Date: Sun, 22 Sep 2024 12:20:55 +0100 Subject: [PATCH 3/3] Only yield matching tasks if the weekly cadence has been hit --- matchy/state.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/matchy/state.py b/matchy/state.py index 66cb1a2..56fbb1d 100644 --- a/matchy/state.py +++ b/matchy/state.py @@ -340,7 +340,10 @@ class _State(): for channel, tasks in self._tasks.items(): for match in tasks.get(_Key.MATCH_TASKS, []): - if match[_Key.WEEKDAY] == weekday and match[_Key.HOUR] == hour: + # Take into account the weekly cadence + start = ts_to_datetime(match[_Key.CADENCE_START]) + weeks = int((time - start).days / 7) + if match[_Key.WEEKDAY] == weekday and match[_Key.HOUR] == hour and weeks % match[_Key.CADENCE] == 0: yield (channel, match[_Key.MEMBERS_MIN]) def get_channel_match_tasks(self, channel_id: str) -> Generator[int, int, int]: