MCQ-XeLaTeX: Quickstart

Date

2019-02-07 (updated 2022-09-05)

Multiple Choice Questions in XeLaTeX, and OMR (Optical Mark Recognition)

Before anything: a full TeX Distribution (such as texlive). Check the Requirements, then download and install both the script mcq.py and the syle file mcq.sty (e.g. in linux):

$ sudo apt-get install fonts-linuxlibertine
$ wget https://www.dlfer.xyz/var/mcq.py
$ wget https://www.dlfer.xyz/var/mcq.sty
$ chmod +x mcq.py

Of course you can move both files in more appropriate places (/usr/local/bin/mcq.py, and mcq.sty somewhere in $TEXINPUTS).

MCQ (Multiple Choice Questions) for XeLaTeX, Version: 2023-11-15

USAGE:

Just put mcq.py in your PATH and run:

$ mcq.py

the instructions and the in-line help are meant to be working (at any point, follow the instructions and enter a question mark ? for help):

->> ?

to get some help. The prompt is meant to give informations on the current directory and the phase of the program. For example, if the working directory is /home/user/tex/myexam the prompt will be:

(Work)mcq[/home/user/tex/myexam]->>

The LaTeX engine to be used is XeLaTeX, and the style file mcq.sty has to be found by XeLaTeX when compiling.

EXAMPLES:

The MCQ CLI prompt is here summarized as ->>. After loading or generating a XeLaTeX exam file file.tex, to compile it:

->> make

To generate a printable PDF with 200 permuted copies of the exam:

->> exam 200

The output will be file_exam.pdf. Check that everything is ok, modify file.tex accordingly, and go back to make. After printing and delivering it, one can use an OMR service (Optical Mark Recognition) or not.

Warning

The scanned images of the bubblesheed should be at least 200DPI, grayscale (better than BW). In PDF format is easier.

Assuming you have a properly configured OMR remote (anyway, to be replaced by a local) service (via OMARSERVICE environment variabile, see below), to import the scanned bubblesheets archived in the scandir folder:

->> omr scandir/scanfiles*.pdf

The output will be a PDF with visual annotations file_answers.pdf (to be visually analysed to check for OMR or human errors) and a text file with the exam data, in CSV (Colon Separated Variables) format, usually named file_answers.txt. Each line will be of the format:

FXZH: :193146:AB0*AAAD0:

It is important to understand the format of this file:

  1. The first field FXZH is the permutation code of the sheet,

  2. the second `` `` is the (empty) field where later the student name will appear,

  3. the third 193146 is the student UID number,

  4. the fourth AB0*AAAD0 is the string with the answers. Each question, a character:

    • 0 means there is no answer,

    • * means there is more than one answers (and hence not a valid answer),

    • A means the answer is A (and the same for B, C, …).

  5. The fifth column is empty here, after the last colon, but can be used later.

OMR outputs uppercase letters by default. Lowercase letters can be used when correcting (manually) the OMR or human errors, just to keep the sets of symbols disjoint. Upper and lower case letters are considered equivalent, later.

In order to proceed, check and remove all the asterisks, and compare the data file with file_answers.pdf until all errors are removed.

If ESSE3 is in your hands, then you can use https://www.dlfer.xyz/var/esse3.html to generate a uid file and align students uid-numbers with their names:

->> uid sc1.uid

(? uid in the CLI if needed). After this, each line will be completed with the student name:

FXZH:FamilyName, venName:193146:AB0aAAAD0:
7yFH:Verdi, Giuseppe    :736220:D0ABC0ACD:
xE72:Rossi, Paolo       :735221:DA0CBBA0C:
6FB2:Bianchi, Michele   :739223:0AADC00C0:
H63z:Neri, Valentina    :735333:BDACCABCC:

If one does not have a OMR service, then this file can be also typed without OMR, simply reading the data fields from the exam papers filled by students and typing them in a text file with the CSV format described above.

If the exam consists in a multiple-choice questions part and in an open-questions part, the score for the second part can be written as the last column of file_answers.txt:

FXZH:FamilyName, GivenName:193146:AB0*AAAD0:21

After the file with the students answers is filled, to mark the exam simply type:

->> mark

Two files will be generated, if everything goes right:

  • file_exam.csv with the full list of students and scores.

  • file_exam.txt with an anonymized list of UID’s and scores.

Afterwards, very important: generate a stats PDF, file_stats.pdf where for each question one can read the number of students for each possible answer, and two indicators of each question: the facility index and the discrimination index:

--> makestats

Also, generate an HTML output:

--> export outputname.html

And generate a GIFT (for MOODLE) format to be imported in any MOODLE instance:

--> export outputname.gift

At any point, check status:

--> status

and get help:

--> ?
--> help

Important

The pseudo-random sequences used to randomize the order of questions and the order of the answers is exactly the same, each time one runs the script. So, when things go wrong, just re-trace all the steps, fix the error and nothing is lost.

Many things can (and usually do) go wrong. The software was built with a few failsafe mechanisms, to prevent error propagation and to allow error corrections, since there are not irreveversible steps.

LATEX

The first time mcq.py is executed it will assist the user in generating a LaTeX exam file, ready to be modified. This step is not necessary, but useful.

Otherwise the format of the file is very simple. Let file.tex be the name of the file. It has to be encoded as utf8. The style file mcq.sty has to be in the XeLaTeX path.

The file file.tex must be compiled with XeLaTeX and it must contain in the preamble the LaTeX command:

\usepackage{mcq}

with (optional) some options such as:

\usepackage[sol]{mcq}

or:

\usepackage[bubblesheet]{mcq}

All options are described in the full LaTeX documentation. Possible commands in the preamble:

\headline{Geometry I - 24 jun 2009 (14:30 - U1-01)}
\puntigiusta{3}
\puntisbagliata{-1}
\puntiempty{0}
\formulavoto{(2*x+y)/3.0} %% python syntax

The two variables x and y here mean, respectively, the score of the multiple-choice part of the test, and a manually-marked score for an optional second part of the test, with open questions.

In the body of the LaTeX document, one of the following (if OMR or not OMR is to be used) will print the front matter of the exam sheet:

\bubblesheet[2]{4}{20} %  OMR
\nomeesame % not OMR: name and uid

After that, the list of exercises has to be inside one of the following environemts (the starred version has a different numbering scheme):

\begin{esercizi}{Group A of exercises}
% here exercises
\end{esercizi}

\begin{esercizi}{Group B of exercises}
% here exercises
\end{esercizi}

\begin{esercizi*}{Other group of exercises}
% here exercises
\end{esercizi*}

There are not that many types of questions/exercises. The basic type is the multiple choice question:

\begin{exerm}[Just a comment]
\qtitle{Title of the exercise (can be used as question-id: it does not appear in TeX}
Body of the question.
\begin{rispm}[3] % The optional '3' argument means answers in 3 columns.
\risp[=] correct answer
\risp wrong answer
\fb{Feedback}
\risp[-2] Wrong answer worth  -2 points.
\risp[0.01] Half-wrong answer worth  0.01 points.
\end{rispm}
\fb{General feedback}
\end{exerm}

A simple true/false question:

\begin{exerm}\qtitle{Quetion title or question id}
Questo è un esercizio vero/falso.
\vero[
Feedback
]
\end{exerm}

Some questions can come in varianti, for each shuffle (permutation) of questions, one of the variants is chosen for that particular question. Questions with variants are supposed to be very similar (only some numerical parameters should change), otherwise the difficulty of the test can be non-homogeneous:

\begin{exerm}
\begin{varianti}
%% Variants should have all the same number of answers.
%% Such a format cannot be converted 100% to GIFT or HTML,
%% and, in the statistics file, only the first variant is printed.
%% Numbered answers, hence, might be not accurate.
\varitem
    Body of the first variant: which number has the smallest absolute value?
    \begin{rispm}
        \risp[=] 1
        \risp 2
        \risp 3
        \risp 4
    \end{rispm}
\varitem
    Body of the second variant: which number has the smallest absolute value?
    \begin{rispm}
         \risp[=] -1
         \risp -2
         \risp -3
         \risp -4
    \end{rispm}
\end{varianti}
\end{exerm}

There is a simple open-answer exercise, that will be translated to an essay GIFT/MOODLE question:

\usepackage[sol,doexe]{mcq}

\begin{esercizi}{}

[...]

\begin{exe}[Just a comment]
\begin{varianti}
\varitem
\qtitle{Title of the exercise (can be used as question-id 1: it does not appear in TeX}
... 1 ...
\blank{solution 1}
\varitem
\qtitle{Title of the exercise (can be used as question-id 2: it does not appear in TeX}
... 2 ...
\blank{solution 2}
\end{varianti}
\end{exe}

[...]

\end{esercizi}

In order to choose variants in exe question types, the option doexe must be set when loading mcq.sty.

This part is a little bit experimental (see the full documentation for the --split-for-moodle option).

OPTIONS:

There are a few options that might be useful, but please use them only for debugging purposes:

--help|-h               this help
-v|--verbose            verbose output
--gift|-g               GIFT output
--xhtml|-x              XHTML output
--output=|-o [FILENAME] explicit output=[FILENAME]
--number=|-n [N]        number of copies = [n]
--db= [FILENAME]        data for the marking
--stats= [FILENAME]     make a stats tex file
--omr= [BASENAME] [SCANFILES]   OMR scan of [BASENAME].tex and [SCANFILES]
--uid= [FILENAME][:3:2] [FILE]  get names from uid file [FILENAME]
--join  [FILE1_exam.csv] [FILE2_exam.csv] join two csv tables
--choose= [N] [files*.tex] random choose N from files*.tex
--split-for-moodle=|-s [template.html] [file_exam.pdf] split for moodle essay

Some aspect of the script are controlled by the following ENVIRONMENT VARIABLES:

MCQRANDOMSEED [alternative random seed]
OMARSERVICE   [alternative Optical Mark Recognition remote service URL]
ANSI_COLORS_DISABLED [disable ANSI colors in some terminals]

Unless you know what you are doing, you do not need to set them. The following copyright notice is written in Italian, since anyhow not so many people read them:

[Quest'opera e' stata rilasciata con licenza Creative Commons Attribuzione
- Non commerciale - Non opere derivate 3.0 Unported. Per leggere una copia
della licenza visita il sito web
http://creativecommons.org/licenses/by-nc-nd/3.0/
o spedisci una lettera a Creative Commons, 171 Second Street, Suite 300,
San Francisco, California, 94105, USA.]

(C)  DLFerrario http://www.dlfer.xyz/var/mcqxelatex.html