It can be very helpful to visualize your state machine as a directed graph. This is possible
with the open source GraphViz library if we convert from our
state machine configuration to the .dot language expected by GraphViz using the
visualize method:
varvisualize=require('javascript-state-machine/lib/visualize');varfsm=newStateMachine({init: 'open',transitions: [{name: 'close',from: 'open',to: 'closed'},{name: 'open',from: 'closed',to: 'open'}]});visualize(fsm)Generates the following .dot syntax:
digraph"fsm" {
"closed";
"open";
"closed"->"open" [ label=" open " ];
"open"->"closed" [ label=" close " ];
}Which GraphViz displays as:
You can customize the generated .dot output - and hence the graphviz visualization - by attaching
dot attributes to your transitions and (optionally) declaring an orientation:
varfsm=newStateMachine({init: 'closed',transitions: [{name: 'open',from: 'closed',to: 'open',dot: {color: 'blue',headport: 'n',tailport: 'n'}},{name: 'close',from: 'open',to: 'closed',dot: {color: 'red',headport: 's',tailport: 's'}}]});visualize(fsm,{name: 'door',orientation: 'horizontal'});Generates the following (enhanced) .dot syntax:
digraph"door" {
rankdir=LR;
"closed";
"open";
"closed"->"open" [ color="blue" ; headport="n" ; label=" open " ; tailport="n" ];
"open"->"closed" [ color="red" ; headport="s" ; label=" close " ; tailport="s" ];
}Which GraphViz displays as:
You can use the same visualize method to generate .dot output for a state machine factory:
varMatter=StateMachine.factory({init: 'solid',transitions: [{name: 'melt',from: 'solid',to: 'liquid',dot: {headport: 'nw'}},{name: 'freeze',from: 'liquid',to: 'solid',dot: {headport: 'se'}},{name: 'vaporize',from: 'liquid',to: 'gas',dot: {headport: 'nw'}},{name: 'condense',from: 'gas',to: 'liquid',dot: {headport: 'se'}}]});visualize(Matter,{name: 'matter',orientation: 'horizontal'})Generates the following .dot syntax:
digraph"matter" {
rankdir=LR;
"solid";
"liquid";
"gas";
"solid"->"liquid" [ headport="nw" ; label=" melt " ];
"liquid"->"solid" [ headport="se" ; label=" freeze " ];
"liquid"->"gas" [ headport="nw" ; label=" vaporize " ];
"gas"->"liquid" [ headport="se" ; label=" condense " ];
}Which GraphViz displays as:
varWizard=StateMachine.factory({init: 'A',transitions: [{name: 'step',from: 'A',to: 'B',dot: {headport: 'w',tailport: 'ne'}},{name: 'step',from: 'B',to: 'C',dot: {headport: 'w',tailport: 'e'}},{name: 'step',from: 'C',to: 'D',dot: {headport: 'w',tailport: 'e'}},{name: 'reset',from: ['B','C','D'],to: 'A',dot: {headport: 'se',tailport: 's'}}]});visualize(Wizard,{orientation: 'horizontal'})Generates:
digraph"wizard" {
rankdir=LR;
"A";
"B";
"C";
"D";
"A"->"B" [ headport="w" ; label=" step " ; tailport="ne" ];
"B"->"C" [ headport="w" ; label=" step " ; tailport="e" ];
"C"->"D" [ headport="w" ; label=" step " ; tailport="e" ];
"B"->"A" [ headport="se" ; label=" reset " ; tailport="s" ];
"C"->"A" [ headport="se" ; label=" reset " ; tailport="s" ];
"D"->"A" [ headport="se" ; label=" reset " ; tailport="s" ];
}Displays:
varATM=StateMachine.factory({init: 'ready',transitions: [{name: 'insert-card',from: 'ready',to: 'pin'},{name: 'confirm',from: 'pin',to: 'action'},{name: 'reject',from: 'pin',to: 'return-card'},{name: 'withdraw',from: 'return-card',to: 'ready'},{name: 'deposit',from: 'action',to: 'deposit-account'},{name: 'provide',from: 'deposit-account',to: 'deposit-amount'},{name: 'provide',from: 'deposit-amount',to: 'confirm-deposit'},{name: 'confirm',from: 'confirm-deposit',to: 'collect-envelope'},{name: 'provide',from: 'collect-envelope',to: 'continue'},{name: 'withdraw',from: 'action',to: 'withdrawal-account'},{name: 'provide',from: 'withdrawal-account',to: 'withdrawal-amount'},{name: 'provide',from: 'withdrawal-amount',to: 'confirm-withdrawal'},{name: 'confirm',from: 'confirm-withdrawal',to: 'dispense-cash'},{name: 'withdraw',from: 'dispense-cash',to: 'continue'},{name: 'continue',from: 'continue',to: 'action'},{name: 'finish',from: 'continue',to: 'return-card'}]})visualize(ATM)Generates:
digraph"ATM" {
"ready";
"pin";
"action";
"return-card";
"deposit-account";
"deposit-amount";
"confirm-deposit";
"collect-envelope";
"continue";
"withdrawal-account";
"withdrawal-amount";
"confirm-withdrawal";
"dispense-cash";
"ready"->"pin" [ label=" insert-card " ];
"pin"->"action" [ label=" confirm " ];
"pin"->"return-card" [ label=" reject " ];
"return-card"->"ready" [ label=" withdraw " ];
"action"->"deposit-account" [ label=" deposit " ];
"deposit-account"->"deposit-amount" [ label=" provide " ];
"deposit-amount"->"confirm-deposit" [ label=" provide " ];
"confirm-deposit"->"collect-envelope" [ label=" confirm " ];
"collect-envelope"->"continue" [ label=" provide " ];
"action"->"withdrawal-account" [ label=" withdraw " ];
"withdrawal-account"->"withdrawal-amount" [ label=" provide " ];
"withdrawal-amount"->"confirm-withdrawal" [ label=" provide " ];
"confirm-withdrawal"->"dispense-cash" [ label=" confirm " ];
"dispense-cash"->"continue" [ label=" withdraw " ];
"continue"->"action" [ label=" continue " ];
"continue"->"return-card" [ label=" finish " ];
}Displays:




