This project has moved. For the latest updates, please go here.
1

Resolved

Nice. But can we add a means to list available triggers?

description

Hi,
Nice first impressions -- specifically that Orthagonal configurations are catered for.
I'm considering using the library to compile a json based description of a StateMachine sequence, and then run it.
As the sequence is custom, uploaded by users, and therefore unknown at compile time, I'd like a property on the to iterate through the list of available Triggers, from which the user can then choose.

Potentially something like

_stateMachine.ActiveStateConfiguration.Transitions;

Would be useful. Thanks!

On another unrelated note, I'm curious regarding the need to define the SourceState when defining new Triggers -- isn't it always the same as the last defined State?

comments

RolandSchneider wrote Jul 27, 2015 at 8:56 PM

Helle SkySigal,

sorry for the delayed response.
As there is not much traffic here, I missed subscribing to the issue notifications.
Next time hopefully faster :-)

(Topic 1) How to get a list of reached transitions for the active state configuration?
StaMa publishes the full state machine metamodel which enables clients to write such methods according to their needs.

See the following example (based on V2.3.0) and console output:
using System;
using System.Collections.Generic;
using StaMa;

namespace GetReachedTransitions
{
    class Program
    {
        static void Main(string[] args)
        {
            StateMachineTemplate t = new StateMachineTemplate();
            t.Region("StateA", false);
                t.State("StateA");
                    t.Transition("T1", "StateC", "Ev1");
                    t.Transition("T2", "StateB", "Ev2");
                    t.Region("StateA1A", false);
                        t.State("StateA1A");
                            t.Transition("T3", "StateD", "Ev3");
                            t.Transition("T4", "StateE", "Ev4");
                        t.EndState();
                        t.State("StateA1B");
                        t.EndState();
                    t.EndRegion();
                t.EndState();
                t.State("StateB");
                t.EndState();
                t.State("StateC");
                    t.Transition("T5", "StateD", "Ev1");
                    t.Transition("T6", "StateE", "Ev2");
                t.EndState();
                t.State("StateD");
                    t.Transition("T7", "StateA1B", "Ev1");
                t.EndState();
                t.State("StateE");
                t.EndState();
            t.EndRegion();

            StateMachine stateMachine = t.CreateStateMachine();

            foreach (String ev in new String[] { "Startup",
                                                 "Ev1",
                                                 "Ev1",
                                                 "Ev1" })
            {
                if (ev == "Startup")
                    stateMachine.Startup();
                else
                    stateMachine.SendTriggerEvent(ev);

                Console.WriteLine("Reached Transitions in State {0}:",
                           stateMachine.ActiveStateConfiguration.ToString());

                TransitionCollector collector = new TransitionCollector();
                stateMachine.ActiveStateConfiguration.PassThrough(collector);
                foreach (Transition transition in collector.Transitions)
                {
                    Console.WriteLine("Transition {0} with event {1} to {2}",
                                      transition.Name,
                                      transition.TriggerEvent,
                                      transition.TargetState.ToString());
                }
            }
        }


        private class TransitionCollector : IStateConfigurationVisitor
        {
            public List<Transition> Transitions = new List<Transition>();

            void IStateConfigurationVisitor.State(State state)
            {
                Transitions.AddRange(state.Transitions);
            }

            void IStateConfigurationVisitor.BeginSubStates() {}
            void IStateConfigurationVisitor.EndSubStates() {}
            void IStateConfigurationVisitor.NextSubState() {}
            void IStateConfigurationVisitor.StateAny() {}
        }
    }
}
Output:
Reached Transitions in State StateA(StateA1A):
Transition T1 with event Ev1 to StateC
Transition T2 with event Ev2 to StateB
Transition T3 with event Ev3 to StateD
Transition T4 with event Ev4 to StateE
Reached Transitions in State StateC:
Transition T5 with event Ev1 to StateD
Transition T6 with event Ev2 to StateE
Reached Transitions in State StateD:
Transition T7 with event Ev1 to StateA(StateA1B)
Reached Transitions in State StateA(StateA1B):
Transition T1 with event Ev1 to StateC
Transition T2 with event Ev2 to StateB
(Topic 2) Why does the Transition definition require the source state?
Your observation is correct, in V2.2.0 this was unnecessarily enforced by the API.
With V2.3.0 it has been relaxed, there are new StateMachinetemplate.Transition(...) overloads that don't require the source state to be passed in when the source state is the same as the transition's parent state.
Still there are special cases where the source state is needed, specifically for transitions on a composite state where the source state is defined through a sub-state (or set of sub-states in case of orthogonal regions) of the composite state.
See e.g. Transition with Event6 in Composite States, Transition with Event4 in Orthogonal Regions or
Transition with Event2 in Guarding a Transition through a State....

Hope this helps,

Roland.

wrote Jul 27, 2015 at 8:57 PM

RolandSchneider wrote Jul 27, 2015 at 9:00 PM

** Closed by RolandSchneider 27.07.2015 13:57

wrote Jul 27, 2015 at 9:00 PM

wrote Jul 27, 2015 at 9:05 PM