View Source Finitomata.Transition (Finitomata v0.29.0)
The internal representation of Transition
.
It includes from
and to
states, and the event
, all represented as atoms.
Summary
Types
The event in FSM
The kind of event
The state of FSM
The transition is represented by from
and to
states and the event
.
Functions
Returns the list of all the transitions, matching the options.
Returns the list of all the transitions, matching the from
state and the event
.
Returns true
if the transition from
→ to
is allowed, false
otherwise.
Returns keyword list of
{Finitomata.Transition.state(), [Finitomata.Transition.event()]}
for transitions
which do not have a determined to state.
Returns the continuation from the state given which inevitably lead to other state(s).
Returns keyword list of
{Finitomata.Transition.state(), Finitomata.Transition.event()}
tuples
for determined transition from the current state.
Returns {:ok, {event(), state()}}
tuple if there is a determined transition
from the current state, :error
otherwise.
Returns the state after starting one, so-called entry
state.
Returns the kind of event.
Returns the not ordered list of events, including or excluding
the internal starting and ending transitions :__start__
and __end__
according to the second argument.
Returns the states before ending one, so-called exit
states.
Returns all the states which inevitably lead to the ending one.
Tries to guess the next state based on current state and event
Returns all the hard transitions which inevitably lead to the next state
(events ending with an exclamation sign,)
which makes the FSM to go to the next state with :continue
callback.
Returns all the loops aka internal paths where starting and ending states are the same one.
Returns all the paths from starting to ending state.
Returns true
if the state from
hsa an outgoing transition with event
, false otherwise.
Returns the shortest path from starting to ending state.
Returns the not ordered list of states, including or excluding
the starting and ending states :*
according to the second argument.
Returns the minimal number of steps required to get from from
state to to
state,
including hard transitions
Returns the minimal number of steps required to get from from
state to to
state,
omitting hard transitions
Returns the straight paths from starting to ending state.
Types
Functions
@spec allowed([t()], from: state(), to: state(), with: event(), as: :states | :transitions ) :: [ {state(), state(), event()} ]
Returns the list of all the transitions, matching the options.
Used internally for the validations.
iex> {:ok, transitions} =
...> Finitomata.Mermaid.parse(
...> "idle --> |to_s1| s1\n" <>
...> "s1 --> |to_s2| s2\n" <>
...> "s1 --> |to_s3| s3\n" <>
...> "s2 --> |to_s3| s3")
...> Finitomata.Transition.allowed(transitions, to: [:idle, :*])
[{:*, :idle, :__start__}, {:s3, :*, :__end__}]
iex> Finitomata.Transition.allowed(transitions, from: :s1)
[{:s1, :s2, :to_s2}, {:s1, :s3, :to_s3}]
iex> Finitomata.Transition.allowed(transitions, from: :s1, to: :s3)
[{:s1, :s3, :to_s3}]
iex> Finitomata.Transition.allowed(transitions, from: :s1, with: :to_s3)
[{:s1, :s3, :to_s3}]
iex> Finitomata.Transition.allowed(transitions, from: :s2, with: :to_s2)
[]
Returns the list of all the transitions, matching the from
state and the event
.
Used internally for the validations.
iex> {:ok, transitions} =
...> Finitomata.PlantUML.parse("[*] --> s1 : foo\ns1 --> s2 : ok\ns2 --> [*] : ko")
...> Finitomata.Transition.allowed(transitions, :s1, :foo)
[:s2]
...> Finitomata.Transition.allowed(transitions, :s1, :*)
[]
Returns true
if the transition from
→ to
is allowed, false
otherwise.
iex> {:ok, transitions} =
...> Finitomata.PlantUML.parse("[*] --> s1 : foo\ns1 --> s2 : ok\ns2 --> [*] : ko")
...> Finitomata.Transition.allowed?(transitions, :s1, :s2)
true
...> Finitomata.Transition.allowed?(transitions, :s1, :*)
false
Returns keyword list of
{Finitomata.Transition.state(), [Finitomata.Transition.event()]}
for transitions
which do not have a determined to state.
Used internally for the validations.
iex> {:ok, transitions} =
...> Finitomata.Mermaid.parse(
...> "idle --> |to_s1| s1\n" <>
...> "s1 --> |to_s2| s2\n" <>
...> "s1 --> |to_s3| s3\n" <>
...> "s2 --> |to_s1| s3\n" <>
...> "s2 --> |ambiguous| s3\n" <>
...> "s2 --> |ambiguous| s4\n" <>
...> "s3 --> |determined| s3\n" <>
...> "s3 --> |determined| s4\n")
...> Finitomata.Transition.ambiguous(transitions)
[s3: {:determined, [:s3, :s4]}, s2: {:ambiguous, [:s3, :s4]}]
@spec continuation(:states | :transitions, state(), [t()]) :: nil | [Finitomata.Transition.Path.t()] | [t()]
Returns the continuation from the state given which inevitably lead to other state(s).
All the transitions from this state are hard (ending with !
,)
which makes the FSM to go through all these states in :continue
callbacks.
iex> {:ok, transitions} =
...> Finitomata.PlantUML.parse("[*] --> entry : start\nentry --> exit : go!\nexit --> done : finish\ndone --> [*] : terminate")
...> Finitomata.Transition.continuation(:entry, Finitomata.Transition.hard(:transitions, transitions))
[%Finitomata.Transition.Path{from: :entry, to: :exit, path: [go!: :exit]}]
@spec count(:states | :transitions, [t()]) :: non_neg_integer()
Returns keyword list of
{Finitomata.Transition.state(), Finitomata.Transition.event()}
tuples
for determined transition from the current state.
The transition is determined, if it is the only transition allowed from the state.
Used internally for the validations.
iex> {:ok, transitions} =
...> Finitomata.Mermaid.parse(
...> "idle --> |to_s1| s1\n" <>
...> "s1 --> |to_s2| s2\n" <>
...> "s1 --> |to_s3| s3\n" <>
...> "s2 --> |to_s1| s3\n" <>
...> "s2 --> |ambiguous| s3\n" <>
...> "s2 --> |ambiguous| s4\n" <>
...> "s3 --> |determined| s3\n" <>
...> "s3 --> |determined| s4\n")
...> Finitomata.Transition.determined(transitions)
[s4: :__end__, s3: :determined, idle: :to_s1]
Returns {:ok, {event(), state()}}
tuple if there is a determined transition
from the current state, :error
otherwise.
The transition is determined, if it is the only transition allowed from the state.
Used internally for the validations.
iex> {:ok, transitions} =
...> Finitomata.Mermaid.parse(
...> "idle --> |to_s1| s1\n" <>
...> "s1 --> |to_s2| s2\n" <>
...> "s1 --> |to_s3| s3\n" <>
...> "s2 --> |to_s3| s3")
...> Finitomata.Transition.determined(transitions, :s1)
:error
iex> Finitomata.Transition.determined(transitions, :s2)
{:ok, {:to_s3, :s3}}
iex> Finitomata.Transition.determined(transitions, :s3)
{:ok, {:__end__, :*}}
Returns the state after starting one, so-called entry
state.
iex> {:ok, transitions} =
...> Finitomata.PlantUML.parse("[*] --> entry : foo\nentry --> exit : go\nexit --> [*] : terminate")
...> Finitomata.Transition.entry(transitions)
:entry
@spec event_kind(event() | t()) :: event_kind()
Returns the kind of event.
If event ends up with an exclamation sign, it’s :hard
, meaning the respective
transition would be initiated automatically when the from
state of such a transition
is reached.
If event ends up with a question mark, it’s :soft
, meaning no error would have
been reported in a case transition fails.
Otherwise the event is :normal
.
iex> {:ok, [_, hard, _]} =
...> Finitomata.PlantUML.parse("[*] --> entry : foo\nentry --> exit : go!\nexit --> [*] : terminate")
...> Finitomata.Transition.event_kind(hard)
:hard
Returns the not ordered list of events, including or excluding
the internal starting and ending transitions :__start__
and __end__
according to the second argument.
iex> {:ok, transitions} =
...> Finitomata.Mermaid.parse("s1 --> |ok| s2\ns1 --> |ko| s3")
...> Finitomata.Transition.events(transitions, true)
[:ok, :ko]
...> Finitomata.Transition.events(transitions)
[:__start__, :ok, :ko, :__end__]
Returns the states before ending one, so-called exit
states.
iex> {:ok, transitions} =
...> Finitomata.Mermaid.parse(
...> "entry --> |process| processing\nprocessing --> |ok| success\nprocessing --> |ko| error"
...> )
...> Finitomata.Transition.exit(transitions)
[:error, :success]
@spec exiting(:states | :transitions, [t()]) :: Enumerable.t([t()]) | [Finitomata.Transition.Path.t()]
Returns all the states which inevitably lead to the ending one.
All the transitions from these states to the ending one are hard (ending with !
,)
which makes the FSM to go through all these states in :continue
callbacks.
iex> {:ok, transitions} =
...> Finitomata.PlantUML.parse("[*] --> entry : start\nentry --> exit : go!\nexit --> [*] : terminate")
...> Finitomata.Transition.exiting(transitions)
[%Finitomata.Transition.Path{from: :entry, to: :*, path: [go!: :exit, terminate: :*]}]
@spec guess_next_state([t()], state(), event(), Finitomata.State.payload()) :: Finitomata.transition_resolution()
Tries to guess the next state based on current state and event
iex> {:ok, transitions} = Finitomata.Mermaid.parse("s1 --> |ok| s2\ns1 --> |ko| s3")
...> Finitomata.Transition.guess_next_state(transitions, :s1, :ok, %{})
{:ok, :s2, %{}}
iex> {:ok, transitions} = Finitomata.Mermaid.parse("s1 --> |ok| s2\ns1 --> |ok| s3")
...> Finitomata.Transition.guess_next_state(transitions, :s1, :ok, %{})
{:error, {:ambiguous_transition, {:s1, :ok}, [:s2, :s3]}}
@spec hard(:states | :transitions, [t()]) :: Enumerable.t(t()) | [Finitomata.Transition.Path.t()]
Returns all the hard transitions which inevitably lead to the next state
(events ending with an exclamation sign,)
which makes the FSM to go to the next state with :continue
callback.
iex> {:ok, transitions} =
...> Finitomata.PlantUML.parse("[*] --> entry : start\nentry --> exit : go!\nexit --> [*] : terminate")
...> Finitomata.Transition.hard(transitions)
[entry: :go!]
...> Finitomata.Transition.hard(:transitions, transitions)
[%Finitomata.Transition{from: :entry, to: :exit, event: :go!}]
@spec loops(:states | :transitions, [t()]) :: Enumerable.t(t()) | [Finitomata.Transition.Path.t()]
Returns all the loops aka internal paths where starting and ending states are the same one.
iex> {:ok, transitions} =
...> Finitomata.PlantUML.parse("[*] --> s1 : foo\ns1 --> s2 : ok\ns2 --> s1 : ok\ns2 --> [*] : ko")
...> Finitomata.Transition.loops(transitions)
[%Finitomata.Transition.Path{from: :s1, to: :s1, path: [ok: :s2, ok: :s1]},
%Finitomata.Transition.Path{from: :s2, to: :s2, path: [ok: :s1, ok: :s2]}]
@spec paths(:states | :transitions, [t()], state(), state()) :: Enumerable.t(t()) | [Finitomata.Transition.Path.t()]
Returns all the paths from starting to ending state.
iex> {:ok, transitions} =
...> Finitomata.PlantUML.parse("[*] --> s1 : foo\ns1 --> s2 : ok\ns1 --> s3 : ok\ns2 --> [*] : ko\ns3 --> [*] : ko")
...> Finitomata.Transition.paths(transitions)
[%Finitomata.Transition.Path{from: :*, to: :*, path: [foo: :s1, ok: :s2, ko: :*]},
%Finitomata.Transition.Path{from: :*, to: :*, path: [foo: :s1, ok: :s3, ko: :*]}]
Returns true
if the state from
hsa an outgoing transition with event
, false otherwise.
iex> {:ok, transitions} =
...> Finitomata.PlantUML.parse("[*] --> s1 : foo\ns1 --> s2 : ok\ns2 --> [*] : ko")
...> Finitomata.Transition.responds?(transitions, :s1, :ok)
true
...> Finitomata.Transition.responds?(transitions, :s1, :ko)
false
@spec shortest_paths(:states | :transitions, [t()], state(), state(), boolean()) :: Enumerable.t(t()) | [Finitomata.Transition.Path.t()]
Returns the shortest path from starting to ending state.
iex> {:ok, transitions} =
...> Finitomata.PlantUML.parse("[*] --> s1 : foo\ns1 --> s2 : ok\ns1 --> s3 : ok\ns2 --> [*] : ko\ns3 --> s4 : step\ns4 --> [*] : ko")
...> Finitomata.Transition.shortest_paths(transitions)
[%Finitomata.Transition.Path{from: :*, to: :*, path: [foo: :s1, ok: :s2, ko: :*]}]
Returns the not ordered list of states, including or excluding
the starting and ending states :*
according to the second argument.
iex> {:ok, transitions} =
...> Finitomata.PlantUML.parse("[*] --> s1 : foo\ns1 --> s2 : ok\ns2 --> [*] : ko")
...> Finitomata.Transition.states(transitions, true)
[:s1, :s2]
...> Finitomata.Transition.states(transitions)
[:*, :s1, :s2]
@spec steps([t()], state(), state()) :: non_neg_integer()
Returns the minimal number of steps required to get from from
state to to
state,
including hard transitions
@spec steps_handled([t()], state(), state()) :: non_neg_integer()
Returns the minimal number of steps required to get from from
state to to
state,
omitting hard transitions
@spec straight_paths(:states | :transitions, [t()], state(), state()) :: Enumerable.t(t()) | Finitomata.Transition.Path.t()
Returns the straight paths from starting to ending state.
iex> {:ok, transitions} =
...> Finitomata.PlantUML.parse("[*] --> s1 : foo\ns1 --> s2 : ok\ns1 --> s3 : ok\ns2 --> s2 : loop\ns2 --> [*] : ko\ns3 --> s4 : step\ns4 --> [*] : ko")
...> Finitomata.Transition.straight_paths(transitions)
[%Finitomata.Transition.Path{from: :*, to: :*, path: [foo: :s1, ok: :s2, ko: :*]},
%Finitomata.Transition.Path{from: :*, to: :*, path: [foo: :s1, ok: :s3, step: :s4, ko: :*]}]