add graph generator

This commit is contained in:
Maxim Slipenko 2021-09-19 00:29:59 +03:00
parent 71bffa4243
commit 5ab525210c
3 changed files with 79 additions and 5 deletions

View File

@ -1,5 +1,7 @@
import os
import sys import sys
from argparse import ArgumentParser from argparse import ArgumentParser
from turinglab.image import get_image
from turinglab.input import from_file from turinglab.input import from_file
from turinglab.emulator import Emulator from turinglab.emulator import Emulator
from turinglab.output import to_docx from turinglab.output import to_docx
@ -8,7 +10,7 @@ def get_parser() -> ArgumentParser:
parser = ArgumentParser() parser = ArgumentParser()
parser.add_argument("input_file", type=str, help="Path to file with program") 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("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 return parser
@ -17,9 +19,15 @@ def main():
args = parser.parse_args() args = parser.parse_args()
program = from_file(args.input_file) 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) tm = Emulator(program, args.input_string)
data = [tm.info()] data = [tm.info()]
@ -28,7 +36,10 @@ def main():
tm.step() tm.step()
data.append(tm.info()) 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__': if __name__ == '__main__':
main() main()

60
turinglab/image.py Normal file
View File

@ -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='<g<SUB>z</SUB>>', shape='circle'))
for i in range(rows):
g.add_node(pydot.Node(f'g{i}', label=f'<g<SUB>{i}</SUB>>', 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)

View File

@ -1,7 +1,8 @@
from turinglab.image import get_image
from docx import Document from docx import Document
from docx.oxml import OxmlElement from docx.oxml import OxmlElement
from docx.oxml.ns import qn 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_LINE_SPACING
from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.enum.text import WD_ALIGN_PARAGRAPH
@ -22,6 +23,8 @@ def to_docx(filename, program, data):
cols = len(program.keys()) cols = len(program.keys())
for x in program.keys(): for x in program.keys():
if len(list(program[x].keys())) == 0:
continue
rows = max(list(program[x].keys())[-1] + 1, rows) rows = max(list(program[x].keys())[-1] + 1, rows)
program_table = [None] * rows program_table = [None] * rows
@ -51,7 +54,7 @@ def to_docx(filename, program, data):
p.add_run(symbols[j] + '') p.add_run(symbols[j] + '')
add_state(p, state) 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() p = document.add_paragraph()