blob: 4314c25668e085fbe1d1fbd01a55dc05220b1d27 [file] [log] [blame]
mpagenkobb47bc22021-04-20 13:29:09 +00001package fsm
2
3import (
4 "fmt"
5 "sort"
6)
7
8// VisualizeType the type of the visualization
9type VisualizeType string
10
11const (
12 // GRAPHVIZ the type for graphviz output (http://www.webgraphviz.com/)
13 GRAPHVIZ VisualizeType = "graphviz"
14 // MERMAID the type for mermaid output (https://mermaid-js.github.io/mermaid/#/stateDiagram) in the stateDiagram form
15 MERMAID VisualizeType = "mermaid"
16 // MERMAID the type for mermaid output (https://mermaid-js.github.io/mermaid/#/stateDiagram) in the stateDiagram form
17 MermaidStateDiagram VisualizeType = "mermaid-state-diagram"
18 // MERMAID the type for mermaid output (https://mermaid-js.github.io/mermaid/#/flowchart) in the flow chart form
19 MermaidFlowChart VisualizeType = "mermaid-flow-chart"
20)
21
22// VisualizeWithType outputs a visualization of a FSM in the desired format.
23// If the type is not given it defaults to GRAPHVIZ
24func VisualizeWithType(fsm *FSM, visualizeType VisualizeType) (string, error) {
25 switch visualizeType {
26 case GRAPHVIZ:
27 return Visualize(fsm), nil
28 case MERMAID:
29 return VisualizeForMermaidWithGraphType(fsm, StateDiagram)
30 case MermaidStateDiagram:
31 return VisualizeForMermaidWithGraphType(fsm, StateDiagram)
32 case MermaidFlowChart:
33 return VisualizeForMermaidWithGraphType(fsm, FlowChart)
34 default:
35 return "", fmt.Errorf("unknown VisualizeType: %s", visualizeType)
36 }
37}
38
39func getSortedTransitionKeys(transitions map[eKey]string) []eKey {
40 // we sort the key alphabetically to have a reproducible graph output
41 sortedTransitionKeys := make([]eKey, 0)
42
43 for transition := range transitions {
44 sortedTransitionKeys = append(sortedTransitionKeys, transition)
45 }
46 sort.Slice(sortedTransitionKeys, func(i, j int) bool {
47 if sortedTransitionKeys[i].src == sortedTransitionKeys[j].src {
48 return sortedTransitionKeys[i].event < sortedTransitionKeys[j].event
49 }
50 return sortedTransitionKeys[i].src < sortedTransitionKeys[j].src
51 })
52
53 return sortedTransitionKeys
54}
55
56func getSortedStates(transitions map[eKey]string) ([]string, map[string]string) {
57 statesToIDMap := make(map[string]string)
58 for transition, target := range transitions {
59 if _, ok := statesToIDMap[transition.src]; !ok {
60 statesToIDMap[transition.src] = ""
61 }
62 if _, ok := statesToIDMap[target]; !ok {
63 statesToIDMap[target] = ""
64 }
65 }
66
67 sortedStates := make([]string, 0, len(statesToIDMap))
68 for state := range statesToIDMap {
69 sortedStates = append(sortedStates, state)
70 }
71 sort.Strings(sortedStates)
72
73 for i, state := range sortedStates {
74 statesToIDMap[state] = fmt.Sprintf("id%d", i)
75 }
76 return sortedStates, statesToIDMap
77}