forked from looplab/fsm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgraphviz_visualizer.go
58 lines (48 loc) · 1.45 KB
/
graphviz_visualizer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package fsm
import (
"bytes"
"fmt"
)
// Visualize outputs a visualization of a FSM in Graphviz format.
func Visualize(fsm *FSM) string {
var buf bytes.Buffer
// we sort the key alphabetically to have a reproducible graph output
sortedEKeys := getSortedTransitionKeys(fsm.transitions)
sortedStatEventKeys, _ := getSortedStates(fsm.transitions)
writeHeaderLine(&buf)
writeTransitions(&buf, fsm.current, sortedEKeys, fsm.transitions)
writeStates(&buf, sortedStatEventKeys)
writeFooter(&buf)
return buf.String()
}
func writeHeaderLine(buf *bytes.Buffer) {
buf.WriteString(fmt.Sprintf(`digraph fsm {`))
buf.WriteString("\n")
}
func writeTransitions(buf *bytes.Buffer, current string, sortedEKeys []eKey, transitions map[eKey]string) {
// make sure the current state is at top
for _, k := range sortedEKeys {
if k.src == current {
v := transitions[k]
buf.WriteString(fmt.Sprintf(` "%s" -> "%s" [ label = "%s" ];`, k.src, v, k.event))
buf.WriteString("\n")
}
}
for _, k := range sortedEKeys {
if k.src != current {
v := transitions[k]
buf.WriteString(fmt.Sprintf(` "%s" -> "%s" [ label = "%s" ];`, k.src, v, k.event))
buf.WriteString("\n")
}
}
buf.WriteString("\n")
}
func writeStates(buf *bytes.Buffer, sortedStatEventKeys []string) {
for _, k := range sortedStatEventKeys {
buf.WriteString(fmt.Sprintf(` "%s";`, k))
buf.WriteString("\n")
}
}
func writeFooter(buf *bytes.Buffer) {
buf.WriteString(fmt.Sprintln("}"))
}