5. Number Lines booklet pythonο
The python below requires 3 .tex files:
number_lines_booklet_template.tex
number_lines_booklet_ans_template.tex
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.
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")