diff --git a/Rasa_Bot/actions/actions_general_activity.py b/Rasa_Bot/actions/actions_general_activity.py index f02d653f..f23731a4 100644 --- a/Rasa_Bot/actions/actions_general_activity.py +++ b/Rasa_Bot/actions/actions_general_activity.py @@ -147,7 +147,10 @@ async def run(self, dispatcher, tracker, domain): .all() ) - lowest_score = top_five_activities[-1].activity_rating + if len(top_five_activities) > 0: + lowest_score = top_five_activities[-1].activity_rating + else: + lowest_score = 0 # if the activity is not in the FAK, add it if not current_record: @@ -486,9 +489,10 @@ async def run(self, dispatcher, tracker, domain): mandatory, _ = get_possible_activities(user_id) activity_title = mandatory[0].intervention_activity_title - + mandatory_ids = [activity.intervention_activity_id for activity in mandatory] return [SlotSet("chosen_activity_slot", activity_title), - SlotSet("general_activity_next_activity_slot", 0)] + SlotSet("general_activity_next_activity_slot", 1), + SlotSet("rnd_activities_ids", mandatory_ids)] class CheckWhoDecides(Action): @@ -667,11 +671,11 @@ def name(self): return "send_persuasive_message_activity" async def run(self, dispatcher, tracker, domain): - chosen_option = int(tracker.get_slot('general_activity_next_activity_slot')) activities_slot = tracker.get_slot('rnd_activities_ids') activity_id = activities_slot[chosen_option - 1] + session = get_db_session(db_url=DATABASE_URL) # Get the activity benefit diff --git a/Rasa_Bot/actions/helper.py b/Rasa_Bot/actions/helper.py index 32260598..ef2d03aa 100644 --- a/Rasa_Bot/actions/helper.py +++ b/Rasa_Bot/actions/helper.py @@ -566,7 +566,7 @@ def get_current_phase_time(user_id: int, phase: str) -> int: The number of days or weeks in the current state """ - if phase not in [FsmStates.TRACKING, FsmStates.GOALS_SETTING, FsmStates.GOALS_SETTING]: + if phase not in [FsmStates.EXECUTION_RUN, FsmStates.RELAPSE]: time = get_days_from_start(user_id) else: time = get_execution_week(user_id) @@ -758,7 +758,7 @@ def get_possible_activities(user_id: int, activity_category: Optional[str] = Non # check if the mandatory activities have been already performed for activity in mandatory: # if the activity has been completed, do not report it as mandatory - if is_activity_done(activity): + if not is_activity_done(activity): mandatory_ids.append(activity) mandatory_ids = [get_activities_from_id(mandatory_id) for mandatory_id in mandatory_ids] diff --git a/scheduler/celery_utils.py b/scheduler/celery_utils.py index 1b27f298..da813091 100644 --- a/scheduler/celery_utils.py +++ b/scheduler/celery_utils.py @@ -383,7 +383,8 @@ def update_scheduled_task_db(user_id: int, task_uuid: str): # if a notification has been triggered, it must be marked as completed # (no further interactions needed) - if component.intervention_component_name in Notifications._value2member_map_: + values = [item.value for item in Notifications] + if component.intervention_component_name in values: task_entry.completed = True session.commit() diff --git a/scheduler/state_machine/const.py b/scheduler/state_machine/const.py index e00b8db3..755fa684 100644 --- a/scheduler/state_machine/const.py +++ b/scheduler/state_machine/const.py @@ -17,7 +17,7 @@ EXECUTION_DURATION_WEEKS = 12 # intervention times (days) -ACTIVITY_C2_9_DAY_TRIGGER = 7 +ACTIVITY_C2_9_DAY_TRIGGER = 6 FUTURE_SELF_INTRO = 8 GOAL_SETTING = 9 # number of days after the weekly reflection for the PA notification to be sent diff --git a/scheduler/state_machine/controller.py b/scheduler/state_machine/controller.py index 94c0f67e..7edbb8fe 100644 --- a/scheduler/state_machine/controller.py +++ b/scheduler/state_machine/controller.py @@ -109,7 +109,7 @@ def schedule_tracking_notifications(self): to day 9 of the preparation phase """ first_date = date.today() + timedelta(days=1) - last_date = get_start_date(self.user_id) + timedelta(days=8) + last_date = get_start_date(self.user_id) + timedelta(days=9) for day in range((last_date - first_date).days): planned_date = create_new_date(start_date=first_date, @@ -137,6 +137,7 @@ def on_dialog_completed(self, dialog): if dialog == Components.FUTURE_SELF_SHORT: logging.info('Future self completed') + self.set_new_state(GoalsSettingState(self.user_id)) def on_dialog_rescheduled(self, dialog, new_date): @@ -164,19 +165,12 @@ def on_new_day(self, current_date: date): # at day 7 activity C2.9 has to be proposed start_date = get_start_date(self.user_id) - - if (current_date - start_date).days >= ACTIVITY_C2_9_DAY_TRIGGER: + ga_completed = get_dialog_completion_state(self.user_id, Components.GENERAL_ACTIVITY) + if (current_date - start_date).days >= ACTIVITY_C2_9_DAY_TRIGGER and not ga_completed: plan_and_store(user_id=self.user_id, dialog=Components.GENERAL_ACTIVITY, phase_id=1) - # if it's time and the self dialog has been completed, - # move to new state - self_completed = get_dialog_completion_state(self.user_id, Components.FUTURE_SELF_SHORT) - if (self.check_if_end_date(current_date) and - self_completed): - self.set_new_state(GoalsSettingState(self.user_id)) - def check_if_end_date(self, date_to_check: date) -> bool: intervention_day = retrieve_intervention_day(self.user_id, date_to_check) # the Goal Setting state starts on day 10 of the intervention @@ -209,6 +203,7 @@ def on_dialog_completed(self, dialog): # phase can be planned self.plan_buffer_phase_dialogs() self.plan_execution_start_dialog() + self.schedule_pa_notifications() elif dialog == Components.FIRST_AID_KIT_VIDEO: logging.info('First aid kit completed, starting buffering state') @@ -260,6 +255,40 @@ def plan_execution_start_dialog(self): planned_date=planned_date, phase_id=1) + def schedule_pa_notifications(self): + # the notifications are delivered according to the group of the user. Group 1 gets + # a notification with the steps goal every day. Group 2 gets a notification with steps + # and intensity goal twice a week, 1 and 4 days after the GA dialog. + # The group is determined during the GA dialog. + + pa_group = get_pa_group(self.user_id) + + first_date = date.today() + timedelta(days=1) + # until the execution starts + last_date = get_quit_date(self.user_id) + # every day + if pa_group == LOW_PA_GROUP: + + for day in range((last_date - first_date).days + 1): + planned_date = create_new_date(start_date=first_date, + time_delta=day) + + plan_and_store(user_id=self.user_id, + dialog=Notifications.PA_STEP_GOAL_NOTIFICATION, + planned_date=planned_date, + phase_id=2) + + else: + # every 3 days + for day in range((last_date - first_date).days)[0::3]: + planned_date = create_new_date(start_date=first_date, + time_delta=day) + + plan_and_store(user_id=self.user_id, + dialog=Notifications.PA_INTENSITY_MINUTES_NOTIFICATION, + planned_date=planned_date, + phase_id=2) + def run(self): start_date = get_start_date(self.user_id) @@ -270,9 +299,9 @@ def run(self): gs_time = None else: - # on day 10 at 10 a.m. send future self plan goal setting - gs_time = create_new_date(start_date=start_date, - time_delta=GOAL_SETTING) + # plan the Goals setting dialog for tomorrow + gs_time = create_new_date(start_date=date.today(), + time_delta=1) plan_and_store(user_id=self.user_id, dialog=Components.GOAL_SETTING, @@ -306,7 +335,6 @@ def on_user_trigger(self, dialog: str): def check_if_end_date(self, current_date: date): quit_date = get_quit_date(self.user_id) - if current_date >= quit_date: logging.info('Buffer sate ended, starting execution state') self.set_new_state(ExecutionRunState(self.user_id)) @@ -426,12 +454,13 @@ def on_new_day(self, current_date: date): def run(self): logging.info("Running state %s", self.state) + update_execution_week(self.user_id, 1) def schedule_pa_notifications(self): # the notifications are delivered according to the group of the user. Group 1 gets # a notification with the steps goal every day. Group 2 gets a notification with steps - # and intensity goal once a wek, 4 days after the GA dialog. The group is determined during - # the GA dialog. + # and intensity goal twice a week, 1 and 4 days after the GA dialog. + # The group is determined during the GA dialog. pa_group = get_pa_group(self.user_id) @@ -452,12 +481,20 @@ def schedule_pa_notifications(self): elif pa_group == HIGH_PA_GROUP: - planned_date = create_new_date(start_date=date.today(), - time_delta=TIME_DELTA_PA_NOTIFICATION) + planned_date_1 = create_new_date(start_date=date.today(), + time_delta=1) plan_and_store(user_id=self.user_id, dialog=Notifications.PA_INTENSITY_MINUTES_NOTIFICATION, - planned_date=planned_date, + planned_date=planned_date_1, + phase_id=2) + + planned_date_4 = create_new_date(start_date=date.today(), + time_delta=TIME_DELTA_PA_NOTIFICATION) + + plan_and_store(user_id=self.user_id, + dialog=Notifications.PA_INTENSITY_MINUTES_NOTIFICATION, + planned_date=planned_date_4, phase_id=2) diff --git a/scheduler/state_machine/state_machine_utils.py b/scheduler/state_machine/state_machine_utils.py index cfb9b954..31793de7 100644 --- a/scheduler/state_machine/state_machine_utils.py +++ b/scheduler/state_machine/state_machine_utils.py @@ -317,7 +317,7 @@ def get_pa_group(user_id: int) -> int: """ session = get_db_session(DATABASE_URL) - user = (session.query(Users).filter(Users.users_nicedayuid == user_id).first()) + user = (session.query(Users).filter(Users.nicedayuid == user_id).first()) return user.pa_intervention_group @@ -367,7 +367,7 @@ def get_preferred_date_time(user_id: int) -> tuple: Users ) .filter( - Users.users_nicedayuid == user_id + Users.nicedayuid == user_id ) .one() )