public void LogInitializeTest() { _loggerMock.Setup(logger => logger.Debug("Initialized StateMachine Test with initial state On")); _stateMachine.Initialize(States.On); _loggerMock.VerifyAll(); }
private void ConfigureStateMachine() { mToiletStateMachine = new PassiveStateMachine <ToiletStates, ToiletEvents>(); mCurrentStateExtension = new CurrentStateExtension(); mToiletStateMachine.AddExtension(mCurrentStateExtension); mToiletStateMachine.In(ToiletStates.WaitingForStart) .ExecuteOnEntry(StopStateMachine) .On(ToiletEvents.StartStateMachine).Goto(ToiletStates.WaitingForMan); mToiletStateMachine.In(ToiletStates.WaitingForMan) .ExecuteOnEntry(WaitForMan) .On(ToiletEvents.ManArrived).Goto(ToiletStates.ManInfrontOfToilet) .On(ToiletEvents.StopStateMachine).Goto(ToiletStates.WaitingForStart); mToiletStateMachine.In(ToiletStates.ManInfrontOfToilet) .ExecuteOnEntry(ManArrived) .On(ToiletEvents.ManPees).Goto(ToiletStates.ManIsPeeing) .On(ToiletEvents.ManLeft).Goto(ToiletStates.WaitingForMan) .On(ToiletEvents.StopStateMachine).Goto(ToiletStates.WaitingForStart); mToiletStateMachine.In(ToiletStates.ManIsPeeing). ExecuteOnEntry(ManIsPeeing) .On(ToiletEvents.ManLeft).Goto(ToiletStates.PeeingFinished) .On(ToiletEvents.StopStateMachine).Goto(ToiletStates.WaitingForStart); mToiletStateMachine.In(ToiletStates.PeeingFinished) .ExecuteOnEntry(Flush) .On(ToiletEvents.FlushFinished).Goto(ToiletStates.WaitingForMan) .On(ToiletEvents.StopStateMachine).Goto(ToiletStates.WaitingForStart); mToiletStateMachine.Initialize(ToiletStates.WaitingForStart); mToiletStateMachine.Start(); }
public void EventsQueueing( IStateMachine <string, int> machine) { const int FirstEvent = 0; const int SecondEvent = 1; bool arrived = false; "establish a passive state machine with transitions"._(() => { machine = new PassiveStateMachine <string, int>(); machine.In("A").On(FirstEvent).Goto("B"); machine.In("B").On(SecondEvent).Goto("C"); machine.In("C").ExecuteOnEntry(() => arrived = true); machine.Initialize("A"); }); "when firing an event onto the state machine"._(() => { machine.Fire(FirstEvent); machine.Fire(SecondEvent); machine.Start(); }); "it should queue event at the end"._(() => arrived.Should().BeTrue("state machine should arrive at destination state")); }
public void Start( PassiveStateMachine <int, int> machine, bool entryActionExecuted) { "establish an initialized state machine".x(() => { machine = new PassiveStateMachine <int, int>(); machine.AddExtension(this.testExtension); machine.In(TestState) .ExecuteOnEntry(() => entryActionExecuted = true); machine.Initialize(TestState); }); "when starting the state machine".x(() => machine.Start()); "should set current state of state machine to state to which it is initialized".x(() => this.testExtension.CurrentState.Should().Be(TestState)); "should execute entry action of state to which state machine is initialized".x(() => entryActionExecuted.Should().BeTrue()); }
public void CustomTypesForStatesAndEvents( PassiveStateMachine <MyState, MyEvent> machine, bool arrivedInStateB) { "establish a state machine with custom types for states and events".x(() => { machine = new PassiveStateMachine <MyState, MyEvent>(); machine.In(new MyState("A")) .On(new MyEvent(1)).Goto(new MyState("B")); machine.In(new MyState("B")) .ExecuteOnEntry(() => arrivedInStateB = true); machine.Initialize(new MyState("A")); machine.Start(); }); "when using the state machine".x(() => machine.Fire(new MyEvent(1))); "it should use equals to compare states and events".x(() => arrivedInStateB.Should().BeTrue("state B should be current state")); }
public void BeforeExecutingEntryActions( PassiveStateMachine <string, int> machine, IExtension <string, int> extension) { "establish an extension".x(() => extension = A.Fake <IExtension <string, int> >()); "establish a state machine using the extension".x(() => { machine = new PassiveStateMachine <string, int>(Name); machine.AddExtension(extension); machine.In("0") .On(1).Goto("1"); machine.Initialize("0"); machine.Start(); }); "when firing an event onto the state machine".x(() => machine.Fire(1)); "it should call EnteringState on registered extensions for target state".x(() => A.CallTo(() => extension.EnteringState( A <IStateMachineInformation <string, int> > .That.Matches(x => x.Name == Name && x.CurrentStateId == "1"), A <IState <string, int> > .That.Matches(x => x.Id == "1"), A <ITransitionContext <string, int> > .That.Matches(x => x.EventId.Value == 1))) .MustHaveHappened()); }
public void MatchingGuard( PassiveStateMachine <int, int> machine, CurrentStateExtension currentStateExtension) { "establish a state machine with guarded transitions".x(() => { machine = new PassiveStateMachine <int, int>(); currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); machine.In(SourceState) .On(Event) .If(() => false).Goto(ErrorState) .If(() => true).Goto(DestinationState) .If(() => true).Goto(ErrorState) .Otherwise().Goto(ErrorState); machine.Initialize(SourceState); machine.Start(); }); "when an event is fired".x(() => machine.Fire(Event)); "it should take transition guarded with first matching guard".x(() => currentStateExtension.CurrentState.Should().Be(DestinationState)); }
public void CustomTypesForStatesAndEvents( PassiveStateMachine<MyState, MyEvent> machine, bool arrivedInStateB) { "establish a state machine with custom types for states and events"._(() => { machine = new PassiveStateMachine<MyState, MyEvent>(); machine.In(new MyState("A")) .On(new MyEvent(1)).Goto(new MyState("B")); machine.In(new MyState("B")) .ExecuteOnEntry(() => arrivedInStateB = true); machine.Initialize(new MyState("A")); machine.Start(); }); "when using the state machine"._(() => machine.Fire(new MyEvent(1))); "it should use equals to compare states and events"._(() => arrivedInStateB.Should().BeTrue("state B should be current state")); }
public void OtherwiseGuard( PassiveStateMachine <int, int> machine, CurrentStateExtension currentStateExtension) { "establish a state machine with otherwise guard and no machting other guard".x(() => { machine = new PassiveStateMachine <int, int>(); currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); machine.In(SourceState) .On(Event) .If(() => false).Goto(ErrorState) .Otherwise().Goto(DestinationState); machine.Initialize(SourceState); machine.Start(); }); "when an event is fired".x(() => machine.Fire(Event)); "it should_take_transition_guarded_with_otherwise".x(() => currentStateExtension.CurrentState.Should().Be(DestinationState)); }
public void NoMatchingGuard( PassiveStateMachine <int, int> machine, CurrentStateExtension currentStateExtension) { bool declined = false; "establish state machine with no matching guard".x(() => { machine = new PassiveStateMachine <int, int>(); currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); machine.In(SourceState) .On(Event) .If(() => false).Goto(ErrorState); machine.TransitionDeclined += (sender, e) => declined = true; machine.Initialize(SourceState); machine.Start(); }); "when an event is fired".x(() => machine.Fire(Event)); "it should notify about declined transition".x(() => declined.Should().BeTrue("TransitionDeclined event should be fired")); }
public void MatchingGuard( PassiveStateMachine<int, int> machine, CurrentStateExtension currentStateExtension) { "establish a state machine with guarded transitions"._(() => { machine = new PassiveStateMachine<int, int>(); currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); machine.In(SourceState) .On(Event) .If(() => false).Goto(ErrorState) .If(() => true).Goto(DestinationState) .If(() => true).Goto(ErrorState) .Otherwise().Goto(ErrorState); machine.Initialize(SourceState); machine.Start(); }); "when an event is fired"._(() => machine.Fire(Event)); "it should take transition guarded with first matching guard"._(() => currentStateExtension.CurrentState.Should().Be(DestinationState)); }
public void Reinitialization( PassiveStateMachine <int, int> machine, Exception receivedException) { "establish an initialized state machine".x(() => { machine = new PassiveStateMachine <int, int>(); machine.Initialize(TestState); }); "when state machine is initialized again".x(() => { try { machine.Initialize(TestState); } catch (Exception e) { receivedException = e; } }); "should throw an invalid operation exception".x(() => { receivedException .Should().BeAssignableTo <InvalidOperationException>(); receivedException.Message .Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized); }); }
public void NoMatchingGuard( PassiveStateMachine<int, int> machine, CurrentStateExtension currentStateExtension) { bool declined = false; "establish state machine with no matching guard"._(() => { machine = new PassiveStateMachine<int, int>(); currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); machine.In(SourceState) .On(Event) .If(() => false).Goto(ErrorState); machine.TransitionDeclined += (sender, e) => declined = true; machine.Initialize(SourceState); machine.Start(); }); "when an event is fired"._(() => machine.Fire(Event)); "it should notify about declined transition"._(() => declined.Should().BeTrue("TransitionDeclined event should be fired")); }
public void Report() { var elevator = new PassiveStateMachine <States, Events>("Elevator"); elevator.DefineHierarchyOn(States.Healthy, States.OnFloor, HistoryType.Deep, States.OnFloor, States.Moving); elevator.DefineHierarchyOn(States.Moving, States.MovingUp, HistoryType.Shallow, States.MovingUp, States.MovingDown); elevator.DefineHierarchyOn(States.OnFloor, States.DoorClosed, HistoryType.None, States.DoorClosed, States.DoorOpen); elevator.In(States.Healthy) .On(Events.ErrorOccured).Goto(States.Error); elevator.In(States.Error) .On(Events.Reset).Goto(States.Healthy) .On(Events.ErrorOccured); elevator.In(States.OnFloor) .ExecuteOnEntry(AnnounceFloor) .ExecuteOnExit(Beep, Beep) .On(Events.CloseDoor).Goto(States.DoorClosed) .On(Events.OpenDoor).Goto(States.DoorOpen) .On(Events.GoUp) .If(CheckOverload).Goto(States.MovingUp) .Otherwise().Execute(AnnounceOverload, Beep) .On(Events.GoDown) .If(CheckOverload).Goto(States.MovingDown) .Otherwise().Execute(AnnounceOverload); elevator.In(States.Moving) .On(Events.Stop).Goto(States.OnFloor); elevator.Initialize(States.OnFloor); elevator.Report(this.testee); string statesReport; string transitionsReport; this.stateStream.Position = 0; using (var reader = new StreamReader(this.stateStream)) { statesReport = reader.ReadToEnd(); } this.transitionsStream.Position = 0; using (var reader = new StreamReader(this.transitionsStream)) { transitionsReport = reader.ReadToEnd(); } const string ExpectedStatesReport = "Source;Entry;Exit;ChildrenOnFloor;AnnounceFloor;Beep, Beep;DoorClosed, DoorOpenMoving;;;MovingUp, MovingDownHealthy;;;OnFloor, MovingMovingUp;;;MovingDown;;;DoorClosed;;;DoorOpen;;;Error;;;"; const string ExpectedTransitionsReport = "Source;Event;Guard;Target;ActionsOnFloor;CloseDoor;;DoorClosed;OnFloor;OpenDoor;;DoorOpen;OnFloor;GoUp;CheckOverload;MovingUp;OnFloor;GoUp;;internal transition;AnnounceOverload, BeepOnFloor;GoDown;CheckOverload;MovingDown;OnFloor;GoDown;;internal transition;AnnounceOverloadMoving;Stop;;OnFloor;Healthy;ErrorOccured;;Error;Error;Reset;;Healthy;Error;ErrorOccured;;internal transition;"; statesReport.Replace("\n", string.Empty).Replace("\r", string.Empty) .Should().Be(ExpectedStatesReport.Replace("\n", string.Empty).Replace("\r", string.Empty)); transitionsReport.Replace("\n", string.Empty).Replace("\r", string.Empty) .Should().Be(ExpectedTransitionsReport.Replace("\n", string.Empty).Replace("\r", string.Empty)); }
public void CanStartFSM() { fsm = new PassiveStateMachine <SM.ProcessState, SM.Command>(); fsm.Initialize(SM.ProcessState.Initial); fsm.Fire(SM.Command.OnOpenBattleFront); fsm.Start(); Assert.IsTrue(fsm.IsRunning); }
public void Loading( StateMachineSaver <State> saver, StateMachineLoader <State> loader, FakeExtension extension, State sourceState, State targetState) { "establish a saved state machine with history".x(() => { var machine = new PassiveStateMachine <State, Event>(); DefineMachine(machine); machine.Initialize(State.A); machine.Start(); machine.Fire(Event.S2); // set history of super state S machine.Fire(Event.B); // set current state to B saver = new StateMachineSaver <State>(); loader = new StateMachineLoader <State>(); machine.Save(saver); }); "when state machine is loaded".x(() => { loader.SetCurrentState(saver.CurrentStateId); loader.SetHistoryStates(saver.HistoryStates); extension = new FakeExtension(); var loadedMachine = new PassiveStateMachine <State, Event>(); loadedMachine.AddExtension(extension); DefineMachine(loadedMachine); loadedMachine.Load(loader); loadedMachine.TransitionCompleted += (sender, args) => { sourceState = args.StateId; targetState = args.NewStateId; }; loadedMachine.Start(); loadedMachine.Fire(Event.S); }); "it should reset current state".x(() => sourceState.Should().Be(State.B)); "it should reset all history states of super states".x(() => targetState.Should().Be(State.S2)); "it should notify extensions".x(() => extension.LoadedCurrentState .Should().BeEquivalentTo(State.B)); }
public void SimpleTransition() { fsm = new PassiveStateMachine <SM.ProcessState, SM.Command>(); fsm.Initialize(SM.ProcessState.Initial); fsm.Fire(SM.Command.OnOpenBattleFront); fsm.Start(); fsm.Fire(SM.Command.OnOuterDoorDown); Assert.IsTrue(fsm.IsRunning); }
public static void Main() { // configure basic logging (all levels enabled, messages are written to the console) log4net.Config.BasicConfigurator.Configure(); var elevator = new PassiveStateMachine <States, Events>("Elevator"); elevator.AddExtension(new Extensions.Log4NetExtension <States, Events>("Elevator")); elevator.DefineHierarchyOn(States.Healthy, States.OnFloor, HistoryType.Deep, States.OnFloor, States.Moving); elevator.DefineHierarchyOn(States.Moving, States.MovingUp, HistoryType.Shallow, States.MovingUp, States.MovingDown); elevator.DefineHierarchyOn(States.OnFloor, States.DoorClosed, HistoryType.None, States.DoorClosed, States.DoorOpen); elevator.In(States.Healthy) .On(Events.ErrorOccured).Goto(States.Error); elevator.In(States.Error) .On(Events.Reset).Goto(States.Healthy); elevator.In(States.OnFloor) .ExecuteOnEntry(AnnounceFloor) .On(Events.CloseDoor).Goto(States.DoorClosed) .On(Events.OpenDoor).Goto(States.DoorOpen) .On(Events.GoUp) .If(CheckOverload).Goto(States.MovingUp) .Otherwise().Execute(AnnounceOverload) .On(Events.GoDown) .If(CheckOverload).Goto(States.MovingDown) .Otherwise().Execute(AnnounceOverload); elevator.In(States.Moving) .On(Events.Stop).Goto(States.OnFloor); elevator.Initialize(States.OnFloor); elevator.Fire(Events.ErrorOccured); elevator.Fire(Events.Reset); elevator.Start(); elevator.Fire(Events.OpenDoor); elevator.Fire(Events.CloseDoor); elevator.Fire(Events.GoUp); elevator.Fire(Events.Stop); elevator.Fire(Events.OpenDoor); elevator.Stop(); Console.ReadLine(); }
public void CommonAncestor( PassiveStateMachine <int, int> machine) { const int CommonAncestorState = 0; const int SourceState = 1; const int ParentOfSourceState = 2; const int SiblingOfSourceState = 3; const int DestinationState = 4; const int ParentOfDestinationState = 5; const int SiblingOfDestinationState = 6; const int Event = 0; bool commonAncestorStateLeft = false; "establish a hierarchical state machine"._(() => { machine = new PassiveStateMachine <int, int>(); machine.DefineHierarchyOn(CommonAncestorState) .WithHistoryType(HistoryType.None) .WithInitialSubState(ParentOfSourceState) .WithSubState(ParentOfDestinationState); machine.DefineHierarchyOn(ParentOfSourceState) .WithHistoryType(HistoryType.None) .WithInitialSubState(SourceState) .WithSubState(SiblingOfSourceState); machine.DefineHierarchyOn(ParentOfDestinationState) .WithHistoryType(HistoryType.None) .WithInitialSubState(DestinationState) .WithSubState(SiblingOfDestinationState); machine.In(SourceState) .On(Event).Goto(DestinationState); machine.In(CommonAncestorState) .ExecuteOnExit(() => commonAncestorStateLeft = true); machine.Initialize(SourceState); machine.Start(); }); "when firing an event resulting in a transition with a common ancestor"._(() => machine.Fire(Event)); "the state machine should remain inside common ancestor state"._(() => commonAncestorStateLeft .Should().BeFalse()); }
public void CommonAncestor( PassiveStateMachine<int, int> machine) { const int CommonAncestorState = 0; const int SourceState = 1; const int ParentOfSourceState = 2; const int SiblingOfSourceState = 3; const int DestinationState = 4; const int ParentOfDestinationState = 5; const int SiblingOfDestinationState = 6; const int Event = 0; bool commonAncestorStateLeft = false; "establish a hierarchical state machine"._(() => { machine = new PassiveStateMachine<int, int>(); machine.DefineHierarchyOn(CommonAncestorState) .WithHistoryType(HistoryType.None) .WithInitialSubState(ParentOfSourceState) .WithSubState(ParentOfDestinationState); machine.DefineHierarchyOn(ParentOfSourceState) .WithHistoryType(HistoryType.None) .WithInitialSubState(SourceState) .WithSubState(SiblingOfSourceState); machine.DefineHierarchyOn(ParentOfDestinationState) .WithHistoryType(HistoryType.None) .WithInitialSubState(DestinationState) .WithSubState(SiblingOfDestinationState); machine.In(SourceState) .On(Event).Goto(DestinationState); machine.In(CommonAncestorState) .ExecuteOnExit(() => commonAncestorStateLeft = true); machine.Initialize(SourceState); machine.Start(); }); "when firing an event resulting in a transition with a common ancestor"._(() => machine.Fire(Event)); "the state machine should remain inside common ancestor state"._(() => commonAncestorStateLeft .Should().BeFalse()); }
public void YEdGraphML() { var elevator = new PassiveStateMachine <States, Events>("Elevator"); elevator.DefineHierarchyOn(States.Healthy, States.OnFloor, HistoryType.Deep, States.OnFloor, States.Moving); elevator.DefineHierarchyOn(States.Moving, States.MovingUp, HistoryType.Shallow, States.MovingUp, States.MovingDown); elevator.DefineHierarchyOn(States.OnFloor, States.DoorClosed, HistoryType.None, States.DoorClosed, States.DoorOpen); elevator.In(States.Healthy) .On(Events.ErrorOccured).Goto(States.Error); elevator.In(States.Error) .On(Events.Reset).Goto(States.Healthy) .On(Events.ErrorOccured); elevator.In(States.OnFloor) .ExecuteOnEntry(AnnounceFloor) .ExecuteOnExit(Beep, Beep) .On(Events.CloseDoor).Goto(States.DoorClosed) .On(Events.OpenDoor).Goto(States.DoorOpen) .On(Events.GoUp) .If(CheckOverload).Goto(States.MovingUp) .Otherwise().Execute(AnnounceOverload, Beep) .On(Events.GoDown) .If(CheckOverload).Goto(States.MovingDown) .Otherwise().Execute(AnnounceOverload); elevator.In(States.Moving) .On(Events.Stop).Goto(States.OnFloor); elevator.Initialize(States.OnFloor); var stream = new MemoryStream(); var textWriter = new StreamWriter(stream); var testee = new YEdStateMachineReportGenerator <States, Events>(textWriter); elevator.Report(testee); stream.Position = 0; var reader = new StreamReader(stream); var report = reader.ReadToEnd(); const string ExpectedReport = "<?xml version=\"1.0\" encoding=\"utf-8\"?><graphml xmlns:y=\"http://www.yworks.com/xml/graphml\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:yed=\"http://www.yworks.com/xml/yed/3\" xmlns:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd\" xmlns=\"http://graphml.graphdrawing.org/xmlns\"> <!--Created by Appccelerate.StateMachine.YEdStateMachineReportGenerator--> <key for=\"graphml\" id=\"d0\" yfiles.type=\"resources\" /> <key for=\"port\" id=\"d1\" yfiles.type=\"portgraphics\" /> <key for=\"port\" id=\"d2\" yfiles.type=\"portgeometry\" /> <key for=\"port\" id=\"d3\" yfiles.type=\"portuserdata\" /> <key attr.name=\"url\" attr.type=\"string\" for=\"node\" id=\"d4\" /> <key attr.name=\"description\" attr.type=\"string\" for=\"node\" id=\"d5\" /> <key for=\"node\" id=\"d6\" yfiles.type=\"nodegraphics\" /> <key attr.name=\"Beschreibung\" attr.type=\"string\" for=\"graph\" id=\"d7\"> <default /> </key> <key attr.name=\"url\" attr.type=\"string\" for=\"edge\" id=\"d8\" /> <key attr.name=\"description\" attr.type=\"string\" for=\"edge\" id=\"d9\" /> <key for=\"edge\" id=\"d10\" yfiles.type=\"edgegraphics\" /> <graph edgedefault=\"directed\" id=\"G\"> <node id=\"Healthy\"> <data key=\"d6\"> <y:ProxyAutoBoundsNode> <y:Realizers active=\"0\"> <y:GroupNode> <y:NodeLabel alignment=\"right\" autoSizePolicy=\"node_width\" backgroundColor=\"#EBEBEB\" modelName=\"internal\" modelPosition=\"t\">Healthy</y:NodeLabel> <y:State closed=\"false\" innerGraphDisplayEnabled=\"true\" /> </y:GroupNode> </y:Realizers> </y:ProxyAutoBoundsNode> </data> <graph edgedefault=\"directed\" id=\"Healthy:\"> <node id=\"OnFloor\"> <data key=\"d6\"> <y:ProxyAutoBoundsNode> <y:Realizers active=\"0\"> <y:GroupNode> <y:NodeLabel alignment=\"right\" autoSizePolicy=\"node_width\" backgroundColor=\"#EBEBEB\" modelName=\"internal\" modelPosition=\"t\">(AnnounceFloor)OnFloor(Beep, Beep)</y:NodeLabel> <y:State closed=\"false\" innerGraphDisplayEnabled=\"true\" /> <y:BorderStyle width=\"2.0\" /> </y:GroupNode> </y:Realizers> </y:ProxyAutoBoundsNode> </data> <graph edgedefault=\"directed\" id=\"OnFloor:\"> <node id=\"DoorClosed\"> <data key=\"d6\"> <y:ShapeNode> <y:NodeLabel>DoorClosed</y:NodeLabel> <y:Shape type=\"ellipse\" /> <y:BorderStyle width=\"2.0\" /> </y:ShapeNode> </data> </node> <node id=\"DoorOpen\"> <data key=\"d6\"> <y:ShapeNode> <y:NodeLabel>DoorOpen</y:NodeLabel> <y:Shape type=\"ellipse\" /> </y:ShapeNode> </data> </node> </graph> </node> <node id=\"Moving\"> <data key=\"d6\"> <y:ProxyAutoBoundsNode> <y:Realizers active=\"0\"> <y:GroupNode> <y:NodeLabel alignment=\"right\" autoSizePolicy=\"node_width\" backgroundColor=\"#EBEBEB\" modelName=\"internal\" modelPosition=\"t\">Moving</y:NodeLabel> <y:State closed=\"false\" innerGraphDisplayEnabled=\"true\" /> </y:GroupNode> </y:Realizers> </y:ProxyAutoBoundsNode> </data> <graph edgedefault=\"directed\" id=\"Moving:\"> <node id=\"MovingUp\"> <data key=\"d6\"> <y:ShapeNode> <y:NodeLabel>MovingUp</y:NodeLabel> <y:Shape type=\"ellipse\" /> <y:BorderStyle width=\"2.0\" /> </y:ShapeNode> </data> </node> <node id=\"MovingDown\"> <data key=\"d6\"> <y:ShapeNode> <y:NodeLabel>MovingDown</y:NodeLabel> <y:Shape type=\"ellipse\" /> </y:ShapeNode> </data> </node> </graph> </node> </graph> </node> <node id=\"Error\"> <data key=\"d6\"> <y:ShapeNode> <y:NodeLabel>Error</y:NodeLabel> <y:Shape type=\"ellipse\" /> </y:ShapeNode> </data> </node> <edge id=\"CloseDoor0\" source=\"OnFloor\" target=\"DoorClosed\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>CloseDoor</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"OpenDoor1\" source=\"OnFloor\" target=\"DoorOpen\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>OpenDoor</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"GoUp2\" source=\"OnFloor\" target=\"MovingUp\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>[CheckOverload]GoUp</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"GoUp3\" source=\"OnFloor\" target=\"OnFloor\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"dashed\" /> <y:Arrows source=\"none\" target=\"plain\" /> <y:EdgeLabel>GoUp(AnnounceOverload, Beep)</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"GoDown4\" source=\"OnFloor\" target=\"MovingDown\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>[CheckOverload]GoDown</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"GoDown5\" source=\"OnFloor\" target=\"OnFloor\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"dashed\" /> <y:Arrows source=\"none\" target=\"plain\" /> <y:EdgeLabel>GoDown(AnnounceOverload)</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"Stop6\" source=\"Moving\" target=\"OnFloor\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>Stop</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"ErrorOccured7\" source=\"Healthy\" target=\"Error\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>ErrorOccured</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"Reset8\" source=\"Error\" target=\"Healthy\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>Reset</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"ErrorOccured9\" source=\"Error\" target=\"Error\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"dashed\" /> <y:Arrows source=\"none\" target=\"plain\" /> <y:EdgeLabel>ErrorOccured</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> </graph> <data key=\"d0\"> <y:Resources /> </data></graphml>"; var cleanedReport = report.Replace("\n", string.Empty).Replace("\r", string.Empty); cleanedReport.Should().Be(ExpectedReport.Replace("\n", string.Empty).Replace("\r", string.Empty)); }
private void createStateMachine() { fsm = new PassiveStateMachine <States, Events>(); fsm.In(States.Edit) .On(Events.InventoryKey).Goto(States.Inventory) .On(Events.PlayKey).Goto(States.Play); fsm.In(States.Inventory).On(Events.InventoryKey).Goto(States.Edit); fsm.In(States.Play).On(Events.PlayKey).Goto(States.Edit); foreach (var s in Enum.GetValues(typeof(States)).Cast <States>()) { fsm.In(s).ExecuteOnEntry(new Action(() => ActiveState = s)); } fsm.Initialize(States.Edit); }
public void BeforeExecutingEntryActionsHierarchical( PassiveStateMachine <string, string> machine, IExtension <string, string> extension) { "establish an extension".x(() => extension = A.Fake <IExtension <string, string> >()); "establish a hierarchical state machine using the extension".x(() => { machine = new PassiveStateMachine <string, string>(Name); machine.AddExtension(extension); machine.DefineHierarchyOn("A") .WithHistoryType(HistoryType.None) .WithInitialSubState("A0"); machine.In("0") .On("A0").Goto("A0"); machine.Initialize("0"); machine.Start(); }); "when firing an event onto the state machine".x(() => machine.Fire("A0")); "it should call EnteringState on registered extensions for entered super states of target state".x(() => A.CallTo(() => extension.EnteringState( A <IStateMachineInformation <string, string> > .That.Matches(x => x.Name == Name && x.CurrentStateId == "A0"), A <IState <string, string> > .That.Matches(x => x.Id == "A"), A <ITransitionContext <string, string> > .That.Matches(x => x.EventId.Value == "A0"))) .MustHaveHappened()); "it should call EnteringState on registered extensions for entered leaf target state".x(() => A.CallTo(() => extension.EnteringState( A <IStateMachineInformation <string, string> > .That.Matches(x => x.Name == Name && x.CurrentStateId == "A0"), A <IState <string, string> > .That.Matches(x => x.Id == "A0"), A <ITransitionContext <string, string> > .That.Matches(x => x.EventId.Value == "A0"))) .MustHaveHappened()); }
public void ExecutingTransition( PassiveStateMachine <int, int> machine, string actualParameter, bool exitActionExecuted, bool entryActionExecuted) { "establish a state machine with transitions".x(() => { machine = new PassiveStateMachine <int, int>(); machine.AddExtension(CurrentStateExtension); machine.In(SourceState) .ExecuteOnExit(() => exitActionExecuted = true) .On(Event).Goto(DestinationState).Execute <string>(p => actualParameter = p); machine.In(DestinationState) .ExecuteOnEntry(() => entryActionExecuted = true); machine.Initialize(SourceState); machine.Start(); }); "when firing an event onto the state machine".x(() => machine.Fire(Event, Parameter)); "it should_execute_transition_by_switching_state".x(() => CurrentStateExtension.CurrentState.Should().Be(DestinationState)); "it should_execute_transition_actions".x(() => actualParameter.Should().NotBeNull()); "it should_pass_parameters_to_transition_action".x(() => actualParameter.Should().Be(Parameter)); "it should_execute_exit_action_of_source_state".x(() => exitActionExecuted.Should().BeTrue()); "it should_execute_entry_action_of_destination_state".x(() => entryActionExecuted.Should().BeTrue()); }
public void ExecutingTransition( PassiveStateMachine<int, int> machine, string actualParameter, bool exitActionExecuted, bool entryActionExecuted) { "establish a state machine with transitions"._(() => { machine = new PassiveStateMachine<int, int>(); machine.AddExtension(CurrentStateExtension); machine.In(SourceState) .ExecuteOnExit(() => exitActionExecuted = true) .On(Event).Goto(DestinationState).Execute<string>(p => actualParameter = p); machine.In(DestinationState) .ExecuteOnEntry(() => entryActionExecuted = true); machine.Initialize(SourceState); machine.Start(); }); "when firing an event onto the state machine"._(() => machine.Fire(Event, Parameter)); "it should_execute_transition_by_switching_state"._(() => CurrentStateExtension.CurrentState.Should().Be(DestinationState)); "it should_execute_transition_actions"._(() => actualParameter.Should().NotBeNull()); "it should_pass_parameters_to_transition_action"._(() => actualParameter.Should().Be(Parameter)); "it should_execute_exit_action_of_source_state"._(() => exitActionExecuted.Should().BeTrue()); "it should_execute_entry_action_of_destination_state"._(() => entryActionExecuted.Should().BeTrue()); }
public void LoadingAnInitializedStateMachine( PassiveStateMachine <string, int> machine, Exception receivedException) { "establish an initialized state machine".x(() => { machine = new PassiveStateMachine <string, int>(); machine.Initialize("initial"); }); "when state machine is loaded".x(() => { receivedException = Catch.Exception(() => machine.Load(A.Fake <IStateMachineLoader <string> >())); }); "it should throw invalid operation exception".x(() => { receivedException.Should().BeOfType <InvalidOperationException>(); receivedException.Message.Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized); }); }
public ApplicationStateMachine(ApplicationCommands commands) { // in uninitialized state _fsm.In(ApplicationState.Uninitialized) .On(ApplicationStateEvent.ChangeVideoDevice) .Goto(ApplicationState.Uninitialized); _fsm.In(ApplicationState.Uninitialized) .On(ApplicationStateEvent.Start) .Goto(ApplicationState.Running) .Execute(commands.StartFaceDetection); _fsm.In(ApplicationState.Uninitialized) .On(ApplicationStateEvent.Stop) .Goto(ApplicationState.Uninitialized); // in running state _fsm.In(ApplicationState.Running) .On(ApplicationStateEvent.ChangeVideoDevice) .Goto(ApplicationState.Running) .Execute(commands.ChangeVideoCaptureDevice); _fsm.In(ApplicationState.Running) .On(ApplicationStateEvent.Stop) .Goto(ApplicationState.Terminated) .Execute(commands.StopFaceDetection); _fsm.In(ApplicationState.Running) .On(ApplicationStateEvent.Start) .Goto(ApplicationState.Running); // in terminated state _fsm.In(ApplicationState.Terminated) .On(ApplicationStateEvent.ChangeVideoDevice) .Goto(ApplicationState.Terminated); _fsm.In(ApplicationState.Terminated) .On(ApplicationStateEvent.Stop) .Goto(ApplicationState.Terminated); _fsm.In(ApplicationState.Terminated) .On(ApplicationStateEvent.Start) .Goto(ApplicationState.Running) .Execute(commands.StartFaceDetection); _fsm.Initialize(ApplicationState.Uninitialized); _fsm.Start(); }
/// <summary> /// Constructor /// </summary> /// <param name="objective"></param> /// <param name="tier"></param> public BattlefieldObjective(RegionMgr region, BattleFront_Objective objective) { Id = objective.Entry; Name = objective.Name; ZoneId = objective.ZoneId; RegionId = objective.RegionId; Tier = (byte)region.GetTier(); State = StateFlags.Unsecure; _x = (uint)objective.X; _y = (uint)objective.Y; _z = (ushort)objective.Z; _o = (ushort)objective.O; _tokdiscovery = objective.TokDiscovered; _tokunlocked = objective.TokUnlocked; Heading = _o; WorldPosition.X = (int)_x; WorldPosition.Y = (int)_y; WorldPosition.Z = _z; CommsEngine = new ApocCommunications(); RewardManager = new RVRRewardManager(); fsm = new CampaignObjectiveStateMachine(this).fsm; fsm.Initialize(CampaignObjectiveStateMachine.ProcessState.Neutral); if (objective.Guards != null) { foreach (BattleFront_Guard Guard in objective.Guards) { Guards.Add(new FlagGuard(this, region, objective.ZoneId, Guard.OrderId, Guard.DestroId, Guard.X, Guard.Y, Guard.Z, Guard.O)); } } _captureProgress = 20000; CaptureDuration = 10; EvtInterface.AddEvent(CheckTimers, 1000, 0); BuffId = 0; }
private PassiveStateMachine <States, Events> createStateMachine(Timer timer) { var fsm = new PassiveStateMachine <States, Events>(); fsm.AddExtension(new ConsoleLoggingExtension <States, Events>()); fsm.Initialize(States.None); fsm.In(States.None).On(Events.SingleSlotPressed).Goto(States.Holding); fsm.In(States.Holding).ExecuteOnEntry(timer.Start); fsm.In(States.Holding).ExecuteOnExit(timer.Stop); fsm.In(States.Holding) .On(Events.MultipleSlotPressed).Goto(States.None); fsm.In(States.Holding) .On(Events.NoSlotPressed).Goto(States.None); fsm.In(States.Holding) .On(Events.Timer).Goto(States.Complete).Execute(SelectTargetedInventoryItem); fsm.In(States.Complete).On(Events.NoSlotPressed).Goto(States.None); return(fsm); }
public static void Main() { // configure basic logging (all levels enabled, messages are written to the console) log4net.Config.BasicConfigurator.Configure(); var elevator = new PassiveStateMachine<States, Events>("Elevator"); elevator.AddExtension(new Extensions.Log4NetExtension<States, Events>("Elevator")); elevator.DefineHierarchyOn(States.Healthy, States.OnFloor, HistoryType.Deep, States.OnFloor, States.Moving); elevator.DefineHierarchyOn(States.Moving, States.MovingUp, HistoryType.Shallow, States.MovingUp, States.MovingDown); elevator.DefineHierarchyOn(States.OnFloor, States.DoorClosed, HistoryType.None, States.DoorClosed, States.DoorOpen); elevator.In(States.Healthy) .On(Events.ErrorOccured).Goto(States.Error); elevator.In(States.Error) .On(Events.Reset).Goto(States.Healthy); elevator.In(States.OnFloor) .ExecuteOnEntry(AnnounceFloor) .On(Events.CloseDoor).Goto(States.DoorClosed) .On(Events.OpenDoor).Goto(States.DoorOpen) .On(Events.GoUp) .If(CheckOverload).Goto(States.MovingUp) .Otherwise().Execute(AnnounceOverload) .On(Events.GoDown) .If(CheckOverload).Goto(States.MovingDown) .Otherwise().Execute(AnnounceOverload); elevator.In(States.Moving) .On(Events.Stop).Goto(States.OnFloor); elevator.Initialize(States.OnFloor); elevator.Fire(Events.ErrorOccured); elevator.Fire(Events.Reset); elevator.Start(); elevator.Fire(Events.OpenDoor); elevator.Fire(Events.CloseDoor); elevator.Fire(Events.GoUp); elevator.Fire(Events.Stop); elevator.Fire(Events.OpenDoor); elevator.Stop(); Console.ReadLine(); }
public void NoCommonAncestor( PassiveStateMachine<string, int> machine) { const string SourceState = "SourceState"; const string ParentOfSourceState = "ParentOfSourceState"; const string SiblingOfSourceState = "SiblingOfSourceState"; const string DestinationState = "DestinationState"; const string ParentOfDestinationState = "ParentOfDestinationState"; const string SiblingOfDestinationState = "SiblingOfDestinationState"; const string GrandParentOfSourceState = "GrandParentOfSourceState"; const string GrandParentOfDestinationState = "GrandParentOfDestinationState"; const int Event = 0; string log = string.Empty; "establish a hierarchical state machine"._(() => { machine = new PassiveStateMachine<string, int>(); machine.DefineHierarchyOn(ParentOfSourceState) .WithHistoryType(HistoryType.None) .WithInitialSubState(SourceState) .WithSubState(SiblingOfSourceState); machine.DefineHierarchyOn(ParentOfDestinationState) .WithHistoryType(HistoryType.None) .WithInitialSubState(DestinationState) .WithSubState(SiblingOfDestinationState); machine.DefineHierarchyOn(GrandParentOfSourceState) .WithHistoryType(HistoryType.None) .WithInitialSubState(ParentOfSourceState); machine.DefineHierarchyOn(GrandParentOfDestinationState) .WithHistoryType(HistoryType.None) .WithInitialSubState(ParentOfDestinationState); machine.In(SourceState) .ExecuteOnExit(() => log += "exit" + SourceState) .On(Event).Goto(DestinationState); machine.In(ParentOfSourceState) .ExecuteOnExit(() => log += "exit" + ParentOfSourceState); machine.In(DestinationState) .ExecuteOnEntry(() => log += "enter" + DestinationState); machine.In(ParentOfDestinationState) .ExecuteOnEntry(() => log += "enter" + ParentOfDestinationState); machine.In(GrandParentOfSourceState) .ExecuteOnExit(() => log += "exit" + GrandParentOfSourceState); machine.In(GrandParentOfDestinationState) .ExecuteOnEntry(() => log += "enter" + GrandParentOfDestinationState); machine.Initialize(SourceState); machine.Start(); }); "when firing an event resulting in a transition without a common ancestor"._(() => machine.Fire(Event)); "it should execute exit action of source state"._(() => log.Should().Contain("exit" + SourceState)); "it should execute exit action of parents of source state (recursively)"._(() => log .Should().Contain("exit" + ParentOfSourceState) .And.Contain("exit" + GrandParentOfSourceState)); "it should execute entry action of parents of destination state (recursively)"._(() => log.Should().Contain("enter" + ParentOfDestinationState) .And.Contain("enter" + GrandParentOfDestinationState)); "it should execute entry action of destination state"._(() => log.Should().Contain("enter" + DestinationState)); "it should execute actions from source upwards and then downwards to destination state"._(() => { string[] states = { SourceState, ParentOfSourceState, GrandParentOfSourceState, GrandParentOfDestinationState, ParentOfDestinationState, DestinationState }; var statesInOrderOfAppearanceInLog = states .OrderBy(s => log.IndexOf(s.ToString(CultureInfo.InvariantCulture), StringComparison.Ordinal)); statesInOrderOfAppearanceInLog .Should().Equal(states); }); }
public void YEdGraphML() { var elevator = new PassiveStateMachine<States, Events>("Elevator"); elevator.DefineHierarchyOn(States.Healthy) .WithHistoryType(HistoryType.Deep) .WithInitialSubState(States.OnFloor) .WithSubState(States.Moving); elevator.DefineHierarchyOn(States.Moving) .WithHistoryType(HistoryType.Shallow) .WithInitialSubState(States.MovingUp) .WithSubState(States.MovingDown); elevator.DefineHierarchyOn(States.OnFloor) .WithHistoryType(HistoryType.None) .WithInitialSubState(States.DoorClosed) .WithSubState(States.DoorOpen); elevator.In(States.Healthy) .On(Events.ErrorOccured).Goto(States.Error); elevator.In(States.Error) .On(Events.Reset).Goto(States.Healthy) .On(Events.ErrorOccured); elevator.In(States.OnFloor) .ExecuteOnEntry(AnnounceFloor) .ExecuteOnExit(Beep) .ExecuteOnExit(Beep) .On(Events.CloseDoor).Goto(States.DoorClosed) .On(Events.OpenDoor).Goto(States.DoorOpen) .On(Events.GoUp) .If(CheckOverload).Goto(States.MovingUp) .Otherwise() .Execute(AnnounceOverload) .Execute(Beep) .On(Events.GoDown) .If(CheckOverload).Goto(States.MovingDown) .Otherwise().Execute(AnnounceOverload); elevator.In(States.Moving) .On(Events.Stop).Goto(States.OnFloor); elevator.Initialize(States.OnFloor); var stream = new MemoryStream(); var textWriter = new StreamWriter(stream); var testee = new YEdStateMachineReportGenerator<States, Events>(textWriter); elevator.Report(testee); stream.Position = 0; var reader = new StreamReader(stream); var report = reader.ReadToEnd(); const string ExpectedReport = "<?xml version=\"1.0\" encoding=\"utf-8\"?><graphml xmlns:y=\"http://www.yworks.com/xml/graphml\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:yed=\"http://www.yworks.com/xml/yed/3\" xmlns:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd\" xmlns=\"http://graphml.graphdrawing.org/xmlns\"> <!--Created by Appccelerate.StateMachine.YEdStateMachineReportGenerator--> <key for=\"graphml\" id=\"d0\" yfiles.type=\"resources\" /> <key for=\"port\" id=\"d1\" yfiles.type=\"portgraphics\" /> <key for=\"port\" id=\"d2\" yfiles.type=\"portgeometry\" /> <key for=\"port\" id=\"d3\" yfiles.type=\"portuserdata\" /> <key attr.name=\"url\" attr.type=\"string\" for=\"node\" id=\"d4\" /> <key attr.name=\"description\" attr.type=\"string\" for=\"node\" id=\"d5\" /> <key for=\"node\" id=\"d6\" yfiles.type=\"nodegraphics\" /> <key attr.name=\"Beschreibung\" attr.type=\"string\" for=\"graph\" id=\"d7\"> <default /> </key> <key attr.name=\"url\" attr.type=\"string\" for=\"edge\" id=\"d8\" /> <key attr.name=\"description\" attr.type=\"string\" for=\"edge\" id=\"d9\" /> <key for=\"edge\" id=\"d10\" yfiles.type=\"edgegraphics\" /> <graph edgedefault=\"directed\" id=\"G\"> <node id=\"Healthy\"> <data key=\"d6\"> <y:ProxyAutoBoundsNode> <y:Realizers active=\"0\"> <y:GroupNode> <y:NodeLabel alignment=\"right\" autoSizePolicy=\"node_width\" backgroundColor=\"#EBEBEB\" modelName=\"internal\" modelPosition=\"t\">Healthy</y:NodeLabel> <y:State closed=\"false\" innerGraphDisplayEnabled=\"true\" /> </y:GroupNode> </y:Realizers> </y:ProxyAutoBoundsNode> </data> <graph edgedefault=\"directed\" id=\"Healthy:\"> <node id=\"OnFloor\"> <data key=\"d6\"> <y:ProxyAutoBoundsNode> <y:Realizers active=\"0\"> <y:GroupNode> <y:NodeLabel alignment=\"right\" autoSizePolicy=\"node_width\" backgroundColor=\"#EBEBEB\" modelName=\"internal\" modelPosition=\"t\">(AnnounceFloor)OnFloor(Beep, Beep)</y:NodeLabel> <y:State closed=\"false\" innerGraphDisplayEnabled=\"true\" /> <y:BorderStyle width=\"2.0\" /> </y:GroupNode> </y:Realizers> </y:ProxyAutoBoundsNode> </data> <graph edgedefault=\"directed\" id=\"OnFloor:\"> <node id=\"DoorClosed\"> <data key=\"d6\"> <y:ShapeNode> <y:NodeLabel>DoorClosed</y:NodeLabel> <y:Shape type=\"ellipse\" /> <y:BorderStyle width=\"2.0\" /> </y:ShapeNode> </data> </node> <node id=\"DoorOpen\"> <data key=\"d6\"> <y:ShapeNode> <y:NodeLabel>DoorOpen</y:NodeLabel> <y:Shape type=\"ellipse\" /> </y:ShapeNode> </data> </node> </graph> </node> <node id=\"Moving\"> <data key=\"d6\"> <y:ProxyAutoBoundsNode> <y:Realizers active=\"0\"> <y:GroupNode> <y:NodeLabel alignment=\"right\" autoSizePolicy=\"node_width\" backgroundColor=\"#EBEBEB\" modelName=\"internal\" modelPosition=\"t\">Moving</y:NodeLabel> <y:State closed=\"false\" innerGraphDisplayEnabled=\"true\" /> </y:GroupNode> </y:Realizers> </y:ProxyAutoBoundsNode> </data> <graph edgedefault=\"directed\" id=\"Moving:\"> <node id=\"MovingUp\"> <data key=\"d6\"> <y:ShapeNode> <y:NodeLabel>MovingUp</y:NodeLabel> <y:Shape type=\"ellipse\" /> <y:BorderStyle width=\"2.0\" /> </y:ShapeNode> </data> </node> <node id=\"MovingDown\"> <data key=\"d6\"> <y:ShapeNode> <y:NodeLabel>MovingDown</y:NodeLabel> <y:Shape type=\"ellipse\" /> </y:ShapeNode> </data> </node> </graph> </node> </graph> </node> <node id=\"Error\"> <data key=\"d6\"> <y:ShapeNode> <y:NodeLabel>Error</y:NodeLabel> <y:Shape type=\"ellipse\" /> </y:ShapeNode> </data> </node> <edge id=\"ErrorOccured0\" source=\"Healthy\" target=\"Error\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>ErrorOccured</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"CloseDoor1\" source=\"OnFloor\" target=\"DoorClosed\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>CloseDoor</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"OpenDoor2\" source=\"OnFloor\" target=\"DoorOpen\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>OpenDoor</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"GoUp3\" source=\"OnFloor\" target=\"MovingUp\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>[CheckOverload]GoUp</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"GoUp4\" source=\"OnFloor\" target=\"OnFloor\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"dashed\" /> <y:Arrows source=\"none\" target=\"plain\" /> <y:EdgeLabel>GoUp(AnnounceOverload, Beep)</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"GoDown5\" source=\"OnFloor\" target=\"MovingDown\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>[CheckOverload]GoDown</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"GoDown6\" source=\"OnFloor\" target=\"OnFloor\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"dashed\" /> <y:Arrows source=\"none\" target=\"plain\" /> <y:EdgeLabel>GoDown(AnnounceOverload)</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"Stop7\" source=\"Moving\" target=\"OnFloor\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>Stop</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"Reset8\" source=\"Error\" target=\"Healthy\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"line\" /> <y:Arrows source=\"none\" target=\"standard\" /> <y:EdgeLabel>Reset</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> <edge id=\"ErrorOccured9\" source=\"Error\" target=\"Error\"> <data key=\"d10\"> <y:PolyLineEdge> <y:LineStyle type=\"dashed\" /> <y:Arrows source=\"none\" target=\"plain\" /> <y:EdgeLabel>ErrorOccured</y:EdgeLabel> </y:PolyLineEdge> </data> </edge> </graph> <data key=\"d0\"> <y:Resources /> </data></graphml>"; var cleanedReport = report.Replace("\n", string.Empty).Replace("\r", string.Empty); cleanedReport.Should().Be(ExpectedReport.Replace("\n", string.Empty).Replace("\r", string.Empty)); }
public void PriorityEventsQueueing( IStateMachine<string, int> machine) { const int FirstEvent = 0; const int SecondEvent = 1; bool arrived = false; "establish a passive state machine with transitions"._(() => { machine = new PassiveStateMachine<string, int>(); machine.In("A").On(SecondEvent).Goto("B"); machine.In("B").On(FirstEvent).Goto("C"); machine.In("C").ExecuteOnEntry(() => arrived = true); machine.Initialize("A"); }); "when firing a priority event onto the state machine"._(() => { machine.Fire(FirstEvent); machine.FirePriority(SecondEvent); machine.Start(); }); "it should queue event at the front"._(() => arrived.Should().BeTrue("state machine should arrive at destination state")); }
public Robot() { #region State machine definition StateMachine.In(State.NotInitialized) .On(Triggers.InitializationStarts).Goto(State.Initializing); StateMachine.In(State.Initializing) .On(Triggers.InitializationEnds).Goto(State.PowerOn); StateMachine.In(State.PowerOn) .On(Triggers.ExecutionStarts).Goto(State.Processing); StateMachine.In(State.Processing) .On(Triggers.ExecutionEnds).Goto(State.PowerOn); StateMachine.In(State.AxesIdle) .On(Triggers.AxesBusy).Goto(State.AxesMoving); StateMachine.In(State.AxesMoving) .On(Triggers.AxesStop).Goto(State.AxesIdle); StateMachine.In(State.PowerOn) .On(Triggers.PowerOff).Goto(State.PoweringOff); StateMachine.In(State.PowerOff) .On(Triggers.PowerOn).Goto(State.PoweringOn); StateMachine.In(State.PoweringOff) .On(Triggers.PowerOffReady).Goto(State.PowerOff); StateMachine.In(State.PoweringOn) .On(Triggers.PowerOnReady).Goto(State.PowerOn); StateMachine.In(State.Error) .On(Triggers.InitializationStarts).Goto(State.Initializing); StateMachine.In(State.Ready) .On(Triggers.Error).Goto(State.Error); StateMachine.In(State.Down) .On(Triggers.Error).Goto(State.Error); StateMachine.In(State.Idle) .On(Triggers.Deinitialize).Goto(State.NotInitialized); StateMachine.DefineHierarchyOn(State.Processing) .WithHistoryType(HistoryType.None) .WithInitialSubState(State.AxesMoving) .WithSubState(State.AxesIdle); StateMachine.DefineHierarchyOn(State.Idle) .WithHistoryType(HistoryType.None) .WithInitialSubState(State.PowerOn) .WithSubState(State.PowerOff) .WithSubState(State.PoweringOff) .WithSubState(State.PoweringOn); StateMachine.DefineHierarchyOn(State.Ready) .WithHistoryType(HistoryType.Deep) .WithInitialSubState(State.Idle) .WithSubState(State.Processing); StateMachine.DefineHierarchyOn(State.Down) .WithHistoryType(HistoryType.None) .WithInitialSubState(State.NotInitialized) .WithSubState(State.Initializing) .WithSubState(State.Error); StateMachine.Initialize(State.NotInitialized); StateMachine.Start(); StateMachine.TransitionCompleted += MyStateMachine_TransitionCompleted; using (Stream stream = File.Open("StateDiagram.graphml", FileMode.Create, FileAccess.Write, FileShare.Read)) using (TextWriter writer = new StreamWriter(stream)) { var generator = new YEdStateMachineReportGenerator <State, Triggers>(writer); StateMachine.Report(generator); } StateMachine.Report(customReporter); }
public void OtherwiseGuard( PassiveStateMachine<int, int> machine, CurrentStateExtension currentStateExtension) { "establish a state machine with otherwise guard and no machting other guard"._(() => { machine = new PassiveStateMachine<int, int>(); currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); machine.In(SourceState) .On(Event) .If(() => false).Goto(ErrorState) .Otherwise().Goto(DestinationState); machine.Initialize(SourceState); machine.Start(); }); "when an event is fired"._(() => machine.Fire(Event)); "it should_take_transition_guarded_with_otherwise"._(() => currentStateExtension.CurrentState.Should().Be(DestinationState)); }
public void Start( PassiveStateMachine<int, int> machine, bool entryActionExecuted) { "establish an initialized state machine"._(() => { machine = new PassiveStateMachine<int, int>(); machine.AddExtension(this.testExtension); machine.In(TestState) .ExecuteOnEntry(() => entryActionExecuted = true); machine.Initialize(TestState); }); "when starting the state machine"._(() => machine.Start()); "should set current state of state machine to state to which it is initialized"._(() => this.testExtension.CurrentState.Should().Be(TestState)); "should execute entry action of state to which state machine is initialized"._(() => entryActionExecuted.Should().BeTrue()); }
public SpeechInteraction(Hpi.Hci.Bachelorproject1617.PhotoBooth.MainWindow mainWindow, SpeechSynthesizer reader) { this.mainWindow = mainWindow; this.reader = reader; this.reader.SpeakStarted += reader_SpeakStarted; this.reader.SpeakCompleted += reader_SpeakCompleted; //SpeakText(@"Welcome to this magical Kinect Photobooth, the camera that produces tactile snapshots of your gestures. If you want a picture just position yourself 1 meter in front of the Kinect-Camera and spread your arms away from you to get recognized"); //SpeakText(@"Hey there, if you want a tactile snapshot of your gesture just position yourself 1 meter in front of the Kinect-Camera and spread your arms away from you to get recognized. I can detect two persons at the time so get a mate and let's go"); fsm = new PassiveStateMachine <ProcessState, Command>(); fsm.In(ProcessState.NoPersonRecognized) .On(Command.Repeat).Execute(() => { SpeakText(NoPersonRecognizedRepeat); StartTimer(35000); }) //reader.Speak(NoPersonRecognizedRepeat) .On(Command.FramesReady).Goto(ProcessState.PersonRecognized).Execute(() => { SpeakText(PersonRecognizedTransition); Console.WriteLine("Frames ready"); StartTimer(35000); }).On(Command.Test).Goto(ProcessState.PictureTaken); fsm.In(ProcessState.PersonRecognized) .On(Command.Repeat).Execute(() => { SpeakText(PersonRecognizedRepeat); StartTimer(35000); }) .On(Command.FramesNotReady).Goto(ProcessState.NoPersonRecognized).Execute(() => { SpeakText(PersonLeft); Console.WriteLine("Frames not ready"); StartTimer(35000); }) .On(Command.Outlines).Goto(ProcessState.PictureTaken).Execute(() => { outlines = true; new Thread(PreparePicture).Start(); StartTimer(45000); }) .On(Command.Skeleton).Goto(ProcessState.PictureTaken).Execute(() => { outlines = false; new Thread(PreparePicture).Start(); StartTimer(45000); }); fsm.In(ProcessState.PictureTaken) .On(Command.Print).Goto(ProcessState.Connected).Execute(() => { SpeakText(ConnectingString); if (mainWindow.BluetoothOn) { mainWindow.BluetoothConnect(); } else { fsm.Fire(Command.Connected); } }) .On(Command.Yes).Goto(ProcessState.Connected).Execute(() => { SpeakText(ConnectingString); if (mainWindow.BluetoothOn) { mainWindow.BluetoothConnect(); } else { fsm.Fire(Command.Connected); } }) .On(Command.Repeat).Execute(() => { SpeakText(PictureTakenRepeat); StartTimer(35000); }) .On(Command.Back).Goto(ProcessState.PersonRecognized).Execute(() => { SpeakText(BackToPersonRecognized); mainWindow.pictureTaken = false; mainWindow.AlreadyConvertedToSVG = false; StartTimer(35000); }); fsm.In(ProcessState.Connected) .On(Command.Connected).Goto(ProcessState.Printed).Execute(() => { SpeakText(PrintingString); if (mainWindow.BluetoothOn) { mainWindow.SendSvgBluetooth(mainWindow.svgImage); } else { mainWindow.SendSvgTCP(mainWindow.svgImage); } }); fsm.In(ProcessState.Printed) .On(Command.Printed).Goto(ProcessState.NoPersonRecognized).Execute(() => { SpeakText(PrintedString); }); fsm.In(ProcessState.Connected); fsm.Initialize(ProcessState.NoPersonRecognized); fsm.Start(); StartTimer(35000); }
public void Report() { var elevator = new PassiveStateMachine<States, Events>("Elevator"); elevator.DefineHierarchyOn(States.Healthy) .WithHistoryType(HistoryType.Deep) .WithInitialSubState(States.OnFloor) .WithSubState(States.Moving); elevator.DefineHierarchyOn(States.Moving) .WithHistoryType(HistoryType.Shallow) .WithInitialSubState(States.MovingUp) .WithSubState(States.MovingDown); elevator.DefineHierarchyOn(States.OnFloor) .WithHistoryType(HistoryType.None) .WithInitialSubState(States.DoorClosed) .WithSubState(States.DoorOpen); elevator.In(States.Healthy) .On(Events.ErrorOccured).Goto(States.Error); elevator.In(States.Error) .On(Events.Reset).Goto(States.Healthy) .On(Events.ErrorOccured); elevator.In(States.OnFloor) .ExecuteOnEntry(AnnounceFloor) .ExecuteOnExit(Beep) .ExecuteOnExit(Beep) .On(Events.CloseDoor).Goto(States.DoorClosed) .On(Events.OpenDoor).Goto(States.DoorOpen) .On(Events.GoUp) .If(CheckOverload).Goto(States.MovingUp) .Otherwise() .Execute(AnnounceOverload) .Execute(Beep) .On(Events.GoDown) .If(CheckOverload).Goto(States.MovingDown) .Otherwise().Execute(AnnounceOverload); elevator.In(States.Moving) .On(Events.Stop).Goto(States.OnFloor); elevator.Initialize(States.OnFloor); elevator.Report(this.testee); string statesReport; string transitionsReport; this.stateStream.Position = 0; using (var reader = new StreamReader(this.stateStream)) { statesReport = reader.ReadToEnd(); } this.transitionsStream.Position = 0; using (var reader = new StreamReader(this.transitionsStream)) { transitionsReport = reader.ReadToEnd(); } const string ExpectedTransitionsReport = "Source;Event;Guard;Target;ActionsHealthy;ErrorOccured;;Error;OnFloor;CloseDoor;;DoorClosed;OnFloor;OpenDoor;;DoorOpen;OnFloor;GoUp;CheckOverload;MovingUp;OnFloor;GoUp;;internal transition;AnnounceOverload, BeepOnFloor;GoDown;CheckOverload;MovingDown;OnFloor;GoDown;;internal transition;AnnounceOverloadMoving;Stop;;OnFloor;Error;Reset;;Healthy;Error;ErrorOccured;;internal transition;"; const string ExpectedStatesReport = "Source;Entry;Exit;ChildrenHealthy;;;OnFloor, MovingOnFloor;AnnounceFloor;Beep, Beep;DoorClosed, DoorOpenMoving;;;MovingUp, MovingDownMovingUp;;;MovingDown;;;DoorClosed;;;DoorOpen;;;Error;;;"; statesReport.Replace("\n", string.Empty).Replace("\r", string.Empty) .Should().Be(ExpectedStatesReport.Replace("\n", string.Empty).Replace("\r", string.Empty)); transitionsReport.Replace("\n", string.Empty).Replace("\r", string.Empty) .Should().Be(ExpectedTransitionsReport.Replace("\n", string.Empty).Replace("\r", string.Empty)); }
public void Reinitialization( PassiveStateMachine<int, int> machine, Exception receivedException) { "establish an initialized state machine"._(() => { machine = new PassiveStateMachine<int, int>(); machine.Initialize(TestState); }); "when state machine is initialized again"._(() => { try { machine.Initialize(TestState); } catch (Exception e) { receivedException = e; } }); "should throw an invalid operation exception"._(() => { receivedException .Should().BeAssignableTo<InvalidOperationException>(); receivedException.Message .Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized); }); }
public void NoCommonAncestor( PassiveStateMachine <string, int> machine) { const string SourceState = "SourceState"; const string ParentOfSourceState = "ParentOfSourceState"; const string SiblingOfSourceState = "SiblingOfSourceState"; const string DestinationState = "DestinationState"; const string ParentOfDestinationState = "ParentOfDestinationState"; const string SiblingOfDestinationState = "SiblingOfDestinationState"; const string GrandParentOfSourceState = "GrandParentOfSourceState"; const string GrandParentOfDestinationState = "GrandParentOfDestinationState"; const int Event = 0; string log = string.Empty; "establish a hierarchical state machine"._(() => { machine = new PassiveStateMachine <string, int>(); machine.DefineHierarchyOn(ParentOfSourceState) .WithHistoryType(HistoryType.None) .WithInitialSubState(SourceState) .WithSubState(SiblingOfSourceState); machine.DefineHierarchyOn(ParentOfDestinationState) .WithHistoryType(HistoryType.None) .WithInitialSubState(DestinationState) .WithSubState(SiblingOfDestinationState); machine.DefineHierarchyOn(GrandParentOfSourceState) .WithHistoryType(HistoryType.None) .WithInitialSubState(ParentOfSourceState); machine.DefineHierarchyOn(GrandParentOfDestinationState) .WithHistoryType(HistoryType.None) .WithInitialSubState(ParentOfDestinationState); machine.In(SourceState) .ExecuteOnExit(() => log += "exit" + SourceState) .On(Event).Goto(DestinationState); machine.In(ParentOfSourceState) .ExecuteOnExit(() => log += "exit" + ParentOfSourceState); machine.In(DestinationState) .ExecuteOnEntry(() => log += "enter" + DestinationState); machine.In(ParentOfDestinationState) .ExecuteOnEntry(() => log += "enter" + ParentOfDestinationState); machine.In(GrandParentOfSourceState) .ExecuteOnExit(() => log += "exit" + GrandParentOfSourceState); machine.In(GrandParentOfDestinationState) .ExecuteOnEntry(() => log += "enter" + GrandParentOfDestinationState); machine.Initialize(SourceState); machine.Start(); }); "when firing an event resulting in a transition without a common ancestor"._(() => machine.Fire(Event)); "it should execute exit action of source state"._(() => log.Should().Contain("exit" + SourceState)); "it should execute exit action of parents of source state (recursively)"._(() => log .Should().Contain("exit" + ParentOfSourceState) .And.Contain("exit" + GrandParentOfSourceState)); "it should execute entry action of parents of destination state (recursively)"._(() => log.Should().Contain("enter" + ParentOfDestinationState) .And.Contain("enter" + GrandParentOfDestinationState)); "it should execute entry action of destination state"._(() => log.Should().Contain("enter" + DestinationState)); "it should execute actions from source upwards and then downwards to destination state"._(() => { string[] states = { SourceState, ParentOfSourceState, GrandParentOfSourceState, GrandParentOfDestinationState, ParentOfDestinationState, DestinationState }; var statesInOrderOfAppearanceInLog = states .OrderBy(s => log.IndexOf(s.ToString(CultureInfo.InvariantCulture), StringComparison.Ordinal)); statesInOrderOfAppearanceInLog .Should().Equal(states); }); }
public void NoExceptionHandlerRegistered( Exception catchedException) { "establish an exception throwing state machine without a registered exception handler"._(() => { machine = new PassiveStateMachine<int, int>(); machine.In(Values.Source) .On(Values.Event).Execute(() => { throw Values.Exception; }); machine.Initialize(Values.Source); machine.Start(); }); "when an exception occurs"._(() => catchedException = Catch.Exception(() => this.machine.Fire(Values.Event))); "should (re-)throw exception"._(() => catchedException.InnerException .Should().BeSameAs(Values.Exception)); }