3. Backtracking 1 step diagram - automatedο
"Enter 1, 2, 3, 4 or 5 for +, -, X, /, random""Enter the base filename to be added to the prefix bt1_:".3.1. A 1-step backtracking diagram with answersο
3.2. Splitting the LaTeX and modifying it for pythonο
3.2.1. Document templateο
1% backtracking worksheet template
2\documentclass[border = 1mm]{standalone}
3\usepackage{tikz}
4\usetikzlibrary{positioning}
5\usetikzlibrary {arrows.meta}
6
7\tikzset{backtrack/.style={rectangle,draw=black,fill=white,
8inner sep=2pt,minimum height=32pt, minimum width=20mm}}
9\tikzset{backtrackeq/.style={rectangle,draw=black,fill=white,
10inner sep=2pt,minimum height=12pt, minimum width=20mm}}
11\tikzset{backtrackstep/.style={rectangle,draw=none,fill=white,
12inner sep=2pt,minimum height=12pt, minimum width=20mm}}
13
14\begin{document}
15 <<diagram>>
16\end{document}
<<diagram>> is placeholder text for the text that python will use to add the LaTeX for the backtracking diagram.3.2.2. Diagram templateο
1\begin{tikzpicture}
2
3 \node[backtrack] (boxA) at (0, 0) {$<<boxA>>$};
4 \node[backtrack] (boxB) [right=1cm of boxA] {$<<boxB>>$};
5
6 \node[backtrackeq] (boxAeq) [below=-1pt of boxA] {$=$};
7 \node[backtrackeq] (boxBeq) [below=-1pt of boxB] {$=$};
8
9 \node[backtrack] (boxArev) [below=-1pt of boxAeq] {$<<boxArev>>$};
10 \node[backtrack] (boxBrev) [below=-1pt of boxBeq] {$<<boxBrev>>$};
11
12 \node(boxAr) at ([yshift=24pt,xshift=5mm]boxA) { };
13 \node(boxBl) at ([yshift=24pt,xshift=-5mm]boxB) { };
14 \draw [line width=0.4pt,-{Stealth[length=2mm]}] (boxAr) --node[backtrackstep, above=3.0pt] {$<<stepAB>>$} (boxBl);
15
16 \node(boxBrevl) at ([yshift=-24pt,xshift=-5mm]boxBrev) { };
17 \node(boxArevr) at ([yshift=-24pt,xshift=5mm]boxArev) { };
18 \draw [line width=0.4pt,-{Stealth[length=2mm]}] (boxBrevl) --node[backtrackstep, below=3.0pt] {$<<stepABrev>>$} (boxArevr);
19
20\end{tikzpicture}
21
22
23
3.2.3. Example of a placeholderο
\node[backtrack] (boxB) [right=1cm of boxA] {$<<boxB>>$} has a placeholder <<boxB>> which is replaced by python.3.2.4. Python to create a 1 step diagramο
This Python code requires two user inputs: a1 to 4 to choose the arithmetic operation, and the filename to be used.
The code reads in three template files: tex_template_path, texans_template_path, and tex_diagram_template_path. The contents of these files are stored in the variables tex_template_txt, tex_template_txt_ans, and tex_diagram_template_txt, respectively.
The code then calls the make1_diagram function, passing in tex_diagram_template_txt as an argument. kv = btf.get_1step_process_dict() gets the dictionary containing the values to be placed in the diagram template. The make1_diagram function generates a diagram and returns two values: diagram_text and diagram_text_ans. These values are then used to replace the <<diagram>> placeholder in the tex_template_txt and tex_template_txt_ans variables.
The resulting text is then written to two output files: tex_output_path and tex_output_path_ans.
The code then waits for 1 second to ensure that the files have been created before calling the convert_to_pdf function to convert these TeX files to PDFs. The PDFs are saved to the paths specified by the pdf_path and pdf_path_ans variables.
After waiting for another second, the code calls the magick_pdf_to_png.convert_pdf_to_png function to convert the PDFs to PNGs. The PNGs are saved to the paths specified by the png_path and png_path_ans variables.
The script prints βstartingβ and βfinishedβ messages to indicate when it begins and ends its execution.
1from pathlib import Path
2import subprocess
3import os
4import time
5import random
6import magick_pdf_to_png
7import backtracking_functions as btf
8
9currfile_dir = Path(__file__).parent
10tex_template_path = currfile_dir / "backtrack_1step_template.tex"
11texans_template_path = currfile_dir / "backtrack_1step_template.tex"
12tex_diagram_template_path = currfile_dir / "backtrack_1step_diagram_template.tex"
13
14
15def convert_to_pdf(tex_path, outputdir):
16 tex_path = Path(tex_path).resolve()
17 outputdir = Path(outputdir).resolve()
18 # for testing
19 # print(f"tex_path: {tex_path}")
20 # print(f"outputdir: {outputdir}")
21 try:
22 # Generate the PDF
23 subprocess.run(["latexmk", "-pdf", "-outdir=" + str(outputdir), str(tex_path)], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
24 # # Clean auxiliary files after successful PDF generation
25 subprocess.run(["latexmk", "-c", "-outdir=" + str(outputdir), str(tex_path)], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
26 # for hosted remove stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL for debugging any errors
27 # Remove the .tex file manually
28 if tex_path.exists():
29 os.remove(tex_path)
30 except subprocess.CalledProcessError as e:
31 print(f"Error: {e}")
32
33
34# tex_keys = ['stepAB','stepABrev','boxA','boxB','boxBrev', 'boxArev' ]
35tex_keys_q = ["stepAB", "boxA", "boxBrev"]
36
37
38def make1_diagram(tex_diagram_template_txt, num):
39 tex_diagram_template_txt_ans = tex_diagram_template_txt
40 kv = btf.get_1step_process_dict(num)
41 for key, value in kv.items():
42 tex_diagram_template_txt_ans = tex_diagram_template_txt_ans.replace(
43 "<<" + key + ">>", value
44 )
45 for key, value in kv.items():
46 if key in tex_keys_q:
47 tex_diagram_template_txt = tex_diagram_template_txt.replace(
48 "<<" + key + ">>", value
49 )
50 else:
51 tex_diagram_template_txt = tex_diagram_template_txt.replace(
52 "<<" + key + ">>", ""
53 )
54 return tex_diagram_template_txt, tex_diagram_template_txt_ans
55
56
57def main():
58 num = input("Enter 1, 2, 3, 4 or 5 for +, -, X, /, random \n")
59 if num.strip().isdigit():
60 num = int(num)
61 if not num in [1, 2, 3, 4, 5]:
62 num = 5 # random by default
63 else:
64 num = 5 # random by default
65 filename = input("Enter the base filename to be added to the prefix bt1_: \n")
66 if not filename:
67 filename = "1" # "bt1_1st_q and bt1_1st_ans as default file"
68 # set names of files that are made
69 # questions
70 tex_output_path = currfile_dir / f"bt1_{filename}_q.tex"
71 pdf_path = currfile_dir / f"bt1_{filename}_q.pdf"
72 png_path = currfile_dir / f"bt1_{filename}_q.png"
73
74 # answers
75 tex_output_path_ans = currfile_dir / f"bt1_{filename}_ans.tex"
76 pdf_path_ans = currfile_dir / f"bt1_{filename}_ans.pdf"
77 png_path_ans = currfile_dir / f"bt1_{filename}_ans.png"
78
79 # Read in the LaTeX template file
80 with open(tex_template_path, "r") as infile:
81 tex_template_txt = infile.read()
82 # Read in the LaTeX template file for answers
83 with open(texans_template_path, "r") as infile:
84 tex_template_txt_ans = infile.read()
85 # Read in the LaTeX diagram template file
86 with open(tex_diagram_template_path, "r") as infile:
87 tex_diagram_template_txt = infile.read()
88
89 # Generate the <<diagram>> replacement tex
90 diagram_text, diagram_text_ans = make1_diagram(tex_diagram_template_txt, num)
91 # Replace the <<diagram>> placeholder in the LaTeX template
92 tex_template_txt = tex_template_txt.replace("<<diagram>>", diagram_text)
93 tex_template_txt_ans = tex_template_txt_ans.replace("<<diagram>>", diagram_text_ans)
94 # Write the question diagram tex to an output file
95 with open(tex_output_path, "w") as outfile:
96 outfile.write(tex_template_txt)
97 # Write the answer diagram tex to an output file
98 with open(tex_output_path_ans, "w") as outfile:
99 outfile.write(tex_template_txt_ans)
100
101 # Wait for the files to be created
102 time.sleep(1)
103 # convert to pdf
104 convert_to_pdf(tex_output_path, currfile_dir)
105 convert_to_pdf(tex_output_path_ans, currfile_dir)
106
107 # Wait for the files to be created
108 time.sleep(1)
109 # convert to png
110 magick_pdf_to_png.convert_pdf_to_png(pdf_path, png_path)
111 magick_pdf_to_png.convert_pdf_to_png(pdf_path_ans, png_path_ans)
112
113
114if __name__ == "__main__":
115 print("starting")
116 main()
117 print("finished")