Пример #1
0
 def _trigger(self, _model, _machine, *args, **kwargs):
     state_tree = _machine._build_state_tree(
         getattr(_model, _machine.model_attribute),
         _machine.state_cls.separator)
     state_tree = reduce(dict.get, _machine.get_global_name(join=False),
                         state_tree)
     ordered_states = _resolve_order(state_tree)
     done = []
     res = None
     for state_path in ordered_states:
         state_name = _machine.state_cls.separator.join(state_path)
         if state_name not in done and state_name in self.transitions:
             state = _machine.get_state(state_name)
             event_data = EventData(state,
                                    self,
                                    _machine,
                                    _model,
                                    args=args,
                                    kwargs=kwargs)
             event_data.source_name = state_name
             event_data.source_path = copy.copy(state_path)
             res = self._process(event_data)
             if res:
                 elems = state_path
                 while elems:
                     done.append(_machine.state_cls.separator.join(elems))
                     elems.pop()
     return res
Пример #2
0
    def on_state_changed(self, event: EventData):
        """Called on each state change"""

        # TODO: check if kwargs already have keys
        event.kwargs["position"] = self.position.to_dict()

        route = self.engine.route
        if route:
            event.kwargs["origin"] = route.origin.to_dict()
            event.kwargs["destination"] = route.destination.to_dict()

            # distance in km
            event.kwargs["trip_distance"] = round(
                route.traveled_distance(self.engine.now), 3
            )

            # duration in clock steps
            event.kwargs["trip_duration"] = round(
                route.traveled_time(self.engine.now), 3
            )

        itinerary = event.kwargs.get("itinerary")
        if itinerary and itinerary.next_jobs:
            next_job = itinerary.next_jobs[0]

            if next_job.is_pickup():
                event.kwargs["pickup"] = next_job.booking.id
            elif next_job.is_dropoff():
                event.kwargs["dropoff"] = next_job.booking.id

        super().on_state_changed(event)
Пример #3
0
    def to_state(self, model, state_name, *args, **kwargs):
        """ Helper function to add go to states in case a custom state separator is used.
        Args:
            model (class): The model that should be used.
            state_name (str): Name of the destination state.
        """

        current_state = getattr(model, self.model_attribute)
        if isinstance(current_state, list):
            raise MachineError("Cannot use 'to_state' from parallel state")

        event = EventData(self.get_state(current_state),
                          Event('to', self),
                          self,
                          model,
                          args=args,
                          kwargs=kwargs)
        event.source_name = current_state
        event.source_path = current_state.split(self.state_cls.separator)
        self._create_transition(current_state, state_name).execute(event)
Пример #4
0
    def on_state_changed(self, event: EventData):
        """The function is called by the state machine on each state change.
        
        Parameters
        ----------

        event : EventData
            Contains information describing state change like a current state and
            a new state
        """

        if event.transition.dest == States.pending.value:
            # TODO: check if kwargs already have keys
            event.kwargs["position"] = self.pickup.to_dict()
            event.kwargs["dropoff"] = self.dropoff.to_dict()

        if event.transition.dest in (
                States.pending.value,
                States.matched.value,
                States.pickup.value,
                States.expired.value,
                States.waiting_dropoff.value,
                States.waiting_pickup.value,
                States.expired.value,
        ):

            # NOTE: created position can be different from pickup position
            # but this is not supported at the moment

            event.kwargs["position"] = self.pickup.to_dict()

        if event.transition.dest in (States.dropoff.value,
                                     States.complete.value):
            # NOTE: pickup
            event.kwargs["position"] = self.dropoff.to_dict()

        itinerary = event.kwargs.get("itinerary")
        if itinerary:
            event.kwargs["vid"] = itinerary.vehicle.id

        super().on_state_changed(event)
Пример #5
0
    async def _trigger(self, model, *args, **kwargs):
        state = self.machine.get_state(model.state)
        while state.parent and state.name not in self.transitions:
            state = state.parent
        if state.name not in self.transitions:
            msg = "%sCan't trigger event %s from state %s!" % (
                self.machine.name, self.name, model.state)
            if self.machine.get_state(model.state).ignore_invalid_triggers:
                logger.warning(msg)
            else:
                raise MachineError(msg)
        event_data = EventData(self.machine.get_state(model.state),
                               self,
                               self.machine,
                               model,
                               args=args,
                               kwargs=kwargs)

        for func in self.machine.prepare_event:
            await self.machine._callback(func, event_data)
            logger.debug(
                "Executed machine preparation callback '%s' before conditions."
                % func)

        try:
            for t in self.transitions[state.name]:
                event_data.transition = t
                transition_result = await t.execute(event_data)
                if transition_result:
                    event_data.result = True
                    break
        except Exception as e:
            event_data.error = e
            raise
        finally:
            for func in self.machine.finalize_event:
                await self.machine._callback(func, event_data)
                logger.debug("Executed machine finalize callback '%s'." % func)
        return event_data.result
Пример #6
0
    def to_state(self, model, state_name, *args, **kwargs):
        """ Helper function to add go to states in case a custom state separator is used.
        Args:
            model (class): The model that should be used.
            state_name (str): Name of the destination state.
        """

        event = EventData(self.get_model_state(model),
                          Event('to', self),
                          self,
                          model,
                          args=args,
                          kwargs=kwargs)
        self._create_transition(getattr(model, self.model_attribute),
                                state_name).execute(event)
Пример #7
0
 def GET(self, action):
     super(DoorOpenClose, self).GET()
     if action not in ('open', 'close'):
         raise web.seeother('/')
     coop = Coop()
     event = EventData(None, None, None, None, None,
                       {'switches': coop.door_dual_sensor})
     if action == 'open':
         coop.door.open(event)
         state = 'open'
     else:
         coop.door.close(event)
         state = 'closed'
     day_night = coop.sunset_sunrise_sensor.state
     if day_night == 'invalid':
         day_night = 'night'
     coop.door.set_state('manual-{}-{}'.format(state, day_night))
     raise web.seeother('/')
Пример #8
0
 def _trigger(self, model, *args, **kwargs):
     state = self.machine.get_model_state(model)
     while state.parent and state.name not in self.transitions:
         state = state.parent
     if state.name not in self.transitions:
         msg = "%sCan't trigger event %s from state %s!" % (
             self.machine.name, self.name,
             self.machine.get_model_state(model))
         if self.machine.get_model_state(model).ignore_invalid_triggers:
             _LOGGER.warning(msg)
         else:
             raise MachineError(msg)
     event_data = EventData(state,
                            self,
                            self.machine,
                            model,
                            args=args,
                            kwargs=kwargs)
     return self._process(event_data)
Пример #9
0
 async def _trigger(self, model, *args, **kwargs):
     state = self.machine.get_state(model.state)
     if state.name not in self.transitions:
         msg = "%sCan't trigger event %s from state %s!" % (
             self.machine.name, self.name, state.name)
         ignore = state.ignore_invalid_triggers if state.ignore_invalid_triggers is not None \
             else self.machine.ignore_invalid_triggers
         if ignore:
             _LOGGER.warning(msg)
             return False
         else:
             raise MachineError(msg)
     event_data = EventData(state,
                            self,
                            self.machine,
                            model,
                            args=args,
                            kwargs=kwargs)
     return await self._process(event_data)