Skip to content

Commit

Permalink
Adds support for exercise environments (fixes #6)
Browse files Browse the repository at this point in the history
Exercises are also included, they are transformed into question format
to fit into an exam.
  • Loading branch information
dbosk committed Sep 11, 2016
1 parent 3377cbd commit 9695430
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 17 deletions.
28 changes: 17 additions & 11 deletions abstract.tex
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
This is a general-purpose, simple exam generator for the \LaTeX\ documentclass
exam~\cite{exam}.
It reads the question database from the source code of old exams or a file with
questions.
The questions are expected to start with the \verb'\question' macro and end by
the start of the next question, the \verb'\end{document}' macro or the end of
the file.
In each question the generator will look for a label with the format
\verb'\label{q:tag1:tag2:...:tagN}' or comments on the form
\verb'% tags: tag1:...:tagN'.
The set of tags is the union of all tags found.
It reads the question database from the source code of old exams, a file with
questions or teaching material with exercises.
The questions are expected to be either questions from the exam document class,
i.e.\ start with the
\verb'\question'
macro and end by the start of the next question, or be an exercise environment,
\verb'\begin{exercise}'
and
\verb'\end{exercise}'.

In each question the generator will look for tags:
tags can be used to tag that a question covers a specific topic or intended
learning outcome (or both).
The set of tags is the union of all tags found in the body of the question.
The tags are used to filter which questions qualify for inclusion in the exam
to be generated.
The tags can be used to represent topic, difficulty level, intended learning
outcomes, etc.
Tags are given in questions as comments on the form
\verb'% tags: tag1:...:tagN',
and several such lines are allowed.

The generation algorithm works as follows:
The set of desired tags, \(D\), is specified on the command line.
Expand Down
29 changes: 23 additions & 6 deletions examgen.py.nw
Original file line number Diff line number Diff line change
Expand Up @@ -153,26 +153,31 @@ two database files.

Since the design allows for using old exams as database files, then we must
adapt our database format to this.
We know that the exams are using the exam~\cite{exam} document class.
We assume that the exams are using the exam~\cite{exam} document class.
As such each question will start with the command \verb'\question' and end at
the beginning of the next question.
Or in the special case of the last question, it ends with the end of the
[[questions]] environment.
(See lines 87--290 in the example exam in \cref{sec:ExampleExam} for an example
of a [[questions]] environment.)
However, we also want to be able to use exercises from teaching material.

We can thus make use of Python's regular expressions facilities~\cite{regex}:
<<imports>>=
import re
@ We can use the following code block to set up a regular expression pattern to
match a question:
<<set up question regex>>=
question_code_pattern = re.compile(
"\\\\question(.|\n)*?(?=(\\\\question|\\\\end{questions}))",
"(\\\\question(.|\n)*?"
"(?=(\\\\question|\\\\end{questions}|\\\\begin{exercise}))|"
"\\\\begin{exercise}(.|\n)*?\\\\end{exercise})",
re.MULTILINE)
@ (See~\cite{regex-lookaround} for a treatment of zero-width assertions in
regular expressions.)
The regular expression consists of two parts.
The first part matches questions (exam format) and the second part matches
exercise environments.
This expression will conveniently also include any parts or solution
environments used in the question.
environments used in the exam question format.

To read the questions database we need to do the following:
<<read questions database>>=
Expand Down Expand Up @@ -212,15 +217,27 @@ A suitable one is to construct the question from its LaTeX code:
<<question constructors>>=
def __init__(self, code):
<<question constructor body>>
@ This LaTeX code is also a natural attribute of the class:
@ This LaTeX code is also a natural attribute of the class.
However, it should be on the exam question format, so for the exercise
environments we must do some transformation.
<<question constructor body>>=
self.__code = code
if self.__code.find(r"\begin{exercise}") >= 0:
<<transform exercise to question form>>
@ We also need a get-method for the code attribute:
<<question methods>>=
def get_code(self):
return self.__code
@

To transform an exercise to a question we can replace the beginning of the
environment with the question command and simply drop the end of the
environment.
<<transform exercise to question form>>=
self.__code = self.__code.replace(r"\begin{exercise}", r"\question ")
self.__code = self.__code.replace(r"\end{exercise}", "")
@

To be able to add a question to a set, the data structure must be <hashable>:
<<question methods>>=
def __hash__(self):
Expand Down

0 comments on commit 9695430

Please sign in to comment.