Professors with focus on (but not restricted to) math sciences can generate individualised exams for each student. Despite the questions are the same, variables and consequently the answers are different. Questions are also shuffled. Latex is in charge to beautifully build the PDFs.
Last but not least, an application for correction is included. All you have to do is to scan the exams and provide the images to the Correction application. See Usage section for details. The correction code will read the images and extract students answers.Then, it will compare them to the right keys, i.e., it will perform the correction process itself. Finally, a .csv file report is generated with students scores.
- ruby
- tex-live
- ImageMagick
- Ruby gems: mini_magick, date, and csv.
If you are using a debian-based distribution, something like
sudo apt-get install ruby ruby-dev texlive-latex-base texlive-science imagemagick
and also
gem install mini_magick csv date
will solve the aforementioned dependencies. For other distros, please check distro-specific docs for directions.
- Download this project and place the whole folder wherever you want.
- Note the executable
examgen.sh
expects to be inside the project folder since it assumes all paths as relatives.
If you are in a hurry, and want a quick result, do as follows:
- Install git (in debian-based distros, do
sudo update && sudo apt install git
) - Clone this repo:
git clone https://github.com/abdeoliveira/examgen
- Enter the cloned repo:
cd examgen
- Run
./examgen.sh 1
If everything went well a PDF will be opened in your screen containing one sample exam.
- Create questions (try to follow the examples in
input/questions/
) - To be written...
- ...
First, you need to clone this repo (this is the jargon for donwloading a git project). For doing that you need to have git installed on your machine.
Once you have git, cast git clone https://github.com/abdeoliveira/examgen
From now on, I will assume examgen/
as being the root of cloned repo folder. Thus if I referr to src
or src/
for example, it means /path/to/examgen/src
.
The only files you must edit lie inside the input/config/
folder. They are formulas
, header
, lang
, and markform
.
-
formulas
: This is an OPTIONAL file. If present, it must have N+1 lines, where the first one is a title (as for example,Formulas
orFormulas and Constants
) and followed by N lines consisting of equations which you want to provide to students during the test. Equations must follow theLaTex
format WITHOUT the symbol$
. -
header
: This is an OPTIONAL file. If present, it is intented to contain information regarding the School/College/University, Professor, Exam, Date, and whatever information the professor/teacher may find relevant to figure out in the exam header. It must follows theLaTex
format. Despite it is optional, as stated before, I particularly think it is important to have one. -
lang
: It is a MUST HAVE file. It must contains a single line with two words separated by a comma as follows:word1,word2
.word1
refers to the language used in in your document (english
for instance).word2
must be eitherpoint
orcomma
and it stands for the symbol used for decimal separation. For example, the resulting number from the operation3/2
is represented as1.5
ifpoint
is used whereas it is1,5
ifcomma
was choosen. -
markform
: A MUST HAVE file containing six words or sentences (spaces are allowed) separated by comma, like this:word1,word2,...,word6
. Each word (or sentence) will appear in a different part of the document. See the images below for details.
Questions must be written in a specific format which will be discussed below. Each question is a single file having the .gnxs
extension name, and must be located in the input/questions/
folder. You may want to take a look in example files inside the input/questions/
folder while reading the following paragraphs.
Each question file must have 4 blocks, which are @config
, @question
, @figure
, and @answer
, and must terminate with @end
.
The number of alternatives for questions is a global variable (all questions must have the same number of alternatives) and will be discussed later.
Must have 2 entries: mode:
and inline:
.
-
mode:
expects one of the following arguments,numeric
ortext
.numeric
is intended for questions with alternatives as numbers.text
is intended for questions with alternatives as texts. -
inline:
expects an integer number as argment and it stands for the number of alternatives in one line. Something between 5 and 8 do well formode:numeric
(e.g.inline:8
) and I recommendinline:1
formode:text
Check screenshots with the inline:
variable in action.
inline:1 [This is a typical question in mode:text
. Note that inline:1
renders a nice visual for such mode:text
questions.]
inline:2 [Here we have mode:numeric
. Note that inline:2
won't display a great layout for this specific case.]
inline:8 [Again mode:numeric
. My recommendation is inline:8
for a two-columns document with number of alternatives less or equal to 8.]
The only entry is a text following LaTex format. Thus equations, bolds, italics, colors and so on, will all follow LaTex format.
Note: If the question is in mode:numeric
then you will have to deal with the @VAR()
function. The @VAR()
function correlates a variable
to a random number belonging to a user-defined number interval. Such an interval is defined in the @answer
block. Check the example below.
mode:numeric
inline:2
@question
A particle of mass @VAR(m) kg is subject to an external force of @VAR(F) N.
Calculate the acceleration in m/s$^2$ in a one-dimensional movement.
@figure
file:none
width:10.0cm
@answer
m:1,10,2
F:10,20,1
correct:$F/$m
minmax:auto,1
@end
Here we have @VAR(m)
and @VAR(F)
in the @question
block, which are correlated to m:1,10,2
and F:10,20,1
in the @answer
block (more about
such a block can be found below).
In this example, the final document will have @VAR(m)
replaced by a random number between 1
and 10
(closed interval) having 2
decimal digits.
For example, @VAR(m)
can be 1.43
, 5.40
, 7.21
, 10.00
, and so on.
As you probably have already antecipated, @VAR(F)
will be replaced by a random number between 10
and 20
with 1
decimal digit, e.g., 10.0
, 12.5
, 19.9
, and so on.
Contains two variables, which are file:
and width:
. The former expects a figure name as argument, if any.
If there is no figure in the question, the argument must be none
. The later expects the figure width as argument, if any.
If file:none
then width:
argument is ignored (although width:
must be present).
File figures must be located in the input/figs/
folder. My setup works well with the png
format but you can use any one suitable to LaTex
.
This block must have N+2 lines, where N is the number of @VAR()
functions used in the @question
block. Each one of the N lines is expected to have the
following format: a:b,c,i
, where:
a
must be associated to a@VAR(a)
function, present in the@question
block.b
is an integer or real number, the lower limit of the interval (closed)c
is an integer or real number, the upper limit of the interval (closed)i
is an integer, and stands for the number of decimal places ofa
.
The last two lines are correct:
and minmax:
.
correct:
has the equation for the correct answer and must be composed by the previously defined N variables. Note: Here each variable must be prepended by the$
symbol. For example, suppose the answer for a given question is calculated by the formulaF/m
(borrowing our previous example). Then the line must becorrect:$F/$m
.
NOTE 1: Mathematical functions are expected to follow Ruby's syntax. Examples:
sin(x)
is written in Ruby asMath.sin(x)
sqrt(x)
is written in Ruby asMath.sqrt(x)
2^3
(which is 8) is written in Ruby as2**3
.Math::PI = 3.1415...
andMath::E = 2.7182...
.
NOTE 2: Real numbers are expected to be written with .
as decimal separator whatever is your language definitions.
NOTE 3: If there are variables declared in @question
but not declared in @answer
the program will give you a Warning
.
minmax:
Defines the interval used to sample numbers to compose the wrong alternatives. It expects eitherauto,i
ora,b,i
as arguments.a
andb
may be integer or real numbers andi
is an integer. Ifauto
is used then the program will try to guess a reasonble interval for sampling numbers.i
is the number of decimal digits. Ifa
andb
are used then the program will respect such a user-defined interval.
NOTE: There is a common pitfall for multiple-choice exams. See for example a question asking to calculate the maximum height H
of an object launched upwards with velocity v0
from a certain initial heigth y0
must have an answer H > y0
. It is possible that certain alternatives will not obbey this condition (due to the way I coded how alternatives are created in auto
mode) and a keen student will easily spot it. This is a typical case in which the minmax:
must NOT be used in auto
mode.
-
Enter the project folder,
cd examgen
. Then, ensureexamgen.sh
is executable by doingchmod +x examgen.sh
. -
Run
./examgen.sh i
, wherei
is the number of exams to be generated. The script can alternatively be run as./examgen.sh i j
, wherej
is the number of alternatives for each question. Ifj
is absent, thenj=5
will be used by default, i.e., questions will have(a) ... (e)
alternatives. -
After running
./examgen.sh i
, if everything was fine, a single PDF document containingi
exams will be opened in your screen. The actual file issession/output.pdf
. -
Each exam is stamped (bottom right of each page) with a code like
i/yyyy.mm.dd-hh.MM.ss
, standing forexam_number/year.month.day-hour.minute.second
. -
The folder
session/
contains all the necessary information to perform the exam correction (see the next section). In case of accidental deletion of such a folder there is no way to use thecorrection/correction.rb
program to automatically correct the exams. For few exams (a dozen or so) this is not a big deal. On the other hand, for a hundred exams the correction involving shuffled questions and alternatives, and also random numbers spread all over the place can be a cumbersome task. Thus every timeexamgen.sh
is run thesession/
folder is saved as a hidden folder as.session_yyyy.mm.dd-hh.MM.ss
. This way you are able to correlate any generated PDF with the folder containg the files necessary for correction.session/
is sanitazed before saved in order to minimize the used space. Thus only the necessary files to perform exam correction are kept along with.tex
files in case you need to regenerate any PDF (you will the need files inside~/input
for that). -
Regarding the point above,
session/
IS NOT saved ifi = 1
, i.e., if you run./examgen.sh 1
. -
Ask students to write their name and ID number in the very end of the exam (in the corresponding fiels). This is important to eventually identify missing exams for any reason.
-
Also ask to students to not write in the exam since this can interfere in the data extraction from the scanned images. You are supposed to provide paper to students in order they can draft their calculations. Data extraction have shown to be pretty reliable even with messy scanned images but it is better to be on the safe side as much as possible.
The correction/
folder contains the programs used to perform exam correction. For doing that you need to:
- Scan the exams into a file format suitable to ImageMagick (this is the program used to manipulate exam images and extract data from). I recommend
jpg
orpng
. - Save the aforementioned scanned images to the
correction/IMAGES/
folder. You will have to create such a folder since it is not shipped with the repo. Please note the cappitalized letters. - Check in which side of the paper the markform lies, left or right. See the image below. In this example the Markform lies in the left side of the paper. You will need this information for the next step below.
- cd
correction/
, then runruby correction.rb <side> <pattern>
, in which<side> = l
or<side> = r
depending on your findings on the step 3 above.<pattern>
is the pattern of scanned file names (see item 1. above). If for example the scanned files are namedscan.1.png
,scan.2.png
,...
, and also the markform is located in the right side, the correction command shall beruby correction.rb r scan
.
For some reason you may want to ignore certain questions during correction. For example, you discovered that there were typos or bad coding in some of them.
To do so, you need to create the file /session/qignore
containning the questions file names (with or without the .gnxs
extension) to ignore, separated
by comma. Like this: question-to-ignore-1.gnxs, question-to-ignore-2, ..., question-to-ignore-N
.
To be written.
To be written.
LaTex
can be quite verbose. All that usual output typically generated by LaTex
is piped to the /tmp/examgen-latex.log
file. Note the /tmp
folder is the one of your system, there is not a tmp
folder inside examgen/
.
Mark forms should be placed in the same position for all exams since the correction/correction.rb
program relies on that. Statistically about 5% of Forms will be placed in the opposite side of most of them. This is something I have to fix soon.