5. Number Lines booklet python

The python below requires 3 .tex files:

  1. number_lines_booklet_template.tex

  2. number_lines_booklet_ans_template.tex

  3. number_lines_booklet_diagram_template.tex

5.1. Python to create multi page booklets of number lines

The python file, number_lines_booklet_maker.py, when run, will ask for these inputs:
Choose the arithmetic process: "Enter 1,2,3,4,5 or 6 for plus,minus_neg,minus,minus_pos,plus_neg,random".
Choose the number of questions from 1 to 100: "Enter the number of questions from 1 to 80, with 8 per page"
Choose the file name base: ""Enter the base filename to be added to the prefix nlBk:".
The filename will have β€œ_q” added for the question booklet and β€œ_ans” for the answer booklet.

number_lines_booklet_maker.py

  1from pathlib import Path
  2import subprocess
  3import os
  4import time
  5import random
  6import os
  7import magick_pdf_to_png
  8import number_lines_functions as nlf
  9
 10
 11currfile_dir = Path(__file__).parent
 12tex_template_path = currfile_dir / "number_lines_booklet_template.tex"
 13texans_template_path = currfile_dir / "number_lines_booklet_ans_template.tex"
 14tex_diagram_template_path = currfile_dir / "number_lines_booklet_diagram_template.tex"
 15
 16# gaps = "\qgap"
 17# gaps = "\dotuline{\phantom{X}}"
 18gaps = "\raisebox{-2pt}{\dotuline{\phantom{X}}"
 19
 20def convert_to_pdf(tex_path, outputdir):
 21    tex_path = Path(tex_path).resolve()
 22    outputdir = Path(outputdir).resolve()
 23    # for testing
 24    # print(f"tex_path: {tex_path}")
 25    # print(f"outputdir: {outputdir}")
 26    try:
 27        # Generate the PDF
 28        subprocess.run(["latexmk", "-pdf", "-outdir=" + str(outputdir), str(tex_path)], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 29        # # Clean auxiliary files after successful PDF generation
 30        subprocess.run(["latexmk", "-c", "-outdir=" + str(outputdir), str(tex_path)], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 31        # for hosted remove stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL for debugging any errors
 32        # Remove the .tex file manually
 33        # if tex_path.exists():
 34        #     os.remove(tex_path)
 35    except subprocess.CalledProcessError as e:
 36        print(f"Error: {e}")
 37
 38
 39
 40kv_keys_ans = ["startval", "endval", "startvaltxt", "endvaltxt", "changevaltxt", "equtxt"]
 41kv_keys_q = ["startval", "endval", "startvaltxt_q", "endvaltxt_q", "changevaltxt_q", "equtxt_q"]
 42
 43
 44def trimkey(key):
 45    key = key.replace("_q", "")
 46    return key
 47
 48
 49def make1_diagram(tex_diagram_template_txt, num):
 50    posttext = r"\vspace{-2pt}"
 51    tex_diagram_template_txt_ans = tex_diagram_template_txt
 52    kv = nlf.getprocess_dict(num)
 53    for key, value in kv.items():
 54        # show answers
 55        if key in kv_keys_ans:
 56            tex_diagram_template_txt_ans = tex_diagram_template_txt_ans.replace("<<" + key + ">>", value)
 57    for key, value in kv.items():
 58        # don't show answers, use ___ for gaps
 59        if key in kv_keys_q:
 60            tex_diagram_template_txt = tex_diagram_template_txt.replace("<<" + trimkey(key) + ">>", value)
 61    return tex_diagram_template_txt + posttext, tex_diagram_template_txt_ans + posttext
 62
 63
 64def main():
 65    num = input(
 66        "Enter 1,2,3,4,5 or 6 for plus,minus_neg,minus,minus_pos,plus_neg,random \n"
 67    )
 68    if num.strip().isdigit():
 69        num = int(num)
 70        if not num in [1, 2, 3, 4, 5, 6]:
 71            num = 6  # random by default
 72    else:
 73        num = 6  # random by default
 74    #
 75    numq = input(
 76        "Enter the number of questions from 1 to 80, with 8 per page \n")
 77    if numq.strip().isdigit():
 78        numq = int(numq)
 79        if not numq in range(1, 81):
 80            numq = 16  # random by default
 81    else:
 82        numq = 16  # random by default
 83    #
 84    filename = input(
 85        "Enter the base filename to be added to the prefix nlBk_: \n")
 86    if not filename:
 87        filename = "1"  # "nlBk_1st_q and nlBk_1st_ans as default file"
 88    # set names of files that are made
 89    tex_output_path = currfile_dir / f"nlBk_{filename}_q.tex"
 90    pdf_path = currfile_dir / f"nlBk_{filename}_q.pdf"
 91
 92    # answers
 93    tex_output_path_ans = currfile_dir / f"nlBk_{filename}_ans.tex"
 94    pdf_path_ans = currfile_dir / f"nlBk_{filename}_ans.pdf"
 95
 96    # Read in the LaTeX template file
 97    with open(tex_template_path, "r") as infile:
 98        tex_template_txt = infile.read()
 99    # Read in the LaTeX template file for answers
100    with open(texans_template_path, "r") as infile:
101        tex_template_txt_ans = infile.read()
102    # Read in the LaTeX diagram template file
103    with open(tex_diagram_template_path, "r") as infile:
104        tex_diagram_template_txt = infile.read()
105
106    # <<diagrams>>
107    # generate diagrams text and text for answers
108    diagrams_text = ""
109    diagrams_text_ans = ""
110    # add the headtext
111    headtext = r"\pagebreak ~ \newline ~ \newline"
112    for i in range(1, numq + 1):
113        img_tex, img_tex_ans = make1_diagram(tex_diagram_template_txt, num)
114        if i > 8 and i % 8 == 1:
115            diagrams_text += headtext
116            diagrams_text_ans += headtext
117        diagrams_text += img_tex
118        diagrams_text_ans += img_tex_ans
119
120    # Replace the <<title>> placeholder in the LaTeX template
121    tex_template_txt = tex_template_txt.replace("<<title>>", title)
122    tex_template_txt_ans = tex_template_txt_ans.replace("<<title>>", title)
123    # Replace the <<diagrams>> placeholder in the LaTeX template with the generated diagrams
124    tex_template_txt = tex_template_txt.replace("<<diagrams>>", diagrams_text)
125    tex_template_txt_ans = tex_template_txt_ans.replace(
126        "<<diagrams>>", diagrams_text_ans)
127    # Write the question tex to an output file
128    with open(tex_output_path, "w") as outfile:
129        outfile.write(tex_template_txt)
130
131    # Write the answer tex to an output file
132    with open(tex_output_path_ans, "w") as outfile:
133        outfile.write(tex_template_txt_ans)
134
135    # Wait for the file to be created
136    time.sleep(2)
137    # Convert the LaTeX files to PDFs
138    convert_to_pdf(tex_output_path, currfile_dir)
139    convert_to_pdf(tex_output_path_ans, currfile_dir)
140
141    # # don't convert to images
142    # time.sleep(1)
143    # # Convert the PDFs to PNGs
144    # magick_pdf_to_png.convert_pdf_to_png(pdf_path,png_path)
145    # magick_pdf_to_png.convert_pdf_to_png(pdf_path_ans,png_path_ans)
146
147
148if __name__ == "__main__":
149    print("starting")
150    main()
151    print("finished")