Example #1
0
 /// <summary>
 /// Add an internal transition to the state machine. An internal action does not cause the Exit and Entry actions to be triggered, and does not change the state of the state machine
 /// </summary>
 /// <typeparam name="TArg0"></typeparam>
 /// <param name="trigger">The accepted trigger</param>
 /// <param name="guard">Function that must return true in order for the trigger to be accepted.</param>
 /// <param name="internalAction">The asynchronous action performed by the internal transition</param>
 /// <returns></returns>
 public StateConfiguration InternalTransitionAsyncIf <TArg0>(TriggerWithParameters <TArg0> trigger, Func <bool> guard, Func <TArg0, Transition, Task> internalAction)
 {
     if (internalAction == null)
     {
         throw new ArgumentNullException(nameof(internalAction));
     }
     if (!internalAction.GetMethodInfo().IsDefined(typeof(AsyncStateMachineAttribute), false))
     {
         throw new ArgumentException("The supplied method is not tagged 'async'", nameof(internalAction));
     }
     _representation.AddTriggerBehaviour(new InternalTriggerBehaviour.Async(trigger.Trigger, guard, (t, args) => internalAction(ParameterConversion.Unpack <TArg0>(args, 0), t)));
     return(this);
 }
 /// <summary>
 ///     Accept the specified trigger and transition to the destination state, calculated
 ///     dynamically by the supplied function.
 /// </summary>
 /// <param name = "trigger">The accepted trigger.</param>
 /// <param name = "destinationStateSelector">Function to calculate the state
 ///     that the trigger will cause a transition to.</param>
 /// <param name = "guard">Function that must return true in order for the
 ///     trigger to be accepted.</param>
 /// <returns>The reciever.</returns>
 /// <typeparam name = "TArg0">Type of the first trigger argument.</typeparam>
 /// <typeparam name = "TArg1">Type of the second trigger argument.</typeparam>
 public StateConfiguration PermitDynamicIf <TArg0, TArg1>(TriggerWithParameters <TArg0, TArg1> trigger,
                                                          Func <TArg0, TArg1, TState> destinationStateSelector,
                                                          Func <bool> guard)
 {
     Enforce.ArgumentNotNull(trigger, "trigger");
     Enforce.ArgumentNotNull(destinationStateSelector, "destinationStateSelector");
     return(InternalPermitDynamicIf(
                trigger.Trigger,
                args => destinationStateSelector(
                    ParameterConversion.Unpack <TArg0>(args, 0),
                    ParameterConversion.Unpack <TArg1>(args, 1)),
                guard));
 }
Example #3
0
 /// <summary>
 /// Accept the specified trigger and transition to the destination state, calculated
 /// dynamically by the supplied function.
 /// </summary>
 /// <param name="trigger">The accepted trigger.</param>
 /// <param name="destinationStateSelector">Function to calculate the state
 /// that the trigger will cause a transition to.</param>
 /// <returns>The reciever.</returns>
 /// <param name="guard">Function that must return true in order for the
 /// trigger to be accepted.</param>
 /// <param name="guardDescription">Guard description</param>
 /// <typeparam name="TArg0">Type of the first trigger argument.</typeparam>
 /// <typeparam name="TArg1">Type of the second trigger argument.</typeparam>
 /// <typeparam name="TArg2">Type of the third trigger argument.</typeparam>
 public StateConfiguration PermitDynamicIf <TArg0, TArg1, TArg2>(TriggerWithParameters <TArg0, TArg1, TArg2> trigger, Func <TArg0, TArg1, TArg2, TState> destinationStateSelector, Func <bool> guard, string guardDescription = null)
 {
     Enforce.ArgumentNotNull(trigger, nameof(trigger));
     Enforce.ArgumentNotNull(destinationStateSelector, nameof(destinationStateSelector));
     return(InternalPermitDynamicIf(
                trigger.Trigger,
                args => destinationStateSelector(
                    ParameterConversion.Unpack <TArg0>(args, 0),
                    ParameterConversion.Unpack <TArg1>(args, 1),
                    ParameterConversion.Unpack <TArg2>(args, 2)),
                guard,
                guardDescription != null ? guardDescription : nameof(guard)));
 }
            /// <summary>
            /// Add an internal transition to the state machine. An internal action does not cause the Exit and Entry actions to be triggered, and does not change the state of the state machine
            /// </summary>
            /// <typeparam name="TArg0"></typeparam>
            /// <typeparam name="TArg1"></typeparam>
            /// <param name="trigger">The accepted trigger</param>
            /// <param name="guard">Function that must return true in order for the trigger to be accepted.</param>
            /// <param name="internalAction">The asynchronous action performed by the internal transition</param>
            /// <returns></returns>
            public StateConfiguration InternalTransitionAsyncIf <TArg0, TArg1>(TriggerWithParameters <TArg0, TArg1> trigger, Func <bool> guard, Func <TArg0, TArg1, Transition, Task> internalAction)
            {
                if (internalAction == null)
                {
                    throw new ArgumentNullException(nameof(internalAction));
                }

                _representation.AddTriggerBehaviour(new InternalTriggerBehaviour(trigger.Trigger, guard));
                _representation.AddInternalAction(trigger.Trigger, (t, args) => internalAction(
                                                      ParameterConversion.Unpack <TArg0>(args, 0),
                                                      ParameterConversion.Unpack <TArg1>(args, 1), t));
                return(this);
            }
Example #5
0
            /// <summary>
            /// Specify an asynchronous action that will execute when transitioning into
            /// the configured state.
            /// </summary>
            /// <typeparam name="TArg0">Type of the first trigger argument.</typeparam>
            /// <typeparam name="TArg1">Type of the second trigger argument.</typeparam>
            /// <param name="entryAction">Action to execute, providing details of the transition.</param>
            /// <param name="trigger">The trigger by which the state must be entered in order for the action to execute.</param>
            /// <param name="entryActionDescription">Action description.</param>
            /// <returns>The receiver.</returns>
            public StateConfiguration OnEntryFromAsync <TArg0, TArg1>(TriggerWithParameters <TArg0, TArg1> trigger, Func <TArg0, TArg1, Transition, Task> entryAction, string entryActionDescription = null)
            {
                if (trigger == null)
                {
                    throw new ArgumentNullException(nameof(trigger));
                }
                if (entryAction == null)
                {
                    throw new ArgumentNullException(nameof(entryAction));
                }

                _representation.AddEntryAction(trigger.Trigger,
                                               (t, args) => entryAction(
                                                   ParameterConversion.Unpack <TArg0>(args, 0),
                                                   ParameterConversion.Unpack <TArg1>(args, 1), t),
                                               Reflection.InvocationInfo.Create(entryAction, entryActionDescription, Reflection.InvocationInfo.Timing.Asynchronous));
                return(this);
            }
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="TArg0"></typeparam>
 /// <param name="trigger"></param>
 /// <param name="entryAction"></param>
 /// <returns></returns>
 public StateConfiguration InternalTransition <TArg0>(TriggerWithParameters <TArg0> trigger, Action <TArg0, Transition> entryAction)
 {
     _representation.AddTriggerBehaviour(new InternalTriggerBehaviour(trigger.Trigger));
     _representation.AddInternalAction(trigger.Trigger, (t, args) => entryAction(ParameterConversion.Unpack <TArg0>(args, 0), t));
     return(this);
 }
 /// <summary>
 /// Accept the specified trigger and transition to the destination state, calculated
 /// dynamically by the supplied function.
 /// </summary>
 /// <param name="trigger">The accepted trigger.</param>
 /// <param name="destinationStateSelector">Function to calculate the state
 /// that the trigger will cause a transition to.</param>
 /// <returns>The reciever.</returns>
 /// <typeparam name="TArg0">Type of the first trigger argument.</typeparam>
 /// <typeparam name="TArg1">Type of the second trigger argument.</typeparam>
 /// <typeparam name="TArg2">Type of the third trigger argument.</typeparam>
 public StateConfiguration PermitDynamic <TArg0, TArg1, TArg2>(TriggerWithParameters <TArg0, TArg1, TArg2> trigger, Func <TArg0, TArg1, TArg2, TState> destinationStateSelector)
 {
     return(PermitDynamicIf(trigger, destinationStateSelector, NoGuard));
 }
 /// <summary>
 ///     Transition from the current state via the specified trigger.
 ///     The target state is determined by the configuration of the current state.
 ///     Actions associated with leaving the current state and entering the new one
 ///     will be invoked.
 /// </summary>
 /// <typeparam name="TArg0">Type of the first trigger argument.</typeparam>
 /// <typeparam name="TArg1">Type of the second trigger argument.</typeparam>
 /// <typeparam name="TArg2">Type of the third trigger argument.</typeparam>
 /// <param name="arg0">The first argument.</param>
 /// <param name="arg1">The second argument.</param>
 /// <param name="arg2">The third argument.</param>
 /// <param name="trigger">The trigger to fire.</param>
 /// <exception cref="System.InvalidOperationException">
 ///     The current state does
 ///     not allow the trigger to be fired.
 /// </exception>
 public void Fire <TArg0, TArg1, TArg2>(TriggerWithParameters <TArg0, TArg1, TArg2> trigger, TArg0 arg0, TArg1 arg1,
                                        TArg2 arg2)
 {
     Enforce.ArgumentNotNull(trigger, "trigger");
     InternalFire(trigger.Trigger, arg0, arg1, arg2);
 }
 /// <summary>
 /// Specify an action that will execute when transitioning into
 /// the configured state.
 /// </summary>
 /// <typeparam name="TArg0">Type of the first trigger argument.</typeparam>
 /// <typeparam name="TArg1">Type of the second trigger argument.</typeparam>
 /// <typeparam name="TArg2">Type of the third trigger argument.</typeparam>
 /// <param name="entryAction">Action to execute, providing details of the transition.</param>
 /// <param name="trigger">The trigger by which the state must be entered in order for the action to execute.</param>
 /// <returns>The receiver.</returns>
 public StateConfiguration OnEntryFrom <TArg0, TArg1, TArg2>(TriggerWithParameters <TArg0, TArg1, TArg2> trigger, Action <TArg0, TArg1, TArg2> entryAction)
 {
     Enforce.ArgumentNotNull(entryAction, "entryAction");
     return(OnEntryFrom <TArg0, TArg1, TArg2>(trigger, (a0, a1, a2, t) => entryAction(a0, a1, a2)));
 }
Example #10
0
 /// <summary>
 /// Add an internal transition to the state machine. An internal action does not cause the Exit and Entry actions to be triggered, and does not change the state of the state machine
 /// </summary>
 /// <typeparam name="TArg0"></typeparam>
 /// <typeparam name="TArg1"></typeparam>
 /// <typeparam name="TArg2"></typeparam>
 /// <param name="trigger">The accepted trigger</param>
 /// <param name="internalAction">The asynchronous action performed by the internal transition</param>
 /// <returns></returns>
 public StateConfiguration InternalTransitionAsync <TArg0, TArg1, TArg2>(TriggerWithParameters <TArg0, TArg1, TArg2> trigger, Func <TArg0, TArg1, TArg2, Transition, Task> internalAction)
 {
     return(InternalTransitionAsyncIf(trigger, () => true, internalAction));
 }
Example #11
0
        private StateMachine <State, Trigger> BuildStateMachine()
        {
            // At the begging every Busker is in Disconnected state.
            var stateMachine = new StateMachine <State, Trigger>(State.Disconnected);

            // Add logging between state transitions.
            stateMachine.OnTransitioned(trans => Logger.LogTransition(this, trans));

            stateMachine.OnUnhandledTrigger((s, t) =>
            {
                Console.WriteLine($"Unhandled exception in state {s} by trigger {t}");
            });

            // Create parametrised triggers.
            acknowledgeTrigger = stateMachine
                                 .SetTriggerParameters <Ack>(Trigger.Ack);
            performancePermissionTrigger = stateMachine
                                           .SetTriggerParameters <Perm>(Trigger.Perm);
            requestPerformanceTrigger = stateMachine
                                        .SetTriggerParameters <Req>(Trigger.Req);
            finishedPerformanceTrigger = stateMachine
                                         .SetTriggerParameters <End>(Trigger.End);

            // Configure Disconntected state.
            stateMachine.Configure(State.Disconnected)
            .Permit(Trigger.Conn, State.Unknown);

            // Configure Unknown state.
            stateMachine.Configure(State.Unknown)
            .OnEntry(UpdateStage)
            .OnEntry(AckNeighs)
            .PermitReentry(Trigger.Notify)
            .Permit(Trigger.Win, State.Winner)
            .Permit(Trigger.Loose, State.Looser)
            .InternalTransition(Trigger.Rst, AckNeighs)
            .InternalTransition <Req>(requestPerformanceTrigger, OnRequest)
            .InternalTransition <Ack>(acknowledgeTrigger, OnAcknowledgeNeighbour)
            .InternalTransition <Perm>(performancePermissionTrigger, OnPerformancePermission)
            .InternalTransition <End>(finishedPerformanceTrigger, OnFinishedPerformance);

            stateMachine.Configure(State.Looser)
            .OnEntry(NotifyNeighs)
            .Permit(Trigger.Rst, State.Unknown)
            .Ignore(Trigger.Notify)
            .Ignore(Trigger.Loose)
            .InternalTransition <Ack>(acknowledgeTrigger, SendBackDecreasedValue)
            .InternalTransition <Req>(requestPerformanceTrigger, OnRequest)
            .InternalTransition <End>(finishedPerformanceTrigger, OnFinishedPerformance);

            // Configure Winner state.
            stateMachine.Configure(State.Winner)
            .OnEntry(LooseToNeighs)
            .OnEntry(Perform)
            .Permit(Trigger.End, State.Inactive)
            .Ignore(Trigger.Notify)
            .OnExit(EndToNeighs)
            .InternalTransition <Req>(requestPerformanceTrigger, OnRequest);

            // Configure Inactive state.
            stateMachine.Configure(State.Inactive)
            .Ignore(Trigger.Notify)
            .Ignore(Trigger.Ack)
            .InternalTransition <Req>(requestPerformanceTrigger, OnRequest);

            return(stateMachine);
        }
Example #12
0
 public StateConfiguration OnEntryFrom <TArg0>(TriggerWithParameters <TArg0> trigger, Action <TArg0> entryAction)
 {
     return(OnEntryFrom <TArg0>(trigger, (a0, t) => entryAction(a0)));
 }
Example #13
0
        public SlideStateMachine(Func <Task> startGameAction,
                                 Func <Task> nextSlideAction,
                                 Func <Task> evaluateSlideResponseAction,
                                 Func <double, Task> blankSlideAction,
                                 Func <double, Task> blankSlideCancelableAction,
                                 Func <Task> rewardSlideAction,
                                 Func <Task> endAction) : base(States.Inactive)
        {
            _showBlankTrigger           = SetTriggerParameters <double>(Triggers.ShowBlank);
            _showBlankCancelableTrigger = SetTriggerParameters <double>(Triggers.Omission);

            Configure(States.Inactive)
            //.OnActivateAsync(async () => await createGameAction())
            .Permit(Triggers.Start, States.Start);

            Configure(States.Start)
            .SubstateOf(States.Inactive)
            .OnEntryAsync(async() => await startGameAction())
            .Permit(Triggers.Exit, States.Exited)     // Exit
            .Permit(Triggers.NextSlide, States.ShowSlide);

            Configure(States.ShowSlide)
            .OnEntryAsync(async() => await nextSlideAction())
            .Permit(Triggers.Exit, States.Exited)     // Exit
            .Permit(Triggers.SlideFinished, States.ShowSlideComplete)
            .Permit(Triggers.NoSlides, States.End)
            .Ignore(Triggers.CorrectCommision)
            .Ignore(Triggers.WrongCommision);

            Configure(States.ShowSlideComplete)
            .OnEntryAsync(async() => await evaluateSlideResponseAction())
            .Permit(Triggers.Exit, States.Exited)              // Exit
            .Permit(Triggers.CorrectCommision, States.ShowRewardSlide)
            .Permit(Triggers.ShowBlank, States.ShowBlankSlide) //
            .Permit(Triggers.Omission, States.ShowBlankCancelableSlide);

            Configure(States.ShowRewardSlide)
            .OnEntryAsync(async() => await rewardSlideAction())
            .Permit(Triggers.Exit, States.Exited)              // Exit
            .Permit(Triggers.ShowBlank, States.ShowBlankSlide) //
            .Ignore(Triggers.NextSlide)                        ////
            .Ignore(Triggers.SlideFinished)
            .Ignore(Triggers.CorrectCommision);

            Configure(States.ShowBlankCancelableSlide)
            .OnEntryFrom(_showBlankCancelableTrigger, t => blankSlideCancelableAction(t))
            .Permit(Triggers.Exit, States.Exited)     // Exit
            .Permit(Triggers.CorrectCommision, States.ShowRewardSlide)
            .Permit(Triggers.NextSlide, States.ShowSlide)
            .Ignore(Triggers.WrongCommision);

            Configure(States.ShowBlankSlide)
            .OnEntryFrom(_showBlankTrigger, t => blankSlideAction(t))
            .Permit(Triggers.Exit, States.Exited)     // Exit
            .Permit(Triggers.SlideFinished, States.ShowSlide)
            .Ignore(Triggers.CorrectCommision);

            Configure(States.End)
            .OnActivateAsync(async() => await endAction())
            .Ignore(Triggers.CorrectCommision);

            Configure(States.Exited)
            .Ignore(Triggers.ShowBlank)
            .Ignore(Triggers.NextSlide)
            .Ignore(Triggers.SlideFinished);

            OnTransitioned
            (
                (t) => { OnPropertyChanged("State"); }
            );

            //used to debug commands and UI components
            OnTransitioned
            (
                (t) => { Debug.WriteLine("{0:HH:mm:ss.fff} - State Machine transitioned from {1} -> {2} [{3}]",
                                         TimerClock.Now, t.Source, t.Destination, t.Trigger); }
            );
        }
Example #14
0
 /// <summary>
 /// Transition from the current state via the specified trigger in async fashion.
 /// The target state is determined by the configuration of the current state.
 /// Actions associated with leaving the current state and entering the new one
 /// will be invoked.
 /// </summary>
 /// <typeparam name="TArg0">Type of the first trigger argument.</typeparam>
 /// <typeparam name="TArg1">Type of the second trigger argument.</typeparam>
 /// <param name="arg0">The first argument.</param>
 /// <param name="arg1">The second argument.</param>
 /// <param name="trigger">The trigger to fire.</param>
 /// <exception cref="System.InvalidOperationException">The current state does
 /// not allow the trigger to be fired.</exception>
 public Task FireAsync <TArg0, TArg1>(TriggerWithParameters <TArg0, TArg1> trigger, TArg0 arg0, TArg1 arg1)
 {
     Enforce.ArgumentNotNull(trigger, "trigger");
     return(InternalFireAsync(trigger.Trigger, arg0, arg1));
 }
Example #15
0
 public void Fire <TArg0, TArg1, TArg2>(TriggerWithParameters <TArg0, TArg1, TArg2> trigger, TArg0 arg0, TArg1 arg1, TArg2 arg2)
 {
     InternalFire(trigger.Trigger, arg0, arg1, arg2);
 }
Example #16
0
 public void Fire <TArg0>(TriggerWithParameters <TArg0> trigger, TArg0 arg0)
 {
     InternalFire(trigger.Trigger, arg0);
 }
Example #17
0
 public StateConfiguration OnEntryFrom <TArg0, TArg1, TArg2>(TriggerWithParameters <TArg0, TArg1, TArg2> trigger, Action <TArg0, TArg1, TArg2> entryAction)
 {
     return(OnEntryFrom <TArg0, TArg1, TArg2>(trigger, (a0, a1, a2, t) => entryAction(a0, a1, a2)));
 }
Example #18
0
 public StateConfiguration OnEntryFrom <TArg0>(TriggerWithParameters <TArg0> trigger, Action <TArg0, Transition> entryAction)
 {
     mRepresentation.AddEntryAction(trigger.Trigger, (t, args) => entryAction(
                                        ParameterConversion.Unpack <TArg0>(args, 0), t));
     return(this);
 }