-
Notifications
You must be signed in to change notification settings - Fork 4
/
fsm_to_graph.py
59 lines (42 loc) · 1.92 KB
/
fsm_to_graph.py
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
59
import argparse
import os
from enum import Enum
from components.fsm.states import (AnchorageState, BerthState, PilotState,
TugState, VesselState)
# To create a png file from the .dot file run
# dot -Tpng file.dot > file.png
parser = argparse.ArgumentParser(description="FSM Graph builder")
parser.add_argument("--out-folder", required=True, help="Output folder", type=str)
args = parser.parse_args()
# Create output folder if it does not exist
if not os.path.exists(args.out_folder):
os.makedirs(args.out_folder)
def generate_graph(state_cls: Enum):
graphviz_code = "digraph G {"
initial_state = state_cls.get_state_graph()["initial"]
for state in state_cls.all_states():
readable_state = state.replace("_", " ").capitalize()
if state == initial_state:
graphviz_code = f'{graphviz_code}\n\t{state}[label="{readable_state}", shape=doublecircle];'
else:
graphviz_code = f'{graphviz_code}\n\t{state}[label="{readable_state}"];'
graphviz_code = f"{graphviz_code}\n"
for transition in state_cls.get_state_graph()["events"]:
src, dst, name = transition["src"], transition["dst"], transition["name"]
if type(src) != list:
src = [src]
if type(dst) != list:
dst = [dst]
for src_state in src:
for dst_state in dst:
graphviz_code = (
f'{graphviz_code}\n\t{src_state} -> {dst_state}[label="{name}"];'
)
graphviz_code += "\n}"
return graphviz_code
state_graphs = [TugState, VesselState, AnchorageState, BerthState, PilotState]
graphs_names = ["tug.dot", "vessel.dot", "anchorage.dot", "berth.dot", "pilot.dot"]
for state_graph, graph_name in zip(state_graphs, graphs_names):
graphviz_code = generate_graph(state_graph)
with open(f"{args.out_folder}/{graph_name}", "w") as tmp_file:
tmp_file.write(graphviz_code)