7. Backtracking 1-step booklet python

The 2 custom python modules required are:
The Python to create a multi page booklet of 1-step backtracking worksheets, with 10 backtracking diagrams per page, is below.
The python file, backtracking_1step_booklet_maker.py, when run, will ask for these inputs:
  • Choose the arithmetic process: "Enter 1, 2, 3, 4 or 5 for +, -, X, /, random".

  • Choose the number of questions from 1 to 100: "Enter the number of questions from 1 to 100"

  • Choose the file name base: "Enter the base filename to be added to the prefix bt1Bk_:". The filename will have β€œ_q” added for the question booklet and β€œ_ans” for the answer booklet.

  1from pathlib import Path
  2import subprocess
  3import time
  4import random
  5import magick_pdf_to_png
  6import backtracking_functions as btf
  7
  8currfile_dir = Path(__file__).parent
  9tex_template_path = currfile_dir / "backtrack_1step_booklet_template.tex"
 10texans_template_path = currfile_dir / "backtrack_1step_booklet_ans_template.tex"
 11tex_diagram_template_path = (
 12    currfile_dir / "backtrack_1step_worksheet_diagram_template.tex"
 13)
 14
 15
 16def convert_to_pdf(tex_path, currfile_dir, aux_path):
 17    """
 18    Converts a TeX file to PDF format using pdfLaTeX.
 19
 20    Args:
 21        tex_path (str): The path to the TeX file.
 22        currfile_dir (str): The path to the directory where the TeX file is located.
 23        aux_path (str): The path to the directory where auxiliary files will be stored.
 24
 25    Returns:
 26        subprocess.CompletedProcess: A subprocess.CompletedProcess object containing information about the completed process.
 27
 28    Raises:
 29        FileNotFoundError: If the TeX file does not exist.
 30        subprocess.CalledProcessError: If pdfLaTeX returns a non-zero exit code.
 31    """
 32    result = subprocess.run(
 33        [
 34            "pdfLaTeX",
 35            tex_path,
 36            "-output-directory",
 37            currfile_dir,
 38            "-aux-directory",
 39            aux_path,
 40        ],
 41        stdout=subprocess.PIPE,
 42    )
 43
 44
 45# tex_keys = ['stepAB','stepABrev','boxA','boxB','boxBrev', 'boxArev' ]
 46tex_keys_q = ["stepAB", "boxA", "boxBrev"]
 47
 48
 49def make1_diagram(tex_diagram_template_txt, num):
 50    tex_diagram_template_txt_ans = tex_diagram_template_txt
 51    posttext = r"\vspace{-2pt}"
 52    kv = btf.get_1step_process_dict(num)
 53
 54    for key, value in kv.items():
 55        tex_diagram_template_txt_ans = tex_diagram_template_txt_ans.replace(
 56            "<<" + key + ">>", value
 57        )
 58
 59    for key, value in kv.items():
 60        if key in tex_keys_q:
 61            tex_diagram_template_txt = tex_diagram_template_txt.replace(
 62                "<<" + key + ">>", value
 63            )
 64        else:
 65            tex_diagram_template_txt = tex_diagram_template_txt.replace(
 66                "<<" + key + ">>", ""
 67            )
 68
 69    # return tex_diagram_template_txt
 70    return tex_diagram_template_txt + posttext, tex_diagram_template_txt_ans + posttext
 71
 72
 73def main():
 74    num = input("Enter 1, 2, 3, 4 or 5 for +, -, X, /, random \n")
 75    if num.strip().isdigit():
 76        num = int(num)
 77        if not num in [1, 2, 3, 4, 5]:
 78            num = 5  # random by default
 79    else:
 80        num = 5  # random by default
 81    #
 82    numq = input("Enter the number of questions from 1 to 100 \n")
 83    if numq.strip().isdigit():
 84        numq = int(numq)
 85        if not numq in range(1,101):
 86            numq = 20  # random by default
 87    else:
 88        numq = 20  # random by default
 89    #
 90    filename = input("Enter the base filename to be added to the prefix bt1WS_: \n")
 91    if not filename:
 92        filename = "1"  # "bt1Bk_1_q and bt1Bk_1_ans as default file"
 93    # set names of files that are made
 94    # questions
 95    tex_output_path = currfile_dir / f"bt1Bk_{filename}_q.tex"
 96    aux_path = currfile_dir / "temp"
 97    # answers
 98    tex_output_path_ans = currfile_dir / f"bt1Bk_{filename}_ans.tex"
 99
100    # Read in the LaTeX template file
101    with open(tex_template_path, "r") as infile:
102        tex_template_txt = infile.read()
103    # Read in the LaTeX template file for answers
104    with open(texans_template_path, "r") as infile:
105        tex_template_txt_ans = infile.read()
106    # Read in the LaTeX diagram template file
107    with open(tex_diagram_template_path, "r") as infile:
108        tex_diagram_template_txt = infile.read()
109
110    # <<cols>>
111    # generate column text and column text for answers
112    col1_text = ""
113    col1_text_ans = ""
114    rmax = numq + 1
115    for _ in range(1, rmax):
116        img_tex, img_tex_ans = make1_diagram(tex_diagram_template_txt, num)
117        col1_text += img_tex
118        col1_text_ans += img_tex_ans
119
120    # Replace the <<cols>> placeholder in the LaTeX template with the generated diagrams
121    tex_template_txt = tex_template_txt.replace("<<cols>>", col1_text)
122    tex_template_txt_ans = tex_template_txt_ans.replace("<<cols>>", col1_text_ans)
123
124    # Write the question tex to an output file
125    with open(tex_output_path, "w") as outfile:
126        outfile.write(tex_template_txt)
127
128    # Write the answer tex to an output file
129    with open(tex_output_path_ans, "w") as outfile:
130        outfile.write(tex_template_txt_ans)
131
132    # Wait for the file to be created
133    time.sleep(1)
134    # Convert the LaTeX files to PDFs
135    convert_to_pdf(tex_output_path, currfile_dir, aux_path)
136    convert_to_pdf(tex_output_path_ans, currfile_dir, aux_path)
137
138
139if __name__ == "__main__":
140    print("starting")
141    main()
142    print("finished")