Structure of an .Rmd-file

The .Rmd is the main file, where all the information about the exercise is contained. It follows a basic structure, with four sections, “Data Generation”, “Question”, “Solution” and “Meta-information”. Their purpose will be described in detail in the following sections.

An empty template containing only the necessary structure can be downloaded here:

Warning

After downloading the template, please remove every instance of “eval = FALSE” from the knitr-tags. This tag is necessary to provide such an empty template for download, but should not be used for creating the exercises!

Basic Structure

  • Data Generation (code chunk)

  • Question

  • Solution

  • Meta-information

The first section Data Generation, is marked by a code chunk, which is different from the other three sections.

```{r, eval=TRUE, echo=FALSE}
# code is placed here, evaluated, but not echoed in the final document
```
Important

Inside the curly braces {}it needs to be specified that the following code is written in R. In addition, so called knitr-tags can be used to alter the appearance of the code and its output within the code chunk. For a detailed overview of knitr-tags see this website here. A brief overview can be found here in the section about knitr-tags.

The other three sections are marked as follows

Question
========
text is written here. 

Solution
========
more text is written here. 

Meta-information 
================
even more text here. 

Data Generation

In this section of the .Rmd-file, the answer options for single/multiple choice questions, solutions, the types of questions, explanations and tolerances for solutions are created and stored in list objects for later. In addition there are many additional possibilities, like sampling data, creating graphs, importing pictures etc. which are described on the following page: Add-ons

Description of the lists

The five necessary lists are answers, solutions, types, explanations and tolerances, which all have the same length, which is equal to the number of questions in the exercise. For example, in an exam with 5 multiple choice questions, the length of the lists is 5.

Depending on the type and simplicity of the question, some of the lists might not be of equal length, however

The list answers contains the answer options for single choice/multiple choice questions, not the questions itself. The actual questions are written down in the section “Question”. For numeric and string questions, this list contains placeholders "", since no answer options are given. More on the types of questions see below.

The list solutions contains the solutions for all the questions. For numeric questions, that is a number, (e.g: 123), for string questions a string like "hello world" is expected. The solution for single & multiple choiche questions is a boolean vector containing TRUE/FALSE. For each answer option, one instance of TRUE or FALSE is needed. For example, a single choice question with 5 answer options, where one option (in this case the second answer option) is correct, would have a solution vector like this:

c(FALSE, TRUE, FALSE, FALSE, FALSE)

The list types specifies the type of question for each individual question. Possible values are

  • numeric (“num”)

  • string (“string”)

  • single choice (“schoice”)

  • multiple choice (“mchoice”)

There are other options avaible, also depending on the output type, see the official R/exams documentation for more information.

The optional list explanations contains the feedback that is shown. This can be the complete solutions (it should be then formatted as a list) or additional information like the seed, that was used to create this exercise, session info, etc., which can be written in the “Solution” section. See the Solution section for more details.

The list tolerances is only necessary for numeric questions, where it is desired to have an interval, in which the solution is accepted as correct, even though the numbers are not perfectly equal. This is important for accommodating rounding differences.

Warning

Proceed with caution when random generating numbers and setting an (absolute) tolerance interval, which is too narrow, then the true solution could lie outside of the tolerance interval.

Creating the lists

They are initialized as empty lists, which are later filled with the desired information via sub-setting. See Creation of the .Rmd-file for more details.

answers <- list() 
solutions <- list() 
types <- list()
explanations <- list() 
tolerances <- list()

Question

In this section, all the questions, that should be included in the exam, are written down. This is done in natural language, however bits of code (including R objects), graphs, data, etc. can be included. See more here

Additonal text, like instructions, hints, context, etc. is also written down in this section.

Questions with answer fields

The answer fields mark the place were the answer input should be placed, for example in a moodle quiz, the place where the empty answer box is placed.

Answer fields are marked by ##ANSWERi##where i is the number of the question, starting with 1.

numeric example

Numeric question: How many continents are there? ##ANSWER1##

In this case, the answer field is a place-holder, nothing will be displayed, which equals an empty answer field in moodle.

For single/multiple choice questions, ##ANSWERi## represents the answer options.

schoice example

Single choice question: Is Vienna the capital of Austria? ##ANSWER2##

With the correct set-up, this will display yes/no instead of the answer field. In moodle this is a drop-down menu with the two answer options.

mchoice example

Multiple choice question with text components as answer options: The number 3 is ##ANSWER3## 1.

Possible answer options are “greater than”, “smaller than”, “equal to”, which would be displayed instead of the answer field. In moodle all answer options are shown as tickable boxes.

For more examples, see the section “Basic Examples” here and the “Advanced Examples here.

The function answerlist() from R/exams package converts the answer options, which are stored in the list object answers into the necessary format. Additionally, the placeholders needed for numeric/string questions in the answers list are automatically added into the list in this code chunk.

for (x in 1:length(types)) {
  if (types[x] %in% c("num", "string")) {
    answers[x] <- ""
  }
}

answerlist(unlist(answers), markup = "markdown")

Solution

The section “Solution” can be used to provide solutions in the form of explanations. It does not create the solutions to the questions and nor is it responsible for assessing/grading questions. Instead it can be used as a reference to review questions or provide feedback. This type of information is created in this section.

The solutions list contains the actual solutions to the questions, which are used for deeming an answer correct/incorrect, however these are not directly displayed in this section.

The explanations list holds any information that can be possibly given as feedback. This can, but does not have to, include the actual solutions, depending on the type of exam one is aiming for. This list is optional, general feedback can be normally written as text in this section, see more details on the actual solutions as feedback and other types of explanations below.

Actual Solutions as explanations

The correct solutions to the questions can be displayed in the appropriate format in the generated output.

Some solutions need to be converted to a more understandable format before being displayed. The solutions to schoice/mchoice questions are stored as TRUE/FALSE vectors and in the following code chunk they are converted to “True” and “False” strings, which are then displayed as explanations to the schoice and mchoice questions.

for (x in 1:length(solutions)) {
  if (types[x] %in% c("schoice", "mchoice")) {
    explanations[x] <- solutions[x] |> lapply(function(x) ifelse(x, "True", "False"))
  } else {
    explanations[x] <- solutions[x]
  }
}

Then the function answerlist() from R/exams processes the explanations list to adjust it to the format needed for conversion of the .Rmd-file to the desired output.

answerlist(unlist(explanations), markup = "markdown")

Other types of explanations

When the desired feedback is any type of text, like in-depth explanations or providing more context, or more technical details like calculation steps, the explanations list is not needed. It can simple written as normal text in the .Rmd file under the “Solution” section.

Examples of feedback:

numeric example
The correct answer is 7, because there are seven recognized continents on Earth: 
Africa, Antarctica, Asia, Europe, North America, Oceania (or Australia), and South America.
mchoice example
The correct answers are "A" and "C." 
Option A is correct because..., and Option C is correct because... 
Option B, however, is incorrect because .....

In some cases it can be useful to document the seed used, for example when randomly generating numbers or doing any kind of sampling. Providing this information in the “Solution” section to either students or oneself, when for example reviewing questions, can ensure reproducibility.

See the page about add-ons for more information on how to dynamically display R objects (like seeds) in the exam.

Some necessary adjustments for conversion

The following code chunk, which is labelled meta in the template, converts the solutions of single/multiple choice questions into the necessary 1/0 format. In addition, the second part changes NULL elements in the tolerances list to 0, in order to avoid an error during the conversion process.

# Convert the format of single/multiple choice from T/F to 1/0
for (x in 1:length(solutions)) {
  if (types[x] %in% c("schoice", "mchoice")) {
    solutions[x] <- solutions[x] |>
      unlist() |>
      mchoice2string()
  }
}

# Set all undefined tolerances to a default value
for (x in 1:length(solutions)) {
  if (tolerances[x] |> unlist() |> is.null()) {
    tolerances[x] <- 0
  }
}

Meta-information

This section contains all the information necessary for the conversion from an .Rmd-file to the desired output (HTML, Moodle (xml), pdf, …). The conversion process is decribed here

Meta-information
Tag Description
exname name for the exam, should be short and informative
extitle longer name for the exam, displayed in Moodle
extype specification of the type of exam, e.g: “cloze”
exsolution solutions to the questions
extypes specification of the types of questions used in the exam
extol tolerances used for numeric questions
exshuffle logical or numeric value, if/how answer options for schoice/mchoice questions should be shuffled
exversion version of the exam

Also see vignette("exams2", package = "exams") for additional tags and more information.

Types of Meta-information tags

exname

Exercise name, typically a unique identifier for each exercise, helping to manage and retrieve exercises easily from an exercise pool.

extitle

Sets the title of the exercise. Titles can be dynamically generated by embedding R objects in the text to adapt the title based on the exam context. For a detailed explanation of inline code, see this page

extype

Specifies the type of exam. This is different to the list object types from the “Data generation” section. A very common type is “cloze”, which is a type of exam which contains different types of questions, for example a combination of numeric and schoice questions in one exam. If the exam just contains one type of question, for example only multiple choice questions, then this can be specified as well.

exsolution

contains the correct solutions for the exam in the necessary format for the conversion of the .Rmd-file. When more than one question (and therefore more than one solution) is created, all solutions need to be in the order of the questions and separated by “|”. This can either be achieved by manually writing down all solutions or with the following code chunk:

paste(solutions, collapse = "|")

The resulting R object needs to be dynmically included in the .Rmd-file (see the section about inline code for details).

exclozetypes

When creating an exam of the type “cloze” (the exam contains different types of questions), the type of each question has to be specified. This information is stored in the list typesfrom above. When more than one question (and therefore more than one type) is created, all types need to be in the order of the questions and separated by “|”. This can either be achieved by manually writing down all solutions or with the following code chunk:

paste(types, collapse = "|")

The resulting R object needs to be dynmically included in the .Rmd-file (see the section about inline code for details).

extol

contains the tolerances used for the answers to numeric questions. When creating an exam of type “cloze”, the tolerances are stored in the list tolerances. They need to be in the order of the questions with 0 for questions where tolerances are not applicable, e.g. string questions. For details see the section about setting tolerances. All tolerances need to be seperated by “|”. This can either be achieved by manually writing down all solutions or with the following code chunk:

paste(tolerances, collapse = "|")

The resulting R object needs to be dynamically included in the .Rmd-file (see the section about inline code for details).

exshuffle

Can be a logical or an integer and determines if or how the answer options are shuffled. When it is set to TRUE the answer options are not always displayed in the same order, for example when creating multiple versions of the same exam. When set to an integer, this determines the number of multiple choice answer options shown. For example, when 6 answer options are available through the list object answers and exshuffle is set to 4, then 4 out of 6 questions (always including the true option(s)) are displayed.

exversion

Specifies the version of the exam, useful for distinction when altering the .Rmd-file and creating a new set of exercises.

exsection

Specifies the category, which is chosen for the Moodle import.

More meta-information parameters can most conveniently seen on this post by Achim Zeileis on stackoverflow.com

Exemplary structure of the Meta-information

Example

This is the meta-information of a very simple exam, containing one numeric question, one single choice and one multiple choice question with three answer options, without any automation using the lists and paste().

exname: homework_1
extitle: Homework 1: Topic A  
extype: cloze
exsolution: 42.1|TRUE|c(FALSE,TRUE, FALSE)
exclozetype: num|schoice|mchoice
extol: 0.5|0|0
exshuffle: TRUE
exversion: v1

Below is an example of how the “meta-information” section could look with some of the R/exams tags explained above, as well as automatic conversion of the solutions, types and tolerances list to the correct format using paste().

Meta-information
================
exname: Abcde
extitle: Abcde: topic xyz 
extype: cloze
exsolution: `r paste(solutions, collapse = "|")`
exclozetype: `r paste(types, collapse = "|")`
extol: `r paste(tolerances, collapse = "|")`
exshuffle: TRUE
exversion: v1