From bd3abc88ea676869dd49c873a5ff699c65471415 Mon Sep 17 00:00:00 2001 From: mesmo Date: Sat, 22 Nov 2014 10:01:15 +0000 Subject: [PATCH] Changed the parameter passing order; bug fix Changed the sequence of parameters for callbacks taking both the context and the triggering message for consistency with other language versions. Fixes #7 - transition selection was favouring outer states over inner states. --- README.md | 2 +- examples/Player.cs | 2 +- src/PseudoState.cs | 2 +- src/Region.cs | 8 +++--- src/State.cs | 58 ++++++++++++++++++++------------------ src/StateMachine.cs | 6 ++-- src/StateMachineElement.cs | 14 ++++----- src/Transition.cs | 51 ++++++++++++++++----------------- src/Vertex.cs | 15 +++++----- tests/History/Shallow.cs | 29 ++++++++----------- tests/Program.cs | 3 ++ tests/Users/Brice1.cs | 34 ++++++++++++++++++++++ tests/Users/Muximise1.cs | 14 ++++----- 13 files changed, 134 insertions(+), 104 deletions(-) create mode 100644 tests/Users/Brice1.cs diff --git a/README.md b/README.md index 1f0dcae..d005d87 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Welcome to state.cs -The current stable release is 5.0.1. +The current stable release is 5.1.0. If you're using state.cs I'd love to hear about it; please e-mail me at mesmo@steelbreeze.net diff --git a/examples/Player.cs b/examples/Player.cs index 95a7d8f..a418369 100644 --- a/examples/Player.cs +++ b/examples/Player.cs @@ -69,7 +69,7 @@ static void Main() { Console.Write( "alamo> " ); // process lines read from the console - if( !model.Evaluate( context, Console.ReadLine() ) ) + if( !model.Evaluate( Console.ReadLine(), context ) ) Console.WriteLine( "unknown command" ); } diff --git a/src/PseudoState.cs b/src/PseudoState.cs index fd9512a..e97d62f 100644 --- a/src/PseudoState.cs +++ b/src/PseudoState.cs @@ -65,7 +65,7 @@ internal override void BootstrapElement( bool deepHistoryAbove ) { base.BootstrapElement( deepHistoryAbove ); if( this.Kind == PseudoStateKind.Terminate ) - this.Enter += ( context, message, history ) => context.IsTerminated = true; + this.Enter += ( message, context, history ) => context.IsTerminated = true; } } } \ No newline at end of file diff --git a/src/Region.cs b/src/Region.cs index dcc3755..a7a0dc2 100644 --- a/src/Region.cs +++ b/src/Region.cs @@ -136,10 +136,10 @@ internal override void BootstrapElement( Boolean deepHistoryAbove ) { vertex.BootstrapElement( deepHistoryAbove || ( this.Initial != null && this.Initial.Kind == PseudoStateKind.DeepHistory ) ); } - this.Leave += ( context, message, history ) => { var current = context[ this ]; if( current.Leave != null ) current.Leave( context, message, history ); }; + this.Leave += ( message, context, history ) => { var current = context[ this ]; if( current.Leave != null ) current.Leave( message, context, history ); }; if( deepHistoryAbove || this.Initial == null || this.Initial.IsHistory ) - this.EndEnter += ( context, message, history ) => ( history || this.Initial.IsHistory ? context[ this ] ?? this.Initial : this.Initial ).Enter( context, message, history || this.Initial.Kind == PseudoStateKind.DeepHistory ); + this.EndEnter += ( message, context, history ) => ( history || this.Initial.IsHistory ? context[ this ] ?? this.Initial : this.Initial ).Enter( message, context, history || this.Initial.Kind == PseudoStateKind.DeepHistory ); else this.EndEnter += this.Initial.Enter; base.BootstrapElement( deepHistoryAbove ); @@ -150,8 +150,8 @@ internal override void BootstrapTransitions() { vertex.BootstrapTransitions(); } - internal Boolean Evaluate( TContext context, Object message ) { - return context[ this ].Evaluate( context, message ); + internal Boolean Evaluate( Object message, TContext context ) { + return context[ this ].Evaluate( message, context ); } } } \ No newline at end of file diff --git a/src/State.cs b/src/State.cs index aeefdd1..6cdca2a 100644 --- a/src/State.cs +++ b/src/State.cs @@ -52,8 +52,8 @@ public class State : Vertex where TContext : IContext[] regions; - private event Action exit; - private event Action entry; + private event Action exit; + private event Action entry; /// /// Creates a new instance of the State class. @@ -67,7 +67,7 @@ public State( String name, Region parent ) } // Constructor used by FinalState - internal State( String name, Region parent, Func[], TContext, Object, Transition> selector ) : base( name, parent, selector ) { } + internal State( String name, Region parent, Func[], Object, TContext, Transition> selector ) : base( name, parent, selector ) { } /// /// Sets optional exit behavior that is called when leaving the State. @@ -76,9 +76,9 @@ internal State( String name, Region parent, Func[ /// One or more actions that take both the state machine context and the triggering message as parameters. /// Returns the State itself. /// If the type of the triggering message does not match TMessage the behavior will not be called. - public State Exit( params Action[] behavior ) where TMessage : class { + public State Exit( params Action[] behavior ) where TMessage : class { foreach( var exit in behavior ) - this.exit += ( state, message ) => { if( message is TMessage ) exit( state, message as TMessage ); }; + this.exit += ( message, context ) => { if( message is TMessage ) exit( message as TMessage, context ); }; this.Root.Clean = false; @@ -94,7 +94,7 @@ public State Exit( params Action[] behav /// If the type of the triggering message does not match TMessage the behavior will not be called. public State Exit( params Action[] behavior ) where TMessage : class { foreach( var exit in behavior ) - this.exit += ( state, message ) => { if( message is TMessage ) exit( message as TMessage ); }; + this.exit += ( message, context ) => { if( message is TMessage ) exit( message as TMessage ); }; this.Root.Clean = false; @@ -108,7 +108,7 @@ public State Exit( params Action[] behavior ) wher /// Returns the State itself. public State Exit( params Action[] behavior ) { foreach( var exit in behavior ) - this.exit += ( state, message ) => exit( state ); + this.exit += ( message, context ) => exit( context ); this.Root.Clean = false; @@ -122,7 +122,7 @@ public State Exit( params Action[] behavior ) { /// Returns the State itself. public State Exit( params Action[] behavior ) { foreach( var exit in behavior ) - this.exit += ( state, message ) => exit(); + this.exit += ( message, context ) => exit(); this.Root.Clean = false; @@ -136,9 +136,9 @@ public State Exit( params Action[] behavior ) { /// One or more actions that take both the state machine context and the triggering message as parameters. /// Returns the State itself. /// If the type of the triggering message does not match TMessage the behavior will not be called. - public State Entry( params Action[] behavior ) where TMessage : class { + public State Entry( params Action[] behavior ) where TMessage : class { foreach( var entry in behavior ) - this.entry += ( state, message ) => { if( message is TMessage ) entry( state, message as TMessage ); }; + this.entry += ( message, context ) => { if( message is TMessage ) entry( message as TMessage, context ); }; this.Root.Clean = false; @@ -154,7 +154,7 @@ public State Entry( params Action[] beha /// If the type of the triggering message does not match TMessage the behavior will not be called. public State Entry( params Action[] behavior ) where TMessage : class { foreach( var entry in behavior ) - this.entry += ( state, message ) => { if( message is TMessage ) entry( message as TMessage ); }; + this.entry += ( message, context ) => { if( message is TMessage ) entry( message as TMessage ); }; this.Root.Clean = false; @@ -168,7 +168,7 @@ public State Entry( params Action[] behavior ) whe /// Returns the State itself. public State Entry( params Action[] behavior ) { foreach( var entry in behavior ) - this.entry += ( state, message ) => entry( state ); + this.entry += ( message, context ) => entry( context ); this.Root.Clean = false; @@ -182,7 +182,7 @@ public State Entry( params Action[] behavior ) { /// Returns the State itself. public State Entry( params Action[] behavior ) { foreach( var entry in behavior ) - this.entry += ( state, message ) => entry(); + this.entry += ( message, context ) => entry(); this.Root.Clean = false; @@ -198,7 +198,7 @@ public State Entry( params Action[] behavior ) { /// /// An internal transition does not exit or enter any states, however the transitions effect will be invoked if the guard condition of the transition is met /// - public Transition When( Func guard ) where TMessage : class { + public Transition When( Func guard ) where TMessage : class { return this.To( null ).When( guard ); } @@ -218,8 +218,8 @@ public Transition When( Func guard ) wher /// The state machine context. /// The message that triggered the state transition. /// A flag denoting if history semantics were in play during the transition. - protected virtual void OnExit( TContext context, Object message, Boolean history ) { - this.exit( context, message ); + protected virtual void OnExit( Object message, TContext context, Boolean history ) { + this.exit( message, context ); } /// @@ -228,8 +228,8 @@ protected virtual void OnExit( TContext context, Object message, Boolean history /// The state machine context. /// The message that triggered the state transition. /// A flag denoting if history semantics were in play during the transition. - protected virtual void OnEntry( TContext context, Object message, Boolean history ) { - this.entry( context, message ); + protected virtual void OnEntry( Object message, TContext context, Boolean history ) { + this.entry( message, context ); } internal override Boolean IsComplete( TContext context ) { @@ -260,7 +260,7 @@ internal override void BootstrapElement( Boolean deepHistoryAbove ) { region.Reset(); region.BootstrapElement( deepHistoryAbove ); - this.Leave += ( context, message, history ) => region.Leave( context, message, history ); + this.Leave += ( message, context, history ) => region.Leave( message, context, history ); this.EndEnter += region.Enter; } } @@ -273,7 +273,7 @@ internal override void BootstrapElement( Boolean deepHistoryAbove ) { if( this.entry != null ) this.BeginEnter += this.OnEntry; - this.BeginEnter += ( context, message, history ) => context[ this.Region ] = this; + this.BeginEnter += ( message, context, history ) => context[ this.Region ] = this; this.Enter = this.BeginEnter + this.EndEnter; } @@ -286,7 +286,7 @@ internal override void BootstrapTransitions() { base.BootstrapTransitions(); } - internal override void BootstrapEnter( ref Action traverse, StateMachineElement next ) { + internal override void BootstrapEnter( ref Action traverse, StateMachineElement next ) { base.BootstrapEnter( ref traverse, next ); if( this.IsOrthogonal ) @@ -295,17 +295,19 @@ internal override void BootstrapEnter( ref Action traver traverse += region.Enter; } - internal override Boolean Evaluate( TContext context, Object message ) { - var processed = base.Evaluate( context, message ); + internal override Boolean Evaluate( Object message, TContext context ) { + var processed = false; + + if( this.IsComposite ) + for( int i = 0, l = this.regions.Length; i < l; ++i ) + if( this.regions[ i ].Evaluate( message, context ) ) + processed = true; if( !processed ) - if( this.IsComposite ) - for( int i = 0, l = this.regions.Length; i < l; ++i ) - if( this.regions[ i ].Evaluate( context, message ) ) - processed = true; + processed = base.Evaluate( message, context ); if( processed == true && message != this ) - this.EvaluateCompletions( context, this, false ); + this.EvaluateCompletions( this, context, false ); return processed; } diff --git a/src/StateMachine.cs b/src/StateMachine.cs index 084bce4..87bf496 100644 --- a/src/StateMachine.cs +++ b/src/StateMachine.cs @@ -86,7 +86,7 @@ public void Initialise( TContext context, Boolean autoInitialise = true ) { if( !this.Clean && autoInitialise ) this.Initialise(); - this.Enter( context, null, false ); + this.Enter( null, context, false ); } /// @@ -113,7 +113,7 @@ public Boolean IsComplete( TContext context ) { /// /// Note that due to the potential for orthogonal Regions in composite States, it is possible for multiple transitions to be triggered. /// - public Boolean Evaluate( TContext context, Object message, Boolean autoInitialise = true ) { + public Boolean Evaluate( Object message, TContext context, Boolean autoInitialise = true ) { if( !this.Clean && autoInitialise ) this.Initialise(); @@ -121,7 +121,7 @@ public Boolean Evaluate( TContext context, Object message, Boolean autoInitialis if( !context.IsTerminated ) for( int i = 0, l = this.regions.Length; i < l; ++i ) - if( this.regions[ i ].Evaluate( context, message ) ) + if( this.regions[ i ].Evaluate( message, context ) ) processed = true; return processed; diff --git a/src/StateMachineElement.cs b/src/StateMachineElement.cs index 5be532e..d00df9c 100644 --- a/src/StateMachineElement.cs +++ b/src/StateMachineElement.cs @@ -26,10 +26,10 @@ public abstract class StateMachineElement : NamedElement where TContex /// public IEnumerable> Ancestors { get { if( this.Parent != null ) foreach( var namedElement in this.Parent.Ancestors ) yield return namedElement; yield return this; } } // yield! please... - internal Action Leave; - internal Action BeginEnter; - internal Action EndEnter; - internal Action Enter; + internal Action Leave; + internal Action BeginEnter; + internal Action EndEnter; + internal Action Enter; internal StateMachineElement( String name, StateMachineElement parent ) : base( name, parent ) { } @@ -42,15 +42,15 @@ internal void Reset() { internal virtual void BootstrapElement( Boolean deepHistoryAbove ) { #if DEBUG - this.Leave += ( context, message, history ) => Console.WriteLine( "{0} leave {1}", context, this.QualifiedName ); - this.BeginEnter += ( context, message, history ) => Console.WriteLine( "{0} enter {1}", context, this.QualifiedName ); + this.Leave += ( message, context, history ) => Console.WriteLine( "{0} leave {1}", context, this.QualifiedName ); + this.BeginEnter += ( message, context, history ) => Console.WriteLine( "{0} enter {1}", context, this.QualifiedName ); #endif this.Enter = this.BeginEnter + this.EndEnter; } internal abstract void BootstrapTransitions(); - internal virtual void BootstrapEnter( ref Action traverse, StateMachineElement next ) { + internal virtual void BootstrapEnter( ref Action traverse, StateMachineElement next ) { traverse += this.BeginEnter; } } diff --git a/src/Transition.cs b/src/Transition.cs index cb8bd6a..015f0a0 100644 --- a/src/Transition.cs +++ b/src/Transition.cs @@ -19,9 +19,9 @@ namespace Steelbreeze.Behavior.StateMachines { /// public class Transition where TContext : IContext { #region Static members - private static Func IsElse = ( context, message ) => false; + private static Func IsElse = ( message, context ) => false; - internal static Func[], TContext, Object, Transition> PseudoState( PseudoStateKind kind ) { + internal static Func[], Object, TContext, Transition> PseudoState( PseudoStateKind kind ) { switch( kind ) { case PseudoStateKind.Initial: case PseudoStateKind.DeepHistory: @@ -37,12 +37,12 @@ internal static Func[], TContext, Object, Transition State( Transition[] transitions, TContext context, object message ) { + internal static Transition State( Transition[] transitions, Object message, TContext context ) { Transition result = null; if( transitions != null ) { for( int i = 0, l = transitions.Length; i < l; ++i ) { - if( transitions[ i ].Predicate( context, message ) ) { + if( transitions[ i ].Predicate( message, context ) ) { if( result != null ) throw new InvalidOperationException( "Multiple outbound transitions evaluated true" ); @@ -54,22 +54,22 @@ internal static Transition State( Transition[] transitions, return result; } - private static Transition Initial( Transition[] transitions, TContext context, Object message ) { + private static Transition Initial( Transition[] transitions, Object message, TContext context ) { if( transitions.Length == 1 ) return transitions[ 0 ]; else throw new InvalidOperationException( "Initial transition must have a single outbound transition" ); } - private static Transition Junction( Transition[] transitions, TContext context, Object message ) { - return transitions.SingleOrDefault( t => t.Predicate( context, message ) ) ?? transitions.Single( transition => transition.Predicate.Equals( Transition.IsElse ) ); + private static Transition Junction( Transition[] transitions, Object message, TContext context ) { + return transitions.SingleOrDefault( t => t.Predicate( message, context ) ) ?? transitions.Single( transition => transition.Predicate.Equals( Transition.IsElse ) ); } private static readonly Random random = new Random(); - private static Transition Choice( Transition[] transitions, TContext context, Object message ) { + private static Transition Choice( Transition[] transitions, Object message, TContext context ) { var transition = default( Transition ); - var items = transitions.Where( t => t.Predicate( context, message ) ); + var items = transitions.Where( t => t.Predicate( message, context ) ); var count = items.Count(); if( count == 1 ) @@ -81,23 +81,22 @@ private static Transition Choice( Transition[] transitions, return transition ?? transitions.Single( t => t.Predicate.Equals( Transition.IsElse ) ); } - internal static Transition Null( Transition[] transitions, TContext context, Object message ) { + internal static Transition Null( Transition[] transitions, Object message, TContext context ) { return null; } #endregion internal readonly Vertex Source; internal readonly Vertex Target; - internal Func Predicate; - internal Action Traverse; + internal Func Predicate; + internal Action Traverse; - private event Action effect; + private event Action effect; internal Transition( Vertex source, Vertex target ) { Trace.Assert( source != null, "Transitions must have a source Vertex" ); this.Source = source; this.Target = target; -// this.Predicate = ( context, message ) => message == this.Source; this.Completion(); } @@ -108,8 +107,8 @@ internal Transition( Vertex source, Vertex target ) { /// The type of the message that can trigger the transition. /// The guard condition taking both the state machine context and the message that must evaluate true for the transition to be traversed. /// Returns the transition. - public Transition When( Func guard ) where TMessage : class { - this.Predicate = ( context, message ) => message is TMessage && guard( context, message as TMessage ); + public Transition When( Func guard ) where TMessage : class { + this.Predicate = ( message, context ) => message is TMessage && guard( message as TMessage, context ); return this; } @@ -121,7 +120,7 @@ public Transition When( Func gu /// A guard condition taking the message that must evaluate true for the transition to be traversed. /// Returns the transition. public Transition When( Func guard ) where TMessage : class { - this.Predicate = ( context, message ) => message is TMessage && guard( message as TMessage ); + this.Predicate = ( message, context ) => message is TMessage && guard( message as TMessage ); return this; } @@ -132,7 +131,7 @@ public Transition When( Func guard ) wher /// A guard condition, taking just the state machine context, that must evaluate true for the transition to be traversed. /// Returns the transition. public Transition When( Func guard ) { - this.Predicate = ( context, message ) => guard( context ); + this.Predicate = ( message, context ) => guard( context ); return this; } @@ -145,7 +144,7 @@ public Transition When( Func guard ) { /// All transitions are completion tansitions when initially created; this method can be used to return a transition to be a completion transition if prior calls to When or Else have been made. /// public Transition Completion() { - this.Predicate = ( context, message ) => message == this.Source; + this.Predicate = ( message, context ) => message == this.Source; return this; } @@ -171,9 +170,9 @@ public Transition Else() { /// /// If the type of the message that triggers the transition does not match TMessage, the behavior will not be called. /// - public Transition Effect( params Action[] behavior ) where TMessage : class { + public Transition Effect( params Action[] behavior ) where TMessage : class { foreach( var effect in behavior ) - this.effect += ( context, message ) => { if( message is TMessage ) effect( context, message as TMessage ); }; + this.effect += ( message, context ) => { if( message is TMessage ) effect( message as TMessage, context ); }; this.Source.Root.Clean = false; @@ -191,7 +190,7 @@ public Transition Effect( params Action[ /// public Transition Effect( params Action[] behavior ) where TMessage : class { foreach( var effect in behavior ) - this.effect += ( context, message ) => { if( message is TMessage ) effect( message as TMessage ); }; + this.effect += ( message, context ) => { if( message is TMessage ) effect( message as TMessage ); }; this.Source.Root.Clean = false; @@ -205,7 +204,7 @@ public Transition Effect( params Action[] behavior /// Returns the transition. public Transition Effect( params Action[] behavior ) { foreach( var effect in behavior ) - this.effect += ( context, message ) => effect( context ); + this.effect += ( message, context ) => effect( context ); this.Source.Root.Clean = false; @@ -219,7 +218,7 @@ public Transition Effect( params Action[] behavior ) { /// Returns the transition. public Transition Effect( params Action[] behavior ) { foreach( var effect in behavior ) - this.effect += ( context, message ) => effect(); + this.effect += ( message, context ) => effect(); this.Source.Root.Clean = false; @@ -235,8 +234,8 @@ public Transition Effect( params Action[] behavior ) { /// /// For completion transitions, the message is the source vertex that was completed. /// - protected void OnEffect( TContext context, Object message, Boolean history ) { - this.effect( context, message ); + protected void OnEffect( Object message, TContext context, Boolean history ) { + this.effect( message, context ); } internal void BootstrapTransitions() { diff --git a/src/Vertex.cs b/src/Vertex.cs index a2a8d4a..a7c486c 100644 --- a/src/Vertex.cs +++ b/src/Vertex.cs @@ -15,14 +15,14 @@ public abstract class Vertex : StateMachineElement where TCo internal Boolean IsFinal { get { return this.transitions == null; } } private Transition[] transitions; // trading off model building performance for runtime performance - private readonly Func[], TContext, Object, Transition> selector; + private readonly Func[], Object, TContext, Transition> selector; /// /// Returns the Vertex's parent element. /// public override StateMachineElement Parent { get { return this.Region; } } - internal Vertex( String name, Region parent, Func[], TContext, Object, Transition> selector ) + internal Vertex( String name, Region parent, Func[], Object, TContext, Transition> selector ) : base( name, parent ) { this.Root = parent.Root; this.Region = parent; @@ -72,25 +72,24 @@ internal override void BootstrapTransitions() { transition.BootstrapTransitions(); } - internal void EvaluateCompletions( TContext context, Object message, Boolean history ) { + internal void EvaluateCompletions( Object message, TContext context, Boolean history ) { if( this.IsComplete( context ) ) - this.Evaluate( context, this ); + this.Evaluate( this, context ); } internal virtual Boolean IsComplete( TContext context ) { return true; } - internal virtual Boolean Evaluate( TContext context, Object message ) { - var transition = this.selector( this.transitions, context, message ); + internal virtual Boolean Evaluate( Object message, TContext context ) { + var transition = this.selector( this.transitions, message, context ); if( transition == null ) return false; - transition.Traverse( context, message, false ); + transition.Traverse( message, context, false ); return true; - } } } diff --git a/tests/History/Shallow.cs b/tests/History/Shallow.cs index 25f49e0..d937f26 100644 --- a/tests/History/Shallow.cs +++ b/tests/History/Shallow.cs @@ -5,12 +5,9 @@ using System; using System.Diagnostics; -namespace Steelbreeze.Behavior.StateMachines.Tests.History -{ - public class Shallow - { - public static void Test() - { +namespace Steelbreeze.Behavior.StateMachines.Tests.History { + public class Shallow { + public static void Test() { var model = new StateMachine( "history" ); var initial = new PseudoState( "initial", model ); @@ -23,22 +20,20 @@ public static void Test() initial.To( shallow ); new PseudoState( "shallow", shallow, PseudoStateKind.ShallowHistory ).To( s1 ); - s1.To(s2).When( ( state, c ) => c.Equals( "move" ) ); - shallow.To( deep ).When( ( state, c ) => c.Equals( "go deep" ) ); - deep.To( shallow ).When( ( state, c ) => c.Equals( "go shallow" ) ); - s2.To( final ).When( ( state, c ) => c.Equals( "end" ) ); - -// model.Initialise(); + s1.To( s2 ).When( c => c == "move" ); + shallow.To( deep ).When( c => c == "go deep" ); + deep.To( shallow ).When( c => c == "go shallow" ); + s2.To( final ).When( c => c == "end" ); var instance = new TestState(); model.Initialise( instance ); - Trace.Assert( model.Evaluate( instance, "move" ) ); - Trace.Assert( model.Evaluate( instance, "go deep" ) ); - Trace.Assert( model.Evaluate( instance, "go shallow" ) ); - Trace.Assert( !model.Evaluate( instance, "go shallow" ) ); - Trace.Assert( model.Evaluate( instance, "end" ) ); + Trace.Assert( model.Evaluate( "move", instance ) ); + Trace.Assert( model.Evaluate( "go deep", instance ) ); + Trace.Assert( model.Evaluate( "go shallow", instance ) ); + Trace.Assert( !model.Evaluate( "go shallow", instance ) ); + Trace.Assert( model.Evaluate( "end", instance ) ); Trace.Assert( model.IsComplete( instance ) ); } } diff --git a/tests/Program.cs b/tests/Program.cs index 458514b..7760aee 100644 --- a/tests/Program.cs +++ b/tests/Program.cs @@ -16,7 +16,10 @@ public static void Main( String[] args ) // TODO: add more transition tests (incl. else) Transitions.Completions.Test(); History.Shallow.Test(); + + // user test cases Users.Muximise1.Test(); + Users.Brice1.Test(); } } } \ No newline at end of file diff --git a/tests/Users/Brice1.cs b/tests/Users/Brice1.cs new file mode 100644 index 0000000..a39140d --- /dev/null +++ b/tests/Users/Brice1.cs @@ -0,0 +1,34 @@ +/* state v5 finite state machine library + * Copyright (c) 2014 Steelbreeze Limited + * Licensed under MIT and GPL v3 licences + */ +using System; +using System.Diagnostics; + +namespace Steelbreeze.Behavior.StateMachines.Tests.Users { + public class Brice1 { + public static void Test() { + var model = new StateMachine( "brice1" ); + + var initial1 = new PseudoState( "initial", model ); + var myComposite1 = new State( "myComposite1", model ); + var myComposite2 = new State( "myComposite2", model ); + + var initial2 = new PseudoState( "initial", myComposite1 ); + var myState1 = new State( "myState1", myComposite1 ); + var myState2 = new State( "myState2", myComposite1 ); + + initial1.To( myComposite1 ); + initial2.To( myState1 ); + + myComposite1.To( myComposite2 ).When( message => message == "A" ).Effect( () => System.Diagnostics.Trace.Fail( "Outer transition fired" ) ); + myState1.To( myState2 ).When( message => message == "A" ); + + var instance = new TestState(); + + model.Initialise( instance ); + + model.Evaluate( "A", instance ); + } + } +} \ No newline at end of file diff --git a/tests/Users/Muximise1.cs b/tests/Users/Muximise1.cs index a12cc8b..3816d93 100644 --- a/tests/Users/Muximise1.cs +++ b/tests/Users/Muximise1.cs @@ -39,20 +39,18 @@ public static void Test() ortho.To( final ); // This should happen once all regions in ortho are complete? - s1.To( f1 ).When( ( s, c ) => c == "complete1" ); - s2.To( f2 ).When( ( s, c ) => c == "complete2" ); + s1.To( f1 ).When( c => c == "complete1" ); + s2.To( f2 ).When( c => c == "complete2" ); - ortho.To( simple ).When( ( s, c ) => c == "jump" ); - simple.To( ortho ).When( ( s, c ) => c == "back" ); - -// main.Initialise(); + ortho.To( simple ).When( c => c == "jump" ); + simple.To( ortho ).When( c => c == "back" ); var instance = new TestState(); model.Initialise( instance ); - model.Evaluate( instance, "complete1" ); - model.Evaluate( instance, "complete2" ); + model.Evaluate( "complete1", instance ); + model.Evaluate( "complete2", instance ); Trace.Assert( model.IsComplete( instance ) );