Tutorial¶
Note
You can visit the Worksheets page if you are just interested to download the existing worksheets of exercises. This document is to show how to create exercises and templates to produce custom worksheets in your own computer.
This tutorial is intended for new users of project worksheet.cc. It does not give an exhaustive account of all the features of worksheet.cc libraries, just of those that you are likely to use right away.
Problem statement¶
Karl is a math secondary-level teacher. He brought math worksheets to students in order to practice routinary skills. In the past, Karl did it by hand, but he saw that he needed some computer program to do it automatically. He searched the internet and found project worksheet.
Karl’s problem is creating a worksheet for practicing fraction addition. He wants a sheet for each student and also wants to have the possibility of generating as many different worksheets as he wants. And he wants to do it automatically. He desires to generate a PDF document file using professional publication system like LaTeX or ConTeXt.
To do that, first of all, he needs to write an exercise. This exercise is simple:
Sum $\frac{a}{b} + \frac{c}{d}$
where \(a\), \(b\), \(c\) and \(d\) are integers, with the constraint \(b, d \neq 0\). Thus, this exercise depends on four parameters.
He decides to put extra conditions of those parameters:
\(1 \leq a, c \leq 100\) to have resulting small numbers in the operations
\(d = b + 2\) to assure some relation between \(d\) and \(b\) (for instance these are different numbers) and \(2 \leq b \leq 100\)
Creating the exercise¶
With all of previous decissions and constraints, he writes his first exercise:
---
parameters:
a: random.randint(1,100)
b: random.randint(2, 100)
c: random.randint(1,100)
d: params['b'] + 2
solution: |
{% set sum = fractions.Fraction(params['a']*params['d'] + params['b']*params['c'], params['b']*params['d']) %}
The solution is $\frac{ {{sum.numerator}} }{ {{sum.denominator}} }$.
---
Calculate the sum of $\frac{ {{params['a']}} }{ {{params['b']}} } + \frac{ {{params['c']}} }{ {{params['d']}} }$
He saves as tutorial-exercise.md
.
Note that:
The exercise has two parts: the YAML header which is enclosed by the symbols
---
, and the rest of the file. By convention, we assume that the rest of the file corresponds to the text or statement of the exercise while in the YAML headers there is the extra information like solution, resolution, author, etc. The YAML-headers keys are totally optional.The parameters are specified in the
parameters
key in the YAML header.We could define relation among parameters using
params[x]
variable. Theparams
corresponds to the evaluation of theparameters
keys (seewklib.Exercise.params()
function).The file uses Jinja template system syntax: in this example, we call a variable
foo
value using{{foo}}
.
Creating the template¶
To generate an instance (mathematically, a numerical value or a evaluation) of the exercise, Karl needs a template. He needs it to compose the different components of the exercise: how statement and solution will be displayed. And also to set the appearance of the exercise sheet: headers, fonts, margins, etc. It can be said that it is the visual part of the resulting worksheet.
To produce the final PDF file, he decides to use LaTeX. Therefore, he creates a simple template file, called mytemplate.tex
:
\documentclass{article}
\usepackage{amsmath}
\usepackage{hyperref}
\title{Fractions worksheet}
\author{Karl Kronecker}
\begin{document}
\maketitle
\section{Exercises}
\begin{enumerate}
{% for e in exercises %}
\item\label{ {{e.id}} } {{e.text}}
{% endfor %}
\end{enumerate}
\newpage
\section{Solutions}
\begin{enumerate}
{% for e in exercises %}
\item[\ref{ {{e.id}} }.] {{e.solution}}
{% endfor %}
\end{enumerate}
\end{document}
Here the exercises
variable contains all the evaluations of the exercises. In our case, there is only one exercise for now.
This template is very simple: it lists all exercises in the first page using enumerate
environment. And it lists their solution in the second page. Karl intends to replace it with a more complex and improved one in the future.
Running the terminal user interface¶
With all of this, Karl runs the terminal user interface (also known as TUI), called wk.py
:
python wk.py mytemplate.tex tutorial-exercise.md > tutorial-sheet.tex
which generates the LaTeX document tutorial-sheet.tex
:
$ cat src/tutorial-sheet.tex
\documentclass{article}
\usepackage{amsmath}
\title{Fractions worksheet}
\author{Karl Kronecker}
\begin{document}
\maketitle
\section{Exercises}
\begin{enumerate}
\item\label{ 31cbc9a1428197e954f092692d3a6f29becbb607c683a855967c837726224692 } Calculate the sum of $\frac{ 19 }{ 65 } + \frac{ 8 }{ 67 }$
\end{enumerate}
\newpage
\section{Solutions}
\begin{enumerate}
\item[\ref{ 31cbc9a1428197e954f092692d3a6f29becbb607c683a855967c837726224692 }.] The solution is $\frac{ 1793 }{ 4355 }$.
\end{enumerate}
\end{document}
Karl finally compiles tutorial-sheet.tex
using pdflatex
and he obtains the desired PDF file
.
Adding more exercises¶
Creating a worksheet with only one exercise is very poor. Worksheet usually have more! Therefore Karl adds more exercises to his worksheet. He simply repeats as many he wants tutorial-exercise.md
in the invocation of wk.py
in comand line:
python wk.py mytemplate.tex tutorial-exercise.md tutorial-exercise.md tutorial-exercise.md tutorial-exercise.md > tutorial-sheet.tex
Thus, repating the previous steps, Karl has a worksheet of 4 exercises
and some promising PDF file
of what he desired at the beginning:
pdflatex tutorial-sheet.tex
# it generates tutorial-sheet.pdf
Using extra variables¶
Karl wants to make the template more abstract in order to use it in a more wide range of situations. In the first place, he decides to pass the title as an extra parameter. Thus, he modifies the template
.
\usepackage{hyperref}
{% if title %}
\title{ {{title}} }
{% else %}
\title{Worksheet}
{% endif %}
It allows to specify the title of the worksheet and if it is not specified, it is set to “Worksheet”.
The way to specify the title is using --metadata
parameter:
python wk.py mytemplate-v2.tex tutorial-exercise.md tutorial-exercise.md tutorial-exercise.md tutorial-exercise.md --metadata title="Fractions Worksheet (version 2)" > tutorial-sheet.tex
pdflatex tutorial-sheet.tex
# it generates tutorial-sheet.pdf
But Karl thinks it is convenient to put the version
of the document. However, it needs that it were an integer, not string, for example to see the revision
of the document (which equals to \(version -1\)). For that, he uses --evals
shell parameter, specifying it:
python wk.py mytemplate-v3.tex tutorial-exercise.md tutorial-exercise.md tutorial-exercise.md tutorial-exercise.md --metadata title="Fractions Worksheet" version="3" --evals version > tutorial-sheet.tex
pdflatex tutorial-sheet.tex
# it generates tutorial-sheet.pdf
He modifies the template
in order to incorporate that change:
[...]
{% if title %}
{% if version %}
\title{ {{title}} (version {{version}}) }
{% else %}
\title{ {{title}} }
{% endif %}
{% else %}
\title{Worksheet}
{% endif %}
[...]
{% if version %}
This document has been revised {{version -1}} times.
{% endif %}
He obtains what he wants
.
Multiplicity¶
It is tedious to repeat the name of an exercise in command line to obtain a repeated exercise in the worksheet. For this reason, Karl uses --multiplicity
argument. Then, the previous example is transformed to:
python wk.py mytemplate-v3.tex tutorial-exercise.md --multiplicity 0:4 --metadata title="Fractions Worksheet" version="3" --evals version > tutorial-sheet.tex
pdflatex tutorial-sheet.tex
# it generates tutorial-sheet.pdf
Note that the index of multiplicity begins at 0, not at 1. In this example, --multiplicity 0:4
means that exercise at position 0 (tutorial-exercise.md
in this case) occurs 4 times. If Karl had two different exercises, he could specify their multiplicity also. For example:
python wk.py mytemplate-v3.tex tutorial-exercise.md tutorial-exercise2.md --multiplicity 0:4 1:5 [...]
which means that the first exercise tutorial-exercise.md
is repeated 4 times and the second exercise tutorial-exercise2.md
is repeated 5 times.
Shortening the process¶
Instead of using >
in order to save result of wk.py
in tutorial-sheet.tex
, Karl uses --outputfile
option:
python wk.py mytemplate-v3.tex tutorial-exercise.md --multiplicity 0:4 --metadata title="Fractions Worksheet" version="3" --evals version --outputfile tutorial-sheet.tex
pdflatex tutorial-sheet.tex
# it generates tutorial-sheet.pdf
And, finally he uses --postprocess
option to automatically run pdflatex
just after save result to tutorial-sheet.tex
file:
python wk.py mytemplate-v3.tex tutorial-exercise.md --multiplicity 0:4 --metadata title="Fractions Worksheet" version="3" --evals version --outputfile tutorial-sheet.tex --postprocess pdflatex
# it generates tutorial-sheet.pdf
Karl, now, generates a reasonably good worksheet of fractions with just one line.