From 289fbf2bb2acf30d8a736cb5981f5d135ac51a69 Mon Sep 17 00:00:00 2001 From: Bendik Christensen Date: Fri, 12 Jan 2024 13:29:47 +0100 Subject: [PATCH 1/3] Check if user changed quit date If user changed quit date we trigger the same logic that we would trigger from the relapse dialog --- scheduler/state_machine/controller.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/scheduler/state_machine/controller.py b/scheduler/state_machine/controller.py index df7e250a..8b9e72be 100644 --- a/scheduler/state_machine/controller.py +++ b/scheduler/state_machine/controller.py @@ -595,6 +595,23 @@ def on_dialog_completed(self, dialog): # for the next week are planned self.schedule_pa_notifications() + + quit_date = get_quit_date(self.user_id) + current_date = date.today() + + # if the quit date is in the future, it has been reset + # during the weekly reflection dialog + if quit_date > current_date: + # if a new quit date has been set, the weekly reflection might be rescheduled, + # a notification on the day before and on the new date are planned. + # Then we go back to the buffer state + self.reschedule_weekly_reflection(quit_date) + self.plan_new_date_notifications(quit_date) + self.set_new_state(BufferState(self.user_id)) + store_completed_dialog(user_id=self.user_id, + dialog=Components.RELAPSE_DIALOG, + phase_id=3) + def on_dialog_rescheduled(self, dialog, new_date): reschedule_dialog(user_id=self.user_id, From 8f19f7f19f0fd9b31a2eeede51ee7047fbf9284c Mon Sep 17 00:00:00 2001 From: Bendik Christensen Date: Thu, 18 Jan 2024 10:14:09 +0100 Subject: [PATCH 2/3] refactored --- scheduler/state_machine/controller.py | 72 ++++++------------- .../state_machine/state_machine_utils.py | 46 +++++++++++- 2 files changed, 66 insertions(+), 52 deletions(-) diff --git a/scheduler/state_machine/controller.py b/scheduler/state_machine/controller.py index 8b9e72be..02e61158 100644 --- a/scheduler/state_machine/controller.py +++ b/scheduler/state_machine/controller.py @@ -19,7 +19,8 @@ schedule_next_execution, store_completed_dialog, store_scheduled_dialog, update_execution_week, update_fsm_dialog_running_status, - dialogs_to_be_completed, get_component_id) + dialogs_to_be_completed, get_component_id, + reschedule_weekly_reflection, plan_new_date_notifications) from state_machine.const import (ACTIVITY_C2_9_DAY_TRIGGER, FUTURE_SELF_INTRO, GOAL_SETTING, TRACKING_DURATION, TIMEZONE, PREPARATION_GA, PAUSE_AND_TRIGGER, MAX_PREPARATION_DURATION, HIGH_PA_GROUP, @@ -528,6 +529,23 @@ def on_dialog_completed(self, dialog): elif dialog == Components.WEEKLY_REFLECTION: logging.info('Weekly reflection completed') + quit_date = get_quit_date(self.user_id) + current_date = date.today() + + # if the quit date is in the future, it has been reset + # during the weekly reflection dialog + if quit_date > current_date: + # if a new quit date has been set, the weekly reflection might be rescheduled, + # a notification on the day before and on the new date are planned. + # Then we go back to the buffer state + reschedule_weekly_reflection(self.user_id, quit_date) + plan_new_date_notifications(self.user_id, quit_date) + self.set_new_state(BufferState(self.user_id)) + store_completed_dialog(user_id=self.user_id, + dialog=Components.RELAPSE_DIALOG, + phase_id=3) + return + week = get_execution_week(user_id=self.user_id) # on the first week, the execution of the general activity dialog @@ -595,23 +613,6 @@ def on_dialog_completed(self, dialog): # for the next week are planned self.schedule_pa_notifications() - - quit_date = get_quit_date(self.user_id) - current_date = date.today() - - # if the quit date is in the future, it has been reset - # during the weekly reflection dialog - if quit_date > current_date: - # if a new quit date has been set, the weekly reflection might be rescheduled, - # a notification on the day before and on the new date are planned. - # Then we go back to the buffer state - self.reschedule_weekly_reflection(quit_date) - self.plan_new_date_notifications(quit_date) - self.set_new_state(BufferState(self.user_id)) - store_completed_dialog(user_id=self.user_id, - dialog=Components.RELAPSE_DIALOG, - phase_id=3) - def on_dialog_rescheduled(self, dialog, new_date): reschedule_dialog(user_id=self.user_id, @@ -807,8 +808,8 @@ def on_dialog_completed(self, dialog): # if a new quit date has been set, the weekly reflection might be rescheduled, # a notification on the day before and on the new date are planned. # Then we go back to the buffer state - self.reschedule_weekly_reflection(quit_date) - self.plan_new_date_notifications(quit_date) + reschedule_weekly_reflection(self.user_id, quit_date) + plan_new_date_notifications(self.user_id, quit_date) self.set_new_state(BufferState(self.user_id)) else: @@ -856,37 +857,6 @@ def on_user_trigger(self, dialog: str): dialog=dialog, phase_id=3) - def plan_new_date_notifications(self, quit_date: date): - # plan the notification for the day before the quit date - - quit_datetime = create_new_date(quit_date) - - plan_and_store(user_id=self.user_id, - dialog=Notifications.BEFORE_QUIT_NOTIFICATION, - planned_date=quit_datetime - timedelta(days=1), - phase_id=3) - - def reschedule_weekly_reflection(self, quit_date: date): - - component = get_intervention_component(Components.WEEKLY_REFLECTION) - - next_occurrence = get_next_scheduled_occurrence( - user_id=self.user_id, - intervention_component_id=component.intervention_component_id, - current_date=datetime.now() - ) - - quit_datetime = create_new_date(quit_date) - - if next_occurrence is not None and next_occurrence.next_planned_date < quit_datetime: - # revoke the planned task - revoke_execution(next_occurrence.task_uuid) - # plan a new one - schedule_next_execution(user_id=self.user_id, - dialog=Components.WEEKLY_REFLECTION, - current_date=quit_datetime, - phase_id=2) - class ClosingState(State): diff --git a/scheduler/state_machine/state_machine_utils.py b/scheduler/state_machine/state_machine_utils.py index 3efd6fe2..6bd7b02c 100644 --- a/scheduler/state_machine/state_machine_utils.py +++ b/scheduler/state_machine/state_machine_utils.py @@ -9,7 +9,7 @@ InterventionActivitiesPerformed, InterventionComponents, InterventionPhases, Users, UserStateMachine, UserInterventionState) -from virtual_coach_db.helper.definitions import Components, ComponentsTriggers, DialogQuestionsEnum +from virtual_coach_db.helper.definitions import Components, ComponentsTriggers, DialogQuestionsEnum, Notifications from virtual_coach_db.helper.helper_functions import get_db_session celery = Celery(broker=REDIS_URL) @@ -1243,3 +1243,47 @@ def schedule_next_execution(user_id: int, dialog: str, phase_id: int, current_da dialog=dialog, planned_date=planned_date, phase_id=phase_id) + +def plan_new_date_notifications(user_id: int, quit_date: date): + """ + Plan the user notification for the day before the quit date + Args: + user_id: id of the user + quit_date: new quit date selected by user + + """ + quit_datetime = create_new_date(quit_date) + + plan_and_store(user_id=user_id, + dialog=Notifications.BEFORE_QUIT_NOTIFICATION, + planned_date=quit_datetime - timedelta(days=1), + phase_id=3) + +def reschedule_weekly_reflection(user_id: int, quit_date: date): + """ + Reschedule the weekly reflection dialog to after the + new quit date + Args: + user_id: id of the user + quit_date: new quit date selected by user + + """ + + component = get_intervention_component(Components.WEEKLY_REFLECTION) + + next_occurrence = get_next_scheduled_occurrence( + user_id=user_id, + intervention_component_id=component.intervention_component_id, + current_date=datetime.now() + ) + + quit_datetime = create_new_date(quit_date) + + if next_occurrence is not None and next_occurrence.next_planned_date < quit_datetime: + # revoke the planned task + revoke_execution(next_occurrence.task_uuid) + # plan a new one + schedule_next_execution(user_id=user_id, + dialog=Components.WEEKLY_REFLECTION, + current_date=quit_datetime, + phase_id=2) \ No newline at end of file From d43a732bbfc31a359edc0da5bd24d1907582d06d Mon Sep 17 00:00:00 2001 From: Bendik Christensen Date: Thu, 18 Jan 2024 10:37:25 +0100 Subject: [PATCH 3/3] linting --- scheduler/state_machine/controller.py | 5 +++-- scheduler/state_machine/state_machine_utils.py | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/scheduler/state_machine/controller.py b/scheduler/state_machine/controller.py index 02e61158..9250c7c0 100644 --- a/scheduler/state_machine/controller.py +++ b/scheduler/state_machine/controller.py @@ -13,14 +13,15 @@ get_quit_date, get_pa_group, get_start_date, is_new_week, plan_and_store, plan_every_day_range, reschedule_dialog, - retrieve_tracking_day, revoke_execution, + retrieve_tracking_day, run_uncompleted_dialog, run_option_menu, save_fsm_state_in_db, schedule_next_execution, store_completed_dialog, store_scheduled_dialog, update_execution_week, update_fsm_dialog_running_status, dialogs_to_be_completed, get_component_id, - reschedule_weekly_reflection, plan_new_date_notifications) + reschedule_weekly_reflection, + plan_new_date_notifications) from state_machine.const import (ACTIVITY_C2_9_DAY_TRIGGER, FUTURE_SELF_INTRO, GOAL_SETTING, TRACKING_DURATION, TIMEZONE, PREPARATION_GA, PAUSE_AND_TRIGGER, MAX_PREPARATION_DURATION, HIGH_PA_GROUP, diff --git a/scheduler/state_machine/state_machine_utils.py b/scheduler/state_machine/state_machine_utils.py index 6bd7b02c..fdb8afcf 100644 --- a/scheduler/state_machine/state_machine_utils.py +++ b/scheduler/state_machine/state_machine_utils.py @@ -9,7 +9,8 @@ InterventionActivitiesPerformed, InterventionComponents, InterventionPhases, Users, UserStateMachine, UserInterventionState) -from virtual_coach_db.helper.definitions import Components, ComponentsTriggers, DialogQuestionsEnum, Notifications +from virtual_coach_db.helper.definitions import (Components, ComponentsTriggers, + DialogQuestionsEnum, Notifications) from virtual_coach_db.helper.helper_functions import get_db_session celery = Celery(broker=REDIS_URL)