def test_get_nearest_choice__2_choices__second_choice(self): choice_1 = facts.Choice(uid='choice_1') choice_2 = facts.Choice(uid='choice_2') option_2_1 = facts.Option(state_from=choice_2.uid, state_to=self.state_1.uid, type='opt_2_1', markers=()) option_2_2 = facts.Option(state_from=choice_2.uid, state_to=self.state_2.uid, type='opt_2_2', markers=()) path_2 = facts.ChoicePath(choice=choice_2.uid, option=option_2_2.uid, default=True) option_1_1 = facts.Option(state_from=choice_1.uid, state_to=self.state_1.uid, type='opt_1_1', markers=()) option_1_2 = facts.Option(state_from=choice_1.uid, state_to=choice_2.uid, type='opt_1_2', markers=()) path_1 = facts.ChoicePath(choice=choice_1.uid, option=option_1_2.uid, default=True) self.kb += (choice_1, option_1_1, option_1_2, path_1, choice_2, option_2_1, option_2_2, path_2, facts.Jump(state_from=self.start.uid, state_to=choice_1.uid), facts.Pointer(state=choice_2.uid) ) choice_, options_, path_ = self.machine.get_nearest_choice() self.assertEqual(choice_.uid, choice_2.uid) self.assertEqual(set(o.uid for o in options_), set([option_2_1.uid, option_2_2.uid])) self.assertEqual([p.uid for p in path_], [path_2.uid])
def change_choice(knowledge_base, new_option_uid, default): choice_uid = knowledge_base[new_option_uid].state_from knowledge_base -= [ path for path in knowledge_base.filter(facts.ChoicePath) if path.choice == choice_uid ] knowledge_base += facts.ChoicePath(choice=choice_uid, option=new_option_uid, default=default) links = [ link for link in knowledge_base.filter(facts.OptionsLink) if new_option_uid in link.options ] if links: link = links[0] for linked_option_uid in link.options: if new_option_uid == linked_option_uid: continue linked_choice_uid = knowledge_base[linked_option_uid].state_from knowledge_base -= [ path for path in knowledge_base.filter(facts.ChoicePath) if path.choice == linked_choice_uid ] knowledge_base += facts.ChoicePath(choice=linked_choice_uid, option=linked_option_uid, default=default) return True
def get_choices(self, default=True): choice = self.quest.knowledge_base['[ns-0]choice_1'] options = sorted((o for o in self.quest.knowledge_base.filter(facts.Option) if o.state_from == choice.uid), key=lambda o: o.uid) defaults = [facts.ChoicePath(choice=choice.uid, option=options[-1].uid, default=default)] return choice, options, defaults
def test_sync_pointer(self): choice = facts.Choice(uid='choice') option_1 = facts.Option(state_from=choice.uid, state_to=self.state_1.uid, type='opt_1', markers=()) option_2 = facts.Option(state_from=choice.uid, state_to=self.state_2.uid, type='opt_2', markers=()) path = facts.ChoicePath(choice=choice.uid, option=option_2.uid, default=True) pointer = facts.Pointer(state=choice.uid, jump=option_1.uid) self.kb += (choice, option_1, option_2, path, pointer) calls_manager = mock.MagicMock() with mock.patch.object(self.machine.interpreter, 'on_state__before_actions') as on_state__before_actions: with mock.patch.object(self.machine.interpreter, 'on_state__after_actions') as on_state__after_actions: with mock.patch.object(self.machine.interpreter, 'on_jump_start__before_actions') as on_jump_start__before_actions: with mock.patch.object(self.machine.interpreter, 'on_jump_start__after_actions') as on_jump_start__after_actions: with mock.patch.object(self.machine.interpreter, 'on_jump_end__before_actions') as on_jump_end__before_actions: with mock.patch.object(self.machine.interpreter, 'on_jump_end__after_actions') as on_jump_end__after_actions: calls_manager.attach_mock(on_state__before_actions, 'on_state__before_actions') calls_manager.attach_mock(on_state__after_actions, 'on_state__after_actions') calls_manager.attach_mock(on_jump_start__before_actions, 'on_jump_start__before_actions') calls_manager.attach_mock(on_jump_start__after_actions, 'on_jump_start__after_actions') calls_manager.attach_mock(on_jump_end__before_actions, 'on_jump_end__before_actions') calls_manager.attach_mock(on_jump_end__after_actions, 'on_jump_end__after_actions') self.machine.sync_pointer() self.assertEqual(calls_manager.mock_calls, [mock.call.on_jump_start__before_actions(jump=option_2), mock.call.on_jump_start__after_actions(jump=option_2)]) self.assertEqual(self.machine.pointer.jump, option_2.uid) self.assertEqual(self.machine.pointer.state, choice.uid)
def test_get_available_jumps__for_choice_state(self): choice = facts.Choice(uid='choice') option_1 = facts.Option(state_from=choice.uid, state_to=self.state_1.uid, type='opt_1', markers=()) option_2 = facts.Option(state_from=choice.uid, state_to=self.state_2.uid, type='opt_2', markers=()) path = facts.ChoicePath(choice=choice.uid, option=option_2.uid, default=True) self.kb += (choice, option_1, option_2, path) for i in xrange(100): self.assertEqual(self.machine.get_available_jumps(choice), [option_2])
def test_get_nearest_choice__choice_after_finish(self): choice = facts.Choice(uid='choice') option_1 = facts.Option(state_from=choice.uid, state_to=self.state_1.uid, type='opt_1', markers=()) option_2 = facts.Option(state_from=choice.uid, state_to=self.state_2.uid, type='opt_2', markers=()) path = facts.ChoicePath(choice=choice.uid, option=option_2.uid, default=True) self.kb += (choice, option_1, option_2, path, facts.Jump(state_from=self.start.uid, state_to=self.finish_1.uid), facts.Jump(state_from=self.finish_1.uid, state_to=choice.uid)) self.assertEqual(self.machine.get_nearest_choice(), (None, None, None))
def determine_default_choices(knowledge_base, preferred_markers=()): ''' ''' processed_choices = set() linked_options = {} restricted_options = set() # options, that can not be used as default preferred_markers = set(preferred_markers) for link in knowledge_base.filter(facts.OptionsLink): for option_uid in link.options: if option_uid in linked_options: raise exceptions.OptionWithTwoLinksError( option=knowledge_base[option_uid]) linked_options[option_uid] = link for choice in knowledge_base.filter(facts.Choice): if choice.uid in processed_choices: continue processed_choices.add(choice.uid) options_choices = [ option for option in knowledge_base.filter(facts.Option) if option.state_from == choice.uid and option.uid not in restricted_options ] if not options_choices: # if there no valid options (in valuid graph), then all options where cancels by other chocices # and we will no go to that state by defaul states (quest author responded for this) # TODO: make restriction, that check if we have full default path continue filtered_options_choices = [] if preferred_markers: filtered_options_choices = [ candidate for candidate in options_choices if set(candidate.markers) & preferred_markers ] if not filtered_options_choices: filtered_options_choices = options_choices default_option = random.choice(filtered_options_choices) if default_option.uid in linked_options: for linked_option_uid in linked_options[ default_option.uid].options: if linked_option_uid == default_option.uid: continue # option can be removed by other transformations if linked_option_uid not in knowledge_base: continue linked_choice_uid = knowledge_base[ linked_option_uid].state_from if linked_choice_uid in processed_choices: raise exceptions.LinkedOptionWithProcessedChoiceError( option=knowledge_base[linked_option_uid]) processed_choices.add(linked_choice_uid) knowledge_base += facts.ChoicePath(choice=linked_choice_uid, option=linked_option_uid, default=True) # if add all options linked to unused to restricted_options for unused_option in options_choices: if unused_option.uid == default_option.uid: continue if unused_option.uid not in linked_options: continue for linked_option_uid in linked_options[unused_option.uid].options: restricted_options.add(linked_option_uid) knowledge_base += facts.ChoicePath(choice=choice.uid, option=default_option.uid, default=True)
def test_linked_choices(self): start = facts.Start(uid='start', type='test', nesting=0) choice_1 = facts.Choice(uid='choice_1') choice_2 = facts.Choice(uid='choice_2') finish_1 = facts.Finish(uid='finish_1', results={}, nesting=0, start='start') finish_2 = facts.Finish(uid='finish_2', results={}, nesting=0, start='start') option_1 = facts.Option(state_from=choice_1.uid, state_to=finish_1.uid, type='opt_1', markers=()) option_2 = facts.Option(state_from=choice_1.uid, state_to=choice_2.uid, type='opt_2', markers=()) option_2_1 = facts.Option(state_from=choice_2.uid, state_to=finish_1.uid, type='opt_2_1', markers=()) option_2_2 = facts.Option(state_from=choice_2.uid, state_to=finish_2.uid, type='opt_2_2', markers=()) facts_list = [ start, choice_1, choice_2, finish_1, finish_2, option_1, option_2, option_2_1, option_2_2, facts.OptionsLink(options=(option_1.uid, option_2_1.uid)), facts.OptionsLink(options=(option_2.uid, option_2_2.uid)) ] self.kb += facts_list choices = [ facts.ChoicePath(choice=choice_1.uid, option=option_2.uid, default=True), facts.ChoicePath(choice=choice_2.uid, option=option_2_2.uid, default=True) ] self.kb += choices transformators.change_choice(self.kb, option_1.uid, default=False) self.check_in_knowledge_base(self.kb, facts_list) self.check_not_in_knowledge_base(self.kb, choices) self.assertEqual(len(list(self.kb.filter(facts.ChoicePath))), 2) self.assertEqual( len(set([path.choice for path in self.kb.filter(facts.ChoicePath)])), 2) self.assertEqual( set([path.option for path in self.kb.filter(facts.ChoicePath)]), set([option_1.uid, option_2_1.uid]))