Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InitialTransition and IsInState API used together , It doesn't work correctly #485

Open
BAI-HANK opened this issue Sep 30, 2022 · 0 comments

Comments

@BAI-HANK
Copy link

The API to test is IsInState

Let's look at the test results

Enter A1 by (_machine.Configure(State.A.ToString()) .InitialTransition(SubAStatueA.A1.ToString()))
not by Trigger the result is A1 outer A1 -----------------------bad

Input initial state
A1
A1-0
input command
EA2
A2 in A -----------------------good
A2 in A2 -----------------------good
it can be trigger:EA3
it can be trigger:EB
A2-0
input command
EA3
it can be trigger:EC
B-0
input command
EC
it can be trigger:EA
C-0
input command
EA
A1 in A -----------------------good
A1 outer A1 -----------------------bad
it can be trigger:EA1
it can be trigger:EA2
it can be trigger:EB
A1-0
input command

Code Sample

using System;
using System.Threading.Tasks;
using Stateless;

namespace ConsoleApp30 {

  internal enum Trigger { EA, EB, EC }

  public enum State { A, B, C }

  public enum SubAStatueA { A1, A2 }

  internal enum SubTriggerA { EA1, EA2, EA3 }

  internal class ObjState {
    public Enum State { get; set; }

    public int Value { get; set; }

    public override string ToString() { return $"{State}-{Value}"; }
  }


  public class Test {
    private readonly StateMachine<string, string> _machine;
    private readonly ObjState _objState;

    public Test(Enum preCommand) {
      if (preCommand == null) throw new ArgumentNullException(nameof(preCommand));
      _objState = new ObjState { State = preCommand };
      _machine = new StateMachine<string, string>(() => _objState.State.ToString(),
                                                  s => { _objState.State = StrToEnum(s); });

      var doCTriggerSetPara = _machine.SetTriggerParameters<int>(Trigger.EC.ToString());
      //A - B
      _machine.Configure(State.A.ToString())
              //------------- may be  bug      --------------------------
              .InitialTransition(SubAStatueA.A1.ToString())
              .Permit(Trigger.EB.ToString(), State.B.ToString());

      //A1(A) - B or A1(A) -A2
      _machine.Configure(SubAStatueA.A1.ToString()).SubstateOf(State.A.ToString())
              .OnEntryAsync(p => Task.Run(() => {
                var tmp1 = _machine.IsInState(State.A.ToString()) ? "in" : "outer";
                Console.WriteLine("A1 " + tmp1 + " A ");
                var tmp2 = _machine.IsInState(SubAStatueA.A1.ToString()) ? "in" : "outer";
                Console.WriteLine("A1 " + tmp2 + "A1 ");
              }))
              .Permit(SubTriggerA.EA1.ToString(), State.B.ToString())
              .Permit(SubTriggerA.EA2.ToString(), SubAStatueA.A2.ToString());

      //A2(A) - B 
      _machine.Configure(SubAStatueA.A2.ToString()).SubstateOf(State.A.ToString())
              .OnEntryAsync(p => Task.Run(() => {
                var tmp1 = _machine.IsInState(State.A.ToString()) ? "in" : "outer";
                Console.WriteLine("A2 " + tmp1 + " A ");
                var tmp2 = _machine.IsInState(SubAStatueA.A2.ToString()) ? "in" : "outer";
                Console.WriteLine("A2 " + tmp2 + " A2 ");
              }))
              .Permit(SubTriggerA.EA3.ToString(), State.B.ToString());


      //B - C
      _machine.Configure(State.B.ToString())
              .Permit(Trigger.EC.ToString(), State.C.ToString());


      //C - A
      _machine.Configure(State.C.ToString())
              .OnEntryFromAsync(doCTriggerSetPara, p => Task.Run(() => { _objState.Value = p; }))
              .Permit(Trigger.EA.ToString(), State.A.ToString());

      _machine.OnUnhandledTrigger((state, trigger) => { });
    }


    public static Enum StrToEnum(string str) {
      Enum foo = null;
      if (Enum.TryParse(str, out State state))
        foo = state;
      else if (Enum.TryParse(str, out SubAStatueA subAStatueA)) foo = subAStatueA;
      return foo;
    }


    public static async Task DoAsync() {
      Console.WriteLine("Input initial state");
      var preCommand = Console.ReadLine();
      var foo = StrToEnum(preCommand);

      var bar = new Test(foo);
      while (true) {
        Console.WriteLine(bar.GetState());
        Console.WriteLine("input command");
        var command = Console.ReadLine();
        await bar._machine.FireAsync(command);
        foreach (var machinePermittedTrigger in bar._machine.PermittedTriggers)
          Console.WriteLine("it can be trigger:" + machinePermittedTrigger);
      }
    }

    public string GetState() { return _objState?.ToString(); }
  }

}
 internal class Program {
    private static async Task Main(string[] args) { await Test.DoAsync(); }
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant