3. Check solutions to equations: 2 step booklet python

The python file to make 2-step check solutions booklets is below.
The 2 custom python modules required are:
check_solution2_functions.py
The python file, check_solution_2step_booklet_maker.py, when run, will ask for these inputs:
Choose the first arithmetic process: "Enter 1, 2, 3, 4 or 5 for +, -, X, /, random"
Choose the second 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; with 10 per page"
Choose the file name base: "Enter the base filename to be added to the prefix check_solution2_Bk_:".
The filename will have β€œ_q” added for the question diagram and β€œ_ans” for the answer diagram.

3.1. Sample check solution 2step booklet

addition_multiplication_q

addition_multiplication_ans

division_subtraction_q

division_subtraction_ans

random_q

random_ans


3.2. Check solution: python

  1from pathlib import Path
  2import subprocess
  3import os
  4import time
  5# import magick_pdf_to_png
  6import check_solution_functions as chsolf
  7
  8
  9currfile_dir = Path(__file__).parent
 10tex_template_path = currfile_dir / "check_solution_2step_booklet_template.tex"
 11texans_template_path = currfile_dir / "check_solution_2step_booklet_ans_template.tex"
 12tex_diagram_template_path = currfile_dir / "check_solution_2step_booklet_diagram_template.tex"
 13
 14q_per_column = 5
 15q_per_page = q_per_column * 2
 16max_q = 100
 17
 18
 19def convert_to_pdf(tex_path, outputdir):
 20    tex_path = Path(tex_path).resolve()
 21    outputdir = Path(outputdir).resolve()
 22    # for testing
 23    # print(f"tex_path: {tex_path}")
 24    # print(f"outputdir: {outputdir}")
 25    try:
 26        # Generate the PDF
 27        subprocess.run(["latexmk", "-pdf", "-outdir=" + str(outputdir), str(tex_path)], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 28        # # Clean auxiliary files after successful PDF generation
 29        subprocess.run(["latexmk", "-c", "-outdir=" + str(outputdir), str(tex_path)], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 30        # for hosted remove stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL for debugging any errors
 31        # Remove the .tex file manually
 32        if tex_path.exists():
 33            os.remove(tex_path)
 34    except subprocess.CalledProcessError as e:
 35        print(f"Error: {e}")
 36
 37
 38# % end modify values for check_solution
 39# tex_keys = []
 40tex_keys_q = ["LHS", "LHSsub", "LHSval", "RHS", "side_equality", "is_a_sol"]
 41
 42
 43def make1_diagram(tex_diagram_template_txt, num1, num2):
 44    tex_diagram_template_txt_ans = tex_diagram_template_txt
 45    kv = chsolf.get_2step_process_dict(num1, num2)
 46
 47    for key, value in kv.items():
 48        tex_diagram_template_txt_ans = tex_diagram_template_txt_ans.replace("<<" + key + ">>", value)
 49
 50    for key, value in kv.items():
 51        if key not in tex_keys_q:
 52            tex_diagram_template_txt = tex_diagram_template_txt.replace("<<" + key + ">>", value)
 53        else:
 54            tex_diagram_template_txt = tex_diagram_template_txt.replace("<<" + key + ">>", kv[f"{key}q"])
 55
 56    return tex_diagram_template_txt, tex_diagram_template_txt_ans
 57
 58
 59def main():
 60    num1 = input("Enter 1, 2, 3, 4 or 5 for +, -, X, /, random for the 1st process \n")
 61    if num1.strip().isdigit():
 62        num1 = int(num1)
 63        if not num1 in [1, 2, 3, 4, 5]:
 64            num1 = 5  # random by default
 65    else:
 66        num1 = 5  # random by default
 67    #
 68    num2 = input("Enter 1, 2, 3, 4 or 5 for +, -, X, /, random for the 2nd process \n")
 69    if num2.strip().isdigit():
 70        num2 = int(num2)
 71        if not num2 in [1, 2, 3, 4, 5]:
 72            num2 = 5  # random by default
 73    else:
 74        num2 = 5  # random by default
 75    #
 76    numq = input("Enter the number of questions from 1 to 100; with 10 per page \n")
 77    if numq.strip().isdigit():
 78        numq = int(numq)
 79        if not numq in range(1, max_q + 1):
 80            numq = max_q  # max
 81    else:
 82        numq = q_per_page  # by default fits on one page
 83    #
 84    filename = input("Enter the base filename to be added to the prefix check_solution2_Bk_: \n")
 85    if not filename:
 86        filename = "1"  # "check_solution2_Bk_1_q and check_solution2_Bk_1_ans as default file"
 87    # set names of files that are made
 88    # questions
 89    tex_output_path = currfile_dir / f"check_solution2_Bk_{filename}_q.tex"
 90    pdf_path = currfile_dir / f"check_solution2_Bk_{filename}_q.pdf"
 91
 92    # answers
 93    tex_output_path_ans = currfile_dir / f"check_solution2_Bk_{filename}_ans.tex"
 94    pdf_path_ans = currfile_dir / f"check_solution2_Bk_{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    # Generate the <<diagram>> replacement tex
107    # diagram_text, diagram_text_ans = make1_diagram(tex_diagram_template_txt, num1)
108
109    # <<diagrams>>
110    # generate diagrams text and text for answers
111    diagrams_text = ""
112    diagrams_text_ans = ""
113    # add the headtext
114    # must have no space in \end{minipage}\columnbreak for column break to occur at correct place.
115    headtext_col = r"""\columnbreak
116    """
117    headtext_page = r"""\newpage
118    """
119    # headtext_page = r'''\newpage ~ \newline ~ \newline'''
120
121    for i in range(1, numq + 1):
122        img_tex, img_tex_ans = make1_diagram(tex_diagram_template_txt, num1, num2)
123        diagrams_text += img_tex
124        diagrams_text_ans += img_tex_ans
125        if i % q_per_page == 0 and numq + 1 > i:
126            diagrams_text += headtext_page
127            diagrams_text_ans += headtext_page
128        elif i % q_per_column == 0 and i > 1 and numq + 1 > i:
129            diagrams_text += headtext_col
130            diagrams_text_ans += headtext_col
131
132    # Replace the <<diagrams>> placeholder in the LaTeX template
133    tex_template_txt = tex_template_txt.replace("<<diagrams>>", diagrams_text)
134    tex_template_txt_ans = tex_template_txt_ans.replace("<<diagrams>>", diagrams_text_ans)
135    # Replace the <<chsol_filename>> placeholder in the LaTeX template
136    tex_template_txt = tex_template_txt.replace("<<chsol_filename>>", filename)
137    tex_template_txt_ans = tex_template_txt_ans.replace("<<chsol_filename>>", filename)
138
139
140    # Write the question diagrams tex to an output file
141    with open(tex_output_path, "w") as outfile:
142        outfile.write(tex_template_txt)
143    # Write the answer diagrams tex to an output file
144    with open(tex_output_path_ans, "w") as outfile:
145        outfile.write(tex_template_txt_ans)
146
147    # Wait for the files to be created
148    time.sleep(1)
149    # convert to pdf
150    convert_to_pdf(tex_output_path, currfile_dir)
151    convert_to_pdf(tex_output_path_ans, currfile_dir)
152
153    # Wait for the files to be created
154    # time.sleep(1)
155    # convert to png
156    # magick_pdf_to_png.convert_pdf_to_png(pdf_path, png_path)
157    # magick_pdf_to_png.convert_pdf_to_png(pdf_path_ans, png_path_ans)
158
159
160if __name__ == "__main__":
161    print("starting")
162    main()
163    print("finished")
The custom python module:

3.3. Check solution: LaTeX

 1%  \begin{enumerate}
 2\refstepcounter{minipagecount} % increments the counter minipagecount by one.
 3\noindent{(\theminipagecount)}\hspace{0.1mm} % By default, LaTeX indents the first line of a new paragraph, but \noindent overrides this
 4% and inserts the current value of the minipagecount counter, enclosed in parentheses
 5\begin{minipage}[t]{0.40\textwidth} % The [t] option aligns the top of the minipage with the baseline of the surrounding text.
 6    % \RaggedRight % From ragged2e to ensure no hyphenation
 7
 8    \noindent Determine whether \(<<pro_value>>\) is a solution to the equation \(<<equation>>\):
 9    \vspace{4pt}  % Ensure spacing between problem statement and solution
10
11    \noindent
12
13    \renewcommand{\arraystretch}{1.3} % Adjust line spacing in the aligned environment
14    \begin{tabular}{@{}p{0.60\linewidth}@{}p{0.40\linewidth}@{}}
15        \(\begin{aligned}
16            \text{LHS} &= <<LHS>> \\
17                    &= <<LHSsub>> \\
18                    &= <<LHSval>>
19        \end{aligned}\) &
20        \(\begin{aligned}
21            \text{RHS} &= <<RHS>>\\
22                    & \\
23                    &
24        \end{aligned}\)
25    \end{tabular}
26    \renewcommand{\arraystretch}{1.0} % Adjust line spacing in the aligned environment
27    \vspace{2pt}  % Optional spacing
28
29    \noindent \(\therefore\) Since \(\text{LHS} <<side_equality>> \text{RHS}\), \(<<pro_value>>\) <<is_a_sol>> a solution to the equation.
30
31\end{minipage}
32
33 \vspace*{16pt}
 1\documentclass[12pt]{article}
 2\usepackage{tikz}
 3\usepackage{amssymb}  % For \therefore symbol
 4\usepackage{amsmath}
 5% Underlining package
 6\usepackage[normalem]{ulem} % [normalem] prevents the package from changing the default behavior of \emph to underline.
 7\usepackage[a4paper, portrait, margin=1cm]{geometry}
 8\usepackage{multicol}
 9\usepackage{fancyhdr}
10\usepackage{ragged2e}
11
12\usepackage[none]{hyphenat}
13
14% \hyphenpenalty=10000
15% \exhyphenpenalty=10000
16% \hyphenchar\font=-1
17
18\def \HeadingQuestions {\section*{\Large Name: \underline{\hspace{8cm}} \hfill Date: \underline{\hspace{3cm}}} \vspace{-3mm}
19{<<chsol_filename>> Check Solution: Questions} \vspace{1pt}\hrule}
20
21% \linespread{1.5} % Adjust line spacing factor
22% \raggedbottom
23
24% raise footer with page number; no header
25\fancypagestyle{myfancypagestyle}{
26  \fancyhf{}% clear all header and footer fields
27  \renewcommand{\headrulewidth}{0pt} % no rule under header
28  \fancyfoot[C] {\thepage} \setlength{\footskip}{14.5pt} % raise page number allowed min 14.5pt
29}
30\pagestyle{myfancypagestyle}  % apply myfancypagestyle
31\newcounter{minipagecount}
32\begin{document}
33\HeadingQuestions
34\vspace{1pt}
35\begin{multicols}{2}
36  <<diagrams>>
37\end{multicols}
38\end{document}
 1\documentclass[12pt]{article}
 2\usepackage{tikz}
 3\usepackage{amssymb}  % For \therefore symbol
 4\usepackage{amsmath}
 5% Underlining package
 6\usepackage[normalem]{ulem} % [normalem] prevents the package from changing the default behavior of `\\emph` to underline.
 7\usepackage[a4paper, portrait, margin=1cm]{geometry}
 8\usepackage{multicol}
 9\usepackage{fancyhdr}
10\usepackage{ragged2e}
11\usepackage[none]{hyphenat}
12
13% \hyphenpenalty=10000
14% \exhyphenpenalty=10000
15% \hyphenchar\font=-1
16
17\def \HeadingAnswers {\section*{\Large Name: \underline{\hspace{8cm}} \hfill Date: \underline{\hspace{3cm}}} \vspace{-3mm}
18{<<chsol_filename>> Check Solution: Answers} \vspace{1pt}\hrule}
19
20% \linespread{1.5} % Adjust line spacing factor
21\raggedbottom
22
23% raise footer with page number; no header
24\fancypagestyle{myfancypagestyle}{
25  \fancyhf{}% clear all header and footer fields
26  \renewcommand{\headrulewidth}{0pt} % no rule under header
27  \fancyfoot[C] {\thepage} \setlength{\footskip}{14.5pt} % raise page number allowed min 14.5pt
28}
29\pagestyle{myfancypagestyle}  % apply myfancypagestyle
30\newcounter{minipagecount}
31\begin{document}
32\HeadingAnswers
33\vspace{1pt}
34\begin{multicols}{2}
35  <<diagrams>>
36\end{multicols}
37\end{document}