#variant #questions #programming #generate #exam #multiple #different

bin+lib vmks-exam-generator

A simple CLI program for pseudo-randomly generating different variants of an embedded programming exam

5 releases (3 stable)

1.3.0 Jan 15, 2024
1.0.1 Nov 7, 2021
0.1.4 Jan 5, 2021
0.1.3 Dec 15, 2020

#118 in Text processing



VMKS exam generator

A simple CLI program for pseudo-randomly generating different variants of an embedded programming exam. Designed for Technological school "Electronic Systems" in Sofia, Bulgaria.

When a new variant is generated an adjustable subset of questions is picked at random from a question bank. Both questions and possible answers for multiple choice questions are shuffled. Supports randomly picking parts of the question text from a predefined list of possible values. This makes it possible to generate slightly different tasks such as
"Write a program that prints asterisks in the shape of a square"
"Write a program that prints hashtags in the shape of a triangle".

The generated exam variants are pdf forms by default or plain text files, if so specified. A working latex distribution and latexmk are required to generate pdf forms.


Currently, VMKS exam generator can only be installed by compiling from source. A working Rust toolchain is required for this. It can be obtained by installing rustup from your distribution's package manager or from rust-lang.org. Once you have rustup installed, the stable toolchain can be installed with the following command:

rustup toolchain install stable

Then, to install VMKS exam generator run:

cargo install vmks-exam-generator


Usage: vmks-exam-generator [OPTIONS]

  -n, --variants <VARIANTS>       Number of variants to generate
  -q, --question-bank <FILENAME>  XML file specifying the questions [default: questions.xml]
  -s, --num-seed <SEED>           Use the number SEED to seed the random number generator
  -S, --text-seed <SEED>          Use the hash-sum of the string SEED to seed the random number generator
  -t, --plain-text                Output plaintext instead of pdf forms
  -e, --no-escape                 Don't escape special characters
  -h, --help                      Print help information (use `--help` for more detail)
  -V, --version                   Print version information

If no seed is provided for the random number generator then the number of seconds since the start of the UNIX epoch is used. The default number of variants to generate is 30 and the default name for the question bank file is "questions.xml". Special characters are escaped by default to avoid LaTeX errors and provide an easy way of indenting text in the questions.

Question bank file format

The set of questions used for generating different exam variants is described in XML format. An example is provided in example_questions.xml.


Being an XML file, naturally the question bank file must start with a declaration of the XML version and encoding, for example:

<?xml version="1.0" encoding="UTF-8"?>

Question bank

The entire set of questions is enclosed in a pair of opening and closing question_bank tags. It can optionally have the title attribute. If it is specified, its value will be present at the beginning of each variant as a title.

question_bank can optionally contain a description tag pair. Any text enclosed in it is displayed at the start of the variant but after the title (if specified).

<question_bank title="Very Difficult Exam">
        This exam will test such and such skills. It requires that much time and the maximum points are X.

Question group

Questions are separated into groups with the question_group tags. These can have the pick attribute that selects how many questions from the given group are to be picked, the shuffle attribute that determines if the questions in the group are to be shuffled and the title attribute which is similar to the question_bank attribute of the same name but is displayed before the corresponding section of the generated exam variant. All question group attributes are optional. The shuffle attribute can be either true (default) or false. It determines whether the order of the questions in the group is to be shuffled. If the pick attribute is not specified then all questions from the group will be present in every variant generated. Each question can be either a multiple choice question or a question with variable segments. Question groups also support the optional description tag pair.

<question_group title="Questions about some topic" pick="5" shuffle="false">
        Each correct answer in this section is worth Y points. There is only one correct answer per question.

Multiple choice question

Multiple choice questions are enclosed by a pair of question_mc tags and can optionally have the shuffle attribute that determines whether the possible answers are to be shuffled. It can be either true (default) or false. question_mc contain one question_text tag pair followed by answer_mc pairs. The actual text of the question is placed between the question_text tags. answer_mc tag pairs are used to specify the possible answer choices.

<question_mc shuffle="false">
    <answer_mc>A long time ago</answer_mc>

Question with variable segments

Questions with variable segments are enclosed in question_var tags and consist of any number of question_text and var_text tag pairs. Each var_text tag pair contains any number of option pairs which in turn contain the different values that can appear at this position in the question text. var_text can also contain question_var to allow multiple levels of variability. Parts of the question text that do not change between variants are placed inside question_text tag pairs.

Questions with variable segments appear with text boxes below them in the generated variants. question_var tags can have one optional attribute - text_field_height. Its value must be an integer between 0 and 65535 (default is 5). It determines how many lines of text can fit in the text box for the respective question without scrolling. Set to 0 to remove the text box. Nesting question_var in var_text does not create an additional text box and the text_field_height attribute is ignored for the nested questions.

<question_var text_field_height="5">
    <question_text>Build a </question_text>
            <question_text>house with a </question_text>
    <question_text> out of </question_text>
    <question_text> in 5 minutes.</question_text>


If the same attribute is specified more than once, its last instance overrides the previous ones. The same applies to multiple instances of the description tag within the same question_bank or question_group.

The sequences \n and \t will be replaced with newlines and tabs respectively when encountered in the question bank text. To avoid this, when it's undesired, slashes can be escaped like so: \\. When generating PDF files the characters #$%_{} are also escaped with a slash because they have special meanings in LaTeX. If you don't want the question text to be altered in any way, you can disable this functionality by running the program with the -e flag. This is useful for adding LaTeX commands to the question text that will be evaluated when generating the variants.

The text in titles, descriptions and multiple choice questions and answers is trimmed of leading and trailing whitespace. The text that forms variable text questions is not trimmed.

Tag and attribute short forms

All tags and some attributes have short forms:

question_bank - qb
question_group - qg
question_mc - qmc
question_var - qv
question_text - qt
answer_mc - amc
var_text - vt
option - o
title - t
description - d
text_field_height - tfh


~28K SLoC