def test_append_db_entry(self): content = 'Question' options = ['choice', 'not choice'] choice1 = options[1] choice2 = options[0] choices = [choice1, choice2] db_key = 'out' self._db.create_key(db_key) self.assertTrue(db_key in self._db.get_keys()) self.assertFalse(self._db.is_set(db_key)) message = Message( content=content, options=options, message_type=Message.Type.MULTIPLE_CHOICE, result_db_key=db_key, ) self._io.set_input(choices) self._interface.run(message) self._interface.run(message) self.assertTrue(db_key in self._db.get_keys()) truth_out = choices out = self._db.create_key(db_key) for i in range(len(truth_out)): self.assertEqual(truth_out[i], out[i])
def test_write_db_entry(self): content = 'Question' options = 'choice' choice = options db_key = 'out' message = Message( content=content, options=options, message_type=Message.Type.MULTIPLE_CHOICE, result_db_key=db_key, ) self._io.set_input(choice) self.assertRaises( KeyError, self._interface.run, message, ) self._db.create_key(db_key) self.assertTrue(db_key in self._db.get_keys()) self.assertFalse(self._db.is_set(db_key)) self._io.set_input(choice) self._interface.run(message) self.assertTrue(db_key in self._db.get_keys()) self.assertEqual(choice, self._db[db_key])
class Messages: no_sync = Message( content=( "I haven't heard from your Fitbit in a while. " + "Try syncing your phone, and then check back with me again." ), options=[ "{affirmative_plus_button_response}", "{Ill_try_that_button_response}", ], message_type=Message.Type.MULTIPLE_CHOICE, text_populator=text_populator, ) give_status = Message( content=( "You've done {'db': '%s'} steps so far today. " % state_db.Keys.STEPS_TODAY + "Think you can meet your goal of {'db': '%s'} steps before our checkin at {'db': '%s'}?" % (state_db.Keys.STEPS_GOAL, state_db.Keys.PM_CHECKIN_TIME) ), options=[ '{affirmative_plus_button_response}', '{affirmative_button_response}', "{Ill_try_that_button_response}", "I don't think that I can today" ], message_type=Message.Type.MULTIPLE_CHOICE, text_populator=text_populator, ) give_status_met_goal = Message( content=( "Your goal was {'db': '%s'} steps today and " % state_db.Keys.STEPS_GOAL + "you've done {'db': '%s'} steps already. " % state_db.Keys.STEPS_TODAY + "Nice job. We'll review your total progress at our evening checkin at {'db': '%s'}." % state_db.Keys.PM_CHECKIN_TIME ), options=[ '{affirmative_button_response}', ], message_type=Message.Type.MULTIPLE_CHOICE, text_populator=text_populator, )
def test_string_markup(self): greetings = ['Hi', 'Hello', 'Hola', "{'var': 'greeting'}"] message = Message( content='{greeting}', options=greetings, message_type=Message.Type.MULTIPLE_CHOICE, text_populator=self._text_populator ) for _ in range(10): self.assertTrue(message.content in greetings) for o in message.options: self.assertTrue(o in greetings)
class Messages: no_sync = Message( content=( "It's time for our evening checkin, but I haven't heard from your Fitbit in a while. " + "Try syncing your phone, and then check back with me again." ), options=[ "{affirmative_plus_button_response}", "{Ill_try_that_button_response}", ], message_type=Message.Type.MULTIPLE_CHOICE, text_populator=text_populator, )
def test_multiple_choice(self): content = 'Question' options = ['choice', 'not choice'] choice = options[0] message = Message( content=content, options=options, message_type=Message.Type.MULTIPLE_CHOICE, ) self._io.set_input(choice) self.assertIsNone(self._io.get_output()) self.assertEqual(choice, self._interface.run(message)) self.assertEqual(content, self._io.get_output())
def test_confirm(self): content = 'Question' options = ['choice', 'not choice'] choice = options[0] message = Message( content=content, options=options, message_type=Message.Type.MULTIPLE_CHOICE, is_confirm=True, ) self._io.set_input([choice, 'Yes']) self._interface.run(message) out = self._io.get_output() truth_out = [content, f"'{str(choice)}', right?"] for i in range(len(truth_out)): self.assertEqual(truth_out[i], out[i])
def test_function_markup(self): greetings_fn_return = ['Foo'] message = Message( content=lambda: random.choice(greetings_fn_return), options=lambda: greetings_fn_return, message_type=Message.Type.MULTIPLE_CHOICE, text_populator=self._text_populator ) greetings_fn_return = ['Hi', 'Hello', 'Hola', "{'var': 'greeting'}"] true_greetings = ['Hi', 'Hello', 'Hola'] for _ in range(1): content = message.content self.assertTrue(content in true_greetings) options = message.options for o in options: self.assertTrue(o in true_greetings)
def test_step_through_nodes(self) -> None: nodes_ = [node1, node2, node3] directed_graph = DirectedGraph(name='graph1', nodes=nodes_, start_node='node1') for _ in range(10): self.assertEqual( Message(**message_kwargs).content, directed_graph.get_message().content) for _ in range(10): self.assertTrue(directed_graph.is_active) directed_graph.transition(right_option()) self.assertEqual( node1.name, directed_graph.current_node, ) self.assertTrue(directed_graph.is_active) directed_graph.transition(left_option()) for _ in range(10): directed_graph.transition(left_option()) directed_graph.transition(left_option()) self.assertEqual( node2.name, directed_graph.current_node, ) self.assertTrue(directed_graph.is_active) directed_graph.transition(right_option()) self.assertTrue(directed_graph.is_active) directed_graph.transition(left_option()) self.assertFalse(directed_graph.is_active) for _ in range(10): self.assertRaises(RuntimeError, directed_graph.transition, left_option()) self.assertIsNone(directed_graph.current_node) directed_graph.reset()
def test_create_new_db_entry(self): content = 'Question' options = 'choice' choice = options db_key = 'out' self.assertFalse(db_key in self._db.get_keys()) message = Message( content=content, options=options, message_type=Message.Type.MULTIPLE_CHOICE, result_db_key=db_key, ) self._io.set_input(choice) self._interface._is_create_db_key_if_not_exist = True self._interface.run(message) self.assertTrue(db_key in self._db.get_keys()) self.assertEqual(choice, self._db[db_key])
def test_error_message(self): content = 'Question' options = ['choice', 'not choice'] error_message = 'Error' error_options = 'Oops' choice = options[0] message = Message( content=content, options=options, message_type=Message.Type.MULTIPLE_CHOICE, error_message=error_message, error_options=error_options, tests=lambda x: x in options, ) self._io.set_input([ "invalid option", error_options, "invalid option", error_options, choice ]) self._interface.run(message) out = self._io.get_output() truth_out = [content, error_message, content, error_message, content] for i in range(len(truth_out)): self.assertEqual(truth_out[i], out[i])
class Messages: set_name = Message( content="What's your name?", options='Okay', args=['Your name'], message_type=Message.Type.DIRECT_INPUT, result_db_key=state_db.Keys.USER_NAME, result_convert_from_str_fn=str, tests=lambda x: len(x) > 1, error_message='Enter something with at least two letters', text_populator=text_populator, ) confirm_name = Message( content="{transitional_statement} I'll call you {'db': '%s'} then." % state_db.Keys.USER_NAME, options='Okay', message_type=Message.Type.MULTIPLE_CHOICE, text_populator=text_populator, ) set_am_checkin = Message( content="When would you like to checkin in the morning?", options='Okay', message_type=Message.Type.TIME_ENTRY, args=['15', '8:30'], result_db_key=state_db.Keys.AM_CHECKIN_TIME, result_convert_from_str_fn=lambda x: datetime.datetime.strptime(x, '%I:%M %p').time(), tests=lambda x: x.hour < 12, error_message="Please pick a time in the morning", is_confirm=False, text_populator=text_populator, ) confirm_am_checkin = Message( content="{transitional_statement} See you for our morning checkin at {'db': '%s'} then." % state_db.Keys.AM_CHECKIN_TIME, options='Okay', message_type=Message.Type.MULTIPLE_CHOICE, text_populator=text_populator, ) set_pm_checkin = Message( content="When should we checkin in the evening?", options='Okay', message_type=Message.Type.TIME_ENTRY, args=['15', '16:00'], result_db_key=state_db.Keys.PM_CHECKIN_TIME, result_convert_from_str_fn=lambda x: datetime.datetime.strptime(x, '%I:%M %p').time(), tests=lambda x: x.hour >= 12, error_message="Please pick a time after noon", is_confirm=False, text_populator=text_populator, ) confirm_pm_checkin = Message( content="{transitional_statement} I'll see you for our evening checkin at {'db': '%s'} then." % state_db.Keys.PM_CHECKIN_TIME, options='Okay', message_type=Message.Type.MULTIPLE_CHOICE, text_populator=text_populator, ) set_day_off = Message( content="Would you like a day off", options=['No', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'], message_type=Message.Type.MULTIPLE_CHOICE, result_db_key=state_db.Keys.DAY_OFF, text_populator=text_populator, ) confirm_day_off = Message( content="{transitional_statement} I'll remember that your day off is {'db': '%s'}!" % state_db.Keys.DAY_OFF, options="Okay", message_type=Message.Type.MULTIPLE_CHOICE, text_populator=text_populator, )
from interaction_engine.planner.messanger_planner import MessagerPlanner from interaction_engine.messager import Message import unittest m = Message( content='name', options='foo', message_type=Message.Type.MULTIPLE_CHOICE, ) class TestMessagePlanner(unittest.TestCase): def test_get_names(self): possible_plans = [m] message_planner = MessagerPlanner(possible_plans) self.assertEqual([], message_planner.plan) message_planner.insert(m) message_planner.insert(m) message_planner.insert(m) self.assertEqual(['name'] * 3, message_planner.plan) def test_hooks(self): var = 0 def set_var_fn(value): nonlocal var def fn():
class FirstMeeting: class Messages: introduce_self = Message( content= ("*QT/hi*Nice to meet you, {'db': '%s'}. " % state_db.Keys.USER_NAME + "*QT/show_QT*My name is QT. I'm a robot made by LuxAI in Luxembourg, a country in Europe. " + "I'm going to try to help you walk more regularly. " + "I won't go on walks with you*wink*. " + "Instead, I'll ask you questions about your plans to walk and " + "keep track of your daily steps by wirelessly talking to your Fitbit watch. " ), message_type=Message.Type.MULTIPLE_CHOICE, text_populator=text_populator, options=['Sure thing!', 'Sure', 'No thanks'], ) explain_checkin = Message( content= ("To help you walk regularly, *QT/bored* we'll talk at least twice a day: " + "once in the morning and once in the evening. " + "In the morning, we'll set a walking goal for the day and I'll ask you some questions. " + "These questions will be about your plans to walk or about you. " + "In the evening, we'll review the day. If you don't meet your walking goal, I may ask you why. " ), options='Sounds good', message_type=Message.Type.MULTIPLE_CHOICE, text_populator=text_populator, ) explain_off_checkin = Message( content=( "You can also talk to me any other time. " + # "I'll be happy to see you. *nod* I can tell you jokes or tell you good things. " + # "You can ask me to introduce myself, if you'd like me to meet someone new. " + # "I can also explain how we'll work together again. " + "Lastly, you can change what I call you or when we have our morning and evening checkins. " ), options='Okay', message_type=Message.Type.MULTIPLE_CHOICE, text_populator=text_populator, ) explain_fitbit = Message( content= ("Now, I'll tell you about how I'll work with your Fitbit watch. " + "This part is important.*nod* " + "To know how much you walk, I'll talk to your Fitbit watch. " + "Unfortunately, this can take some time. " + "Since I want to give you credit for all the steps you do, " + "please try to have your watch sync with the phone before our evening checkin. " + "Can you try to do that?"), options=['Definitely', 'Alright', "I'll try"], message_type=Message.Type.MULTIPLE_CHOICE, text_populator=text_populator, ) first_meeting = DirectedGraph( name='first meeting', start_node='ask name', nodes=[ Node( name='ask name', message=Options.Messages.set_name, options='Okay', transitions='introduce self', ), Node(name='introduce self', message=Messages.introduce_self, options=['Nice to meet you', 'Sounds great', 'Okay'], transitions='can explain?'), Node( name='can explain?', content="Can I explain how we'll work together?", message_type=Message.Type.MULTIPLE_CHOICE, options=['Sure thing', 'Okay', 'No thanks'], transitions=[ 'explain checkins', 'explain checkins', 'set am checkin' ], text_populator=text_populator, ), Node( name='explain checkins', message=Messages.explain_checkin, transitions='explain off-checkins', ), Node( name='explain off-checkins', message=Messages.explain_off_checkin, transitions='explain fitbit', ), Node( name='explain fitbit', message=Messages.explain_fitbit, transitions='set am checkin', ), Node( name='set am checkin', message=Options.Messages.set_am_checkin, transitions='confirm am checkin', ), Node( name='confirm am checkin', message=Options.Messages.confirm_am_checkin, options=[ '{affirmative_button_response}', '{oops_button_response}' ], transitions=['set pm checkin', 'set am checkin'], ), Node( name='set pm checkin', message=Options.Messages.set_pm_checkin, transitions='confirm pm checkin', ), Node( name='confirm pm checkin', message=Options.Messages.confirm_pm_checkin, options=[ '{affirmative_button_response}', '{oops_button_response}' ], transitions=['set steps goal', 'set pm checkin'], ), # THIS NODE IS SKIPPED Node( name='set day off', message=Options.Messages.set_day_off, transitions='set steps goal', ), Node( name='confirm day off', message=Options.Messages.confirm_day_off, options=[ '{affirmative_button_response}', '{oops_button_response}' ], transitions=['set steps goal', 'set day off'], ), # --------------------- Node( name='set steps goal', content=( lambda: "The last thing to do is to set walking goals for today. " + "You did {'db': '%s'} steps last week. " % state_db.Keys. STEPS_LAST_WEEK + "To work towards the goal of %s steps in %s weeks, " % (param_db.get(param_db.Keys.FINAL_STEPS_GOAL), param_db.get(param_db.Keys.WEEKS_WITH_ROBOT) ) + "I suggest that you do {'db': '%s'} steps today. " % state_db.Keys.SUGGESTED_STEPS_TODAY + "How many steps would you like to do today?"), options='steps', message_type=Message.Type.SLIDER, args=[ lambda: "{'db': '%s'}" % state_db.Keys. MIN_SUGGESTED_STEPS_TODAY, lambda: "{'db': '%s'}" % state_db.Keys. MAX_SUGGESTED_STEPS_TODAY, '1', lambda: "{'db': '%s'}" % state_db.Keys. SUGGESTED_STEPS_TODAY, ], result_convert_from_str_fn=int, result_db_key=state_db.Keys.STEPS_GOAL, tests=lambda x: x >= state_db.get(state_db.Keys. MIN_SUGGESTED_STEPS_TODAY), error_message= "Please select a goal that is at least {'db': '%s'} steps" % state_db.Keys.MIN_SUGGESTED_STEPS_TODAY, text_populator=text_populator, transitions='set when walk', ), Node( name='set when walk', message=Message( content="{when_question}", options='is when', message_type=Message.Type.TIME_ENTRY, args=[ '15', lambda: (datetime.datetime.now() + datetime.timedelta( hours=1)).strftime("%H:%M"), ], result_db_key=state_db.Keys.WALK_TIME, result_convert_from_str_fn=lambda x: datetime.datetime. strptime(x, '%I:%M %p').time(), tests=lambda x: (state_db.get(state_db.Keys.AM_CHECKIN_TIME) <= x <= state_db.get(state_db.Keys.PM_CHECKIN_TIME)), error_message= "Please pick a time after now and before our evening checkin", text_populator=text_populator, ), transitions=['first closing'], ), Node(name='first closing', content=("*QT/bye*Alright, we're all setup! " + "I'll see you for checkin this evening!"), message_type=Message.Type.MULTIPLE_CHOICE, options=['Bye', 'Talk to you later'], transitions='exit') ], )