Esempio n. 1
0
 def test_react_on_property(self):
     performer = Performer(self.schedule, self.ensemble)
     self.assertEqual(1, self.ensemble[0].state)
     action = Model.Property(None, self.ensemble[0], "state", 0)
     rv = performer.react(action)
     self.assertIs(action, rv)
     self.assertEqual(0, self.ensemble[0].state)
Esempio n. 2
0
    def test_exact_matching(self):
        content = textwrap.dedent("""
            .. entity:: WHATEVER

            Test exact
            ~~~~~~~~~~

            One
            ---

            .. condition:: WHATEVER.value 1

            One.

            Two
            ---

            .. condition:: WHATEVER.value 2

            Two.

        """)
        script = SceneScript("inline", doc=SceneScript.read(content))
        selection = script.select([DataObject(value=1)])
        self.assertTrue(all(selection.values()))
        script.cast(selection)
        model = script.run()
        conditions = [l for s, l in model if isinstance(l, Model.Condition)]
        self.assertEqual(2, len(conditions))

        self.assertTrue(Performer.allows(conditions[0]))
        self.assertFalse(Performer.allows(conditions[1]))
Esempio n. 3
0
 def test_react_on_memory(self):
     performer = Performer(self.schedule, self.ensemble)
     self.assertEqual(1, self.ensemble[0].state)
     action = Model.Memory(self.ensemble[0], None, 0, "text", "<html/>")
     rv = performer.react(action)
     self.assertIs(action, rv)
     self.assertEqual(0, self.ensemble[0].state)
Esempio n. 4
0
    def frame(self, dwell=0.3, pause=1, react=True):
        """ Return the next shot of dialogue as an animated frame."""
        while True:
            try:
                frame = self.frames.pop(0)
            except IndexError:
                self.log.debug("No more frames.")
                raise

            if all([Performer.allows(i) for i in frame[Model.Condition]]):
                frame[Model.Line] = list(
                    self.animate_lines(frame[Model.Line], dwell, pause))
                frame[Model.Audio] = list(
                    self.animate_audio(frame[Model.Audio]))
                frame[Model.Still] = list(
                    self.animate_stills(frame[Model.Still]))
                for p in frame[Model.Property]:
                    if react and p.object is not None:
                        setattr(p.object, p.attr, p.val)
                for m in frame[Model.Memory]:
                    if react and m.object is None:
                        m.subject.set_state(m.state)
                    try:
                        if m.subject.memories[-1].state != m.state:
                            m.subject.memories.append(m)
                    except AttributeError:
                        m.subject.memories = deque([m], maxlen=6)
                    except IndexError:
                        m.subject.memories.append(m)
                return frame
Esempio n. 5
0
 def setUpClass(cls):
     cls.asscns = associations()
     cls.ensemble = list(cls.asscns.ensemble()) + [
         Player(name="Player").set_state(Spot.grid_1205).set_state(Time.eve_predawn)
     ]
     cls.dialogue = copy.deepcopy(episodes)
     cls.characters = {
         k.__name__: v for k, v in group_by_type(cls.ensemble).items()
     }
     cls.performer = Performer(cls.dialogue, cls.ensemble)
Esempio n. 6
0
    def frame(session, entities):
        """Return the next frame of action for presentation handling."""
        while not session.frames:
            matcher = Matcher(carmen.logic.episodes)
            branching = list(matcher.options(session.cache.get("metadata",
                                                               {})))
            performer = Performer(branching, entities)
            folder, index, script, selection, interlude = performer.next(
                branching, entities)
            scene = performer.run(react=False)
            frames = list(
                Handler.frames(folder.paths[index], scene, dwell=0.3, pause=1))
            if frames and interlude:
                frames[-1].append(
                    Handler.Element(
                        None,
                        functools.partial(interlude, folder, index, entities,
                                          **session.cache), None, None, None))
            session.frames.extend(frames)

        return session.frames.popleft()
Esempio n. 7
0
 def setUpClass(cls):
     cls.ensemble = bluemonday78.story.ensemble(
         bluemonday78.story.build_narrator())
     cls.characters = collections.defaultdict(list)
     for obj in cls.ensemble:
         cls.characters[obj.get_state(Look)].append(obj)
     for obj in cls.ensemble:
         cls.characters[obj.get_state(Mode)].append(obj)
     for obj in cls.ensemble:
         cls.characters[obj.get_state(Trade)].append(obj)
     cls.performer = Performer(list(bluemonday78.story.prepare_folders()),
                               cls.ensemble)
Esempio n. 8
0
    def test_condition_evaluation_two(self):
        effects = [
            ConditionDirectiveTests.Rain().set_state(
                ConditionDirectiveTests.Weather.quiet),
            ConditionDirectiveTests.Sleet().set_state(
                ConditionDirectiveTests.Weather.stormy),
            ConditionDirectiveTests.Snow().set_state(
                ConditionDirectiveTests.Weather.stormy),
        ]

        script = SceneScript("inline", doc=SceneScript.read(self.content))
        selection = script.select(effects)
        self.assertTrue(all(selection.values()))
        script.cast(selection)
        model = script.run()
        conditions = [l for s, l in model if isinstance(l, Model.Condition)]
        self.assertEqual(4, len(conditions))

        self.assertTrue(Performer.allows(conditions[0]))
        self.assertFalse(Performer.allows(conditions[1]))
        self.assertTrue(Performer.allows(conditions[2]))
        self.assertFalse(Performer.allows(conditions[3]))
Esempio n. 9
0
    def test_run_filters_conditional_content(self):

        parent = str(Path(__file__).parent)
        with tempfile.NamedTemporaryFile(dir=parent,
                                         suffix=".rst") as scriptFile:
            scriptFile.write(
                ConditionDirectiveTests.content.replace(
                    "test_model", "test_performer").encode("utf8"))
            scriptFile.flush()

            folder = SceneScript.Folder(
                pkg=__name__,
                description="Test dialogue",
                metadata={},
                paths=[str(Path(scriptFile.name).relative_to(parent))],
                interludes=None)

            performer = Performer([folder],
                                  ConditionDirectiveTests.effects[0:1])
            output = list(performer.run())
            self.assertEqual(
                2, len([i for i in output if isinstance(i, Model.Line)]))
Esempio n. 10
0
    def test_regex_matching_state(self):
        content = textwrap.dedent("""
            .. entity:: WHATEVER

            Test exact
            ~~~~~~~~~~

            Even
            ----

            .. condition:: WHATEVER.state ([02468])

            Even.

            Odd
            ---

            .. condition:: WHATEVER.state ([13579])

            Odd.

        """)
        obj = Stateful()
        script = SceneScript("inline", doc=SceneScript.read(content))
        selection = script.select([obj])
        self.assertTrue(all(selection.values()))
        script.cast(selection)
        model = script.run()
        conditions = [l for s, l in model if isinstance(l, Model.Condition)]
        self.assertEqual(2, len(conditions))

        self.assertTrue(Performer.allows(conditions[0]), conditions[0])
        self.assertFalse(Performer.allows(conditions[1]))

        obj.state = 1
        self.assertFalse(Performer.allows(conditions[0]), conditions[0])
        self.assertTrue(Performer.allows(conditions[1]))
Esempio n. 11
0
def main(args):
    log_manager = LogManager()
    log = log_manager.get_logger("main")

    if args.log_path:
        log.set_route(args.log_level, LogAdapter(), sys.stderr)
        log.set_route(log.Level.NOTSET, LogAdapter(), args.log_path)
    else:
        log.set_route(args.log_level, LogAdapter(), sys.stderr)

    folders, references = resolve_objects(args)
    matcher = Matcher(folders)
    performer = Performer(folders, references)
    interlude = None
    handler = HTMLHandler(dwell=args.dwell, pause=args.pause)
    items = []
    folder = True
    log.info("Reading sources...")
    while folder and not performer.stopped:
        for i in range(args.repeat + 1):
            if performer.script:
                log.info("Script {0.fP}".format(performer.script))

            folder, index, script, selection, interlude = performer.next(
                folders, references, strict=args.strict, roles=args.roles)
            for item in performer.run(strict=args.strict, roles=args.roles):
                items.extend(list(handler(item)))

            if interlude is not None:
                metadata = interlude(folder, index, references)
                folder = next(matcher.options(metadata))

    log.info("Writing {0} items to output...".format(len(items)))
    print(handler.to_html(metadata=performer.metadata))
    log.info("Done.")
    return 0
Esempio n. 12
0
def rehearse(
    folders, references, handler,
    repeat=0, roles=1, strict=False,
    loop=None
):
    """Cast a set of objects into a sequence of scene scripts. Deliver the performance.

    :param folders: A sequence of
        :py:class:`turberfield.dialogue.model.SceneScript.Folder` objects.
    :param references: A sequence of Python objects.
    :param handler: A callable object. This will be invoked with every event from the
                    performance.
    :param int repeat: Extra repetitions of each folder.
    :param int roles: Maximum number of roles permitted each character.
    :param bool strict: Only fully-cast scripts to be performed.

    This function is a generator. It yields events from the performance.

    """
    if isinstance(folders, SceneScript.Folder):
        folders = [folders]

    yield from handler(references, loop=loop)

    matcher = Matcher(folders)
    performer = Performer(folders, references)
    while True:
        folder, index, script, selection, interlude = performer.next(
            folders, references, strict=strict, roles=roles
        )
        yield from handler(script, loop=loop)

        for item in performer.run(react=False, strict=strict, roles=roles):
            yield from handler(item, loop=loop)

        if isinstance(interlude, Callable):
            metadata = next(handler(
                interlude, folder, index, references, loop=loop
            ), None)
            yield metadata
            if metadata is None:
                return

            branch = next(matcher.options(metadata))
            if branch != folder:
                performer = Performer([branch], references)

        if not repeat:
            break
        else:
            repeat -= 1
Esempio n. 13
0
 def test_play(self):
     performer = Performer(self.schedule, self.ensemble)
     self.assertEqual(10, len(list(performer.run())))
     self.assertEqual(1, len(performer.shots))
     self.assertEqual("action", performer.shots[-1].name)
Esempio n. 14
0
 def test_stopped(self):
     performer = Performer(self.schedule, self.ensemble)
     self.assertFalse(performer.stopped)
Esempio n. 15
0
 def pending(self) -> int:
     return len([
         frame for frame in self.frames
         if all([Performer.allows(i) for i in frame[Model.Condition]])
     ])
Esempio n. 16
0
 def test_run_game(self):
     performer = Performer(self.schedule, self.ensemble)
     while not performer.stopped:
         list(performer.run())
Esempio n. 17
0
    def test_handler_frames_conditional_dialogue(self):
        content = textwrap.dedent("""

        .. entity:: PLAYER
           :types: carmen.logic.Player

        .. entity:: NARRATOR
           :types: carmen.logic.Narrator

        Feels
        ~~~~~

        Hungry
        ------

        .. condition:: PLAYER.state carmen.types.Time.day_lunch

        [NARRATOR]_

            You're hungry.

        [NARRATOR]_

            Nom nom nom.

        Tired
        -----

        .. condition:: PLAYER.state carmen.types.Time.eve

        [NARRATOR]_

            You're tired.


        [NARRATOR]_

            ZZZZZZZZ.

            """)
        script = SceneScript("inline", doc=SceneScript.read(content))
        ensemble = [Player(name="test").set_state(Time.day_lunch), Narrator()]
        script.cast(script.select(ensemble))
        scene = list(HandlerTests.dialogue(script.run()))
        conditions = [i for i in scene if isinstance(i, Model.Condition)]
        self.assertEqual(2, len(conditions))
        self.assertTrue(Performer.allows(conditions[0]))
        self.assertFalse(Performer.allows(conditions[1]))

        rv = list(Handler.frames(None, scene, dwell=0.3, pause=1))
        self.assertEqual(2, len(rv), rv)
        self.assertIsInstance(rv[0][0].dialogue, Model.Line)
        self.assertEqual(0, rv[0][0].offset)
        self.assertEqual(1.3, rv[0][0].duration)
        self.assertEqual(1.3, rv[0][1].offset)
        self.assertEqual(1.6, rv[0][1].duration)
        self.assertAlmostEqual(2.9, Handler.refresh(rv[0], min_val=0))

        self.assertIsInstance(rv[1][0].dialogue, Model.Line)
        self.assertEqual(0, rv[1][0].offset)
        self.assertEqual(1.3, rv[1][0].duration)
        self.assertEqual(1.3, rv[1][1].offset)
        self.assertEqual(1.0, rv[1][1].duration)
        self.assertAlmostEqual(2.3, Handler.refresh(rv[1], min_val=0))

        # A reminder that conditions require exact matches, unlike the
        # prefix-based casting by state
        ensemble[0].set_state(Time.eve_midnight)
        scene = list(HandlerTests.dialogue(script.run()))
        conditions = [i for i in scene if isinstance(i, Model.Condition)]
        self.assertEqual(2, len(conditions))
        self.assertFalse(Performer.allows(conditions[0]))
        self.assertFalse(Performer.allows(conditions[1]))