From 5ab525210cc74f6880f9c6f60adfc969ec5aa652 Mon Sep 17 00:00:00 2001 From: Maxim Slipenko <36362599+Maks1mS@users.noreply.github.com> Date: Sun, 19 Sep 2021 00:29:59 +0300 Subject: [PATCH] add graph generator --- turinglab/__main__.py | 17 +++++++++--- turinglab/image.py | 60 +++++++++++++++++++++++++++++++++++++++++++ turinglab/output.py | 7 +++-- 3 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 turinglab/image.py diff --git a/turinglab/__main__.py b/turinglab/__main__.py index fb1e220..d45286a 100644 --- a/turinglab/__main__.py +++ b/turinglab/__main__.py @@ -1,5 +1,7 @@ +import os import sys from argparse import ArgumentParser +from turinglab.image import get_image from turinglab.input import from_file from turinglab.emulator import Emulator from turinglab.output import to_docx @@ -8,7 +10,7 @@ def get_parser() -> ArgumentParser: parser = ArgumentParser() parser.add_argument("input_file", type=str, help="Path to file with program") parser.add_argument("input_string", type=str, help="Input symbols") - parser.add_argument("output_file", type=str, help="Output file") + parser.add_argument("output_dir", type=str, help="Output dir") return parser @@ -17,9 +19,15 @@ def main(): args = parser.parse_args() - program = from_file(args.input_file) + if os.path.exists(args.output_dir): + print('Directory already exists!') + return -1 + + os.makedirs(args.output_dir) + + tm = Emulator(program, args.input_string) data = [tm.info()] @@ -28,7 +36,10 @@ def main(): tm.step() data.append(tm.info()) - to_docx(args.output_file, program, data) + to_docx(os.path.join(args.output_dir, 'report.docx'), program, data) + + get_image(os.path.join(args.output_dir, 'graph'), program) + if __name__ == '__main__': main() \ No newline at end of file diff --git a/turinglab/image.py b/turinglab/image.py new file mode 100644 index 0000000..7ab4341 --- /dev/null +++ b/turinglab/image.py @@ -0,0 +1,60 @@ +import pydot +import requests +import shutil + +def get_image(filename, program): + g = pydot.Dot('my_graph', nodesep=0.5) + g.set_node_defaults( + width='1.5', + fontsize='18', + shape='circle' + ) + + rows = 0 + cols = len(program.keys()) + + for x in program.keys(): + if len(list(program[x].keys())) == 0: + continue + rows = max(list(program[x].keys())[-1] + 1, rows) + + program_table = [None] * rows + + for i in range(rows): + program_table[i] = [None] * cols + + symbols = [None] * cols + + for j, (symbol, value) in enumerate(program.items()): + symbols[j] = symbol + for i, (state, action) in enumerate(value.items()): + program_table[state][j] = action + + g.add_node(pydot.Node(f'gz', label='z>', shape='circle')) + + for i in range(rows): + g.add_node(pydot.Node(f'g{i}', label=f'{i}>', shape='circle')) + for j in range(cols): + action = program_table[i][j] + if action is None: continue + + symbol, direction, state = action + label = symbols[j] + '/' + symbol + '/' + ('R' if direction == '>' else 'L') + src = f'g{i}' + dst = f'g{"z" if state == -1 else state}' + if src == dst: + src = src + ':ne' + dst = dst + ':se' + g.add_edge(pydot.Edge(src, dst, label = label)) + + + g.write_raw(f'{filename}.dot', encoding='utf-8') + + try: + g.write_svg(f'{filename}.svg', encoding='utf-8') + except Exception: + output_raw_dot = g.to_string() + img_data = requests.get("https://quickchart.io/graphviz?graph=" + output_raw_dot).content + with open(f'{filename}_quickchart.svg', 'wb') as handler: + handler.write(img_data) + \ No newline at end of file diff --git a/turinglab/output.py b/turinglab/output.py index 3ab0f78..88daf3e 100644 --- a/turinglab/output.py +++ b/turinglab/output.py @@ -1,7 +1,8 @@ +from turinglab.image import get_image from docx import Document from docx.oxml import OxmlElement from docx.oxml.ns import qn -from docx.shared import Pt +from docx.shared import Pt, Inches from docx.enum.text import WD_LINE_SPACING from docx.enum.text import WD_ALIGN_PARAGRAPH @@ -22,6 +23,8 @@ def to_docx(filename, program, data): cols = len(program.keys()) for x in program.keys(): + if len(list(program[x].keys())) == 0: + continue rows = max(list(program[x].keys())[-1] + 1, rows) program_table = [None] * rows @@ -51,7 +54,7 @@ def to_docx(filename, program, data): p.add_run(symbols[j] + ' → ') add_state(p, state) - p.add_run(symbol + 'R' if direction == '>' else 'L') + p.add_run(symbol + ('R' if direction == '>' else 'L')) p = document.add_paragraph()