Numbas is an opensource eassessment system aimed at mathematics and other numerate disciplines. It generates SCORM 2004compliant, selfcontained assessment packages.
Find out more about Numbas, including case studies and the latest blog posts, at numbas.org.uk.
A free to use Numbas editor is open to the public at numbas.mathcentre.ac.uk.
This documentation is a work in progress. If you have any questions, please email us or join the numbasusers mailing list.
What do I need to use Numbas?¶
The Numbas editor¶
The Numbas editor is used to write questions and collect them into exams. The editor at numbas.mathcentre.ac.uk is free to use, and hosted by Newcastle University.
If you want to set up your own instance of the editor, you can: it’s open source. See the editor installation instructions.
What students need¶
Students access Numbas through a web browser. The exam runs entirely on the student’s device. Numbas is compatible with all major browsers and devices.
For standalone tests, you just need to upload your exam to the web and give your students a link to it. See recording scores for information on integrating Numbas with a virtual learning environment.
We have tested Numbas on the following browsers. Any more recent versions should be assumed to work.
 Chrome version 10.
 Firefox version 7.
 Internet Explorer 9.
 Edge any version.
 Safari 5.0 on desktop.
 iOS (iPhone/iPad) 8.0 with Safari.
 Android 5.0 (Lollipop) with Chrome.
Recording scores¶
In order to record students’ scores and other attempt data, you need to connect to a virtual learning environment (VLE). Numbas can use the SCORM 2004 standard, if your VLE supports it. Several VLEs have builtin SCORM players: the ones we know of are Blackboard Learn 9.1+, Moodle 2.6+, desire2learn Brightspace.
Warning
Blackboard Learn’s SCORM player has several bugs and missing features. Many users have reported Blackboard failing to record attempt data for 510% of student attempts, apparently at random. We don’t recommend using Blackboard’s builtin SCORM player for summative assessment.
Our recommended method of integrating with a VLE is the Numbas LTI provider. The LTI provider is software which you must run on a server you control; see the guide on what you need to run the LTI provider.
The LTI provider works with any Basic LTI 1.1 tool consumer, which includes most VLEs. The major ones we know of are: Blackboard Learn 9.1+, Moodle 2.2+, Canvas, desire2learn Brightspace.
Students can also print out or produce PDF transcripts of their attempts once completed.
Create an account¶
Click on the create an account button at the top right of the page.
After filling in your details and pressing Register, you will be sent an email with a link to verify your email address. When you’ve opened that link, you can log in: click on the Log in button at the top right of the page and enter the username and password you chose.
Getting Started¶
Once you have logged in you will be prompted to take a look at these tutorials. When you are ready to get started using the editor, click on the Home button to navigate to your home page.
On the left you will find your activity timeline. This will display notifications about activity on content that you have either created or have access to.
On the right you will find buttons to create a question or exam and to browse the public database.
At the bottom of the right column you will find a list of projects of which you are a member. You will already have a project of your own which will be the default home for your questions and exams.
Create an exam¶
Once you have created an account on the editor, you can create your own questions and exams, as well as look at and make copies of those made by others.
Let’s create an exam using questions already in the database.
Creating an exam using existing questions¶
On your home page, click on the Questions link under Browse the public database. You can use the options on the left to filter the results, or use the search box at the top of the page to search for content that you are interested in.
Once you have found a question that you are interested in, click on the Preview icon to try it out. If you are happy with the question, click on the basket icon to add it to your question basket.
Once you’ve collected a few questions, click on the basket icon at the top of the page, and then click Create an exam from these questions. You’ll be taken to the editing page for your new exam.
Enter a name in the text box. Below is a dropdown list of projects that the exam can be assigned to. By default it will be added to your personal project.
Once created, you can try out your exam straight away. Click the Test Run link in the sidebar on the left. The compiled exam will open in a new window and you can have a go at answering the questions.
Once you have tried out the exam, close its window and return to the exam editor. Consider adding some text to the description field. The description should be short – one or two lines – and will appear underneath the exam’s name in the exam listing page.
Adding more questions to your exam¶
On the editing page for your exam, click the Questions link in the sidebar to go to the question selection area. On the left is space for your selected questions, and on the right are tabs offering different ways of finding questions to add. The Recent questions tab shows questions you have recently edited. The Basket tab shows questions you’ve added to your basket: you can browse the question editor to find questions, add them to your basket, and then go back to the exam editing page and add them in.
You can click on any question’s name to open it in a new window. This is useful to verify that the question contains content that you find relevant before including it in your exam.
Click the plus icon on one of the question results to add it to your exam.
You can drag and drop questions in the list on the left to reorder them.
The changes that you make to the exam content are active immediately. You can see how your exam looks by clicking on Test Run again.
Publish your exam¶
Once you’re happy with your exam, why not publish it the public database so others can use it? Before you can publish an exam, you must fill out the metadata fields so others can find it easily:
 Give the exam a name.
 Write a description.
 Select a licence under which others can use your exam. Make sure this doesn’t conflict with the licence attached to your exam’s questions.
 Your exam must contain at least one question.
Once you’ve filled out the required fields, click on the Access tab, and then click Publish. Your exam will now be included when anyone searches the public database.
Uploading an exam to the web¶
Numbas exams are, from the point of view of a web browser, just web pages with script files attached. So it’s very easy to put a fully functional Numbas test on the web  all you need is somewhere to put it.
Note
These instructions will show you how to get a version of your exam which runs on the web and doesn’t track scores. For instructions on obtaining and using a version which can be uploaded to a VLE such as Blackboard or Moodle, see Uploading an exam to a virtual learning environment.
Each question and exam has a download link in the sidebar which, when clicked, offers a selecton of options. Click on the standalone .zip (no SCORM) link to download a package suitable for standalone use on the web.
Extract the zip file on your computer, and then upload the resulting files to a new directory on your webspace. Most often you’ll be able to do this through an FTP client  ask your server administrator.
Once you’ve uploaded the exam files, you’re done! The exam will be available at the address you uploaded it to.
Uploading an exam to a virtual learning environment¶
Numbas produces SCORM objects which can be uploaded to any SCORM 2004compatible VLE (virtual learning environment).
This page contains instructions on uploading a Numbas exam to Blackboard and Moodle. The first step is to create a SCORM package of your exam.
Creating a SCORM package¶
Each question and exam has a download link in the sidebar which, when clicked, offers a selecton of options. If you just want to make an exam available on the web and don’t need to track scores, click the standalone .zip (no SCORM) link. For a version which can be uploaded to a VLE such as Blackboard or Moodle, click the SCORM package link.
In both cases, a .zip file containing everything needed to run the exam will be downloaded to your computer.
Uploading to the Numbas LTI provider¶
See the Numbas LTI provider documentation.
Uploading to Blackboard¶
Note
At least Blackboard 9.1 Service Pack 6 is required to run Numbas exams. There’s no way of checking your Blackboard version from within Blackboard, so check with your server admin that you’re using a sufficiently recent version.
Log in to Blackboard, and go to the content section of the relevant course. Click on the Content package (SCORM) item under the Build Content menu.
On the next screen, select the .zip file you downloaded earlier, then click Submit.
On the next screen you can set some options for your exam.
The default options are usually fine, but you should make sure that the settings under SCORM availability in particular are how you want them.
Click Submit, and your exam is ready to use!
Uploading to Moodle¶
Log in to Moodle, and go to the relevant course. Turn editing mode on, then click on the Add an activity or resource link and select SCORM package.
Enter your exam’s name in the Name field, and write a description in the field beneath. Then drag the .zip file you downloaded earlier onto the Package file field.
Take a look at the rest of the settings on the page to make sure they’re set how you want. The default settings are usually fine, though you might like to set Hide navigation buttons to Yes to save screen space.
When you’re ready, click on Save and display. Your exam is ready to use!
Writing your first question¶
In this tutorial you will learn about the structure and features of a Numbas question by creating a simple arithmetic test, starting with basic functionality and elaborating on that as we cover the more advanced tools available.
We’ve embedded screencasts of someone running through this tutorial at the start of each section. You might like to follow along with the video while reading the tutorial.
To begin, let’s make a question asking the student to add two numbers.
Log in to the Numbas editor and, in the Create box, click on the Question link.
You will be prompted to give your question a name, and to assign it to a project. As this is your first question you will probably want to use the default project, which is your own workspace.
The structure of a question¶
You are taken to the editing page for your new question. It is worth spending a few moments finding your way around this page.
At the top of the page are the question’s name and, above that, a link to the project which it belongs to. Below are options to run, give feedback and download the question. Below this there are options to navigate through the various steps involved in editing a question.
In the Admin box there are links to copy or delete the question. And in the Metadata box you can manage how your question is organised in the Numbas database.
In the centre is the main editing interface. Before moving any further, let’s change your question name from “My First Question” to something more descriptive so that you can find it later. Type “Numbas tutorial: arithmetic” in the Name field.
Every Numbas question consists of three sections: Statement, Parts, and Advice. In the Statement, the context for the question is given to the student. Parts are where the student enters their answers. A question can have one or more parts, each of which is one of several types, depending on what kind of input you want from the student. Finally, the optional Advice section can be used to give a full solution to the question, which the student can request to see if they’re stuck.
Each of these sections of the editor can be accessed from the links in the sidebar, or you can use the buttons at the bottom of each section to guide you through in a logical order.
Let’s make a question with a short statement, one part asking for a number to be entered, and a little bit of advice.
A very basic arithmetic question¶
We’re going to ask the student to add together the numbers \(3\) and \(5\). If you are still on the Settings page, click on the Statement button at the bottom, or on the Statement link in the sidebar. Type
What is 3+5?
in the Question statement box.
Click on the Test Run button. Your question will open in a new browser window. There is a statement, but nowhere to enter an answer. We need to create a number entry part. Go back to the editing window and click on Parts in the sidebar, or follow the navigation buttons at the bottom of the page, skipping past Variables, which we will consider later.
Once on the Parts page, click on the Add a part button, and select Number entry.
Every part has a Prompt, which you can use to ask the student for the particular answer the part assesses. We’ve already asked our question in the question’s statement, so we can leave this part’s prompt empty. Instead, click on the Marking link, where you’ll state the correct answer for the part.
Enter 1
in the Marks field, so the student is given one mark if their answer is marked correct.
Number entry parts are marked by checking if the student’s answer is within the range defined by the Minimum accepted value and Maximum accepted value fields.
For this question the answer is exactly \(8\), so put that in both fields.
Now press Test Run again to try out the question.
If you put 8
in the entry box and press Submit part, the answer is marked correct; any other number is marked incorrect.
To finish off this question, add a solution to the Advice section. There isn’t much to explain for this particular question, so just click on the Advice tab and enter
3+5 = 8
in the box.
Now click Test Run again; if you press the Reveal answers button at the bottom of the question page, the number input is filled in with the correct answer, and the advice text you wrote is displayed at the bottom.
You have created your first complete question!
Things to try before moving on:
 Enter a decimal number as the correct answer, and set the minimum and maximum accepted values to allow an error of plus or minus \(0.005\).
 Look at the documentation for the Number entry part and try out the precision restrictions.
Better maths display and randomised numbers¶
Now let’s add another part to the question, asking the student to multiply two numbers.
Add another Number entry part to your question. Now that we have two parts, it doesn’t make sense to ask for the answer to the first part in the question statement, so remove the text from the Statement and put it back in the first part’s Prompt.
Now, for the second part’s Prompt, enter:
What is 3*5?
And set the correct answer to 15
.
When you Test Run the question, you should be immediately offended by the unattractiveness of the rendering of the multiplication 3*5.
Mathematical notation is distinct from normal text and needs to be treated separately.
For this reason, Numbas uses LaTeX to mark up mathematical notation.
Note
While LaTeX is wonderfully expressive, it has quite a steep learning curve; if you’re not familiar with it, see LaTeX notation.
Replace the Prompt for the second part with
What is $3 \times 5$?
The dollar symbols delimit the LaTeX notation. Now when you Test Run the question again, you will see neatly typeset maths:
For consistency, go back and change the prompt for the first part to:
What is $3 + 5$?
The most important feature of computerbased assessment is the ability to dynamically generate questions which are different every time they are run. In Numbas this is achieved using variables.
Let’s change the question so that the two numbers to be added are picked at random.
Click on the Variables link. Click on the Add a variable button. Every variable needs a name and a definition. The definition is given in JME syntax.
Note
For information on what constitutes a valid variable name, see Variable names.
For more on JME syntax, see the JME reference.
Call this variable a
, and give it the definition:
random(1..9)
The variable will take a random wholenumber value between \(1\) and \(9\) (inclusive).
To the right of the variable’s name, a possible value for the variable is displayed. You can get a feel for what values a variable can take by pressing the Regenerate values button a few times.
Add a second variable called b
and give it the same definition.
The next step is to use these variables to define the prompts and acceptable values for both parts.
Change the prompt for the first part to
What is $\var{a} + \var{b}$?
\var{}
is a special LaTeX command which inserts the calculated value of the given expression directly into the LaTeX.
It doesn’t do anything to cancel out redundant terms or symbols  more on that later.
Now go to the Marking tab and change both accepted values to a+b
.
Click Test Run to see how your changes have affected the question. You can use the Try another question like this one button to regenerate the question without having to go back to the editor.
Now your question has nicely rendered maths and uses randomised numbers.
Things to try before moving on:
 Add two new variables
c
andd
, and change the second part to use them instead ofa
andb
.  Make sure that
a
andb
don’t both take the same value by using theexcept
operator in the definition ofb
.  Add a solution for the second part to the Advice section.
More complicated mathematical expressions¶
Until now, you’ve only written very simple mathematical expressions, where the randomised variables could be substituted in without any changes to the surrounding symbols.
Often, this isn’t the case; for such occasions, there is the \simplify
command.
\simplify
is a special LaTeX command which takes an expression in JME syntax, like \var
does, but rather than evaluating it to a number, tidies it up using a set of simplification rules.
Let’s add another part to the question, using \simplify
to present a quadratic equation with random coefficients, and ask the student to factorise it.
Add a new part and set its type to Mathematical expression.
This part will be constructed in reverse  we’ll generate the roots of the equation randomly, and use those to calculate the coefficients of the quadratic shown to the student. This way, the question is guaranteed to have a nice answer.
Add two new variables x0
and x1
:
x0 = random(9..9)
x1 = random(9..9 except x0)
The except
operator in the definition of x1
ensures that it doesn’t take the same value as x0
, so the quadratic doesn’t have repeated roots.
It’s a good idea to add comments to your variable definitions to explain what they represent and how they’re generated.
A comment starts with two forward slashes //
and continues until the end of the line.
A reasonable comment for x0
would be:
A root of the quadratic equation. Chosen not to be zero.
A reasonable comment for x1
would be:
The other root of the quadratic equation. Not the same asx1
.
Now the Prompt for the part might go something like this:
Factorise $x^2 + \var{x0+x1}x + \var{x0*x1}$.
But that can produce unnatural expressions, like these:
In the first, only a subtraction sign should be shown; in the second the x term should be omitted.
Rewrite the prompt using the \simplify
command:
Factorise $\simplify{ x^2 + {x0+x1}*x + {x0*x1} }$
The command takes an expression in JME syntax. The expressions between curly braces are evaluated to numbers using the defined variables, and then the whole expression is rearranged to produce something that looks more natural.
Note
For more on what exactly the \simplify
command does, see Simplification rules.
Click on the part’s Marking tab and set the Correct answer to:
(x+{x0})(x+{x1})
(Again, expressions in curly braces are evaluated as numbers when the question is run.)
Numbas marks Mathematical expression parts by choosing a random sample of points on which to evaluate them, and comparing the result given by the student’s answer with that given by the Correct answer. Because it doesn’t pay any attention to the form of the student’s answer, it has no way of distinguishing between the factorised and expanded forms of our quadratic  the student could just enter the same expression they’re given and it would be marked correct.
To prevent this, you can specify a pattern restrictions to constrain the form of the student’s answer.
Go to the part’s Restrictions tab and enter (x + ?`?)(x + ?`?) ` (x + ?`?)^2
in the Pattern student’s answer must match field.
This accepts either the product of two linear factors, or a single linear factor, squared.
Click Test Run and check that your question is marked correctly.
That’s it for this tutorial. You’ve created a very simple Numbas question asking the student to enter some numbers and a mathematical expression, with randomised parameters and neatly rendered maths. If you got lost along the way, you can compare what you’ve got with this question we prepared earlier.
What next?¶
Now you’ve written your own question, you’ll probably want to dive into more advanced topics. Here are some things you could try next:
 Set up a project so you can collaborate with your colleagues.
 If you’ve got an idea of something you’d like to do, the How do I… section probably contains an example showing you how to do it.
 Look at the question highlights on the Numbas blog for some inspiration.
 Start writing your own questions!
Collaborating using Numbas¶
Numbas has several features to make collaborating with colleagues easier.
Gather material in projects¶
Projects grant automatic editing access to their members.
Rather than granting editing access to each of your colleagues for each item you’re collaborating on, organise all the material inside a project and add your colleagues as members. Every member of the project will be able to see and give feedback on all the material.
Use the project timeline, and the editing history tab on individual items, to keep track of changes you and your colleagues make. Write comments to discuss changes or problems.
Give feedback¶
Use the feedback stamps to tell your colleagues which of your questions are ready to use, and which need more attention.
It’s a good idea to have someone else test a question once it’s complete; they should proofread the text and then attempt the question, giving both correct and incorrect answers to check that the marking works as intended.
If a colleague makes a copy of a question and you decide to use that instead, mark the original version as “Should not be used” to avoid confusion later on.
When it’s time to compile an exam, every question in it should be labelled “Ready to use”. That way, you know there won’t be any problems when your students take the exam.
Pull requests¶
If you see a problem in someone else’s question but don’t have editing access, make a copy and fix it, but don’t just leave the original to languish  create a pull request so your changes can be merged back into the original.
Use the editing history tab¶
Each time you make a change to a question, set a checkpoint to save a snapshot of your question when you make a change. Write an informative description of the current state of the question, and what you’ve changed since the last restore point.
This is useful when you’re editing your own questions, but doubly so when editing other people’s  they can quickly see what’s different, and decide if they’re happy with the changes.
You can write comments on the editing history. Use this to suggest changes, report bugs, and so on.
Give feedback on quality¶
Add descriptions to variables and use sensible names¶
Short variable names are quick to type, but not easy to understand.
Try to avoid singleletter variable names as much as possible, and prefer longer names over shorter ones.
For example, it isn’t immediately obvious what sm
represents, while sample_mean
is very clear.
In addition, make sure to write a description of each variable in the box under its definition. You should explain what the variable represents, and also describe any important points about how the variable is generated, or what values it can take.
Tag questions¶
Use tags to categorise your questions. Agree with your colleagues how to tag questions  if everyone makes up their own tags, they’re no use at all!
Here are some tagging schemes you might want to use:
 By topic  tag a question with the part of the curriculum it covers, separately from the name of the particular course you’re making it for, so colleagues teaching other courses can find it.
 By level  use a tag to tell other authors which age range or ability level your question is suitable for.
How do I…¶
This section largely draws from the “Howtos” project on the numbas.mathcentre.ac.uk editor, where we gather example questions created to demonstrate authoring techniques.
If you’ve got a question that isn’t answered here, try asking on the Numbas users mailing list.
Delivering an exam¶
Delay showing students scores until a certain date¶
This is only possible when delivering the exam through the Numbas LTI provider.
First, turn off the feedback options Show current score? and Show answer state?, so students don’t get any feedback while completing the exam.
Then, set Show results page to When entering in review mode.
Finally, after uploading the exam to the Numbas LTI provider, set the Allow students to review attempt from setting to the date and time after which you’d like to allow students to see their scores and feedback.
When a student completes the exam, they won’t see any feedback. Once the chosen time has passed, the student will be able to reenter the exam in review mode and see their scores and full feedback.
Images, diagrams and other media¶
Include an image¶
It’s best practice to attach images to questions so that they’re distributed with the final compiled exam, rather than linking to images stored on a webserver.
When editing a content area, click on the Insert/Edit Image button. You can then either pick an image you’ve already uploaded, or click the Choose file button to upload an image from your computer.
You can resize images and add a title attribute by selecting the image in the content area and clicking on the Insert/Edit Image button.
Embed a video¶
Upload your video to somewhere like YouTube or Vimeo. Including videos in downloaded exam packages is a terrible idea, so we discourage that. Click the Embed image/video button (it’s a blue cloud), and paste in the URL of your video.
Include an interactive diagram¶
There are a couple of ways of including an interactive diagram in a Numbas question. You can either embed a GeoGebra applet, or use JSXGraph.
For JSXGraph diagrams, there is an extension which takes care of most of the setup. You will need to write a fair amount of JavaScript code to create a diagram using JSXGraph.
GeoGebra applets are much easier to create and use, but are loaded from geogebra.org so the student must have internet access in order to use any questions containing GeoGebra applets.
The screencast below explains how to use a GeoGebra applet in a question. For more information, see the page on the geogebra extension.
Substitute random variables into an image¶
Text inside an SVG image follows the same variable substitution rules as prose text: expressions enclosed in curly braces are evaluated and replaced with the resulting string.
Pay attention to the text alignment options when designing your image: randomly generated values are usually not the same width as the expressions they replace.
See the question Volume of a swimming pool for an example of an SVG image with variables substituted into text.
Show one of several images based on a random variables¶
See the question Using a randomly chosen image for an example of one method.
Display a random line in a GeoGebra applet¶
A neat way to create a random line is to randomly pick the positions of two points on the line.
Create two points in your GeoGebra worksheet, and a line between those two points.
Set the positions of the points in the parameters to the geogebra_applet()
function.
Use student input in a JSXGraph diagram¶
This question shows how to construct a line corresponding to an equation given by the student.
Appearance and display¶
Change how the question looks¶
You can use the formatting tools in the question editor to style your text. However, if you repeat the same styles over and over, or want to change aspects of the layout such as space between elements or decoration, you’ll need to write some CSS.
CSS is a language for defining how things should look  there’s a good introduction at Khan Academy. In the Numbas editor, you can add CSS rules to a question in the Preamble section.
The following questions demonstrate how to use CSS to change the look of a Numbas question:
 Style a table of sales figures 
 Use CSS to style parallel translation  CSS classes “english” and “cymraeg” apply different background colours to English and Welsh portions of text.
 CSS Lemma environment  defines a CSS class in the preamble which styles the “Lemma” environment, used in the statement.
 More space between multiple choice answers
Reveal the answer to a single part after submitting an answer¶
Someone wanted to know how to reveal the answer to one part of a question as soon as the student submits an answer, because the following part depends on having the correct answer to the first part.
This example question shows a few different ways of doing this.
Think very carefully before using this: by revealing the answer, you are removing the opportunity for the student to later on realise they’ve got that step wrong, as a consequence of some further work. It’s often possible to use adaptive marking to use the student’s answer in place of the correct answer in later parts.
Set an attribute on an HTML element based on the value of a question variable¶
Use the Source code view in a content area to edit its HTML code.
You can set the value of an attribute on an HTML tag to the result of a JME expression by prefixing the attribute’s name with eval
.
Variables are substituted into the attribute’s value using curly braces.
For example, this tag will have its class
attribute set to the value of the variable classes
:
<div evalclass="{classes}">
Question text¶
Show one of several blocks of text based on a random variable¶
Suppose you have a random variable a
, which has the value 1,2 or 3, corresponding to three different scenarios.
First, write out the text for each scenario.
There is a button in the rich text editor labelled Conditional visibility.
This allows you to give an expression (in JME syntax) which dictates whether or not the selected text is shown.
For each scenario, select the corresponding text and click on the Conditional visibility button.
Enter a=1
for the first block, a=2
for the second, and a=3
for the third.
When you run the question, only the block of text corresponding to the value of a
is shown.
You can see an example of this technique in the question Conditional visibility.
Display a dollar sign¶
Because the dollar symbol is used to delimit portions of LaTeX maths, you need to escape dollar signs intended for display by placing a backslash before them – that is, write \$
.
See this example question.
Use random names for people in question statements¶
Whenever you have a named person in a question, you should try to randomise the name. It doesn’t really matter what people are called in word problems, but it can have a bad effect on students’ perceptions of the world if the plumber’s always called Gary and the nurse is always called Julie.
We’ve written a “random person” extension which makes it easy to randomly pick a name for a person, and use the correct pronouns.
There’s documentation on the extension’s GitHub repository, and an example question showing how to use it most effectively.
Randomise the names of variables in an expression¶
Suppose you want the student to solve an equation in terms of some variables, but you want to change the names of those variables each time the question is run. There are a couple of ways of achieving this.
One straightforward method is to use the expression()
command to substitute variable names, randomly generated as strings, into JME expressions as variables.
See this example question.
Use commas or spaces to separate powers of 1,000 in numbers¶
By default, numbers substituted into question text do not have any separators between powers of 1,000.
When working with realworld data, separating blocks of figures can improve readability.
Use the formatnumber()
function to render numbers following one of the supported Number notation styles.
This example question shows how the formatnumber()
function in use.
Show amounts of money with trailing zeros¶
Use the currency()
function to ensure that amounts of money are displayed as you’d expect: the figure is either a whole number or given to two decimal places, and the appropriate symbol for the unit of currency is shown before or after the figure.
LaTeX¶
Include a randomised LaTeX command¶
If you want to include a LaTeX command in a string variable, remember that backslashes and curly braces in strings must be escaped.
That means you should type two backslashes where you’d normally type one, and add a backslash before each left or right curly brace, for example \\frac\{1\}\{2\}
produces the LaTeX \frac{1}{2}
.
You need to do this because the backslash is used as an escape character in strings so you can include quote marks, which would normally end the string.
(For example, "he said \"hello\" to me"
)
If you substitute a string variable into a mathematical expression using \var
, it’s normally assumed to represent plain text and displayed using the plain text font.
If your string is really a partial LaTeX expression, you must mark it as such by wrapping it in latex()
, e.g. \var{latex(mystring)}
.
Substituted randomised raw LaTeX into question text¶
The majority of the time, substituting raw LaTeX into a question is not the neatest way of achieving what you want. It’s often possible to achieve the desired effect by good use of the simplify command.
However, if you do need to substitute raw LaTeX code into question text for some reason, the latex()
command is normally what you want.
See this example question, which shows how different methods of substituting a string into question text end up being displayed.
Custom marking scripts¶
Use LaTeX in a comment created during a custom marking script¶
Remember that backslashes must be escaped in JavaScript strings, i.e. this.markingComment("$\\sqrt{x}$")
instead of this.markingComment("$\sqrt{x}$")
.
Check that the student has simplified a polynomial fraction¶
This question uses patternmatching to check that the student’s answer is in the form \(\frac{x+?}{?}\). In combination with the normal mathematical expression marking algorithm, this confirms that the student has simplified a fraction of the form \(\frac{x+a}{x+b}\).
Check that the student has factorised a quadratic expression¶
This question uses Patternmatching mathematical expressions to check that the student’s answer is the product of two factors. In combination with the normal mathematical expression marking algorithm, this confirms that the student has factorised the expression.
Use data from a CSV file that the student has uploaded¶
This question uses some custom JavaScript to process a file that the student uploads, and use it to set the correct answers for the question’s parts.
Variable generation¶
Generate a random list of unique numbers¶
Suppose you want to pick a list of numbers from a given range, but don’t want any repeats.
Use the shuffle()
function to put the numbers in random order, then take as many as you need from the front of the resulting list.
The example below picks three distinct numbers between 0 and 10:
shuffle(0..10)[0..3]
Assign several variables corresponding to a scenario¶
A simple way of randomising a question, particularly when working with realworld data, is to come up with a number of distinct scenarios.
Use the dictionary
data type to list the values of variables corresponding to each scenario, then pick randomly from a list of these dictionaries.
This more sophisticated example combines lists of names with JSON data to construct a table of data about people’s hobbies.
Load JSON data¶
JSON is a commonlyused format to store data in a way that is easy for both people and computers to read.
The following questions show how to use large JSON data sets in Numbas questions:
 Items from the CooperHewitt collection, with associated images.
 Data about members of the Scottish Parliament.
Maths¶
Find the factors of a number¶
If your number is small enough  as a rule of thumb, at most 5 digits  the easiest way to list all the factors of a number \(N\) is to check each lower number for divisibility by \(N\):
filter(xn, x, 1..n)
Find the prime factorisation of a number¶
Primality testing is a difficult topic, but if your number is small enough it’s easiest just to check against a hardcoded list of prime numbers.
The following produces a list of pairs [prime, power]
for the primepower factors of the number n
:
filter(x[1]>0,x,zip(primes,factorise(n)))
See this example question, which also produces LaTeX code to show the factorisation.
Randomly give two of hypotenuse, opposite, and adjacent side of a triangle¶
This question shows how to randomly generate a Pythagorean triple  a rightangled triangle with integerlength sides  and randomly show two of the lengths to the student. The student is asked to calculate the length of the third side.
Take a logarithm to a randomlychosen base.¶
The builtin JME functions ln()
and log()
compute logarithms to base \(e\) and \(10\), respectively.
log()
can take a second parameter defining the base.
For example:
log(x,3)
Computes \(\log_3(x)\).
This example question shows how to ask the student to enter a mathematical expression containing a logarithm to a randomlychosen base, or with an unbound variable as the base.
Projects¶
Projects provide a way of collecting together all your work on a particular topic or course, and automatically granting access to your collaborators.
In the Numbas editor, every exam or question must belong to a single project. Your account always has one project attached to it  your workspace. When you create a new exam or question, you’ll be asked which project you want to attach it to, and the default option is your workspace.
If you’re putting together content for a course you’re teaching, it’s a good idea to create a new project as a single gathering point for your material. A project is effectively a “fenced off” area of the editor where you can concentrate on just the material you want to work on, without having to wade through unrelated items.
Creating a new project¶
Click on the New button at the top of the page, and then on Project. You need to give some information about your new project:
 A name for the project. This should succinctly describe what the project is for, or what it contains.
 A longer description of the project. You could include a link to your course homepage, or some information about the aims of the project.
 A default language for content created in this project. Any new exams created in this project will use this language by default.
 A default licence for content created in this project. Any new exams created in this project will have this licence attached by default.
The project home page¶
A project’s home page shows a timeline of activity on the project, the list of members, and links to create new content or browse the project’s existing content.
The timeline shows all activity on exams or questions belonging to the question, as well as comments attached to the project itself. Timeline items belonging to each project you’re a member of will also be shown in your personal timeline on the editor homepage.
The cog icon at the top of the page takes you to the project’s options page. On this page you can change any of the project’s settings or, if you’re the project’s owner and it isn’t your personal workspace, delete it.
Finding content inside a project¶
From the project homepage, click on either of the Browse links to see the questions or exams belonging to the project. You can narrow down your search by adding a query in the search bar at the top of the page, or selecting one of the filters.
Project settings¶
Click on the cog icon at the topright of the page to change a project’s settings.
If Visible to nonmembers? is ticked, the project and all of its published content will be visible to the general public.
Adding someone to a project¶
From the project’s homepage, click on the settings icon at the top of the list of members to go to the member settings page. In the Add a member box, type the name of the person you want to invite. If they don’t have an account yet, their email address; they’ll get an email asking them to create an account and when they do, they’ll be given access to your project immediately.
You can control what project members are allowed to do: if you select Can view then the user will be able to look at, comment on, and download all content in the project, but not change anything. If you select Can edit, then they will also be able to create new content or change existing content. You can also give project members access to individual exams or questions using the access controls on their respective edit pages.
Changing or removing a project member’s access¶
From the project’s homepage, click on the settings icon at the top of the list of members to go to the member settings page.
Change a project member’s access rights by selecting an option from the dropdown next to their name.
To remove a user from the project, tick the checkbox corresponding to their name, then click the Save changes button.
Transferring ownership of a project to someone else¶
The owner of a project has certain privileges which no other user does, such as deleting the project.
To transfer ownership of a project to somebody else, go to the Members settings page and click on the Transfer ownership button, then enter the name of the person you’d like to transfer ownership to. That user will become the owner of the project, and you will be given editing access to the project.
Deleting a project¶
To delete a project, you must be its owner. You can’t delete your personal workspace.
Warning
Only delete a project if you’re absolutely sure you don’t need it any more. Deleting a project is an irreversible action that will result in the loss of data belonging to the project.
To delete a project, go to the project’s Options page and click on the Delete this project button.
Questions and exams belonging to the project will be reassigned to their authors’ personal workspaces, but any comments on the project’s activity timeline will be deleted.
Exams¶
An exam is a collection of questions which you will give to your students. Within an exam you can set a pass mark, as well as configure how much feedback students can receive and how they can navigate between questions.
For a quick introduction to the workflow involved in putting an exam together, see the tutorial on creating an exam.
Creating an exam¶
To create an exam from any page in the Numbas editor, click on the plus icon at the top of the page, and select Exam.
You must give a name for your exam, and select a project for it to go in. The default project is your personal workspace; you can always move the exam to another of your projects later on.
The exam editor¶
At the top of the exam editor is the exam’s name, as well as a stamp showing the status of the exam.
Click on the status stamp to give feedback about the quality of an exam, after test running it. The options are listed in descending order of “suitability for use”:
 Ready to use  this exam is of sufficient quality to give to students.
 Should not be used  this exam works, but you deprecate its use  for example, if it’s not intended for use by students, or there’s a better version elsewhere.
 Has some problems  this exam works, but has some problems which mean it’s not ready for use by students  for example, the exam is incomplete, or changes need to be made to the text. Further work is needed before this exam can be given to students.
 Doesn’t work  this exam doesn’t even run!
 Needs to be tested  this exam looks alright to me, but it should be checked thoroughly before being used.
On the left of the screen are Admin controls and labels for each of the editing tabs.
Admin controls¶
 Test Run
Opens a preview of the exam in a new window.
Warning
Do NOT use this link to deliver the exam to students. This link is not permanent and could stop working at any time. Instead, download the exam and put it either on your own webspace or in a VLE.
 Make a copy
 Create a copy of the exam. Use this to make changes to an exam which does not belong to you.
 Delete
 Delete the exam permanently from the database. The associated questions are not deleted  you must delete them individually, if you want them to be deleted too.
 Download
Links to download standalone packages of the exam.
 SCORM package  a compiled package of the exam with SCORM files included, so it can be uploaded to a VLE and communicate with its gradebook.
 standalone .zip  a compiled package of the exam, ready to run anywhere without connecting to a VLE.
 source  a plaintext representation of the exam, to be used with the Numbas commandline tools or as a backup.
Questions¶
Select the questions you want to include in your exam on this tab.
Questions are organised into groups. For each group, you can decide how many of the available questions to show to the student, and the order they should appear. You can use every question selected, or pick a random subset each time the exam is started.
 Show group names to student?
 If this is ticked, the names you give to each group of questions will be shown to the student in the navigation menu when they run the exam, and in the score breakdown at the end of the exam.
 Questions to use
The strategy for picking questions to show to the student.
 All questions, in this order  all of the questions in the list below are shown to the student, in the order you’ve chosen.
 All questions, in random order  all of the questions in the list below are shown to the student, in a different order for each attempt.
 Pick a random subset  A subset of the questions in the list below are shown to the student. The questions chosen, and the order they appear, will differ for each attempt.
 Number of questions to choose
 If using the “Pick a random subset” strategy, this many questions from this group will be shown to the student.
 Pass threshold
 Define a pass/fail threshold for the student’s total score, as a percentage of the available marks. The pass/fail message will be displayed when the student ends the exam. If this is set to zero, then no message is displayed.
The tabs on the right hand side offer different ways of finding questions to add to the exam.
 The Basket tab shows questions you’ve added to your basket: you can browse the question editor to find questions, add them to your basket, and then go back to the exam editing page and add them in.
 The Recent questions tab shows questions you have recently edited.
You can check a question does what you want and give it a test run before including it in your exam: click on the question’s name to open its editing page in a new window.
Click the plus icon on one of the question results to add it to your exam.
You can drag and drop questions in the list on the left to reorder them, or move them between groups.
The Replace this question with a copy lets you quickly swap in a duplicate of a question you’ve included in your exam. If you’re using a question created by someone else, this is a convenient way of getting a version of the question you can make changes to.
Note
Removing a question from an exam does not remove it from the database. To permanently delete a question, click on its name to open its edit page, and click the Delete button there.
Display¶
 Interface theme
 Themes control the user interface of an exam, changing the look and feel. The default theme is designed for exams which will be delivered over the web. There is also a worksheet theme which can be used to print out multiple, randomised copies of an exam for students to complete on paper.
 Interface language
 Specify which translation to use for the text in the user interface, i.e. button labels, error messages, etc.
Timing¶
 Exam duration
 The length of time students are allowed to attempt the exam. If set to zero, then there is no time limit.
 Allow pausing?
 If ticked, the student can pause the exam while running it, and the timer will stop. If unticked, there is no pause button, and the end time is fixed when the session starts  leaving and resuming through the VLE will not affect the end time.
 On timeout (event)
 If set to Warn, the given message is displayed when the student runs out of time.
 5 minutes before timeout (event)
 If set to Warn, the given message is displayed five minutes before the student runs out of time.
Feedback¶
 Show current score?
 If ticked, the student will be shown their score for each question and part immediately after submitting their answers.
 Show maximum score?
 If ticked, the student will be shown the maximum attainable score for each question and part.
 Show answer state?
 If ticked, then when the student submits an answer an icon will be displayed to let the student know if their answer was marked correct, partially correct or incorrect, and feedback messages will be displayed underneath.
 Allow reveal answer?
 If ticked, then the Reveal answer button is enabled on each question. If the student chooses to reveal the answer to a question, they are shown the correct answer but lose all their marks and can not reattempt the question.
 Show student’s name?
 If ticked, the student’s name is shown on the results page after the exam has finished. The student’s name is only available when running the exam through a VLE  exams run standalone do not know the student’s name.
 Introduction
 This text is shown to the student on the front page, before the exam starts. You could use it to outline the rules of the exam, or just summarise the subjects covered.
 Feedback messages
You can write a list of messages, paired with threshold percentages, to show to the student at the end of the exam. The student’s score is calculated as a percentage, rounded to the nearest 1%, and compared with the thresholds for each message. The message with the largest threshold less than or equal to the student’s score is displayed.
You could use these messages to suggest topics for the student to revise, direct them to support resources, or detail the consequences of failing the test.
Events¶
Some of the properties described above are marked as events. These all have the same structure: an action setting which determines how to react to the event, and a message to display to the student when appropriate.
Settings¶
The settings tab is where you set up metadata describing the exam.
Try to make sure not to ignore the settings tab, even if you just want to get a working exam as quickly as possible  a good name and description will make it much easier to find your exam again in the future!
 Name
 This is shown to the student and used for searching within the editor, so make it something intelligible. “Linear algebra diagnostic test” is a good name; “L.A. t1 v1” is not.
 Description
 Use this field to describe the exam’s contents, what it assesses, and so on. This is shown in the exams index, so make sure it’s fairly concise.
Use tags to categorise exams so they can be found through the search function. Your guiding principle should be “more is better”  try to write down all words that someone searching for this exam might use.
After typing a tag in the box, press the Enter key to add it to the list.
Metadata¶
 Transfer ownership
 Click this button to transfer ownership of the exam to somebody else. You will be given editing access automatically, but the new owner can revoke this.
 Move to another project
 Click this button to move the exam to another project. You can move an exam to any project to which you have editing access.
 Licence
 You can specify the licence under which you are making your resources available. Different licences allow other users to copy, modify or reuse your content in different ways  consider which licence to choose carefully. CC BY allows other users to reuse your content however you like, as long as they give appropriate credit to you.
 Subjects and Topics
The Subjects and Topics fields provide a more structured way to categorise exams according to the subjects they assess. Database search results can be filtered by subject or topic.
Once you have selected one or more subjects, topics belonging to those subjects appear underneath.
The options for these fields are defined by the server administrator.
 Ability levels
Use this field to describe which ability levels the exam is appropriate for.
Several ability frameworks are available to choose from  pick the framework which most closely matches your own, and select one or more ability levels. An ability level is modelled as an interval in the range 0 to 1, so when you filter database search results by ability level, any items whose ability levels overlap the ones you selected are included in the results.
The options for these fields are defined by the server administrator.
Access¶
You can control who is allowed to see, and to edit, your exams.
When you create a new exam, access is limited to you and any other members of the project the exam belongs to. You can grant extra access to indvidual users or publish your exam to the public database, where it can be viewed by any other user.
Public visibility
 Only you and users named in the Individual access rights section can see this exam.
 Anyone can see this
 Anyone, even users who are not logged in, can see this exam. Only you and users named in the Individual access rights section can edit this exam.
 Anyone can edit this
 Anyone, even users who are not logged in, can see and edit this exam.
Give access to a user
Type a name into the search box to find a user. Click on a user’s name in the results list to add them to the access list.
Named users can have the following rights:
 Can view this
 The named user can see, but not edit, this exam.
 Can edit this
 The named user can see this exam and make changes to it.
Access Links
The URLs in this section automatically grant access to whoever follows them. You could use these links to share a question with someone who hasn’t yet created an account on the editor (they’ll be prompted to create an account when they click on the link), or to share a question with a group of people without inviting each person individually.
Warning
These URLs grant access to whoever clicks on them, so be careful about how they’re shared.
Other versions¶
In this tab you can see all exams which are related to this one. Exams are related if one is a copy of the other, or they are both copies of a common ancestor. You can use this tab to compare the current exam with related versions, and offer to merge your version of the exam into another.
Click on the Compare link to go to a screen where you can offer to replace the other version with your version, or vice versa. If you have editing access to the destination exam, you can replace it with the other version automatically. If you don’t have editing access, the owner of the exam will be sent a Request to merge, which they must accept before the exams are merged.
Before creating the request, you’ll be asked to describe how your version differs from the one you want to replace. Try to sum up all your changes  this will show up in the exam’s editing history if your request is accepted.
Warning
If the exam you want to replace has changed since you made a copy of it, those changes will be lost if the request to merge is accepted  the exam is completely overwritten with the new version.
You can always restore an old version of an exam after a merge, by clicking on the appropriate restore link in the Editing history tab.
Active requests to merge other versions into the current exam are shown underneath the list of related versions. You can accept the request, in which case your version will be replaced with the other version, or reject it, in which case your version will be unchanged and the person who made the request will be notified that it was rejected.
Editing history¶
Use this tab to keep a record of changes made to your exam. Write comments to discuss problems or suggested changes.
The Contributors list shows everyone who has made a change to this exam. This list is included with the exam when you download it, and if you reupload this exam to an instance of the Numbas editor.
Each time you make a change to an exam, it’s saved to the database. To save a snapshot of the current state of the exam, click the Set a checkpoint button. You’ll be asked to write a description of the exam as it stands  describe what you’ve changed since the last snapshot, and why you’re making a snapshot.
To restore a checkpoint, click its Restore button. The current state of the exam will be overwritten with the saved state.
Other activity on this exam will also be shown in this tab: for example, each time somebody uses the Feedback button to provide feedback on this exam, an entry is added to the editing history.
Questions¶
In Numbas, a question is a selfcontained assessment of a particular scenario. Every Numbas question consists of three sections: Statement, Parts, and Advice.
 In the Statement, the context for the question is given to the student.
 Parts are where the student enters their answers. A question can have one or more parts, each of which is one of several types, depending on what kind of input you want from the student.
 Finally, the optional Advice section can be used to give a full solution to the question, which the student can request to see if they’re stuck, or once they’ve finished the exam.
The content in each section is generated each time the question is run, based on the question’s variables.
Creating a question¶
To create a question from any page in the Numbas editor, click on the plus icon at the top of the page, and select Question.
You must give a name for your question, and select a project for it to go in. The default project is your personal workspace; you can always move the question to another of your projects later on.
The question editor¶
At the top of the question editor is the question’s name, as well as a stamp showing the status of the question.
Click on the status stamp to give feedback about the quality of an question, after test running it. The options are listed in descending order of “suitability for use”:
 Ready to use  this question is of sufficient quality to give to students.
 Should not be used  this question works, but you deprecate its use  for example, if it’s not intended for use by students, or there’s a better version elsewhere.
 Has some problems  this question works, but has some problems which mean it’s not ready for use by students  for example, the question is incomplete, or changes need to be made to the text. Further work is needed before this question can be given to students.
 Doesn’t work  this question doesn’t even run!
 Needs to be tested  this question looks alright to me, but it should be checked thoroughly before being used.
On the left of the screen are Admin controls and labels for each of the editing tabs.
Admin controls¶
 Test Run
Opens a preview of the question in a new window. A specially simplified theme will be used, different from the one used for exams.
You can also use the keyboard shortcut Ctrl+B to open a preview.
Warning
Do NOT use this link to deliver the question to students. This link is not permanent and could stop working at any time. Instead, download the question and put it either on your own webspace or in a VLE.
 Make a copy
 Create a copy of the question. Use this to make changes to an question which does not belong to you.
 Delete
 Delete the question permanently from the database.
 Download
Links to download standalone packages of the question.
 standalone .zip  a compiled package of the question, ready to run anywhere without connecting to a VLE.
 SCORM package  a compiled package of the question with SCORM files included, so it can be uploaded to a VLE and communicate with its gradebook.
 source  a plaintext representation of the question, to be used with the Numbas commandline tools.
 Add to your basket
 Add this question to your basket, so you can include it in an exam.
Content areas¶
Each portion of text displayed to the student (for example, the statement, advice, and part prompts) is a content area. A content area can include text, images, or more dynamic content such as videos and interactive diagrams.
By default, text is edited using the rich text editor. Click on the Source code button to edit the raw HTML code for the content area.
You can write mathematical notation in content areas using LaTeX; see the section on LaTeX notation.
There is a button in the rich text editor labelled Conditional visibility. This allows you to give an expression (in JME syntax) which dictates whether or not the selected text is shown. You can use this to show one of several blocks of text based on a random variable.
Substituting variables into content areas¶
There are two modes of variable subsitution: substitution into plain text (or HTML), and substitution into mathematical expressions.
Here’s a quick summary of the different methods of substituting variables into question text, to help you choose:
I want to substitute  Such as  So use 

A text string  Someone’s name  Curly braces, e.g. {name} is a farmer. 
A single number into a LaTeX expression with no surrounding operators  \(x\) in \(a = x\)  \var,
e.g. $a = \var{x}$ 
Several numbers into a LaTeX expression  \(a\), \(b\) and \(c\) into \(ax^2+bx+c\)  \simplify,
e.g. \simplify{ {a}x^2 + {b}x + {c} } 
Substitution of variables into plain text is straightforward: just enclose the variable name (or any JME expression) in curly braces. For example:
Bob the farmer has {num_animals} {animal_name}.
produces:
Bob the farmer has 12 sheep.
when num_animals = 12
and animal_name = "sheep"
.
The substitution of variables into a mathematical expression is more complicated: depending on context, the surrounding expression may need to be change for different values of the substituted variables. Numbas provides a simple system to handle substitution of variables into mathematical expressions; see the section on Substituting variables into displayed maths.
Statement¶
The statement is a content area which appears at the top of the question, before any input boxes. Use the statement to set up the question and provide any information the student needs to answer it.
Parts¶
Each question has one or more parts. The student is given a separate score for each part of the question, and their total score is the sum of their scores for each part.
In the editor, parts are displayed in a list on the right of a page; you can click on a part in the list to start editing it. You can drag up or down a part to change its position in the question.
To add a new part to your question, click the Add a part button at the bottom of the list, then click on one of the part types shown. Click on the more part types button to browse the list of custom part types available to you. You can filter the list by typing keywords in the search box at the top.
See Question parts for more on part settings.
Variables¶
The Generated value column shows a generated value for each variable. Note that when the question is delivered to students, the variable values are generated with each new attempt, so students won’t necessarily see the same values as those displayed here. It’s a good idea to use the Regenerate values button a few times to check that randomised variables don’t take unsuitable values.
You can reorder the variables in the list by dragging them. Doing this doesn’t affect the way values are computed.
This screencast gives a quick summary of how the variable editing interface works:
This screencast describes which variable names are valid, and gives some advice on how you should pick names:
Definition¶
 Name
 The name of the variable. See the section on variable names.
 Data type
Specify what type of data the variable should hold. The JME code option allows you to define the variable using JME syntax, while the other options provide simplified forms.
The JSON data option allows you to enter raw JSON data, which is parsed into JME data.
The Short text string and Long text string options have a checkbox labelled Is this a template?. If ticked, the string will be marked as
safe
, and variable values will not be substituted into it. Use this in conjunction with therender()
function to write reusable pieces of text. Value
 Define the variable’s value. The format of this field depends on the data type.
 Description
Describe what the variable means, and how it is used. It’s also often helpful to explain how it’s defined, and what changes can be made to it.
Note
Don’t underestimate the value of the description field! Variables whose meaning seems clear when you write them have a habit of becoming indecipherable months later.
 Depends on
 A list of all variables used in this variable’s definition. You can click on a variable name to go to its definition. If the variable hasn’t been defined yet, it’ll be created.
 Used by
 A list of all variables which use this variable in their definition. You can click on a variable name to go to its definition.
Locking variable values¶
The preview values for each question variable are regenerated each time you click on the Regenerate variables button or, if the Automatically regenerate variables when changes are made option is ticked, whenever a variable definition is changed.
You can lock the value of a variable so that it doesn’t change when the other variables are regenerated. To do so, click on the padlock icon next to the variable’s name. Any variables used in the definition of the locked variable (those which appear in the Depends on list) will also be locked implicitly, so that you don’t end up with an inconsistent set of variables. You can unlock a variable by clicking on the padlock icon again.
Warning
Variables are only locked inside the editor’s preview area  when you test run the question, or include it in an exam, a fresh value for the variable will be generated.
Variable testing¶
This tab provides tools to test your variables for desired properties, so you can automatically rerandomise your questions’ variables until you get a suitable set of values.
Example question using variable testing tools.
Warning
While this tool allows you to pick sets of variables that would be hard to generate constructively, it’s a random process so you must be aware that there’s a chance no suitable set of values will ever be found. Use the Test condition button to see how likely this is.
 Condition to satisfy
A JME expression which should evaluate to true when the set of variables generated has the properties you want. For example, if a, b and c are the coefficients of a quadratic equation and you want it to have real roots, the condition could be b^24*a*c>=0.
When the student runs this question, the system will regenerate the set of variables until it finds one which satisfies this condition.
 Test condition
When you press this button, the editor will generate as many sets of variables as possible within the time given. When it finishes, you’ll be presented with statistics including the proportion of runs which produced acceptable sets of values, and the expected number of runs before an acceptable set of values is found.
If the calculate probability of getting an acceptable set of variables within 1 second is lower than 99%, you should make changes to your variable definitions.
 Maximum number of runs
 The maximum number of times the system should regenerate the set of variables without finding a set which satisfies the condition before giving up. If the system exceeds this number in a compiled exam, the entire exam will fail, so try to avoid it!
Advice¶
Advice is a content area which is shown when the student presses the Reveal button to reveal the question’s answers, or at the end of the exam.
The advice area is normally used to present a worked solution to the question.
Extensions & scripts¶
This tab contains tools to change the behaviour of your question, using prebuilt extensions or by adding custom JME functions and JavaScript.
Extensions¶
Extensions can provide new functionality, such as extra JME functions or content types. To use an extension in your question, tick its checkbox here. All functionality provided by the extension will become available immediately. See the section on Extensions.
Functions¶
If you need to do something a bit more complicated with variables, or you find yourself repeating the same pattern over and over, you can define a custom function. Custom functions can be used in any JME expression in the question, such as variable definitions or part answers.
 Name
 The name of the function. Should be a valid JME name  it should start with a letter, and contain only letters and numbers, with no spaces or punctuation.
 Language
Functions can be defined either with a JME expression or with JavaScript code. In the case of a JME expression, the value returned is the result of evaluating the expression on the function’s parameters. You can also refer to the question’s variables.
JavaScript functions should return their result with a
return
expression. You don’t need to write thefunction(parameters) {}
part  just write the function body. Output type
 The type of the value returned by the function.
 Parameters
 The parameters given to the function. You can refer to them by name in the function’s definition. Make sure you correctly set the types of the parameters. You can define several functions with the same name but different parameter types, if it makes sense to do so.
JME functions¶
Functions defined using JME work similarly to variables  the function’s parameters are substituted into the expression, which is then evaluated.
Comments can be added to function definitions in the same way as variable definitions  anything on a line after two forward slashes is interpreted as a comment and not evaluated. For example:
map(
log(n), //take log of n
n, //for n in
1..10 //the range 1 to 10 (inclusive)
)
JME does not allow for much control over program flow. Most importantly, there are no loops. Some functions can naturally be defined recursively, but note that recursive function calls can be very slow, since recursion isn’t optimised.
Here’s an example of a function which computes the \(n\)^{th} Fibonacci number recursively:
//nth fibonacci number
//f(0) = f(1) = 1
//f(n+2) = f(n)+f(n+1)
if(n<=1,
1,
//else
f(n2)+f(n1)
)
Javascript functions¶
Writing a function in Javascript allows you to use all of that language’s features, such as loops, anonymous functions and DOM manipulation.
Functions defined in Javasript don’t need the function(parameters) { ... }
enclosure  that’s provided by Numbas  but they do need to return a value.
Numbas provides a large library of functions which you can use.
These are accessed from the objects Numbas.math
and Numbas.util
.
The best way to see what’s available is to look at the Numbas code documentation.
jQuery is also available.
While the JME system has its own type system for variables, separate from Javascript’s, function parameters are unwrapped to native Javascript values on evaluation so you normally don’t need to worry about it.
Examples
This function takes a list of strings and returns an HTML bullet list:
var ol = $('<ol>'); // create list element
for(var i=0; i<things.length; i++) {
ol.append($('<li>').html(things[i])); //append list item to list
}
return ol; //return list
This function creates an HTML5 canvas
element and draws a rectangle with the given dimensions, along with labels:
var c = document.createElement('canvas');
$(c).attr('width',w+40).attr('height',h+40);
var context = c.getContext('2d');
//fill in rectangle with a light shade
context.fillStyle = '#eee';
context.fillRect(5,5,w,h);
//draw outline
context.strokeStyle = '#000';
context.lineWidth = 3;
context.strokeRect(5,5,w,h);
//draw labels
context.fillStyle = '#000';
context.font = '20px sansserif';
var wstring = w+'m';
var tw = context.measureText(wstring).width;
context.fillText(wstring,5+(wtw)/2,5+h+25);
var hstring = h+'m';
var hw = context.measureText(hstring).width;
context.save();
context.translate(5+w+25,5+(h+hw)/2);
context.rotate(Math.PI/2);
context.fillText(hstring,0,0);
return c;
You can see this function in use at https://numbas.mathcentre.ac.uk/question/759/usecanvastodrawarectangle/.
This function formats a number with commas to separate every third digit, i.e. \(1,\!000,\!000\) instead of \(1000000\):
var parts=n.toString().split(".");
if(parts[1] && parts[1].length<2) {
parts[1]+='0';
}
return parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",") + (parts[1] ? "." + parts[1] : "");
You can see this function in use at https://numbas.mathcentre.ac.uk/question/396/numericalreasoningaveragesalary/.
Rulesets¶
A “ruleset” defines a list of named simplification rules used to manipulate mathematical expressions.
If you find yourself using the same set of rules repeatedly in \simplify
commands, define a new ruleset with a shorter name to save yourself some typing.
Preamble¶
The preambles allow you to add some code which affects the entire question.
The code written in the Javascript preamble is executed when the question is generated, just before the question’s variables are calculated. The Javascript preamble can access the question’s properties through the question variable. You can see an example of the Javascript preamble in use at https://numbas.mathcentre.ac.uk/question/2705/jsxgraphtestpreambleversion/.
You can see what functions are available in JavaScript at the Numbas code documentation.
If you want to do something with the display of the question on the page, you have to wait until its HTML has been generated, using the onHTMLAttached
method.
Here’s an example which hides an element in the statement with a given id:
question.onHTMLAttached(function() {
question.display.html.find('.statement #secret').hide();
});
The preamble also runs before the question’s variables are generated; if you’d like to do something that uses the question’s variables, you can either wait for onHTMLAttached
, or use question.onVariablesGenerated
if you need to do something before the HTML is generated.
The question’s variables are stored in question.scope.variables
as JME data types, or in question.unwrappedVariables
as simple JavaScript data.
Here’s an example use:
question.onVariablesGenerated(function() {
alert("a = "+question.unwrappedVariables.a);
});
Warning
Since JME variable names are caseinsensitive, all names are converted to lower case when used in JavaScript.
For example, a JME variable firstItem
would be available in JavaScript as question.unwrappedVariables.firstitem
.
The CSS preamble can be used to change the look of elements in your question. You can see an example of the CSS preamble in use at https://numbas.mathcentre.ac.uk/question/2704/csspreamble/.
Resources¶
You can upload any file as a resource to make it available for use elsewhere in the question.
Uploaded files are available from the relative URL resources/questionresources/
.
The URL for each resource you’ve uploaded is displayed next to its thumbnail.
The most common use case is to include images in content areas; see the tutorial on including an image in a question.
Settings¶
 Name
 This is shown to the student and used for searching within the editor, so make it something intelligible. “Find the roots of a quadratic equation” is a good name; “Alg102 q2” is not.
 Licence
 You can specify the licence under which you are making your resources available. Different licences allow other users to copy, modify or reuse your content in differnet ways  consider which licence to choose carefully. CC BY allows other users to reuse your content however you like, as long as they give appropriate credit to you.
 Description
 Use this field to describe the question’s contents, what it assesses, and so on. This is shown in the questions index and in the questions list of any exams containing this question, so make sure it’s fairly concise.
Use tags to categorise questions so they can be found through the search function. Your guiding principle should be “more is better”  try to write down all words that someone searching for this question might use.
After typing a tag in the box, press the Enter key to add it to the list.
Access¶
You can control who is allowed to see, and to edit, your questions.
When you create a new question, access is limited to you and any other members of the project the question belongs to. You can grant extra access to indvidual users or publish your question to the public database, where it can be viewed by any other user.
Public visibility
 Only you and users named in the Individual access rights section can see this question.
 Anyone can see this
 Anyone, even users who are not logged in, can see this question. Only you and users named in the Individual access rights section can edit this question.
 Anyone can edit this
 Anyone, even users who are not logged in, can see and edit this question.
Give access to a user
Type a name into the search box to find a user. Click on a user’s name in the results list to add them to the access list.
Named users can have the following rights:
 Can view this
 The named user can see, but not edit, this question.
 Can edit this
 The named user can see this question and make changes to it.
Access Links
The URLs in this section automatically grant access to whoever follows them. You could use these links to share a question with someone who hasn’t yet created an account on the editor, or to share a question with a group of people without inviting each person individually.
Warning
These URLs grant access to whoever clicks on them, so be careful about how they’re shared.
Exams using this question¶
A list of links to each of the exams which contain this question, for convenience.
Other versions¶
In this tab you can see all questions which are related to this one. Questions are related if one is a copy of the other, or they are both copies of a common ancestor. You can use this tab to compare the current question with related versions, and offer to merge your version of the question into another.
Click on the Compare link to go to a screen where you can offer to replace the other version with your version, or vice versa. If you have editing access to the destination question, you can replace it with the other version automatically. If you don’t have editing access, the owner of the question will be sent a Request to merge, which they must accept before the questions are merged.
Before creating the request, you’ll be asked to describe how your version differs from the one you want to replace. Try to sum up all your changes  this will show up in the question’s editing history if your request is accepted.
Warning
If the question you want to replace has changed since you made a copy of it, those changes will be lost if the request to merge is accepted  the question is completely overwritten with the new version.
You can always restore an old version of an question after a merge, by clicking on the appropriate restore link in the Editing history tab.
Active requests to merge other versions into the current question are shown underneath the list of related versions. You can accept the request, in which case your version will be replaced with the other version, or reject it, in which case your version will be unchanged and the person who made the request will be notified that it was rejected.
Editing history¶
Use this tab to keep a record of changes made to your question. Write comments to discuss problems or suggested changes.
The Contributors list shows everyone who has made a change to this question. This list is included with the question when you download it, and if you reupload this question to an instance of the Numbas editor.
Each time you make a change to an question, it’s saved to the database. To save a snapshot of the current state of the question, click the Set a checkpoint button. You’ll be asked to write a description of the question as it stands  describe what you’ve changed since the last snapshot, and why you’re making a snapshot.
To restore a checkpoint, click its Restore button. The current state of the question will be overwritten with the saved state.
Other activity on this question will also be shown in this tab: for example, each time somebody uses the Feedback button to provide feedback on this question, an entry is added to the editing history.
Question parts¶
Each question has one or more parts. The student is given a separate score for each part of the question, and their total score is the sum of their scores for each part.
In the editor, parts are displayed in a list; you can click on the title bar of a part to hide it, making room for the others. Use the Expand every part and Collapse every part buttons to show or hide every part at once.
The type of a part defines how it appears to the student, and how it is marked. Different part types offer different settings fields to configure the display and marking of the part.
Generic part properties¶
The following properties are available on every type of part.
 Name
Every part is automatically assigned a name, displayed at the top of the editing area, next to the part’s type. Click the part’s name to edit it.
Question variables can be substituted into the name by enclosing them in curly braces.
 Prompt
 A content area used to prompt the student for an answer.
 Marks
 The number of marks to award for answering the part correctly.
 Steps
 An optional list of subparts which the student can reveal by clicking on a button. Marks awarded for steps don’t increase the total available for the part, but are given in case the student gets a lower score for the main part.
 Penalty for revealing steps
 If the student reveals the Steps, reduce the total available marks by this amount. Credit for the part is scaled down accordingly. For example, if there are 6 marks available and the penalty for revealing steps is 2 marks, the total available after revealing steps is 4. An answer worth 3 marks without revealing steps is instead worth \(3 \times \frac{4}{6} = 2\) marks after revealing steps.
 Show correct answer on reveal?
 When the student reveals answers to the question, or views the question in review mode, should a correct answer be shown? You might want to turn this off if you’re doing custom marking and the part has no “correct” answer.
 Show score feedback icon?
 After the student submits an answer to this part, should an icon describing their score be shown? This is usually shown next to the input field, as well as in the feedback box. This option also controls whether feedback messages are shown for this part. You might want to turn this off if you’ve set up a question with a custom marking script which assigns a score based on the answers to two or more parts (or gapfills), meaning the individual parts have no independent “correct” or “incorrect” state.
Part types¶
The following part types are builtin to Numbas:
Mathematical expression¶
Mathematical expression parts require the student to enter an algebraic expression, using JME syntax.
These parts are marked by picking a sample of random values for the free variables in the expression, and evaluating both the student’s answer and the correct answer on those values. If the two expressions agree on enough inputs, then they are considered to be equivalent and the student’s answer is marked as correct.
For questions where the student is asked to rearrange an expression, just evaluating both answers won’t detect the difference  you want to look at the form of the student’s answer, as well as the values it produces. Use a pattern restriction to check that the student’s answer is in the form you want.
You can find the mathematical expression part’s builtin marking algorithm at GitHub.
Marking¶
 Correct answer
The expected answer to the part. Question variables (or, more broadly, JME expressions which should be evaluated to a single value when the question is generated), can be included by enclosing them in curly braces.
If the answer is an equation, see the note on Marking an equation.
 Show preview of student’s answer?
 If ticked, a rendering of the student’s answer in mathematical notation is displayed beeside the input box. You should leave this on unless you expect the answer to be veery simple and need the space  the feedback about how their answer is interpreted is very useful to students.
 Answer simplification rules
Simplification rules to apply to the correct answer, if it is displayed to the student (for example, after clicking the Reveal answers button). This shouldn’t affect marking.
If this field is empty, the following rules are applied:
basic
,unitFactor
,unitPower
,unitDenominator
,zeroFactor
,zeroTerm
,zeroPower
,collectNumbers
,zeroBase
,constantsFirst
,sqrtProduct
,sqrtDivision
,sqrtSquare
,otherNumbers
.
Restrictions¶
The Restrictions tab provides several methods for restricting the form of the student’s answer.
Pattern restriction¶
 Pattern student’s answer must match
The student’s answer must match the given pattern. If it does not, then a penalty is applied.
You can use this to ensure the student’s answer is in a particular form.
See Patternmatching examples for examples of patterns which ensure the expression is in particular forms.
 Part of expression to mark
If Whole expression is selected, then the student’s entire expression is compared against the correct answer. If the name of a subexpression captured by the pattern is selected, then only the subexpression captured in the student’s answer is compared against the corresponding subexpression in the correct answer.
You can use this to mark answers which could not otherwise be marked using the standard marking algorithm, for example function definitions or equations where one side is fixed, such as \(y = f(x)\).
 Partial credit for not matching pattern
 If the student’s answer does not match the given pattern, their score is multiplied by this percentage.
Variables¶
 Warn if student uses an unexpected variable name?
 If this is ticked, all variable names used in the student’s are checked against the variable names used in the correct answer.
The first variable name which is not used in the correct answer will trigger a warning.
You can use this option to prevent students incorrectly entering answers such as
xy
, which is interpreted as a single variable, when they meanx*y
, the product of two variables.
String restrictions¶
Note
String restrictions are an unreliable method of restricting the form of a student’s answer. They are deprecated and retained only for backwards compatibility; use a pattern restriction instead.
Before string restrictions are applied, surplus brackets and whitespace are removed, and spaces are inserted between some operations, to minimise the possibility of the length restrictions being triggered for the wrong reasons.
 Minimum length restriction
 If the student’s answer contains fewer than this many characters, the penalty is applied. A value of zero means no restriction is applied. See the comment above on how the length is calculated.
 Maximum length restriction
 If the student’s answer contains more than this many characters, the penalty is applied.
A value of zero means no restriction is applied.
The student’s answer is tidied up slightly so that things like extra or missing space characters don’t affect the calculated length.
All spaces are removed, and then spaces are inserted between binary operations.
For example, the answer
1+x
(three characters) is marked as1 + x
(five characters).  Required strings
 If the student’s answer doesn’t contain all of these strings, the penalty is applied.
 Forbidden strings
 If the student’s answer contains any of these strings, the penalty is applied.
Accuracy¶
These settings define the range of points over which the student’s answer will be compared with the correct answer, and the method used to compare them.
For each of the variables in the correct answer, a value is chosen at random. How this value is chosen depends on the type of the variable: for example, in the expression \(k \det(A)\), the variable \(A\) must be a matrix, and \(k\) can be assumed to be a number. The system can usually infer the type of each variable and pick an appropriate value automatically.
Numbers are chosen uniformly at random from the defined checking range. Matrices and vectors have entries chosen uniformly at random from the defined checking range.
Care must be taken if the correct answer has a singularity or is undefined for some values of the variables. Either set the checking range to a safe interval on which the expression is always defined, or write a variable value generator.
 Checking type
The rule to use to compare the student’s answer with the correct answer. In the lines below, \(x\) represents the value of the student’s answer at a particular point and \(y\) represents the value of the correct answer, while \(\delta\) is the value of the checking accuracy property.
 Absolute difference. Fail if \(\left xy \right > \delta\).
 Relative difference. Fail if \(\left \frac{x}{y}  1 \right > \delta\).
 Decimal points. \(x\) and \(y\) are rounded to \(\delta\) decimal places, and the test fails if the rounded values are unequal.
 Significant figures. \(x\) and \(y\) are rounded to \(\delta\) significant figures, and the test fails if the rounded values are unequal.
 Checking accuracy
 The parameter for the checking type.
 Points to check
 The number of comparisons to make between the student’s answer and the correct answer.
 Maximum no. of failures
 If the comparison fails this many times or more, the student’s answer is marked as wrong.
 Checking range start
 The minimum value sample points can take.
 Checking range end
 The maximum value sample points can take.
Variable value generators¶
Variable value generators override the default method used to pick values for variables when comparing the correct answer with the student’s answer.
A text field for each variable used in the correct answer appears in this section.
If left blank, the default value generator will be used.
To override it, enter a JME expression producing a value for the variable.
The variable vRange
represents the checking range defined for this part: a continuous interval between the checking range start and checking range end.
The expression for each variable can be written in terms of the other variables, as long as there are no circular dependencies. The values will be evaluated in order, like question variables.
Marking an equation¶
If the correct answer is an equation, such as \(A = 6t\) or \(x^2 + y^2 = 1\), it will produce a boolean
value, representing whether the values of the variables constitute a solution of the equation.
Two equations are equivalent if they have the same solution sets. For example, the equations \(y=2x\) and \(y2x=0\) are equivalent because exactly the same sets of \((x,y)\) pairs satisfy them both. We can make a fairly confident decision about whether two equations are equivalent by checking that they agree on a few randomlychosen values.
We need to check both solutions and nonsolutions of the expected equation. If we don’t check any solutions, then an equation which can never be satisfied would be marked correct. Conversely, if we don’t check any nonsolutions, then an equation which holds for any input would be marked correct.
It’s extremely unlikely that randomlychosen values for the variables will satisfy any given equation, so you need to change the way values are chosen to produce solutions about half of the time, using variable value generators.
For example, in a part with correct answer \(x^2+y^2=1\), the expression random(sqrt(1x^2), random(vRange))
for the variable \(y\) will produce a solution of the equation roughly half of the time.
By setting the points to check to a big enough number, say 10, we can be reasonably confident that the student’s answer is equivalent to the expected answer.
Marking settings¶
This part type provides the following properties to the settings
object:

correctAnswer
The Correct answer to the question.

answerSimplification
¶

checkingType
¶ The Checking type setting, representing the name of the checking function to use. One of
"absdiff"
,"reldiff"
,"dp"
or"sigfig"
. Seeresultsequal()
.

checkingAccuracy
¶ See Checking accuracy.

failureRate
¶

vsetRangeStart
¶ See Checking range start.

vsetRangeEnd
¶ See Checking range end.

vsetRangePoints
¶ See Points to check.

valueGenerators
¶ A dictionary of variable value generator expressions.

checkVariableNames
¶

mustMatchPattern
¶

mustMatchPC
¶ The proportion of credit awarded if the student’s answer does not match the pattern.

mustMatchMessage
¶ Message to add to marking feedback if the student’s answer does not match the pattern.

nameToCompare
¶ The name of the captured subexpression to compare against the corresponding subexpression in the correct answer. See Part of expression to mark.

maxLength
¶ The maximum length, in characters, of the student’s answer, as set in Maximum length restriction.

maxLengthPC
¶ The proportion of credit awarded if the student’s answer is too long.

maxLengthMessage
¶ Message to add to marking feedback if the student’s answer is too long.

minLength
¶ The minimum length, in characters, of the student’s answer, as set in Minimum length restriction.

minLengthPC
¶ The proportion of credit to award if the student’s answer is too short.

minLengthMessage
¶ Message to add to the marking feedback if the student’s answer is too short.

mustHave
¶ A list of strings which must be present in the student’s answer, as set in Required strings.

mustHavePC
¶ The proportion of credit to award if any musthave string is missing.

mustHaveMessage
¶ Message to add to the marking feedback if the student’s answer is missing a musthave string.

mustHaveShowStrings
¶ Tell the students which strings must be included in the marking feedback, if they’re missing a musthave?

notAllowed
¶ A list of strings which must not be present in the student’s answer, as set in Forbidden strings.

notAllowedPC
¶ The proportion of credit to award if any notallowed string is present.

notAllowedMessage
¶ Message to add to the marking feedback if the student’s answer contains a notallowed string.

notAllowedShowStrings
¶ Tell the students which strings must not be included in the marking feedback, if they’ve used a notallowed string?
Number entry¶
Number entry parts ask the student to enter a number, which is marked if it is in a specified range.
You can find the number entry part’s builtin marking algorithm at GitHub.
Marking¶
 Minimum accepted value
 The smallest value accepted as correct.
 Maximum accepted value
 The largest value accepted as correct.
 Precision restriction
You can insist that the student gives their answer to a particular number of decimal places or significant figures. For example, if you want the answer to be given to 3 decimal places, \(3.1\) will fail this restriction, while \(3.100\) will pass.
The minimum and maximum answer are both rounded off to the same precision as the student used, or the required precision  whichever is greater. If the student’s answer is between the roundedoff minimum and maximum, then it is marked correct. Finally, if the student’s answer is not given to the required precision, the penalty is applied.
If the precision doesn’t matter, select None.
 Allow the student to enter a fraction?
 This option is only available when no precision restriction is applied, since they apply to decimal numbers.
If this is ticked, the student can enter a ratio of two whole numbers, e.g.
3/8
, as their answer.  Must the fraction be reduced?
 This option only applies when “Allow the student to enter a fraction” is ticked.
If this is ticked, the student must enter their fractional answer reduced to lowest terms.
For example, consider a part whose correct answer is \(5/4\).
If this is ticked,
10/8
will be marked as incorrect.  Show fraction input hint?
 If this is ticked and Must the fraction be reduced? is ticked, then text explaining that the student must reduce their fraction to lowest terms is shown next to the input box.
 Display the correct answer as a fraction?
 This option is only available when no precision restriction is applied.
If this is ticked, the correct answer to the part will be rendered as a fraction of two whole numbers instead of a decimal.
For example, if the answer is \(0.5\), it will be displayed as
1/2
instead of0.5
.  Require trailing zeros?
 This option only applies when a precision restriction is selected. If this is ticked, the student must add zeros to the end of their answer (when appropriate) to make it represent the correct precision. For example, consider a part whose correct answer is \(1.4\), and you want the student’s answer to be correct to three decimal places. If “Require trailing zeros?” is ticked, only the answer \(1.400\) will be marked correct. If it is not ticked, any of \(1.4\), \(1.40\) or \(1.400\) will be marked as correct. If too many zeros are used, e.g. \(1.4000\), the answer is marked as incorrect.
 Partial credit for wrong precision
 This option only applies when a precision restriction is selected. If the student does not give their answer to the required precision, they only get this much of the available credit for the part.
 Message if wrong precision
 This option only applies when a precision restriction is selected. If the student does not give their answer to the required precision, they are given this feedback message.
 Show precision restriction hint?
 If this is ticked, then some text describing the rounding the student must perform is shown next to the input box. For example, “round your answer to 3 decimal places”.
 Allowed notation
 The styles of number notation that the student can use to enter their answer.
There are different ways of writing numbers, based on culture and context.
Tick an option to allow the student to use that style in their answer.
Note that some styles conflict with each other: for example,
1.234
is a number between 1 and 2 in English, while it’s the integer 1234 in French. The student’s answer will be interpreted using the first allowed style for which it is a valid representation of a number. See Number notation for more on styles of notation.  Correct answer style
 The style of number notation to use when displaying the student’s answer.
Marking settings¶
This part type provides the following properties to the settings
object:

minvalue
¶ Minimum accepted value, as a
number
.

maxvalue
¶ Maximum accepted value, as a
number
.

correctAnswerFraction
¶

allowFractions

mustBeReduced
¶

mustBeReducedPC
¶ The proportion of credit to award if the student’s answer is a nonreduced fraction.

notationStyles
¶ A
list
of the styles of notation to allow, other than<digits>.<digits>
. See Number notation.

displayAnswer
A representative correct answer to display, as a
number
.

precisionType
¶ The type of precision restriction to apply, as set by Precision restriction. One of
"none"
,"dp"
, or"sigfig"
.

strictPrecision
¶

precision
¶ The number of decimal places or significant figures to require.

precisionPC
¶ The proportion of credit to award if the student’s answer is not given to the required precision.

precisionMessage
¶ A message to display in the marking feedback if the student’s answer was not given to the required precision.
Matrix entry¶
Matrix entry parts ask the student to enter a matrix of numbers. Marks are awarded if every cell in the student’s answer is equal to the corresponding cell in the correct answer, within the allowed margin of error.
You can find the matrix entry part’s builtin marking algorithm at GitHub.
Marking¶
 Correct answer
 The expected answer to the part.
This is a JME expression which must evaluate to a
matrix
.  Number of rows
 The default number of rows in the student’s answer field.
 Number of columns
 The default number of columns in the student’s answer field.
 Allow student to change size of matrix?
 If this is ticked, then the student can change the number of rows or columns in their answer. Use this if you don’t want to give a hint about the dimensions of the answer.
 Margin of error allowed in each cell
 If the absolute difference between the student’s value for a particular cell and the correct answer’s is less than this value, then it will be marked as correct.
 Gain marks for each correct cell?
 If this is ticked, the student will be awarded marks according to the proportion of cells that are marked correctly. If this is not ticked, they will only receive the marks for the part if they get every cell right. If their answer does not have the same dimensions as the correct answer, they are always awarded zero marks.
 Precision restriction
You can insist that the student gives their answer to a particular number of decimal places or significant figures. For example, if you want the answer to be given to 3 decimal places, \(3.1\) will fail this restriction, while \(3.100\) will pass.
The cells of the correct answer are rounded off to the maximum precision as the student used in any of their cells, or the required precision  whichever is greater. If the student’s answer is within the specified tolerance of the roundedoff correct value, it is classed as correct. Finally, if any of the cells in the student’s answer are not given to the required precision, the penalty is applied.
If the precision doesn’t matter, select None.
 Allow the student to enter fractions?
 This option is only available when no precision restriction is applied, since they apply to decimal numbers.
If this is ticked, the student can enter a ratio of two whole numbers, e.g.
3/8
, as their answer.  Display numbers in the correct answer as fractions?
 If this is ticked, then noninteger numbers in the correct answer will be displayed as fractions instead of decimals.
 Require trailing zeros?
 This option only applies when a precision restriction is selected. If this is ticked, the student must add zeros to the end of their answer (when appropriate) to make it represent the correct precision. For example, consider a part whose correct answer is \(1.4\), and you want the student’s answer to be correct to three decimal places. If “Require trailing zeros?” is ticked, only the answer \(1.400\) will be marked correct. If it is not ticked, any of \(1.4\), \(1.40\) or \(1.400\) will be marked as correct. If too many zeros are used, e.g. \(1.4000\), the answer is marked as incorrect.
 Partial credit for wrong precision
 This option only applies when a precision restriction is selected. If the student does not give all of the cells in their answer to the required precision, they only get this much of the available credit for the part.
 Message if wrong precision
 This option only applies when a precision restriction is selected. If the student does not give all of the cells in their answer to the required precision, they are given this feedback message.
Marking settings¶
This part type provides the following properties to the settings
object:

correctAnswer
The correct answer to the part, as set in Correct answer.

numRows
¶ The default Number of rows in the student’s answer.

numColumns
¶ The default Number of columns in the student’s answer.

allowResize
¶

tolerance
¶

markPerCell
¶

allowFractions

precisionType
The type of precision restriction to apply: one of
"none"
,"dp"
or"sigfig"
, as set in Precision restriction.

precision
The number of decimal places or significant figures to require.

precisionPC
The proportion of credit to award if any cell is not given to the required precision.

precisionMessage
A message to display in the marking feedback if any cell in the student’s answer was not given to the required precision.

strictPrecision
Match text pattern¶
Use a text pattern part when you want the student to enter short, nonmathematical text.
You can find the match text pattern part’s builtin marking algorithm at GitHub.
Marking¶
 Match test
The test to use to decide if the student’s answer is correct.
 The Regular expression test checks that the student’s answer matches the regular expression given in Answer pattern.
 The Exact match test marks the student’s answer as correct only if it is exactly the same as the text given in Answer pattern. Space characters are removed from the start and end of the student’s answer as well as the answer pattern before comparison.
 Answer pattern
The text or pattern the student must match.
When Match test is Regular expression, this is a regular expression defining the strings to be accepted as correct. If there are several valid answers, separate them with a

character. If you’re using the full regular expression functionality, note that^
and$
are automatically added to the start and end of the answer pattern to ensure that the student’s whole answer matches the pattern.You can substitute variables, the same as in content areas, by enclosing expressions in curly braces, e.g.
{answervar}
. Display answer
 A representative correct answer string to display to the student, in case they press the Reveal answers button. You can substitute variables by enclosing expressions in curly braces, the same as in content areas.
 Must the answer be in the correct case?
 If this is ticked, the capitalisation of the student’s answer must match that of the answer pattern. If it doesn’t, partial credit (defined using the slider below the checkbox) will be awarded.
Marking settings¶
This part type provides the following properties to the settings
object:

correctAnswer
The Answer pattern string.

displayAnswer
¶ The Display answer string.

caseSensitive
¶

partialCredit
¶ The proportion of credit to award if the answer is correct except for the case.

matchMode
¶ The Match test setting: either
"regex"
or"exact"
.
Examples¶
In the following examples, the variable name
has the value Epictetus
Regular expressions¶
Correct answer  Must be correct case?  Student answer  Correct? 
Hello 
✓  Hello 
✓ 
Hello 
✓  hello 
✗ 
Hello 
✗  hello 
✓ 
HelloHi 
✓  Hi 
✓ 
(ab)+ 
✓  ababab 
✓ 
[^d]+ 
✓  abcefgh 
✓ 
[^d]+ 
✓  abcdefgh 
✗ 
{name} 
✓  Epictetus 
✓ 
{name}( {name})+ 
✓  Epictetus Epictetus 
✓ 
Exact match¶
Answer pattern  Must be correct case?  Student answer  Correct? 
Hello 
✓  Hello 
✓ 
Hello 
✓  hello 
✗ 
HelloHi 
✓  Hi 
✗ 
HelloHi 
✓  HelloHi 
✓ 
{name} 
✓  Epictetus 
✓ 
{name} 
✓  epictetus 
✗ 
{name} 
✗  epictetus 
✓ 
{name} Jr. 
✓  Epictetus Jr. 
✓ 
Choose one from a list / Choose several from a list / Match choices with answers¶
There are three kinds of “multiple response” part types in Numbas, with similar settings. They are listed here together.
You can find the multiple response part’s builtin marking algorithm at GitHub.
Multiple response part types
 Choose one from a list
 The student must choose one of several options
 Choose several from a list
 The student can choose any of a list of options
 Match choices with answers
 The student is presented with a 2D grid of choices and answers. Depending on how the part is set up, they must either match up each choice with an answer, or select any number of choiceanswer pairs.
Marking¶
 Minimum marks
 If the student would have scored less than this many marks, they are instead awarded this many. Useful in combination with negative marking.
 Maximum marks
 If the student would have scored more than this many marks, they are instead awarded this many. The value 0 means “no maximum mark”.
 Minimum answers
 For choose several from a list and match choices with answers parts, the student must select at least this many choices. The value 0 means “no minimum”, though the student must make at least one choice to submit the part.
 Maximum answers
 For choose several from a list and match choices with answers parts, the student must select at most this many choices. The value 0 means “no maximum”.
 What to do if wrong number of answers selected
 If the student selects too few or too many answers, either do nothing, show them a warning but allow them to submit, or prevent submission until they pick an acceptable number of answers.
 Shuffle order of choices?
 If this is ticked, the choices are displayed in random order.
 Shuffle order of answers?
(Match choices with answers only)
If this is ticked, the answers are displayed in random order.
 Number of display columns
 For choose one from a list and choose several from a list parts, this dictates how many columns the choices are displayed in. If 0, the choices are displayed on a single line, wrapped at the edges of the screen.
 Selection type
For match choices with answers parts, “One from each row” means that the student can only select one answer from each row and “Checkboxes” means that the student can select any number of choiceanswer pairs.
For choose one from a list parts, users can select only one of the choices.
“Drop down list” means that the choices are shown as a selection box; the student can click to show the choices in a vertical list.
Warning
Drop down lists can only display plain text, due to how selection boxes are implemented in HTML. This means that any formatting applied in the editor will not be displayed, and LaTeX will not render properly.
“Radio buttons” means that choices are shown separately, inline with the part prompt.
 Custom marking matrix
 If the checkbox is ticked, the JME expression in the box below is evaluated and used to assign numbers of marks to choices.
 Custom matrix expression
 Define the number of marks to award for each of the choices. For choose one from a list and choose several from a list parts, the expression should evaluate to a list of numbers, while for match choices with answers it should evaluate to a list of lists of numbers representing a 2d array, or a matrix object, giving the number of marks to associate with each choiceanswer pair.
 Layout
(Match choices with answers only)
Define which choices are available to be picked. If Custom expression is selected, give either a list of lists of boolean values, or a matrix with as many rows as the part has choices and as many columns as the part has answers. Any nonzero value in the matrix indicates that the corresponding choiceanswer pair should be available to the student.
 Show choice feedback state?
If ticked, choices selected by the student will be highlighted as ‘correct’ if they have a positive score, and ‘incorrect’ if they are worth zero or negative marks. If show score feedback icon? is not ticked, the ticked choices will be given a neutral highlight regardless of their scores.
If this is not ticked, no highlighting will be applied to ticked choices. This is appropriate if the part uses a custom marking algorithm which awards a score based on the set of choices considered as a whole.
Choices¶
 Variable list of choices?
 Should the list of choices be defined by a JME expression? If this is ticked, you must give a custom matrix expression.
 List of choices
 If Variable list of choices? is ticked, this JME expression defines the list of choice strings to display to the student.
 Marks (choose one from a list / choose several from a list only)
 The number of marks to award (or take away, if you enter a negative number) when the student picks this choice.
 Distractor message (choose one from a list / choose several from a list only)
 A message to display to the student in the part’s feedback section after they select a particular choice. It can be useful to give some explanation of why a choice is incorrect.
Answers¶
Only Match choices with answers parts have answers as well as choices.
 Variable list of answers?
 Should the list of answers be defined by a JME expression? If this is ticked, you must give a custom matrix expression.
 List of answers
 If Variable list of answers? is ticked, this JME expression defines the list of answer strings to display to the student.
Marking matrix¶
Only Match choices with answers parts have a marking matrix tab: for the other part types, the marking matrix is defined implicitly by the score for each choice.
Assign marks to each pair of choice and answer using the input boxes.
 Custom marking matrix
 If the checkbox is ticked, the JME expression in the box below is evaluated and used to assign numbers of marks to choices.
 Custom matrix expression
 Define the number of marks to award for each of the choices. Either a list of lists representing a 2d array, or a matrix object, giving the number of marks to associate with each choiceanswer pair.
Marking settings¶
This part type provides the following properties to the settings
object:

maxMarksEnabled
¶ Is there a maximum number of marks the student can get? Set by Maximum marks.

minAnswers
¶ The minimum number of responses the student must select, set by Minimum answers.

maxAnswers
¶ The maximum number of responses the student must select, set by Maximum answers.

shuffleChoices
¶

shuffleAnswers
¶

matrix
A 2D
list
of marks for each answer/choice pair. Arranged assettings["matrix"][answer][choice]
.

displayType
¶ Selection type: one of
"radiogroup"
,"checkbox"
or"dropdownlist"
.

warningType
¶ What to do if the student picks the wrong number of responses? Either
"none"
(do nothing),"prevent"
(don’t let the student submit), or"warn"
(show a warning but let them submit)
Gapfill¶
Gapfill parts allow you to include answer inputs inline with the prompt text, instead of at the end of the part.
The gaps are subparts. Include them in text by clicking on the Insert gap button on the toolbar, and entering the number of the gap you want to insert in the dialog box. You can doubleclick on a gap placeholder to change its number.
To insert a gap in the plain text editor, type the gap’s number between two square brackets, e.g. [[0]]
for the first gap.
You can find the gapfill part’s builtin marking algorithm at GitHub.
Marking
 Sort student’s answers before marking?
 If ticked, then the student’s answers will be put in ascending order before the gaps are marked. The lowest answer will be submitted against the first gap, and so on. Because the order of marking might not correspond with the order in which the gaps are shown to the student, no feedback icon is shown next to the gap input boxes, only in the feedback summary for the whole part.
This part type provides one property to the settings
object:

sortAnswers
¶
Information only¶
An information part contains only a prompt and no answer input. It is most often used as a Step to provide a hint for a parent part.
Extension¶
An extension part acts as a placeholder for any interactive element added by an extension, or custom code in the question, which awards marks to the student.
To use an extension part, your code must implement the following methods: (links go to the relevant pages in the Numbas JavaScript API documentation)
If you can create a JME value representing the student’s answer to the part, you should also implement studentAnswerAsJME so that it can be used in adaptive marking by later parts.
See the GeoGebra extension for an example of how to use the extension part.
Custom part types defined by you or other Numbas users provide extra functionality. The list of available custom part types comprises those published by their authors, as well as those made by you or other members of the project your question belongs to.
Marking algorithm¶
The marking algorithm tab allows you to customise the script used to mark the student’s answer, and test that it works correctly on answers that you provide.
See the page on marking algorithms for more on how marking algorithms work.
 Use custom marking algorithm?
 If this is ticked, the algorithm entered in the code field below will be used.
 Extend base marking algorithm?
 If this is ticked, all marking notes provided by the part’s standard marking algorithm will be available. If the same note is defined in both the standard algorithm and your custom algorithm, your version will be used.
In the part editor, the entire marking algorithm is written in one field. Notes are separated by doublelinebreaks, and are of the following format:
name (Label):
definition
The name must be a valid variable name. The label is an optional string of text enclosed in parentheses, which can describe in more readable language what the note represents. The definition is a JME expression used to evaluate the note.

settings
The following settings are available for every type of part. Other part types will provide further settings.

stepsPenalty
¶ The number of marks to deduct when the steps are shown.

enableMinimumMarks
¶ Is there a lower limit on the score the student can be awarded for this part?

minimumMarks
¶ Lower limit on the score the student can be awarded for this part.

showCorrectAnswer
¶ Should the expected answer to this part be shown when answers to this question are revealed?

hasVariableReplacements
¶ Does this part have any variable replacement rules?

adaptiveMarkingPenalty
¶ The number of marks to deduct when adaptive marking is used.

showFeedbackIcon
¶ Show the tick/cross feedback symbol after this part is submitted? See Show score feedback icon?

Test that the marking algorithm works¶
Whether you’re using a custom marking algorithm or not, you can test how it behaves given certain answers.
The first half of the testing section provides a field to enter an answer to the part, and the table below shows the feedback notes produced by the marking algorithm. Click on a note to toggle its visibility  most of the time, you’ll only be interested in a few of the notes.
The Variable values tab shows the current values of the question’s variables, which you may need in order to come up with an answer for the part. The values here are the same as shown in the Variables tab, and are regenerated whenever the question changes, or when you click the Regenerate values button. You can lock the value of a variable, so it is not regenerated until you unlock it, by clicking on the padlock icon next to its name.
Click on the Create a unit test button to add a unit test with the current variable values and student answer. Only the marking notes you’ve selected to show will be included in the unit test.
Unit tests¶
Unit tests allow you to save the state of the marking algorithm after it has run, to confirm after making any changes to the part or question that the same behaviour is produced. The student’s answer and the values of all question variables are saved, along with the value and feedback corresponding to marking notes that you have selected.
Give a unit test a label which describes the behaviour it is testing for, for example, “correct answer” for a test that checks the correct answer earns full credit, or “give feedback when student adds instead of subtracting” for a test that checks the right feedback message is displayed when the student makes a particular error.
Clicking the Run this test button inside a unit test will cause the marking algorithm to be run against the stored student answer and variable values. If any of the notes included in the test produce a different value or different feedback than expected, the test will fail. When that happens, you can use the Expected entries in the feedback table to guide the process of fixing the marking algorithm so it produces the expected feedback. Alternatively, you can choose to Accept the current values if you want to accept the new behaviour  this will update the test to accept the current values, and reject any others.
Click the Run all unit tests button to run all unit tests belonging to a part.
Scripts¶
The script fields allow you to override the builtin algorithms used by Numbas. They take JavaScript code; the Numbas JavaScript API documentation for parts is a useful reference.
Note
Most customisation of marking can be done using a custom marking algorithm. The scripts feature was introduced before custom marking algorithms, so the scope for its use is now quite limited.
Scripts have access to the global Numbas
object, as well as the following variables:

part
¶ The current part

question
¶ The part’s parent question

variables
¶ The question’s variables, unwrapped to JavaScript objects (so numbers can be used as JavaScript numbers, instead of having to go through the JME system)
Custom scripts can run before, instead of, or after the builtin script. If instead of is chosen, the builtin script never runs; you must make sure that your script does everything required. You might want to run a custom script before the builtin one to modify a setting before the normal logic is applied, or run it after to do some extra processing or add information.
The following scripts can be customised:
 When the part is created
 This function runs when the part is created (either at the start of the exam, or when the question is regenerated), after the builtin constructor for the part. You could use this to change any of the part’s settings, if it’s not convenient to do so by other means.
 Mark student’s answer
 This function runs when the student clicks the Submit part button.
It should establish what proportion of the available credit to award to the student for their answer, and give feedback messages.
Use
this.setCredit(credit,message)
to set the credit and (optionally) give a message. Note thatthis.answered
should be set to true if the student’s answer can be marked  otherwise, the student will be shown a warning message.  Validate student’s answer
 This functions runs after the marking function, and should return
true
if the student’s answer is in a form that can be marked, orfalse
otherwise. If the answer can’t be marked, you should usethis.giveWarning(message)
to tell the student what’s wrong.
There are several example questions using custom scripts at numbas.mathcentre.ac.uk/exam/1016/custommarking/.
Adaptive marking¶
Adaptive marking allows you to incorporate the student’s answers to earlier parts when marking their answer to another part. You could use this to allow an “error carried forward” marking scheme, or in more freeform questions where one part has no correct answer  for example, “think of a number and find its square root”. This is achieved by replacing the values of question variables with the student’s answers to other parts. When a variable is replaced, any other variables depending on that one are recalculated using the new value. All other variables keep their original values.
As an example, suppose part a of your question asks the student to calculate the mean of a set of numbers.
The correct answer for this part is the variable sample_mean
.
Part b then asks the student to calculate a zstatistic based on the mean of the sample.
The correct answer to this part is the variable z_statistic
, which is defined as (sample_meanpopulation_mean)/sqrt(population_variance)
.
(population_mean
and population_variance
in this case are random numbers)
If the student makes an error in calculating the sample mean but uses the right method to find a zstatistic, they shouldn’t be penalised in part b.
We can ensure this by replacing the value of sample_mean
with the student’s answer to part a when marking part b.
When the student submits an answer to part b, the value of z_statistic
will be automatically recalculated using the student’s value of sample_mean
.
Then, if the student correctly applies the formula, their answer will match the new value of z_statistic
and they will receive full credit for the part.
Settings
 Variable replacement strategy
The circumstances under which the variable replacements are used, and adaptive marking is applied. There are two variable replacement strategies:
Try without replacements first: The student’s answer is first marked using the original values of the question variables. If the credit given by this method is less than the maximum available, the marking is repeated using the defined variable replacements. If the credit gained with variable replacements is greater than the credit gained under the original marking, that score is used, and the student is told that their answers to previous parts have been used in the marking for this part.
Always replace variables: The student’s answer is only marked once, with the defined variable replacements applied.
 Penalty when adaptive marking is used
 If adaptive marking is used, reduce the total available marks by this amount. Credit for the part is scaled down accordingly. For example, if there are 6 marks available and the penalty for using adaptive marking is 2 marks, the total available after revealing steps is 4. An answer worth 3 marks without the penalty is instead worth \(3 \times \frac{4}{6} = 2\) marks when adaptive marking is used.
Warning
This feature can be very powerful, but make sure you don’t introduce any new random variation in these dependent variables, or the correct answer will change each time the student submits their answer.
The editor will try to catch these cases and show you a warning, with a list of the problematic variables. Resolve this by moving the random elements to new variables.
For example, in the following set of variables, b
depends on a
and also has a random element:
a = random(1..5)
b = a*random(1,1)
In a part where a
is replaced with the answer to a previous part, b
will be regenerated with the new value of a
.
However, each time this happens, it will be multiplied by a random value.
To fix this, create a new variable b_sign
:
a = random(1..6)
b_sign = random(1,1)
b = a*b_sign
With this setup, b
is always multiplied by the same value because b_sign
does not depend on the replaced variable a
, so it is not regenerated when the part is submitted.
Variable replacements
 Variable
 The name of the variable to replace
 Answer to use
 The part whose answer the variable’s value should be replaced with. Different part types produce different types of values.
 Must be answered?
 If this is ticked, the student must submit an answer to the referenced part before they can submit an answer to this part.
Values obtained from the answers to each part type
Part type  Value obtained 

Gapfill  A list containing the values obtained from each of the gaps 
Mathematical expression  A JME expression .
When used in a variable definition, the subexpression will be substituted in, and any references to question variables in the subexpression will be replaced with their respective values. 
Number entry  A number 
Matrix entry  A matrix 
Match text pattern  A string 
Choose one from a list  The number index of the answer the student chose, starting at 0 
Choose several from a list  A list of boolean values: true if the student ticked the corresponding choice, false otherwise 
Match choices with answers  A 2D list of lists of boolean values, in the same format as a custom marking matrix for this part  cells are addressed by choice first, and answer second. 
The following screencast shows the addition of adaptive marking to a question:
Question authoring cheat sheet¶
Click here to see a handy onepage reference on common question authoring topics.
There is also a printable PDF version.
LaTeX notation¶
LaTeX is the de facto standard markup language for mathematical notation. It’s syntactically very simple, but there’s a fairly steep learning curve in learning the names of commands.
In Numbas, inline maths (maths notation that sits on the same line as the surrounding text) is delimited either by dollar signs, e.g.:
Calculate the expansion up to the $x^4$ term.
produces
Calculate the expansion up to the \(x^4\) term.
Displaymode maths, which is displayed on its own line and rendered less compactly, is delimited by \[
and \]
.
For example:
The quadratic formula is \[ x = \frac{ b \pm \sqrt{ b^24ac } }{ 2a } \]
produces
The quadratic formula is
\[x = \frac{ b \pm \sqrt{ b^24ac } }{ 2a }\]
If you’ve never used LaTeX before, a couple of good places to start are the LaTeX maths Wikibook and the Art of Problem Solving LaTeX Guide. Bear in mind that LaTeX is only used for mathsmode, so the textmode LaTeX commands don’t apply.
To find the command for a symbol you want to use, draw it in Detexify and it will show you the commands for the most similarlooking symbols.
MathJax¶
Numbas uses MathJax to render LaTeX notation. The default Numbas theme loads MathJax from cdnjs.org, a free service provided by a combination of sponsors.
If you’d like your exams to load MathJax from a different location, you can set your preferred URL in your account settings page: click on the account dropdown at the topright of the page, then Settings. Any exams or questions you download from the editor will load MathJax from your preferred URL.
JME¶
JME expressions are used by students to enter answers to algebraic questions, and by question authors to define variables. JME syntax is similar to what you’d type on a calculator.
Variable names¶
Variable names are caseinsensitive, so y
represents the same thing as Y
.
The first character of a variable name must be an alphabet letter; after that, any combination of letters, numbers and underscores is allowed, with any number of '
on the end.
 Examples:
x
x_1
time_between_trials
var1
row1val2
y''
e
, i
and pi
are reserved names representing mathematical constants.
They are rewritten by the interpreter to their respective numerical values before evaluation.
This screencast describes which variable names are valid, and gives some advice on how you should pick names:
Variable name annotations¶
Names can be given annotations to change how they are displayed. The following annotations are builtin:
verb
– does nothing, but names likei
,pi
ande
are not interpreted as the famous mathematical constants.op
– denote the name as the name of an operator — wraps the name in the LaTeX operatorname command when displayedv
orvector
– denote the name as representing a vector — the name is displayed in boldfaceunit
– denote the name as representing a unit vector — places a hat above the name when displayeddot
– places a dot above the name when displayed, for example when representing a derivativem
ormatrix
– denote the name as representing a matrix — displayed using a nonitalic font
Any other annotation is taken to be a LaTeX command.
For example, a name vec:x
is rendered in LaTeX as \vec{x}
, which places an arrow above the name.
You can apply multiple annotations to a single variable.
For example, v:dot:x
produces a bold x with a dot on top: \(\boldsymbol{\dot{x}}\).
Names with different annotations are considered to represent different values, for the purpose of simplification and evaluation.
For example, in the expression dot:x + x
, the two terms will not be collected together.
Data types¶
JME expressions are composed of the following data types. Some extensions add new data types.

number
¶ A real or complex floatingpoint number.
i
,e
,infinity
andpi
are reserved keywords for the imaginary unit, the base of the natural logarithm, ∞ and π, respectively.Examples:
0.0
,1.0
,0.234
,i
,e
,pi
Numbers of this type are represented using JavaScript’s builtin
Number
object, which is a 64bit IEEE 754 floatingpoint number. This representation offers a very good compromise between precision and the range of values that can be stored, but can behave in unexpected ways. Accuracy is easily lost when dealing with very big or very small numbers, and on division.See functions related to Arithmetic, Number operations, Trigonometry and Number theory.
 Automatically converts to:

integer
¶ An element of the set of integers, \(\mathbb{Z}\).
Examples:
0
,1
,2
, 431`.

rational
¶ A fraction; an element of the set of rationals, \(\mathbb{Q}\). The numerator and denominator are integers.
Instances of this data type may be topheavy, with numerator bigger than the denominator, and are not required to be reduced.
Examples:
1/1
,34/2
, 3/4`.

decimal
¶ A number with a guaranteed level of precision, and arbitrary order of magnitude.
Numbers of this type are represented using the Decimal.js library. They’re guaranteed to be accurate to 40 significant figures. The order of magnitude is stored separately from the significant digits, so there’s no less of precision for very big or very small numbers.
Examples:
dec(0)
,dec("1.23e5")
,6.0221409*10^23
 Automatically converts to:

boolean
¶ Booleans represent either truth or falsity. The logical operations and, or and xor operate on and return booleans.
Examples:
true
,false
See functions related to Logic and Control flow.

string
¶ Use strings to create nonmathematical text. Either
'
or"
can be used to delimit strings.You can escape a character by placing a single backslash character before it. The following escape codes have special behaviour:
\n
Newline \{
\{
\}
\}
If you want to write a string which contains a mixture of single and double quotes, you can delimit it with tripledoublequotes or triplesinglequotes, to save escaping too many characters.
Examples:
"hello there"
,'hello there'
,""" I said, "I'm Mike's friend" """
See functions related to Strings.

list
¶ An ordered list of elements of any data type.
Examples:
[0,1,2,3]
,[a,b,c]
,[true,false,true]
See functions related to Lists.

dict
¶ A ‘dictionary’, mapping key strings to values of any data type.
A dictionary is created by enclosing one or more keyvalue pairs (a string followed by a colon and any JME expression) in square brackets, or with the
dict
function.Key strings are casesensitive.
Examples:
["a": 1, "b": 2]
["name": "Tess Tuser", "age": 106, "hobbies": ["reading","writing","arithmetic"] ]
dict("key1": 0.1, "key2": 1..3)
dict([["key1",1], ["key2",2]])
Warning
Because lists and dicts use similar syntax,
[]
produces an empty list, not an empty dictionary. To create an empty dictionary, usedict()
.See functions related to Dictionaries and JSON.

range
¶ A range
a..b#c
represents (roughly) the set of numbers \(\{a+nc \:  \: 0 \leq n \leq \frac{ba}{c} \}\). If the step size is zero, then the range is the continuous interval \([a,b]\).Examples:
1..3
,1..3#0.1
,1..3#0
See functions related to Ranges.

set
¶ An unordered set of elements of any data type. The elements are pairwise distinct  if you create a set from a list with duplicate elements, the resulting set will not contain the duplicates.
Examples:
set(a,b,c)
,set([1,2,3,4])
,set(1..5)
See functions related to Sets.
 Automatically converts to:

vector
¶ The components of a vector must be numbers.
When combining vectors of different dimensions, the smaller vector is padded with zeros to make up the difference.
Examples:
vector(1,2)
,vector([1,2,3,4])
See functions related to Vector and matrix arithmetic.

matrix
¶ Matrices are constructed from lists of numbers, representing the rows.
When combining matrices of different dimensions, the smaller matrix is padded with zeros to make up the difference.
Examples:
matrix([1,2,3],[4,5,6])
,matrix(row1,row2,row3)
See functions related to Vector and matrix arithmetic.

name
¶ A variable name. When an expression is evaluated, all variable names are replaced withe their corresponding value in the current scope.

function
¶ An application of a function.
Examples:
f(x)
,sin(x)

op
¶ An infix binary operation, or a pre/postfix unary operation.
Examples:
x+y
,n!
,a and b

expression
¶ A JME subexpression. Subexpressions can be simplified, rearranged, patternmatched, or evaluated using given values for their free variables.
See functions related to Subexpressions.
Automatic data type conversion¶
Some data types can be automatically converted to others when required.
For example, the numberlike types such as integer
and decimal
can be automatically converted to number
values.
The data types of the arguments to a function application determine which version of the function is used. Ideally, this will do what you expect without you having to think about it. For reference, the process for deciding on what conversions to perform is as follows:
 If there is a version of the function which takes exactly the given data types, that is used.
 Otherwise, each definition of the function is compared by looking at each of the arguments, working from left to right.
 A definition which does not convert an argument is preferred to one that does.
 If both definitions being compared need to convert an argument, the type that occurs first in the input type’s list of automatic conversion methods is used. (This follows the order of the types under the “Automatically converts to” headers above)
The following examples illustrate how this works.
Expression  Type of result  Explanation 
1+3.3 
number 
The 1 is converted to a number , and then added to 3.3 . 
1+1/2 
rational 
integer prefers to convert to rational over 
1.23+dec("1.2") 
decimal 
decimal values are preferred to number because they’re more precise. 
1/2+0.5 
number 
rational can convert to number , but not the other way round, so number addition is used. 
set(1,2,3,4) except [2] 
list 
except() is only defined on list values, so the set is converted to a list automatically. 
Function reference¶
Arithmetic¶

x+y
Addition.
 Definitions:
number
,number
→number
list
,list
→list
 concatenate two listslist
, anything →list
 add an item to the end of a listdict
,dict
→dict
 merge two dictionaries, with values from the righthand side taking precedence when the same key is present in both dictionaries.string
, anything →string
 convert the righthand argument to a string, and concatenate anything,
string
→string
 convert the lefthand argument to a string, and concatenate vector
,vector
→vector
matrix
,matrix
→matrix
integer
,integer
→integer
rational
,rational
→rational
decimal
,decimal
→decimal
number
,decimal
→decimal
 Examples:
1+2
→3
vector(1,2)+vector(3,4)
→vector(4,6)
matrix([1,2],[3,4])+matrix([5,6],[7,8])
→matrix([6,8],[10,12])
[1,2,3]+4
→[1,2,3,4]
[1,2,3]+[4,5,6]
→[1,2,3,4,5,6]
"hi "+"there"
→"hi there"

xy
Subtraction.
 Definitions:
 Examples:
12
→1
vector(3,2)vector(1,4)
→vector(2,2)
matrix([5,6],[3,4])matrix([1,2],[7,8])
→matrix([4,4],[4,4])

x*y
Multiplication.
 Definitions:
number
,number
→number
number
,vector
→vector
vector
,number
→vector
matrix
,vector
→vector
number
,matrix
→matrix
matrix
,number
→matrix
matrix
,matrix
→matrix
vector
,matrix
→vector
integer
,integer
→integer
rational
,rational
→rational
decimal
,decimal
→decimal
number
,decimal
→decimal
 Examples:
1*2
→2
2*vector(1,2,3)
→vector(2,4,6)
matrix([1,2],[3,4])*2
→matrix([2,4],[6,8])
matrix([1,2],[3,4])*vector(1,2)
→vector(5,11)

x/y
Division. Only defined for numbers.
Number operations¶

decimal
(n) 
decimal
(x) Construct a
decimal
value. Any string accepted by Decimal.js is accepted.

int
(n)¶ Convert
n
to an integer, rounding to the nearest integer.

abs
(x)¶ 
len
(x)¶ 
length
(x)¶ Absolute value, or modulus.
 Definitions:
 Examples:
abs(8)
→8
abs(34i)
→5
abs("Hello")
→5
abs([1,2,3])
→3
len([1,2,3])
→3
len(set([1,2,2]))
→2
length(vector(3,4))
→5
abs(vector(3,4,12))
→13
len(["a": 1, "b": 2, "c": 1])
→3

isint
(x)¶ Returns
true
ifx
is an integer  that is, it is real and has no fractional part.

log
(x, b)¶ Logarithm with base
b
, or base 10 ifb
is not given.

log
(x, b) Logarithm with base
b
. Example:
log(8,2)
→3
.

radians
(x)¶ Convert degrees to radians.
 Example:
radians(180)
→pi

max
(a, b)¶ Greatest of the given numbers.

min
(a, b)¶ Least of the given numbers.

clamp
(x, a, b)¶ Return the point nearest to
x
in the interval \([a,b]\).Equivalent to
max(a,min(x,b))
.

precround
(n, d)¶ Round
n
tod
decimal places. On matrices and vectors, this rounds each element independently.

siground
(n, f)¶ Round
n
tof
significant figures. On matrices and vectors, this rounds each element independently.

withintolerance
(a, b, t)¶ Returns
true
if \(bt \leq a \leq b+t\).

dpformat
(n, d[, style])¶ Round
n
tod
decimal places and return a string, padding with zeros if necessary.If
style
is given, the number is rendered using the given notation style. See the page on Number notation for more on notation styles.

countdp
(n)¶ Assuming
n
is a string representing a number, return the number of decimal places used. The string is passed throughcleannumber()
first.

sigformat
(n, d[, style])¶ Round
n
tod
significant figures and return a string, padding with zeros if necessary.

countsigfigs
(n)¶ Assuming
n
is a string representing a number, return the number of significant figures. The string is passed throughcleannumber()
first.

togivenprecision
(str, precisionType, precision, strict)¶ Returns
true
ifstr
is a string representing a number given to the desired number of decimal places or significant figures.precisionType
is either"dp"
, for decimal places, or"sigfig"
, for significant figures.If
strict
istrue
, then trailing zeroes must be included.

tonearest
(a, b)¶ Round
a
to the nearest multiple ofb
.

formatnumber
(n, style)¶ Render the number
n
using the given number notation style.See the page on Number notation for more on notation styles.

cleannumber
(str, styles)¶ Clean a string potentially representing a number. Remove space, and then try to identify a notation style, and rewrite to the
plainen
style.styles
is a list of notation styles. Ifstyles
is given, str will be tested against the given styles. If it matches, the string will be rewritten using the matched integer and decimal parts, with punctuation removed and the decimal point changed to a dot.

matchnumber
(str, styles)¶ Try to match a string representing a number in any of the given styles at the start of the given string, and return both the matched text and a corresponding
number
value.

parsenumber
(string, style)¶ Parse a string representing a number written in the given style.
If a list of styles is given, the first that accepts the given string is used.
See the page on Number notation for more on notation styles.
 Examples:
parsenumber("1 234,567","sifr")
→1234.567
parsenumber("1.001",["sifr","eu"])
→1001

parsenumber_or_fraction
(string, style)¶ Works the same as
parsenumber()
, but also accepts strings of the formnumber/number
, which it interprets as fractions. Example:
parsenumber_or_fraction("1/2")
→0.5

parsedecimal
(string, style)¶ Parse a string representing a number written in the given style, and return a
decimal
value.If a list of styles is given, the first that accepts the given string is used.
See the page on Number notation for more on notation styles.

parsedecimal_or_fraction
(string, style)¶ Works the same as
parsedecimal()
, but also accepts strings of the formnumber/number
, which it interprets as fractions.
Trigonometry¶
Trigonometric functions all work in radians, and have as their domain the complex numbers.

tan
(x)¶ Tangent: \(\tan(x) = \frac{\sin(x)}{\cos(x)}\)

arcsin
(x)¶ Inverse of
sin()
. When \(x \in [1,1]\),arcsin(x)
returns a value in \([\frac{\pi}{2}, \frac{\pi}{2}]\).

arccos
(x)¶ Inverse of
cos()
. When \(x \in [1,1]\),arccos(x)
returns a value in \([0, \frac{\pi}]\).

arctan
(x)¶ Inverse of
tan()
. When \(x\) is noncomplex,arctan(x)
returns a value in \([\frac{\pi}{2}, \frac{\pi}{2}]\).

sinh
(x)¶ Hyperbolic sine: \(\sinh(x) = \frac{1}{2} \left( \mathrm{e}^x  \mathrm{e}^{x} \right)\)

cosh
(x)¶ Hyperbolic cosine: \(\cosh(x) = \frac{1}{2} \left( \mathrm{e}^x + \mathrm{e}^{x} \right)\)

tanh
(x)¶ Hyperbolic tangent: \(\tanh(x) = \frac{\sinh(x)}{\cosh(x)}\)

cosech
(x)¶ Hyperbolic cosecant: \(\operatorname{cosech}(x) = \frac{1}{\sinh(x)}\)

sech
(x)¶ Hyperbolic secant: \(\operatorname{sech}(x) = \frac{1}{\cosh(x)}\)
Number theory¶

x!
Factorial. When
x
is not an integer, \(\Gamma(x+1)\) is used instead.fact(x)
is a synoynm forx!
.

factorise
(n)¶ Factorise
n
. Returns the exponents of the prime factorisation ofn
as a list.

gamma
(x)¶ Gamma function.

ceil
(x)¶ Round up to the nearest integer. When
x
is complex, each component is rounded separately.

floor
(x)¶ Round down to the nearest integer. When
x
is complex, each component is rounded separately.

round
(x)¶ Round to the nearest integer.
0.5
is rounded up.

trunc
(x)¶ If
x
is positive, round down to the nearest integer; if it is negative, round up to the nearest integer.

fract
(x)¶ Fractional part of a number. Equivalent to
xtrunc(x)
.

rational_approximation
(n[, accuracy])¶ Compute a rational approximation to the given number by computing terms of its continued fraction, returning the numerator and denominator separately. The approximation will be within \(e^{\text{accuracy}}\) of the true value; the default value for
accuracy
is 15.

mod
(a, b)¶ Modulo; remainder after integral division, i.e. \(a \bmod b\).

perm
(n, k)¶ Count permutations, i.e. \(^n \kern2pt P_k = \frac{n!}{(nk)!}\).

comb
(n, k)¶ Count combinations, i.e. \(^n \kern2pt C_k = \frac{n!}{k!(nk)!}\).

gcd_without_pi_or_i
(a, b)¶ Take out factors of \(\pi\) or \(i\) from
a
andb
before computing their greatest common denominator.

coprime
(a, b)¶ Are
a
andb
coprime? True if theirgcd()
is \(1\), or if either ofa
orb
is not an integer.

lcm
(a, b)¶ Lowest common multiple of integers
a
andb
. Can be used with any number of arguments; it returns the lowest common multiple of all the arguments.
Vector and matrix arithmetic¶

vector
(a1, a2, ..., aN) Create a vector with given components. Alternately, you can create a vector from a single list of numbers.

matrix
(row1, row2, ..., rowN) Create a matrix with given rows, which should be either vectors or lists of numbers. Or, you can pass in a single list of lists of numbers.

id
(n)¶ Identity matrix with \(n\) rows and columns.

numrows
(matrix)¶ The number of rows in the given matrix

numcolumns
(matrix)¶ The number of columns in the given matrix

rowvector
(a1, a2, ..., aN)¶ Create a row vector (\(1 \times n\) matrix) with the given components. Alternately, you can create a row vector from a single list of numbers.

dot
(x, y)¶ Dot (scalar) product. Inputs can be vectors or column matrices.

cross
(x, y)¶ Cross product. Inputs can be vectors or column matrices.

angle
(a, b)¶ Angle between vectors
a
andb
, in radians. Returns0
if eithera
orb
has length 0.

is_zero
(x)¶ Returns
true
if every component of the vectorx
is zero.

det
(x)¶ Determinant of a matrix. Throws an error if used on anything larger than a 3×3 matrix.

transpose
(x)¶ Matrix transpose.
Strings¶

x[n]
Get the Nth character of the string
x
. Indices start at 0. Example:
"hello"[1]
→"e"

x[a..b]
Slice the string
x
 get the substring between the given indices. Note that indices start at 0, and the final index is not included. Example:
"hello"[1..4]
→"ell"

substring in string
Test if
substring
occurs anywhere instring
. This is casesensitive. Example:
"plain" in "explains"
→true

string
(x) Convert
x
to a string.

latex
(x)¶ Mark string
x
as containing raw LaTeX, so when it’s included in a mathmode environment it doesn’t get wrapped in a\textrm
environment.Note that backslashes must be double up, because the backslash is an escape character in JME strings.

safe
(x)¶ Mark string
x
as safe: don’t substitute variable values into it when this expression is evaluated.Use this function to preserve curly braces in string literals.

render
(x, values)¶ Substitute variable values into the string
x
, even if it’s marked as safe (seesafe()
).The optional dictionary
values
overrides any previouslydefined values of variables. Definitions:
 Example:
render(safe("I have {num_apples} apples."), ["num_apples": 5])
→"I have 5 apples."
render(safe("Let $x = \\var{x}$"), ["x": 2])
→"Let $x = {2}$"
Note
The variable dependency checker can’t establish which variables will be used in the string until
render
is evaluated, so you may encounter errors if usingrender
in the definition of a question variable. You can ensure a variable has been evaluated by including it in thevalues
argument, e.g.:render("a is {}",["a": a])
This function is intended for use primarily in content areas.

capitalise
(x)¶ Capitalise the first letter of a string.

pluralise
(n, singular, plural)¶ Return
singular
ifn
is 1, otherwise returnplural
.

lower
(x)¶ Convert string to lowercase.

join
(strings, delimiter)¶ Join a list of strings with the given delimiter.

split
(string, delimiter)¶ Split a string at every occurrence of
delimiter
, returning a list of the the remaining pieces.

trim
(str)¶ Remove whitespace from the start and end of
str
.

currency
(n, prefix, suffix)¶ Write a currency amount, with the given prefix or suffix characters.

separateThousands
(n, separator)¶ Write a number, with the given separator character between every 3 digits
To write a number using notation appropriate to a particular culture or context, see
formatnumber()
.

unpercent
(str)¶ Get rid of the
%
on the end of a percentage and parse as a number, then divide by 100.

lpad
(str, n, prefix)¶ Add copies of
prefix
to the start ofstr
until the result is at leastn
characters long.

rpad
(str, n, suffix)¶ Add copies of
suffix
to the end ofstr
until the result is at leastn
characters long.

formatstring
(str, values)¶ For each occurrence of
%s
instr
, replace it with the corresponding entry in the listvalues
.

letterordinal
(n)¶ Get the \(n\)^{th} element of the sequence
a, b, c, ..., aa, ab, ...
.Note that the numbering starts from 0.

match_regex
(pattern, str, flags)¶ If
str
matches the regular expressionpattern
, returns a list of matched groups, otherwise returns an empty list.This function uses JavaScript regular expression syntax.
flags
is an optional string listing the options flags to use.

translate
(str, arguments)¶ Translate the given string, if it’s in the localisation file.
Look at the default localisation file for strings which can be translated. This function takes a key representing a string to be translated, and returns the corresponding value from the current localisation file.
arguments
is a dictionary of named substitutions to make in the string.
Logic¶

x<y
Returns
true
ifx
is less thany
.

x>y
Returns
true
ifx
is greater thany
.

x<=y
Returns
true
ifx
is less than or equal toy
.

x>=y
Returns
true
ifx
is greater than or equal toy
.

x<>y
Returns
true
ifx
is not equal toy
. Returnstrue
ifx
andy
are not of the same data type. Definitions:
 anything, anything →
boolean
 anything, anything →
 Examples:
'this string' <> 'that string'
1<>2
'1' <> 1

x=y
Returns
true
ifx
is equal toy
. Returnsfalse
ifx
andy
are not of the same data type. Definitions:
 anything, anything →
boolean
 anything, anything →
 Examples:
vector(1,2)=vector(1,2,0)
4.0=4

isclose
(x, y, rel_tol, abs_tol)¶ Returns
true
ifx
is close toy
.Equivalent to the following expression:
abs(xy) <= max( rel_tol*max(abs(a),abs(b)), abs_tol )

resultsequal
(a, b, checkingFunction, accuracy)¶ Returns
true
ifa
andb
are both of the same data type, and “close enough” according to the given checking function.Vectors, matrices, and lists are considered equal only if every pair of corresponding elements in
a
andb
is “close enough”.checkingFunction
is the name of a checking function to use. These are documented in the Numbas runtime documentation.

x and y

x && y

x & y
Logical AND. Returns
true
if bothx
andy
are true, otherwise returnsfalse
.

x or y
Logical OR. Returns
true
when at least one ofx
andy
is true. Returns false when bothx
andy
are false.

x xor y
Logical XOR. Returns
true
when at eitherx
ory
is true but not both. Returnsfalse
whenx
andy
are the same expression.
Collections¶

x[y]
Get the
y
^{th} element of the collectionx
.For matrices, the
y
^{th} row is returned.For dictionaries, the value corresponding to the key
y
is returned. If the key is not present in the dictionary, an error will be thrown.

x[a..b]

x[a..b#c]
Slice the collection
x
 return elements with indices in the given range. Note that list indices start at 0, and the final index is not included.

x in collection
Is element
x
incollection
? Definitions:
 Examples:
3 in [1,2,3,4]
→true
3 in (set(1,2,3,4) and set(2,4,6,8))
→false
"a" in ["a": 1]
→true
1 in ["a": 1]
throws an error because dictionary keys must be strings.
Ranges¶

a..b
Define a range. Includes all integers between and including
a
andb
.

range#step
Set the step size for a range. Default is 1. When
step
is 0, the range includes all real numbers between the limits.

a except b
Exclude a number, range, or list of items from a list or range.
 Definitions:
 Examples:
9..9 except 0
9..9 except [1,1]
3..8 except 4..6
[1,2,3,4,5] except [2,3]
Lists¶

repeat
(expression, n)¶ Evaluate
expression
n
times, and return the results in a list.

all
(list)¶ Returns
true
if every element oflist
istrue
.

some
(list)¶ Returns
true
if at least one element oflist
istrue
.

map
(expression,name[s],d)¶ Evaluate
expression
for each item in list, range, vector or matrixd
, replacing variablename
with the element fromd
each time.You can also give a list of names if each element of
d
is a list of values. The Nth element of the list will be mapped to the Nth name.Note
Do not use
i
ore
as the variable name to map over  they’re already defined as mathematical constants!

filter
(expression, name, d)¶ Filter each item in list or range
d
, replacing variablename
with the element fromd
each time, returning only the elements for whichexpression
evaluates totrue
.Note
Do not use
i
ore
as the variable name to map over  they’re already defined as mathematical constants!

take
(n, expression, name, d)¶ Take the first
n
elements from list or ranged
, replacing variablename
with the element fromd
each time, returning only the elements for whichexpression
evaluates totrue
.This operation is lazy  once
n
elements satisfying the expression have been found, execution stops. You can use this to filter a few elements from a large list, where the condition might take a long time to calculate.Note
Do not use
i
ore
as the variable name to map over  they’re already defined as mathematical constants!

let
(name, definition, ..., expression)¶ 
let
(definitions, expression) Evaluate
expression
, temporarily defining variables with the given names. Use this to cut down on repetition. You can define any number of variables  in the first calling pattern, follow a variable name with its definition. Or you can give a dictionary mapping variable names to their values. The last argument is the expression to be evaluated.

sort_destinations
(x)¶ Return a list giving the index that each entry in the list will occupy after sorting.

sort_by
(key, list)¶ Sort the given list of either
list
ordict
values by their entries corresponding to the given key. When sorting a list of lists, the key is a number representing the index of each list to look at. When sorting a list of dictionaries, the key is a string. Definitions:
 Examples:
sort_by(0, [[5,0], [3,2], [4,4]])
→[[3,2], [4,4], [5,0]]
sort_by("width", [["label": "M", "width": 20], ["label": "L", "width": 30], ["label": "S", "width": 10]])
→[["label": "S", "width": 10], ["label": "M", "width": 20], ["label": "L", "width": 30]]

group_by
(key, list)¶ Group the entries in the given list of either
list
ordict
values by their entries corresponding to the given key. The returned value is a list of lists of the form[key, group]
, wherekey
is the value all elements of the listgroup
have in common.When grouping a list of lists, the
key
argument is a number representing the index of each list to look at. When grouping a list of dictionaries, thekey
argument is a string. Definitions:
 Examples:
group_by(0, [[0,0], [3,2], [0,4]])
→[[0, [[0,0], [0,4]]], [3, [[3,2]]]]
group_by("a", [["a": 1, "b": "M"], ["a": 2, "b": "S"], ["a": 1, "b": "XL"]])
→[[1,[["a": 1, "b": "M"], ["a": 1, "b": "XL"]]], [2, [["a": 2, "b": "S"]]]]

indices
(list, value)¶ Find the indices at which
value
occurs inlist
.

distinct
(x)¶ Return a copy of the list
x
with duplicates removed.

list
(x) Convert a value to a list of its components (or rows, for a matrix).
 Definitions:
 Examples:
list(set(1,2,3))
→[1,2,3]
(note that you can’t depend on the elements of sets being in any order)list(vector(1,2))
→[1,2]
list(matrix([1,2],[3,4]))
→[[1,2], [3,4]]

make_variables
(definitions)¶ Evaluate a dictionary of variable definitions and return a dictionary containing the generated values.
definitions
is a dictionary mapping variable names toexpression
values corresponding to definitions.The definitions can refer to other variables to be evaluated, or variables already defined in the current scope. Variables named in the dictionary which have already been defined will be removed before evaluation begins.
 Definitions:
dict
ofexpression
,range
→dict
 Example:
make_variables(["a": expression("random(1..5)"), "b": expression("a^2")])
→["a": 3, "b": 9]

satisfy
(names, definitions, conditions, maxRuns)¶ Each variable name in
names
should have a corresponding definition expression indefinitions
.conditions
is a list of expressions which you want to evaluate totrue
. The definitions will be evaluated repeatedly until all the conditions are satisfied, or the number of attempts is greater thanmaxRuns
. IfmaxRuns
isn’t given, it defaults to 100 attempts.Note
This function is deprecated, and retained only for backwards compatibility. Use
make_variables()
instead.

sum
(numbers)¶ Add up a list of numbers

prod
(list)¶ Multiply a list of numbers together

product
(list1, list2, ..., listN) or product(list, n)¶ Cartesian product of lists. In other words, every possible combination of choices of one value from each given list.
If one list and a number are given, then the
n
th Cartesian power of the list is returned: the Cartesian product ofn
copies of the list.

zip
(list1, list2, ..., listN)¶ Combine two (or more) lists into one  the Nth element of the output is a list containing the Nth elements of each of the input lists.

combinations
(collection, r)¶ All ordered choices of
r
elements fromcollection
, without replacement.

combinations_with_replacement
(collection, r)¶ All ordered choices of
r
elements fromcollection
, with replacement.
Dictionaries¶

dict[key]
Get the value corresponding to the given key string in the dictionary
d
.If the key is not present in the dictionary, an error will be thrown.

get
(dict, key, default)¶ Get the value corresponding to the given key string in the dictionary.
If the key is not present in the dictionary, the
default
value will be returned.

dict
(a:b, c:d, ...) 
dict
(pairs) Create a dictionary with the given keyvalue pairs. Equivalent to
[ .. ]
, except when no keyvalue pairs are given:[]
creates an empty list instead.You can alternately pass a list of pairs of the form
[key, value]
, to transform a list into a dictionary. Definitions:
 multiple
keypair
→dict
 multiple
 Examples:
dict()
dict("a": 1, "b": 2)
dict([ ["a",1], ["b",2] ])

keys
(dict)¶ A list of all of the given dictionary’s keys.

values
(dict[, keys])¶ A list of the values corresponding to each of the given dictionary’s keys.
If a list of keys is given, only the values corresponding to those keys are returned, in the same order.
Sets¶

set
(a,b,c,...) or set([elements]) Create a set with the given elements. Either pass the elements as individual arguments, or as a list.

union
(a, b)¶ Union of sets
a
andb

intersection
(a, b)¶ Intersection of sets
a
andb
, i.e. elements which are in both sets.

ab
Set minus  elements which are in a but not b
 Example:
set(1,2,3,4)  set(2,4,6)
→set(1,3)
Randomisation¶

random
(x)¶ Pick uniformly at random from a range, list, or from the given arguments.

deal
(n)¶ Get a random shuffling of the integers \([0 \dots n1]\)
Control flow¶

award
(a, b)¶ Return
a
ifb
istrue
, else return0
.

if
(p, a, b)¶ If
p
istrue
, returna
, else returnb
. Only the returned value is evaluated. Definitions:
boolean
, anything, anything → unspecified
 Example:
if(false,1,0)
→0

switch
(p1, a1, p2, a2, ..., pn, an, d)¶ Select cases. Alternating boolean expressions with values to return, with the final argument representing the default case. Only the returned value is evaluated.
 Definitions:
 multiple
boolean
,anything, anything → unspecified
 multiple
 Examples:
switch(true,1,false,0,3)
→1
switch(false,1,true,0,3)
→0
switch(false,1,false,0,3)
→3

assert
(condition, value)¶ If
condition
isfalse
, then returnvalue
, otherwise don’t evaluatevalue
and returnfalse
. This is intended for use in marking scripts, to apply marking feedback only if a condition is met. Definitions:
boolean
, anything → unspecified
 Example:
assert(studentAnswer<=0, correct("Student answer is positive"))

try
(expression, name, except)¶ Try to evaluate
expression
. If it is successfully evaluated, return the result. Otherwise, evaluateexcept
, with the error message available asname
. Definitions:
 anything,
name
, anything → unspecified
 anything,
 Examples:
try(eval(expression("x+")),err, "Error: "+err)
→"Error: Not enough arguments for operation <code>+</code>"
try(1+2,err,0)
→3
HTML¶

isnonemptyhtml
(str)¶ Does
str
represent a string of HTML containing text? Returns false for the empty string, or HTML elements with no text content.

table
(data), table(data, headers)¶ Create an HTML with cell contents defined by
data
, which should be a list of lists of data, and column headers defined by the list of stringsheaders
.

image
(url)¶ Create an HTML img element loading the image from the given URL. Images uploaded through the resources tab are stored in the relative URL resources/images/<filename>.png, where <filename> is the name of the original file.
 Definitions:
 Examples:
image('resources/images/picture.png')
image(chosenimage)
 Question using randomly chosen images.
JSON¶
JSON is a lightweight datainterchange format. Many public data sets come in JSON format; it’s a good way of encoding data in a way that is easy for both humans and computers to read and write.
For an example of how you can use JSON data in a Numbas question, see the exam Working with JSON data.

json_decode
(json)¶ Decode a JSON string into JME data types.
JSON is decoded into numbers, strings, booleans, lists, or dictionaries. To produce other data types, such as matrices or vectors, you will have to postprocess the resulting data.
Warning
The JSON value
null
is silently converted to an empty string, because JME has no “null” data type. This may change in the future. Definitions:
string
→ unspecified
 Example:
json_decode(safe(' {"a": 1, "b": [2,true,"thing"]} '))
→["a": 1, "b": [2,true,"thing"]]
Subexpressions¶

expression
(string) Parse a string as a JME expression. The expression can be substituted into other expressions, such as the answer to a mathematical expression part, or the
\simplify
LaTeX command.parse(string)
is a synonym forexpression(string)
. Definitions:
 Example:

eval
(expression, values)¶ Evaluate the given subexpression.
If
values
is given, it should be a dictionary mapping names of variables to their values. Definitions:
expression
→ unspecifiedexpression
,dict
→ unspecified
 Example:
eval(expression("1+2"))
→3
eval(expression("x+1"), ["x":1])
→2

args
(expression)¶ Returns the arguments of the toplevel operation of
expression
, as a list of subexpressions. Ifexpression
is a data type other than an operation or function, an empty list is returned.Binary operations only ever have two arguments. For example,
1+2+3
is parsed as(1+2)+3
. Definitions:
 Examples:
args(expression("f(x)"))
→[expression("x")]
args(expression("1+2+3"))
→[expression("1+2"), expression("3")]
args(expression("1"))
→[]

type
(expression)¶ Returns the name of the data type of the top token in the expression, as a string.
 Definitions:
 Examples:
type(expression("x"))
→"name"
type(expression("1"))
→"integer"
type(expression("x+1"))
→"op"
type(expression("sin(x)"))
→"function"

name
(string) Construct a
name
token with the given name.

exec
(op, arguments)¶ Returns a subexpression representing the application of the given operation to the list of arguments.
 Definitions:
op
,list
→expression
 Example:
exec(op("+"), [2,1])
→expression("2+1")
exec(op(""), [2,name("x")])
→expression("2x")

findvars
(expression)¶ Return a list of all unbound variables used in the given expression. Effectively, this is all the variables that need to be given values in order for this expression to be evaluated.
Bound variables are those defined as part of operations which also assign values to those variables, such as
map
orlet
. Definitions:
 Examples:
findvars(expression("x+1"))
→["x"]
findvars(expression("x + x*y"))
→["x","y"]
findvars(expression("map(x+2, x, [1,2,3])"))
→[]

simplify
(expression, rules)¶ Apply the given simplification rules to
expression
, until no rules apply.rules
is a list of names of rules to apply, given either as a string containing a commaseparated list of names, or a list of strings.Unlike the \simplify` command in content areas, the
basic
rule is not turned on by default.See Substituting variables into displayed maths for a list of rules available.
 Definitions:
 Examples:
simplify(expression("1*x+cos(pi)"),"unitfactor")
→expression("x+cos(pi)")
simplify(expression("1*x+cos(pi)"),["basic","unitfactor","trig"])
→expression("x1")

canonical_compare
(expr1, expr2)¶ Compare expressions
a
andb
using the “canonical” ordering. Returns1
ifa
should go beforeb
,0
if they are considered “equal”, and1
ifa
should go afterb
.Expressions are examined in the following order:
 Names used: all variable names used in each expression are collected in a depthfirst search and the resulting lists are compared lexicographically.
 Data type: if
a
andb
are of different data types,op
andfunction
go first, and then they are compared using the names of their data types.  Polynomials: terms of the form
x^b
ora*x^b
, wherea
andb
are numbers andx
is a variable name, go before anything else.  Function name: if
a
andb
are both function applications, they are compared using the names of the functions. If the functions are the same, the arguments are compared. Powers, or multiples of powers, go after anything else.  Number: if
a
andb
are both numbers, the lowest number goes first. Complex numbers are compared by real part and then by imaginary part.  Elements of other data types are considered to be equal to any other value of the same data type.
 Definitions:
 anything, anything →
number
 anything, anything →
 Examples:
canonical_compare(a,b)
→1
canonical_compare(f(y),g(x))
→1
canonical_compare(f(x),g(x))
→1
canonical_compare("a","b")
→0

numerical_compare
(a, b)¶ Compare expression
a
andb
by substituting random values in for the free variables.Returns
true
ifa
andb
have exactly the same free variables, and produce the same results when evaluated against the randomly chosen values.For more control over the evaluation, see
resultsequal()
. Definitions:
 Example:
numerical_compare(expression("x^2"), expression("x*x"))
→true
numerical_compare(expression("x^2"), expression("2x"))
→false
numerical_compare(expression("x^2"), expression("y^2"))
→false
Patternmatching subexpressions¶

match
(expr, pattern, options)¶ If
expr
matchespattern
, return a dictionary of the form["match": boolean, "groups": dict]
, where"groups"
is a dictionary mapping names of matches to subexpressions.See the documentation on patternmatching mathematical expressions.
If you don’t need to use any parts of the matched expression, use
matches()
instead. Definitions:
expression
,string
→dict
expression
,string
,string
→dict
 Examples:
match(expression("x+1"),"?;a + ?;b")
→["match": true, "groups": ["a": expression("x"), "b": expression("1"), "_match": expression("x+1")]]
match(expression("sin(x)"), "?;a + ?;b")
→["match": false, "groups": dict()]
match(expression("x+1"),"1+?;a")
→["match": true, "groups": ["a": expression("x"), "_match": expression("x+1")]]

matches
(expr, pattern, options)¶ Return
true
ifexpr
matchespattern
.Use this if you’re not interested in capturing any parts of the matched expression.
 Definitions:
expression
,string
→boolean
expression
,string
,string
→boolean
 Examples:
matches(expression("x+1"),"?;a + ?;b")
→true
matches(expression("sin(x)"), "?;a + ?;b")
→false

replace
(pattern, replacement, expr)¶ Replace occurrences of
pattern
inexpr
with the expression created by substituting the matched items intoreplacement
. Definitions:
 Examples:
replace("?;x + ?;y", "x*y", expression("1+2"))
→expression("1*2")
replace("?;x + ?;y", "f(x,y)", expression("1+2+3"))
→expression("f(f(1,2),3)")
replace("0*?", "0", expression("0*sin(x) + x*0 + 2*cos(0*pi)"))
→expression("0 + 0 + 2*cos(0)")
Identifying data types¶

type
(x) Returns the name of the data type of
x
. Example:
type(1)
→"integer"

x isa type
Returns
true
ifx
is of the data typetype
.

x as type
Convert
x
to the given data type, if possible.If
x
can not be automatically converted totype
, an error is thrown. Definitions:
 anything,
string
→ given type
 anything,
 Examples:
dec(1.23) as "number"
→1.23
set(1,2,3) as "list"
→[1,2,3]

infer_variable_types
(expression)¶ Attempt to infer the types of free variables in the given expression.
There can be more than one valid assignment of types to the variables in an expression. For example, in the expression
a+a
, the variablea
can be any type which has a defined addition operation.Returns the first possible assignment of types to variables, as a dictionary mapping variable names to the name of its type. If a variable name is missing from the dictionary, the algorithm can’t establish any constraint on it.
 Definitions:
 Example:
infer_variable_types(expression("x^2"))
→["x": "number"]
infer_variable_types(expression("union(a,b)"))
→["a": "set", "b": "set"]
infer_variable_types(expression("k*det(a)"))
→[ "k": "number", "a": "matrix" ]
Inspecting the evaluation scope¶

definedvariables
()¶ Returns a list containing the names of every variable defined in the current scope, as strings.
 Definitions:
 () →
list
 () →

isset
(name)¶ Returns
true
if the variable with the given name has been defined in the current scope.
Marking algorithms¶
Every question part has a marking algorithm, which is is responsible for:
 Rejecting the student’s answer if it’s invalid. If the answer is rejected, no credit or feedback will be given and the student must change their answer before resubmitting.
 If the student’s answer is valid, assigning credit and giving feedback messages.
The credit for a part is the proportion of the marks available which should be awarded to the student. The total marks available are set by the question author, and might be reduced if the student reveals steps, or if this part is a gap in a gapfill part.
The feedback messages shown to the student are strings of text shown after the part has been marked. These might only become visible to the student after they have finished the exam, so don’t rely on feedback messages to convey information that students might need in subsequent parts.
The marking algorithm comprises a set of marking notes written in JME syntax, which are evaluated similarly to question variables.
Two marking notes are required:

mark
¶ The
mark
note should award credit and provide feedback based on the student’s answer. If the student’s answer is invalid,mark
shouldfail()
.

interpreted_answer
¶ The
interpreted_answer
note should produce a value representing the student’s answer to this part, which can be used by other parts with adaptive marking.
Each note evaluates to a value, and also produces a list of feedback items, which modify the amount of credit awarded or give a message to the student. When a feedback item modifies the amount of credit awarded, a message describing the number of marks awarded or taken away from the previous total is displayed to the student.
If a note fails, either because it applies the fail()
function or an error is thrown while it is evaluated, it will produce no value and no feedback items.
Any notes referring to a failed note also fail.
If the mark
or interpreted_answer
notes fail, the student’s answer is rejected and the student must change their answer before resubmitting.
Like question variables, marking notes can refer to each other.
When another note is referred to in another note’s definition, its value is substituted in.
To apply another note’s feedback items, use apply()
.
Variables available to marking algorithms¶
The following variables are available for use by marking algorithms:

path
¶ The path to this part, in the form
pN(gNsN)
. The first part (part a) has pathp0
. As an example, the second gap in part c would have pathp2g1
.

studentAnswer
¶ The student’s answer to the part. The data type of this value depends on the part of the type. See the list of standard part type values, and custom part type answer input methods for details on the data types produced by different part types.

settings
¶ A
dict
of the part’s settings.For builtin parts, see the relevant part type’s documentation. For custom part types this is all of the settings defined in the part.

gaps
¶ A
list
of the gaps belonging to this part. Each element in the list is adict
of the same variables that would be available in the gap’s own marking algorithm.

steps
¶ A
list
of the steps belonging to this part. Each element in the list is adict
of the same variables that would be available in the gap’s own marking algorithm.

input_options
¶ (Only for custom part types)
A
dict
of the options for the part’s answer input method.
Markingspecific JME functions¶
All the builtin JME functions are available in marking notes, as well as the following functions specifically to do with marking:

correct
(message)¶ Set the credit to 1 and give the feedback message
message
. Ifmessage
is omitted, the default “Your answer is correct” message for the current locale is used.

incorrect
(message)¶ Set the credit to 0 and give the feedback message
message
. Ifmessage
is omitted, the default “Your answer is incorrect” message for the current locale is used.

correctif
(condition)¶ If
condition
evaluates totrue
, set the credit to 1 and give the default feedback message. Otherwise, set the credit to 0 and give the default feedback message.Equivalent to
if(condition,correct(),incorrect())
.

set_credit
(credit, message)¶ Set the credit to
credit
, and give the feedback messagemessage
. The message should explain why the credit was awarded.

add_credit
(credit, message)¶ Add
credit
to the current total, to a maximum of 1, and give the feedback messagemessage
. The message should explain why the credit was awarded.If
credit
is negative, credit is taken away, to a minimum of 0.

sub_credit
(credit, message)¶ Subtract
credit
from the current total and give the feedback messagemessage
. The message should explain why the credit was taken away.

multiply_credit
(proportion, message)¶ Multiply the current credit by
proportion
and give the feedback messagemessage
. The message should explain why the credit was modified.This operation is displayed to the student as an absolute change in marks awarded, not a multiplication. For example, if the student already had 2 marks and multiply_credit(0.5,message) was applied, the message displayed would be along the lines of “1 mark was taken away”.

end
()¶ End the marking here. Any feedback items produced after this one are not applied.
This is most useful as a way of stopping marking once you’ve decided the student’s answer is incorrect partway through a multistep marking process.

fail
(message)¶ Reject the student’s answer as invalid, set the credit to 0 and give the feedback message
message
. The message should explain why the student’s answer was rejected.Since the student might not see the feedback message until the exam is over, you should also use
warn()
to add a warning message next to the input field describing why the student’s answer was rejected.

feedback
(message)¶ Give the feedback message
message
, without modifying the credit awarded.

x ; y
Add feedback items generated by
x
to those generated byy
, and returny
.This is a way of chaining multiple feedback items together.
 Example:
incorrect() ; end()
 mark the student’s answer as incorrect, then end marking.apply(note1) ; apply(note2)
 apply feedback generated bynote1
, then feedback generated bynote2
.

apply
(feedback)¶ If
feedback
is the name of a marking note, apply its feedback items to this note.If
feedback
is a list of feedback items generated by a function such assubmit_part()
, apply them to this note. Examples:
apply(validNumber)
 add the feedback from the notevalidNumber
to this note.apply([submit_part(gaps[0]["path"]), submit_part(gaps[1]["path"])])
 mark the first two gaps and add their feedback to this note.

apply_marking_script
(name, studentanswer, settings, marks)¶ Apply the marking script with the given name, with the given values of the variables
studentanswer
andsettings
and withmarks
marks available.Any feedback items generated by the marking script are applied to this note.
The builtin marking scripts are stored in the marking_scripts folder of the Numbas source repository. Use the name of the script without the
.jme
extension as thename
parameter of this function. Example:
apply_marking_script("numberentry",studentAnswer,settings+["minvalue":4,"maxvalue":5],1)
 mark this part using the number entry part’s marking script, but with the minimum and maximum accepted values set to 4 and 5.

submit_part
(path[, answer])¶ Submit the part with the given path. If
answer
is given, the answer stored for that part is overwritten with the given value. Returns a dictionary of the following form:[ "answered": has the student given a valid answer to the part?, "credit": credit awarded for the part, "marks": number of marks awarded, "feedback": feedback items generated by the part's marking algorithm ]
Custom part types can’t depend on other parts being available. However, you might want to allow the question author to provide the path of another part, or do something with this part’s gaps or steps, whose paths are listed in
gaps
andsteps
.

mark_part
(path, studentanswer)¶ Mark the part with the given path, using the given value for
studentanswer
.Returns a dictionary of the following form:
[ "valid": is the given answer a valid answer to the part?, "credit": credit awarded for the part, "marks": number of marks awarded, "feedback": feedback items generated by the part's marking algorithm, "states": a dictionary mapping the name of each marking note to a list of feedback items, "state_valid": a dictionary mapping the name of each marking note to a boolean representing whether that note failed, "values": a dictionary mapping the name of each marking note to its value ]
This function is most useful in a custom marking algorithm for a gapfill part, when you want to reassign the student’s answers to each of the gaps. For example, in a part with two number entry gaps, you could ensure that the lowest answer is marked by the first gap, and the highest answer is marked by the second. This would allow the student to enter their answers in any order, and the question author to set the expected answer for the first and second gaps to the lowest and highest correct answers, respectively.

concat_feedback
(items, scale[, strip_messages])¶ Apply the given list of feedback items (generated by
submit_part()
ormark_part()
) to this note, scaling the credit awarded byscale
.If
strip_messages
istrue
, then all messages are stripped from the feedback items, leaving only items which modify the credit awarded. Example:
Mark gap 0, and award credit proportional to the number of marks available:
let(result,mark_part(gaps[0]["path"],studentanswer[0]), concat_feedback(result["feedback"], result["marks"]) )
Number notation¶
There are many different ways of writing a number, depending on culture and context.
Numbas can interpret and display numbers in several styles.
Styles of notation¶
Numbas supports the following styles of notation. The entry in the “Code” column is the string you should use to identify the style in JME or JavaScript code.
Style  Code  Description  Example 

English (plain)  plain 
Powers of 1000 not separated, and a dot is used for the decimal mark.  1234567.890123 
English  en 
Positive powers of 1000 are separated with commas, and a dot is used for the decimal mark.  1,234,567.890123 
SI (English)  sien 
Powers of 1000 are separated with spaces, and a dot is used for the decimal mark.  1 234 567.890 123 
SI (French)  sifr 
Powers of 1000 are separated with spaces, and a comma is used for the decimal mark.  1 234 567,890 123 
Continental  eu 
Positive powers of 1000 are separated with dots, and a comma is used for the decimal mark.  1.234.567,890123 
Continental (plain)  plaineu 
Powers of 1000 are not separated, and a comma is used for the decimal mark.  1234567,890123 
Swiss  ch 
Positive powers of 1000 are separated with apostrophes, and a dot is used for the decimal mark.  1‘234‘567.890123 
Indian  in 
Groups of digits in the integer part are separated with commas. The rightmost group is three digits, and other digits are grouped in pairs. A dot is used for the decimal mark.  12,34,567.890123 
Scientific  scientific 
A mantissa between 1 and 10, then the letter ‘e’, followed by an integer exponent  1.234567e+6 
Warning
Note that some styles conflict with each other: for example, 1.234
is a number between 1 and 2 in English, while it’s the integer 1234 in French.
In the JavaScript runtime, these styles are defined in Numbas.util.numberNotationStyles
.
Numbers in JME¶
In JME code, and Mathematical expression parts, numbers are written in the “English (plain)” form only.
You can parse a string representing a number written in a different style using the parsenumber()
function, and display it using a particular style using the formatnumber()
function, or by giving a style code to dpformat()
or sigformat()
.
Substituting variables into displayed maths¶
Attention
This page is about substituting variables into mathematical expressions. You can substitute text strings into plain text using curly braces; see Substituting variables into content areas for a description of the different methods of substituting variables into question text.
In Numbas, maths is displayed using LaTeX. For help with LaTeX, see LaTeX notation.
LaTeX is purely a typesetting language and is illsuited for representing meaning in addition to layout. For this reason, dynamic or randomised maths expressions must be written in JME syntax and converted to LaTeX. Numbas provides two new LaTeX commands to do this for you.
To substitute the result of an expression into a LaTeX expression, use the \var
command.
Its parameter is a JME expression, which is evaluated and then converted to LaTeX.
For example:
\[ \var{2^3} \]
produces:
\[ 8 \]
and if a variable called x has been defined to have the value 3:
\[ 2^{\var{x}} \]
produces:
\[ 2^{3} \]
This simple substitution doesn’t always produce attractive results, for example when substituted variables might have negative values. If \(y=4\):
\[ \var{x} + \var{y} \]
produces:
\[ 3 + 4 \]
To deal with this, and other more complicated substitutions, there is the \simplify
command.
The main parameter of the \simplify
command is a JME expression.
It is not evaluated  it is converted into LaTeX as it stands.
For example:
\[ \simplify{ x + (1/y) } \]
produces:
\[ x  \frac{1}{y} \]
Variables can be substituted in by enclosing them in curly braces. For example:
\[ \simplify{ {x} / {y} } \]
produces, when \(x=2,y=3\):
\[ \frac{ 2 }{ 3 } \]
The \simplify
command automatically rearranges expressions, according to a set of simplification rules, to make them look more natural.
Sometimes you might not want this to happen, for example while writing out the steps in a worked solution.
The set of rules to be used is defined in a list enclosed in square brackets before the main argument of the \simplify
command.
You can control the \simplify
command’s behaviour by switching rules on or off.
For example, in:
\[ \simplify{ 1*x } \]
I have not given a list of rules to use, so they are all switched on.
The unitFactor
rule cancels the redundant factor of 1 to produce:
\[ x \]
while in:
\[ \simplify[!unitFactor]{ 1*x } \]
I have turned off the unitFactor rule, leaving the expression as it was:
\[ 1 x \]
When a list of rules is given, the list is processed from left to right. Initially, no rules are switched on. When a rule’s name is read, that rule is switched on, or if it has an exclamation mark in front of it, that rule is switched off.
Sets of rules can be given names in the question’s Rulesets section, so they can be turned on or off in one go.
Display options¶
The \simplify
and \var
commands take an optional list of settings, separated by commas.
These affect how certain elements, such as numbers or vectors, are displayed.
The following display options are available:
 fractionNumbers
This rule doesn’t rewrite expressions, but tells the maths renderer that you’d like noninteger numbers to be displayed as fractions instead of decimals.
Example:
\var[fractionNumbers]{0.5}
produces \(\frac{1}{2}\). mixedFractions
Improper fractions (with numerator larger than the denominator) are displayed in mixed form, as an integer next to a proper fraction.
Example:
\var[fractionNumbers,mixedFractions]{22/7}
produces \(3 \frac{1}{7}\). rowVector
 This rule doesn’t rewrite expressions, but tells the maths renderer that you’d like vectors to be rendered as rows instead of columns.
 alwaysTimes
The multiplication symbol is always included between multiplicands.
Example:
\simplify[alwaysTimes]{ 2x }
produces \(2 \times x\).
Simplification rules¶
As well as the display options, the \simplify
command takes an optional list of names of simplification rules to use, separated by commas.
These rules affect how the command rearranges the expression you give it.
Lists of simplification rule names are read from left to right, and rules are added or removed from the set in use as their names are read.
To include a rule, use its name, e.g. unitfactor
.
To exclude a rule, put an exclamation mark in front of its name, e.g. !unitfactor
.
Rule names are not casesensitive: any mix of lowercase or uppercase works.
To turn all builtin rules on, use the name all
.
To turn all builtin rules off, use !all
.
Note: Because they can conflict with other rules, the canonicalOrder and expandBrackets rules are not included in all
.
You must include them separately.
If you don’t give a list of options, e.g. \simplify{ ... }
, all the builtin rules are used.
If you give an empty list of options, e.g. \simplify[]{ ... }
, no rules are used.
For example, the following code:
\simplify[all,!collectNumbers,fractionNumbers]{ 0.5*x + 1*x^2  2  3 }
turns on every rule, but then turns off the collectNumbers
rule, so every rule except collectNumbers
can be applied.
Additionally, the display option fractionNumbers
is turned on, so the 0.5
is displayed as \(\frac{1}{2}\).
Altogether, this produces the following rendering: \(\frac{1}{2} x + x^2  2  3\)
The following simplification rules are available:
 basic
These rules are always turned on, even if you give an empty list of rules. They must be actively turned off, by including
!basic
in the list of rules. See this behaviour in action.+x
→x
(get rid of unary plus)x+(y)
→xy
(plus minus = minus)x(y)
→x+y
(minus minus = plus)(x)
→x
(unary minus minus = plus)x
→eval(x)
(if unary minus on a complex number with negative real part, rewrite as a complex number with positive real part)x+y
→eval(x+y)
(always collect imaginary parts together into one number)x+y
→eval(xy)
(similarly, for negative numbers)(x)/y
→(x/y)
(take negation to left of fraction)x/(y)
→(x/y)
(x)*y
→(x*y)
(take negation to left of multiplication)x*(y)
→(x*y)
x+(y+z)
→(x+y)+z
(make sure sums calculated lefttoright)x(y+z)
→(xy)z
x+(yz) ``(x+y)z'
x(yz)
>(xy)+z
(x*y)*z
→x*(y*z)
(make sure multiplications go righttoleft)n*i
→eval(n*i)
(always collect multiplication by \(i\))i*n
→eval(n*i)
 unitFactor
Cancel products of 1
1*x
→x
x*1
→x
 unitPower
Cancel exponents of 1
x^1
→x
 unitDenominator
Cancel fractions with denominator 1
x/1
→x
 zeroFactor
Cancel products of zero to zero
x*0
→0
0*x
→0
0/x
→0
 zeroTerm
Omit zero terms
0+x
→x
x+0
→x
x0
→x
0x
→x
 zeroPower
Cancel exponents of 0
x^0
→1
 noLeadingMinus
Rearrange expressions so they don’t start with a unary minus
x+y
→yx
0
→0
 collectNumbers
Collect together numerical (as opposed to variable) products and sums. The rules below are only applied if
n
andm
are numbers.xy
→(x+y)
(collect minuses)n+m
→eval(n+m)
(add numbers)nm
→eval(nm)
(subtract numbers)n+x
→x+n
(numbers go to the end of expressions)(x+n)+m
→x+eval(n+m)
(collect number sums)(xn)+m
→x+eval(mn)
(x+n)m
→x+eval(nm)
(xn)m)
→xeval(n+m)
(x+n)+y
→(x+y)+n
(numbers go to the end of expressions)(x+n)y
→(xy)+n
(xn)+y
→(x+y)n
(xn)y
→(xy)n)
n*m
→eval(n*m)
(multiply numbers)x*n
→n*x
(numbers go to left hand side of multiplication, unless \(n=i\))m*(n*x)
→eval(n*m)*x
 simplifyFractions
Cancel fractions to lowest form. The rules below are only applied if
n
andm
are numbers and \(gcd(n,m) > 1\).n/m
→eval(n/gcd(n,m))/eval(m/gcd(n,m))
(cancel simple fractions)(n*x)/m
→(eval(n/gcd(n,m))*x)/eval(m/gcd(n,m))
(cancel algebraic fractions)n/(m*x)
→eval(n/gcd(n,m))/(eval(m/gcd(n,m))*x)
(n*x)/(m*y)
→(eval(n/gcd(n,m))*x)/(eval(m/gcd(n,m))*y)
 zeroBase
Cancel any power of zero
0^x
→0
 constantsFirst
Numbers go to the left of multiplications
x*n
→n*x
x*(n*y)
→n*(x*y)
 sqrtProduct
Collect products of square roots
sqrt(x)*sqrt(y)
→sqrt(x*y)
 sqrtDivision
Collect fractions of square roots
sqrt(x)/sqrt(y)
→sqrt(x/y)
 sqrtSquare
Cancel square roots of squares, and squares of square roots
sqrt(x^2)
→x
sqrt(x)^2
→x
sqrt(n)
→eval(sqrt(n))
(ifn
is a square number)
 trig
Simplify some trigonometric identities
sin(n)
→eval(sin(n))
(ifn
is a multiple of \(\frac{\pi}{2}\))cos(n)
→eval(cos(n))
(ifn
is a multiple of \(\frac{\pi}{2}\))tan(n)
→0
(ifn
is a multiple of \(\pi\))cosh(0)
→1
sinh(0)
→0
tanh(0)
→0
 otherNumbers
Evaluate powers of numbers. This rule is only applied if
n
andm
are numbers.n^m
→eval(n^m)
 cancelTerms
Collect together and cancel terms. Like collectNumbers, but for any kind of term.
x +x
→2*x
(z+n*x)  m*x
→z + eval(nm)*x
1/x + 3/x
→4/x
 cancelFactors
Collect together and cancel factors inside a term.
x*x
→x^2
x^2 * x
→x^3
(1/x^3)*x
→1*x^(2)
 collectLikeFractions
Collect together fractions over the same denominator.
x/3 + 4/x
→(x+4)/3
 canonicalOrder
Rearrange the expression into a “canonical” order, using
canonical_compare()
.Note: This rule can not be used at the same time as noLeadingMinus  it can lead to an infinite loop.
 expandBrackets
Expand out products of sums.
(x+y)*z
→x*z + y*z
3*(xy)
→3x  3y
Displayonly JME functions¶
There are a few “virtual” JME functions which can not be evaluated, but allow you to express certain constructs for the purposes of display, while interacting properly with the simplification rules.

int
(expression, variable)¶ An indefinite integration, with respect to the given variable.
int(x^2+2,x)
→ \(\displaystyle{\int \! x^2+2 \, \mathrm{d}x}\)int(cos(u),u)
→ \(\displaystyle{\int \! \cos(u) \, \mathrm{d}u}\)

defint
(expression, variable, lower bound, upper bound)¶ A definite integration between the two given bounds.
defint(x^2+2,x,0,1)
→ \(\displaystyle{\int_{0}^{1} \! x^2+2 \, \mathrm{d}x}\)defint(cos(u),u,x,x+1)
→ \(\displaystyle{\int_{x}^{x+1} \! \cos(u) \, \mathrm{d}u}\)

diff
(expression, variable, n)¶ \(n\)th derivative of expression with respect to the given variable
diff(y,x,1)
→ \(\frac{\mathrm{d}y}{\mathrm{d}x}\)diff(x^2+2,x,1)
→ \(\frac{\mathrm{d}}{\mathrm{d}x} \left (x^2+2 \right )\)diff(y,x,2)
→ \(\frac{\mathrm{d}^{2}y}{\mathrm{d}x^{2}}\)

partialdiff
(expression, variable, n)¶ \(n\)th partial derivative of expression with respect to the given variable
partialdiff(y,x,1)
→ \(\frac{\partial y}{\partial x}\)partialdiff(x^2+2,x,1)
→ \(\frac{\partial }{\partial x} \left (x^2+2 \right )\)partialdiff(y,x,2)
→ \(\frac{\partial{2}y}{\partial x^{2}}\)

sub
(expression, index)¶ Add a subscript to a variable name. Note that variable names with constant subscripts are already rendered properly – see Variable names – but this function allows you to use an arbitray index, or a more complicated expression.
sub(x,1)
→ \(x_{1}\)sub(x,n+2)
→ \(x_{n+2}\)
The reason this function exists is to allow you to randomise the subscript. For example, if the index to be used in the subscript is held in the variable
n
, then this:\simplify{ sub(x,{n}) }
will be rendered as
\(x_{1}\)when
n = 1
.

sup
(expression, index)¶ Add a superscript to a variable name. Note that the simplification rules to do with powers won’t be applied to this function, since it represents a generic superscript notation, rather than the operation of raising to a power.
sup(x,1)
→ \(x^{1}\)sup(x,n+2)
→ \(x^{n+2}\)
Patternmatching mathematical expressions¶
Numbas includes a sophisticated patternmatching algorithm for mathematical expressions. The algorithm decides whether an input expression matches a given pattern, and also identifies named matching groups, which are subexpressions of the input expression.
Patternmatching is used to power the simplification rules, as well as to establish the form of mathematical expressions entered by the student.
The patternmatcher should be considered to work similarly to a regular expression algorithm, except it operates on algebraic syntax trees instead of text strings.
Patternmatching syntax¶
Patterns are written in JME syntax, but there are extra operators available to specify what does or doesn’t match.
The patternmatching algorithm uses a variety of techniques to match different kinds of expression.
Data elements such as numbers, strings, booleans are matched by comparison: a pattern consisting of a single data element matches only that exact element.
A pattern consisting of a function application function application f(arguments...)
matches any expression consisting of an application of exactly that function, and whose arguments, considered as a sequence, match the sequence of patterns arguments
.
There are some special functions which match differently.
If the same group name is captured by more than one argument, then all the groups captured under that name are gathered into a list.
A pattern consisting of a sequence of terms joined by a binary operator, or a single term with a unary operator applied, is considered as a sequence. If a way of matching up the terms in the input expression with the terms in the pattern can be found, considering quantifiers and the properties of commutativity and associativity, then the expression matches the pattern. If the same group name is captured by more than one argument, then all the groups captured under that name are gathered into a sequence joined by the operator being matched.
A pattern consisting of a list matches any expression consisting of a single list, whose elements match the elements of the list in the pattern. Quantifiers allow you to write a pattern which matches lists with different numbers of terms.
Special names¶

?
¶ Matches anything.

$n
¶ Matches a number.
This only matches single number tokens, not expressions which would evaluate to a number, such as
3
(unary negation) orsqrt(2)
.This does not match unary negation, but does match negative numbers which have been substituted into an expression. To robustly match a positive or negative number, use
`+ $n
.You can use the following annotations to restrict the kinds of numbers that are matched:
real
 has no imaginary part.complex
 has a nonzero imaginary part.imaginary
 has a nonzero imaginary part and zero real part.positive
 real and strictly greater than 0.nonnegative
 real and greater than or equal to 0.negative
 real and less than 0.integer
 an integer.decimal
 written with at least one digit after the decimal place, or any real number with a fractional part.rational
 an integer, or the division of one integer by another. This doesn’t only match a single token  it’s equivalent to the patterninteger:$n / integer:n`?
.
 Examples:
real:$n
matches3
andpi
but not4+i
orsqrt(2)
.complex:$n
matches1+2i
andi
but not3
.decimal:$n
matches4.1
and2.0
but not2
.rational:$n
matches3/4
and2
but not4.1
.

$v
¶ Matches any variable name.

$z
¶ Match nothing. Use this as the righthand side of a
+
or*
operation to force the patternmatcher to match a sum or product, respectively, when the pattern would otherwise only contain one term, due to use of a quantifier. Example:
($n ` $v)`+ + $z
matches a sum of any length consisting of numbers or variable names, such as3 + x + 1 + 2 + y
.
Arithmetic Operators¶

`+ X
Match either
X
orX

`*/ X
Match either
X
or1/X
 Example:
$n * (`*/ $n)
matches either the product or the quotient of two numbers, such as3*4
or6/2
.
Combining patterns¶

A ` B
Match either
A
orB
. Example:
x*x ` x^2
matches two different ways of writing “x squared”.

A `& B
The expression must match both
A
andB
. Example:
? = ? `& m_uses(x)
matches an equation which contains the variablex
somewhere.

`! X
Match anything except
X
. Example:
`! m_uses(x)
matches any expression which does not use the variablex
.

X `where C
The expression must match
X
, and then the conditionC
is evaluated, with any names corresponding to groups captured inX
substituted in. If the conditionC
evaluates totrue
, the expression matches this pattern. Example:
$n;x + $n;y `where x+y=5
matches the sum of two numbers which add up to a total of 5.

macros `@ X
macros
is a dictionary of patterns. The macros are substituted intoX
to produce a new pattern, which the expression must match. Example:
["x": a ` b] `@ ["trig": sin(x) ` cos(x) ` tan(x)] `@ trig*trig + trig*trig
matchessin(a)*cos(b) + cos(a)*sin(b)
.
Capturing named groups¶
The capturing operator ;
attaches to a part of a pattern, and captures the part of the input expression matching that pattern under the given name.

X;g
Capture the input expression in the group named
g
if it matches the patternX
. Example:
$n;a
captures a number asa
. For the expression15
,a=15
.$n;a + $n;b
captures two numbersa
andb
. For the expression3+4
,a=3
andb=4
.(x$?;root);term
when matched against the expressionx2
capturesroot = 2
andterm = x2
.

X;g:v
Match
X
, and capture the valuev
in the group namedg
.You can use this to provide a default value for a value that’s missing or implied, for example a coefficient of \(1\) in \(x\).
 Example:
(`+ $n);a * x ` x;a:1 ` x;a:1
captures the coefficient ofx
asa
. When the expression isx
,a = 1
.

X;=g
Match
X
only if it’s identical to every other occurrence captured under the nameg
. Example:
?;=t + ?;=t
matches two copies of the same thing, added together. It matches1 + 1
,x+x
andsin(x*pi) + sin(x*pi)
, but not1+2
orx+y
. When the expression is2x + 2x
,t = 2x
.
Quantifiers¶
Quantifiers are used to capture terms that may appear a variable number of times in a sequence.

X `?
Either one occurrence of
X
or none. Example:
$n`? * x
matchesx
and5x
.

X `: Y
If the expression matches
X
, match that, otherwise match as the default valueY
.In a sequence, this acts the same as the
`?
quantifier, additionally capturing the default valueY
ifX
does not appear in the sequence. Example:
($n `: 1);coefficient * x
matchesx
and5x
, and capturescoefficient
as1
when it’s omitted.x^(? `: 1);p
captures any power ofx
asp
, settingp=1
when the power is omitted.

X `*
Any number of occurrences of
X
, or none. Examples:
x * integer:$n`*
matches the product ofx
and any number of integers, such asx
,x*5
orx*2*3
, but notx*x
orx*x*5
.[$n `*]
matches a list containing any number of numbers, such as[]
,[1]
or[6,2]
.

X `+
At least one occurrence of
X
. Example:
x * integer:$n`+
matches the product ofx
and at least one integer, such asx*5
orx*5*6
, but notx
.
Matching modes¶
The following functions change the way the matcher works.
 Allow other terms
 When matching an associative operation, allow the presence of terms which don’t match the pattern, as long as there are other terms which do satisfy the pattern.
This allows you to write patterns which pick out particular parts of sums and products, for example, while ignoring the rest.
This is equivalent to adding something like
+ ?`*
to the end of every sum, and likewise for other associative operations.  Use commutativity
When matching an associative operation, allow the terms to appear in any order. A sequence matches if an ordering of the terms which satisfies the pattern can be found.
For nonsymmetric operators with converses, such as \(\lt\) and \(\leq\), also match the converse relation, reversing the order of the operands.
 Use associativity
For an associative operator \(\circ\), sequences of terms such as \(a \circ b \circ c\) will be considered together.
If this mode is not enabled, terms are not gathered into sequences before trying to match, so \((a \circ b) \circ c\) is not considered to be the same as \(a \circ (b \circ c)\).
 Gather as a list
For an associative operator, when the same name is captured by multiple terms, the resulting captured group for that name is a list whose elements are the captured subexpressions from each term.
If this mode is not enabled, the subexpressions from each term are joined together by the associative operator. This doesn’t always make sense, particularly if the group captures only portions of each term.
 Strict inverse
If this mode is not enabled, then
ab
is matched as if it’sa+(b)
, anda/b
is matched as if it’sa*(1/b)
. This makes matching sums of terms that may have negative coefficients easier.If this mode is enabled, then the behaviour described above is not used.

m_exactly
(X)¶ Turn off allow other terms mode when matching
X
.

m_commutative
(X)¶ Turn on use commutativity mode when matching
X
.

m_noncommutative
(X)¶ Turn off use commutativity mode when matching
X
.

m_associative
(X)¶ Turn on use associativity mode when matching
X
.

m_nonassociative
(X)¶ Turn off use associativity mode when matching
X
.

m_strictinverse
(X)¶ Turn on strict inverse mode when matching
X
.

m_gather
(X)¶ Turn on gather as a list mode when matching
X
.

m_nogather
(X)¶ Turn off gather as a list mode when matching
X
.
Special conditions¶

m_type
(type)¶ Match any item with the given data type.
 Example:
m_type("string")
matches"hi"
,"5,000"
and"x"
but not1
,true
orx
.

m_func
(name, arguments)¶ Match a function whose name, as a string, matches the given pattern, and whose arguments, considered as a
list
, match the given pattern. Example:
m_func(?, [?,?])
matches any function of two variables.

m_op
(name, operands)¶ Match a binary or unary operator whose name, as a string, matches the given pattern, and whose operands, considered as a
list
, match the given pattern.Note that any properties of matched operators, such as commutativity or associativity, aren’t exploited with this matching method.

m_uses
(name)¶ Match if the expression uses the variable with the given name as a free variable.
 Example:
m_uses(x)
matchesx
,1+x
andsin(x/2)
but noty
,42
, ormap(2x,x,[1,2,3])
.

m_anywhere
(X)¶ Match if a subexpression matching the pattern
X
can be found anywhere inside the input expression. Example:
m_anywhere(sin(?))
matchessin(x)
andsin(pi/2) + cos(pi/2)
but nottan(x)
.
Patternmatching examples¶
The following examples demonstrate different features of the patternmatching syntax, and particular behaviours that might not be immediately obvious.
In the following, the Use commutativity and Use associativity modes are enabled, and Allow other terms is disabled, unless otherwise specified.
Match exactly the expression 1+2
:
1 + 2
If commutativity is enabled, 2 + 1
will also match this pattern.
Whitespace and brackets are ignored when they don’t change the meaning of the expression, so 1+2
, 1 + 2
and (1)+(2)
all match this pattern.
Any power of 2:
2^?
Forbid decimals anywhere (so only allow integers):
`!m_anywhere(decimal:$n)
A sum consisting of any number of fractions, all over the same denominator, which is captured as d
:
(`+( $n/($n;=d) ))`* + $z
Ensure that there are no unexpanded brackets:
`! m_anywhere(?*(? + ?`+))
The sum of two positive integers:
positive:$n + positive:$n
A product of at least two factors, where no factor is numerically equal to 1:
m_nogather(
?;factors*?`+;factors
`where
all(map(not numerical_compare(x,expression("1")),x,factors))
)
This is a fairly cheap way of checking that a number or expression has been decomposed into factors (assuming it’s not already irreducible).
Note that it doesn’t check that the expression has been fully factorised: for example, 4*6
matches this pattern.
Complete the square:
(x+$n)^2+$n`?
A number of the form \(a \cdot e^{\theta i}\), where the coefficient \(a\) is optional, and the power can be any multiple or fraction of \(i\):
($n`? `: 1)*e^(((`*/ `+ $n)`*;x)*i)
The following expressions all match this pattern: e^i
, 2e^(pi*i)
, e^(i * 2/3 pi)
.
A complex number in the form \(a + ib\), allowing for either the real or imaginary part to be omitted, and zero by default.
The real part is captured as re
and the imaginary part as im
:
((`+real:$n)`? `: 0);re + ((`+i*real:$n`?)`? `: 0);im
A polynomial with integer coefficients:
`+ ((`*/ $n)`* * ($v);=base^?`? ` $n/$n`?)`* + $z
The base of the polynomial is captured as base
.
A fraction with rational denominator: disallow square roots or noninteger powers in the denominator:
`+ ? / (`!m_anywhere(sqrt(?) ` ?^(`! `+integer:$n)))
A sum of fractions, where no denominator is numerically equivalent to 1 and no numerator is numerically equivalent to 0:
m_nogather(m_gather(`+ (?;tops/?;bottoms));fractions`* + $z)
`where
len(fractions)>1
and all(map(not numerical_compare(x,expression("1")),x,bottoms))
and all(map(not numerical_compare(x,expression("0")),x,tops))
This pattern could be used to establish that a student has decomposed an expression into partial fractions.
Javascript APIs¶
Numbas provides a JavaScript API through the Numbas
object.
It’s documented online at numbas.github.io/Numbas
Extensions¶
An extension is a folder containing one or more files that should be included in an exam. They can be javascript files, CSS stylesheets, or any other kind of resource.
Each extension must have a unique short name, which is used both in the Numbas editor and by the scriptloader in compiled exams.
The minimum an extension must contain is a file named <extensionname>.js
, containing the following:
Numbas.addExtension('<extensionname>',['base'],function(extension) {
});
(See the API documentation for Numbas.addExtension for details on how this function works)
This function call tells Numbas that the extension has loaded.
Because Numbas can’t guarantee the order script files will be loaded in, code which uses the Numbas object must be placed inside the callback function given to Numbas.addExtension
.
Using an extension with the editor¶
Package your extension’s files into a .zip file. Next, go to the Numbas editor click on the Profile link, then Extensions. The Upload a new extension link takes you to a form where you can upload the .zip file you created.
 Name:
 A humanreadable name for the extension. This should concisely describe what it does, or what feature it provides.
 Short name:
A unique identifier for the extension.
Warning
An extension’s short name must be unique, and match the short name used when uploading it to the editor. This means that if you reuse an extension and use a different name when uploading it to the editor, you must rename its JavaScript file and change the name given to
Numbas.addExtension
. Documentation URL:
 The URL of a page describing how to use the extension.
Adding JME functions¶
An extension can add JME functions (or rulesets, or anything else that goes in a Scope object by manipulating the extension.scope
object.
Here’s an example which adds a single JME function:
Numbas.addExtension('difference',['jme'],function(extension) {
var funcObj = Numbas.jme.funcObj;
var TNum = Numbas.jme.types.TNum;
extension.scope.addFunction(new funcObj('difference',[TNum,TNum],TNum,function(a,b){ return Math.abs(ab); }, {unwrapValues:true}));
})
(Download this extension: difference.zip
)
Adding a new JME data type¶
JME data types are JavaScript objects, distinguished by their type
property.
The object should have a value property which contains the data it represents.
The JME system can happily use new data types, but you’ll need to tell it how to render them as LaTeX or JME code.
This is done by adding methods to Numbas.jme.display.typeToTeX
and Numbas.jme.display.typeToJME
.
Once you’ve defined how to create and display the new data type, you can add functions dealing with it in the same way as for the builtin data types.
Here’s an example extension which defines a toy “chemical” data type (excuse the bad chemistry):
Numbas.addExtension('chemicals',['jme','jmedisplay'],function(chemicals) {
var chemicalsScope = chemicals.scope;
// Define the constructor for a new data type representing a chemical formula
// `formula` is a dictionary mapping element symbols to the number of atoms present
function TChemical(formula) {
this.value = formula;
}
TChemical.prototype.type = 'chemical';
// define a couple of example formulas
chemicalsScope.variables.oxygen = new TChemical({O:2});
chemicalsScope.variables.water = new TChemical({H:2, O:1});
// Code to render a chemical formula as LaTeX
Numbas.jme.display.typeToTeX.chemical = function(thing,tok,texArgs,settings) {
var out = '';
for(var element in tok.value){
out += element;
var num = tok.value[element];
if(num>1) {
out += '_{'+num+'}';
}
}
return '\\mathrm{'+out+'}';
}
// Code to render a chemical formula as a JME expression
Numbas.jme.display.typeToJME.chemical = function(tree,tok,bits,settings) {
var out = '';
for(var element in tok.value) {
if(out.length) {
out += '+';
}
out += 'molecule("'+element+'",'+tok.value[element]+')'
}
return out;
}
var funcObj = Numbas.jme.funcObj;
var TString = Numbas.jme.types.TString;
var TNum = Numbas.jme.types.TNum;
// define addition on chemicals: add up the elements in each formula
chemicalsScope.addFunction(new funcObj('+',[TChemical,TChemical],TChemical,function(c1,c2) {
var nformula = {};
var element;
for(element in c1) {
nformula[element] = c1[element];
}
for(element in c2) {
if(element in nformula) {
nformula[element] += c2[element];
} else {
nformula[element] = c2[element];
}
}
return nformula;
}));
// define a function to create a molecule with given number of atoms of given element
chemicalsScope.addFunction(new funcObj('molecule',[TString,TNum],TChemical,function(element,numatoms) {
var formula = {};
formula[element] = numatoms;
return formula;
}));
// define a JME functions which tells you how many of the given element are in a formula
chemicalsScope.addFunction(new funcObj('numatoms',[TChemical,Numbas.jme.types.TString],Numbas.jme.types.TNum,function(chemical,element) {
if(element in chemical) {
return chemical[element];
} else {
return 0;
}
}));
});
(Download this extension: chemicals.zip
)
Firstparty extensions¶
JSXGraph¶
The JSXGraph extension provides a function Numbas.extensions.jsxgraph.makeBoard
which creates a JSXGraph board and wraps it inside an HTML div element to embed in the page.
The simplest use is to define a custom function in Javascript which returns an HTML value, like so:
// First, make the JSXGraph board.
// The function provided by the JSXGraph extension wraps the board up in
// a div tag so that it's easier to embed in the page.
var div = Numbas.extensions.jsxgraph.makeBoard('400px','400px',
{boundingBox: [13,16,13,16],
axis: false,
showNavigation: false,
grid: true
});
// div.board is the object created by JSXGraph, which you use to
// manipulate elements
var board = div.board;
// Then do whatever you want with the board....
// and return the container div
return div;
The question Using student input in a JSXGraph diagram is a more complete example of creating a JSXGraph diagram based on question variables and student input.
For help on using JSXGraph, see the official documentation.
GeoGebra¶
The GeoGebra extension provides a couple of functions to load a GeoGebra material from geogebra.org and embed it in a question.
For more information on how to use the extension, see its documentation.
The screencast below shows how to use GeoGebra in a question.
Statistical functions¶
The statistical functions extension provides many new functions for generating samples from random distributions, and calculating statistics.
It is built on the jStat library and follows its API quite closely.
Here’s a list of the supported functions, as of January 2013. For information on usage, please see the jStat documentation.
sum
sumsqrd
sumsqerr
product
min
max
mean
meansqerr
geomean
median
cumsum
diff
mode
range
variance
stdev
meandev
meddev
coeffvar
quartiles
covariance
corrcoeff
betapdf
betacdf
betainv
betamean
betamedian
betamode
betasample
betavariance
centralfpdf
centralfcdf
centralfinv
centralfmean
centralfmode
centralfsample
centralfvariance
cauchypdf
cauchycdf
cauchyinv
cauchymedian
cauchymode
cauchysample
chisquarepdf
chisquarecdf
chisquareinv
chisquaremean
chisquaremedian
chisquaremode
chisquaresample
chisquarevariance
exponentialpdf
exponentialcdf
exponentialinv
exponentialmean
exponentialmedian
exponentialmode
exponentialsample
exponentialvariance
gammapdf
gammacdf
gammainv
gammamean
gammamode
gammasample
gammavariance
invgammapdf
invgammacdf
invgammainv
invgammamean
invgammamode
invgammasample
invgammavariance
kumaraswamypdf
kumaraswamycdf
kumaraswamymean
kumaraswamymedian
kumaraswamymode
kumaraswamyvariance
lognormalpdf
lognormalcdf
lognormalinv
lognormalmean
lognormalmedian
lognormalmode
lognormalsample
lognormalvariance
normalpdf
normalcdf
normalinv
normalmean
normalmedian
normalmode
normalsample
normalvariance
paretopdf
paretocdf
paretomean
paretomedian
paretomode
paretovariance
studenttpdf
studenttcdf
studenttinv
studenttmean
studenttmedian
studenttmode
studenttsample
studenttvariance
weibullpdf
weibullcdf
weibullinv
weibullmean
weibullmedian
weibullmode
weibullsample
weibullvariance
uniformpdf
uniformcdf
uniformmean
uniformmedian
uniformmode
uniformsample
uniformvariance
binomialpdf
binomialcdf
geometricpdf
geometriccdf
geometricmean
geometricmedian
geometricmode
geometricsample
geometricvariance
negbinpdf
negbincdf
hypgeompdf
hypgeomcdf
poissonpdf
poissoncdf
poissonmean
poissonsample
poissonvariance
triangularpdf
triangularcdf
triangularmean
triangularmedian
triangularmode
triangularsample
triangularvariance
zscore
ztest
tscore
ttest
anovafscore
anovaftest
ftest
normalci
tci
betafn
betaln
betacf
ibetainv
ibeta
gammaln
gammafn
gammap
factorialln
factorial
combination
permutation
gammapinv
erf
erfc
erfcinv
randn
randg
Random person¶
The “random person” extension provides a collection of functions to generate random people, for use in word problems.
It doesn’t really matter what people are called in word problems, but it can have a bad effect on students’ perceptions of the world if the plumber’s always called Gary and the nurse is always called Julie. This extension makes it easy to randomly pick names, following the distribution of names and genders in the population of England and Wales.
For more information on how to use the extension, see its documentation.
Themes¶
A Numbas theme is a package of files containing everything needed to display an exam in the browser. This includes an HTML file, CSS stylesheets, and JavaScript to manage coordination between the page and the exam runtime.
Contents of a theme¶
A theme is a folder containing the following three things:
 An optional file called
inherit.txt
containing the name of a theme to extend.  A folder called
files
containing static files to be included in the compiled exam. For a theme which does not extend another, this contains at the minimum a JavaScript filescripts/display.js
.  A folder called
templates
containing, at the least, two files calledindex.html
andquestion.xslt
. These files are jinja2 templates which will produce the HTML for the exam and the XSLT stylesheet for questions, respectively.
Oldstyle themes¶
Before Numbas 2.1, the files index.html
and question.xslt
were static, with index.html
residing in the files
folder, and question.xslt
residing in a folder called xslt
.
For backwards compatibility, if either of these files are found in those paths, they’re used instead of any template files.
This way, if an oldstyle theme extends the default
theme and overrides index.html
, it will still work.
JavaScript and CSS files¶
All JavaScript and CSS files used by a Numbas exam are collected into two files, scripts.js
and styles.css
.
These are the only files you need to load from your theme’s index.html
 all script and stylesheet files, including those provided by your theme, are collected into these.
HTML and XSLT templates¶
The files index.html
and question.xslt
are produced using jinja2.
The main reason for this is to allow authors to override sections of the layout, while inheriting the rest from the base theme.
While jinja2 is a very powerful templating language, it’s used in the default theme solely as a way of including subtemplates with the {% include "filename.html" %}
tag.
However, if you wish to do something more sophisticated, the variables exam
and options
are available in the template context.
See the Numbas compiler source code to find out what properties these objects have.
Building off an existing theme¶
At the top of your theme folder, place a file called inherit.txt
containing the name of the theme to extend, e.g. default
.
When an exam is compiled using your theme, all of the parent theme’s files will be included, and then all of the files belonging to your theme, overriding any files of the same name from the parent theme.
For example, to change the logo displayed in the navigation bar, you could create a theme containing only inherit.txt
and templates/logo.html
.
The default theme is packaged with the Numbas compiler; if you want to modify it you should first download the Numbas repository from https://github.com/numbas/Numbas and copy the folder themes/default
.
It’s a good idea to remove from your theme package any files that you don’t change from the default, so that bugfixes in the base theme will be carried through to your version.
Uploading a theme to the editor¶
Package your theme’s files into a .zip file. Next, go to the Numbas editor and click on the Profile link, then Themes. The Upload a new theme takes you to a form where you can upload the .zip file you created, and give it a humanreadable name. You will be able to select any of your themes in the exam edit page.
If you make changes to your theme, go back to the Themes page and click on the Edit link, then upload a revised .zip file.
Examples¶
 Replace the Numbas logo:
changelogotheme.zip
 Add custom CSS rules:
extracsstheme.zip
Custom part types¶
Custom part types allow you to reuse marking algorithms you’ve written, while providing fields for the part’s settings, like the builtin parts.
Creating a new part type¶
To create a new custom part type, click on your user icon at the top of the page, and then Profile. Once on your profile, click Part types, and then Create a new part type.
The first step is to pick a name for your part type. It should concisely describe what the part type is for, ideally by describing how the student should answer it or how it is marked. For example, “Give a root of a function” is a good name for a part type where the student has to provide a value which is mapped to zero by a function defined by the question author.
You can change the name of your part type later on if you need to.
The editing interface for custom part types is arranged similarly to the question and exam editors: the sections are separated into tabs, and you should work through them all in order to define how the part type works.
Description¶
 Name
 The name of the part type as it appears in the question editor. It should concisely describe what the part type is for, ideally by describing how the student should answer it or how it is marked. For example, “Give a root of a function” is a good name for a part type where the student has to provide a value which is mapped to zero by a function defined by the question author.
 Description
 Use this field to describe how this part type works, and what kinds of questions it is appropriate for. This text will appear in the list of part types on your profile, and in the public list if you make your part type public, to help question authors decide if the part type is right for their use.
 URL of documentation
 Use this field to provide a link to any more documentation about your custom part type. You might link to a blog post explaining what the part type is for, or a page giving more information on the theory behind the part type.
Required extensions¶
If your part type requires functions from a Numbas extension, select it here. Any questions using this part type will automatically load the required extensions.
Part settings¶
Define setting fields to allow question authors to configure your part type. They appear in the question editor’s Marking settings tab for any parts of this type.
Each setting produces a JME value which can be used to set up the part type’s answer input and in the marking algorithm.
There is a dictionary variable called settings
with keys for each setting.
For example, a setting with name correct_answer
will be available as settings["correct_answer"]
.
The following fields are common to all setting types:
 Name
 A short name for this setting, used to refer to it in the part type’s answer input or marking algorithm. The name should uniquely identify the setting, but doesn’t need to be very descriptive  the label can do that.
 Label
 The label shown next to the setting in the question editor. Try to make it as clear as possible what the setting is for. For example, a checkbox which dictates whether an input hint is shown should be labelled something like “Hide the input hint?” rather than “Input hint visibility”  the latter doesn’t tell the question author whether ticking the checkbox will result in the input hint appearing or not.
 Help URL
 The address of documentation explaining this setting in further depth. This is optional.
 Use this field to give further guidance to question authors about this setting, if the label is not enough. For example, you might use this to say what data type a JME code setting should evaluate to.
 Default value
 The initial value of the setting in the question editor. If the setting has a sensible default value, set it here. If the value of the setting is likely to be different for each instance of this part type, leave this blank. (Not present for Dropdown box or Choose one or more
Setting types¶
String¶
A string of text. If Substitute values into text is ticked, then JME expressions enclosed in curly braces will be evaluated and the results substituted back into the text when the question is run. Otherwise, the string will be untouched.
Mathematical expression¶
A mathematical expression, in JME syntax. If Substitute variables into value? is ticked, then JME expressions enclosed in curly braces will be evaluated and the results substituted back into the string.
This setting type produces a value of type expression
.
Checkbox¶
If the question author ticks the checkbox, this setting type produces true
, otherwise it produces false
.
Dropdown box¶
The question author must pick one option from a list that you provide. The Label field is shown to the question author, and the setting produces the Value field as a string.
Choose one or more¶
The choices are presented to the question author as a list, with a checkbox next to each label. This setting type produces a list containing the Value fields of ticked choices, as strings.
If Default on? is ticked for a particular choice, that choice is selected when a new part of this type is created.
JME code¶
A code editing area for the question author to write a JME expression.
If Evaluate? is ticked, the expression will be evaluated when the question is run, and the setting produces the resulting value. The evaluation happens inside the question’s scope, so any variables and functions defined by the question author are substituted in before evaluation.
If Evaluate? is not ticked, this setting will produce a expression
value representing the question author’s expression.
Percentage¶
A sliding scale between 0% and 100%.
This setting type produces a number between 0 and 1.
HTML content¶
An HTML content area.
If Substitute variables into value? is ticked, then JME expressions enclosed in curly braces will be evaluated and the results substituted back into the text.
List of strings¶
This setting type produces a list of strings entered by the question author.
If Substitute variables into value? is ticked, then JME expressions enclosed in curly braces in each string will be evaluated and the results substituted back in.
Answer input¶
The answer input method determines how the student enters their answer to the part.
The following fields are common to all input methods:
 Expected answer
A JME expression which evaluates to the expected answer to the part.
Available in the marking algorithm as
input_options["correctAnswer"]
. Input hint
A string displayed next to the input field, giving any necessary information about how to enter their answer.
If there are any requirements the student’s answer must meet that aren’t obvious from the way the input is displayed, for example a maximum length or required number of decimal places, these should be described here.
Available in the marking algorithm as
input_options["hint"]
.
Many of the fields can be either static or dynamic.
A static field takes the same value in every instance of the part type.
A dynamic field is defined by a JME expression which is evaluated when the question is run.
You can use the part’s settings in these expressions with the settings
variable.
The values of input_options are available in the marking script under the input_options
dictionary.
In the tables below, the Name column gives the key in the dictionary corresponding to the option.
Answer input methods¶
String¶
The student enters a single line of text.
Label  Name  Data type  Description 

Allow student to submit an empty string?  allowEmpty 
boolean 
If false , the part will only be marked if their answer is nonempty. 
The answer is a string
.
Number¶
The student enters a number, using any of the allowed notation styles. If the student’s answer is not a valid number, they are shown a warning and can not submit the part.
Label  Name  Data type  Description 

Allow fractions?  allowFractions 
boolean 
Allow the student to enter their answer as a fraction? 
Allowed notation styles  allowedNotationStyles 
list of string 
The allowed styles of number notation. 
The answer is a number
, as interpreted by parsenumber()
.
If the student’s answer is not a valid representation of a number, the part will not be submitted.
If you wish to allow number notation styles other than those builtin, a string input is more appropriate, so you can parse the student’s answer yourself in the marking script.
Mathematical expression¶
The student enters a JME expression.
Label  Name  Data type  Description 

Show preview of student’s answer?  showPreview 
boolean 
If true , a LaTeX rendering of the student’s answer will be shown next to the input box. 
The answer is an expression
value corresponding to the student’s input.
If the student’s answer is not a valid expression, the part will not be marked.
Matrix¶
The student enters a twodimensional array of values.
Label  Name  Data type  Description 

Allow student to change size of matrix?  allowResize 
boolean 
If true , the student can change the size of the matrix. Otherwise, it is fixed to the specified size. 
Number of rows  numRows 
number 
The initial number of rows in the input matrix. 
Number of columns  numColumns 
number 
The initial number of rows in the input matrix. 
Parse cell values  parseCells 
boolean 
If true , the answer will be a matrix of numbers. Otherwise, it is a 2dimensional list of lists of string values. 
Allowed notation styles  allowedNotationStyles 
list of string 
The allowed styles of number notation. 
Allow fractions?  allowFractions 
boolean 
Allow the student to enter numbers as fractions? 
If parseCells
is true
, the answer is a matrix
value corresponding to the student’s input.
The part will not be marked unless all of the cells in the student’s matrix are valid numbers.
If parseCells
is false
, the answer is a list
of lists of string
values.
Radio buttons¶
The student chooses one from a list of choices by selecting a radio button.
Label  Name  Data type  Description 

Choices  choices 
list of string 
The labels for the choices to offer to the student. 
The answer is the index of the student’s choice in the list. The first item in the list is index 0.
The part will not be marked unless the student selects one of the choices.
Choose several from a list¶
The student chooses any number of items from a list of choices by ticking checkboxes.
Label  Name  Data type  Description 

Choices  choices 
list of string 
The labels for the choices to offer to the student. 
The answer is a list
of booleans
describing whether the student ticked the corresponding choice.
Dropdown box¶
The student chooses one from a list of choices in a dropdown box.
Label  Name  Data type  Description 

Choices  choices 
list of string 
The labels for the choices to offer to the student. 
The answer is the index of the student’s choice in the list. The first item in the list is index 0.
The part will not be marked unless the student selects one of the choices.
Marking¶
The Marking tab is where you construct the marking algorithm for your part type.
The interface is similar to that for question variables  a list of defined notes is shown on the righthand side, and the currently selected note is shown on the left.
The two required notes, mark
and interpreted_answer
, can not be deleted.
 Name
 The name of the note. This must be a valid JME variable name.
 Definition
A JME expression used to evaluate the note.
See the list of variables available in a marking script, in particular
studentAnswer
,settings
andinput_options
. Description
Describe what the note means, and how it is used.
You should try to describe the value the note produces, as well as any feedback.
Note
Don’t underestimate the value of the description field! Notes whose meaning seems clear when you write them have a habit of becoming indecipherable months later.
 Depends on
 A list of all notes used in this note’s definition. You can click on a note’s name to go to its definition. If the note hasn’t been defined yet, it’ll be created.
 Used by
 A list of all notes which use this note in their definition. You can click on a note name to go to its definition.
Making sure that the marking algorithm works¶
You must make sure that your part type will mark all possible answers that a student can enter.
Decide how you want to handle different kinds of “invalid” input  do you want to strip space characters from the student’s answer, for example?
Use the fail()
function to stop the marking algorithm and force the student to change their answer before resubmitting, if the student’s answer is of a form .
However, it’s important not to reject plausible answers that are simply incorrect  you should make every effort to accept answers that follow the input hints you’ve given.
There’s no facility to test the marking algorithm inside the custom part type editor  for this, you need to create an instance of the part type inside a question so you can configure its settings.
When a student attempts a question using a custom part type, if any errors are encountered while evaluating your part type’s marking algorithm, the student will be shown a generic error asking them to report the problem. In order to see what the problem is, you’ll have to reproduce the student’s input in the question editor’s marking algorithm tab. A more descriptive error message, detailing the note affected and the exact nature of the error, will be shown.
Access¶
Your custom part types are available only to you, and other members of projects you belong to. If you’ve created a part type that could be useful to others, please consider publishing it.
Before a custom part type can be published, the following conditions must be met:
 The part type must have a name and a description.
 There must be at least one setting, and all settings must be complete.
 The expected answer and input hint must be set.
 The
mark
andinterpreted_answer
notes must be defined.
To publish a part type, click the Publish button in the Access tab.
You can unpublish a part type by clicking the Unpublish button. It will no longer be available to other users when creating new parts, but any instances of the part in existing questions will remain in place.
Installing an editor server¶
If you just want to create your own Numbas content, the editor hosted by mathcentre is free to use and doesn’t need any setup.
These instructions are only needed if you want to set up your own private editing server.
Installing a local instance for personal use¶
Follow these instructions to set up an instance of the editor that only one person will use.
Running a personal instance of the editor on Windows¶
These are outline instructions on setting up the Numbas editor on a PC running Windows, for personal use. For instances where multiple users need access to the editor, we recommend following the Ubuntu installation instructions.
The Numbas editor uses Django, a web framework written in the Python programming language. Django has many configuration options, which we won’t detail here. For more information, consult the Django documentation.
Installation¶
Install Python 3 from python.org/download.
Warning
If you already have two versions of Python installed on your PC, the command
python
might run the wrong version. The easiest way of making sure you use the right one is to create a virtual environment. Here’s how to do that:pip3 install virtualenv virtualenv p python3 numbas_venv numbas_venv\Scripts\activate
You’ll need to activate the virtual environment each time you want to use it.
You can either download static copies of the Numbas software, or get a versiontracked copy which is easier to update through git. If you’re using git, you’ll need to install Git for Windows first.
Either download the Numbas runtime tools from GitHub and extract to a folder called
numbas_runtime
, or use git to clone the repository:git clone git://github.com/numbas/Numbas.git numbas_runtime
Either download the Numbas editor from GitHub and extract to a folder called
numbas_editor
, or use git to clone the repository:git clone git://github.com/numbas/editor.git numbas_editor
Install all the required Python modules:
pip3 install r numbas_editor/requirements.txt pip3 install r numbas_runtime/requirements.txt
Configuration¶
Run the “first setup” script:
cd numbas_editor python first_setup.py
This will configure the editor based on your answers to a few questions, and write the file
numbas/settings.py
.The default answers for most of the questions apply only to Linux systems; make the appropriate changes using the paths described in the earlier steps.
If you’ve followed these instructions exactly, you should use the following values:
Path of the Numbas compiler ../numbas_runtime
Which database engine are you using? sqlite3
Where are static files stored? static/
Where are uploaded files stored? media/
Where are preview exams stored? static/previews/
Base URL of previews /static/previews/
Python command python
If you make any mistakes, you can run the script again, or edit
numbas/settings.py
directly.Start the server:
python manage.py runserver
Open http://localhost:8000 in your web browser.
Ongoing maintenance¶
If you used git to clone the runtime and editor repositories, run the following commands to update your installation:
cd numbas_editor
git pull origin master
python manage.py migrate
pip install r requirements.txt
cd ../numbas_runtime
git pull origin master
pip install r requirements.txt
The admin site, where you can manually edit entries in the database, is at http://localhost:8000/admin.
Running a personal instance of the editor on a Mac¶
These are outline instructions on setting up the Numbas editor on a Mac, for personal use. For instances where multiple users need access to the editor, we recommend following the Ubuntu installation instructions.
The Numbas editor uses Django, a web framework written in the Python programming language. Django has many configuration options, which we won’t detail here. For more information, consult the Django documentation.
Installation¶
Install Python 3 from python.org/download.
Warning
If you already have two versions of Python installed on your PC, the command
python
might run the wrong version. The easiest way of making sure you use the right one is to create a virtual environment. Here’s how to do that:pip3 install virtualenv virtualenv p python3 numbas_venv source numbas_venv/bin/activate
You’ll need to activate the virtual environment each time you want to use it.
Either download the Numbas runtime tools from GitHub and extract to a folder called
numbas_runtime
, or use git to clone the repository:git clone git://github.com/numbas/Numbas.git numbas_runtime
Either download the Numbas editor from GitHub and extract to a folder called
numbas_editor
, or use git to clone the repository:git clone git://github.com/numbas/editor.git numbas_editor
Install all the required Python modules:
pip3 install r numbas_editor/requirements.txt pip3 install r numbas_runtime/requirements.txt
Configuration¶
Run the “first setup script”:
cd numbas_editor python first_setup.py
This will configure the editor based on your answers to a few questions, and write the file
numbas/settings.py
.The default answers for most of the questions apply only to Linux systems; make the appropriate changes using the paths described in the earlier steps.
If you’ve followed these instructions exactly, you should use the following values:
Path of the Numbas compiler ../numbas_runtime
Which database engine are you using? sqlite3
Where are static files stored? static/
Where are uploaded files stored? media/
Where are preview exams stored? static/previews/
Base URL of previews /static/previews/
If you make any mistakes, you can run the script again, or edit
numbas/settings.py
directly.Start the server:
python manage.py runserver
Open http://localhost:8000 in your web browser.
Ongoing maintenance¶
If you used git to clone the runtime and editor repositories, run the following commands to update your installation:
cd numbas_editor
git pull origin master
python manage.py migrate
pip install r requirements.txt
cd ../numbas_runtime
git pull origin master
pip install r requirements.txt
The admin site, where you can manually edit entries in the database, is at http://localhost:8000/admin.
Running a personal instance of the editor on Ubuntu¶
These are outline instructions on setting up the Numbas editor on a machine running Ubuntu 16.04+, for personal use. For instances where multiple users need access to the editor, we recommend following the Ubuntu web server installation instructions.
The Numbas editor uses Django, a web framework written in the Python programming language. Django has many configuration options, which we won’t detail here. For more information, consult the Django documentation.
Installation¶
Install Git and Python 3 using the packaging system:
apt install git python3
Warning
If you already have two versions of Python installed on your PC, the command
python
might run the wrong version. The easiest way of making sure you use the right one is to create a virtual environment. Here’s how to do that:pip3 install virtualenv virtualenv p python3 numbas_venv source numbas_venv/bin/activate
You’ll need to activate the virtual environment each time you want to use it.
Either download the Numbas runtime tools from GitHub and extract to a folder called
numbas_runtime
, or use git to clone the repository:git clone git://github.com/numbas/Numbas.git numbas_runtime
Either download the Numbas editor from GitHub and extract to a folder called
numbas_editor
, or use git to clone the repository:git clone git://github.com/numbas/editor.git numbas_editor
Install all the required Python modules:
pip3 install r numbas_editor/requirements.txt pip3 install r numbas_runtime/requirements.txt
Configuration¶
Run the “first setup” script:
cd numbas_editor python first_setup.py
This will configure the editor based on your answers to a few questions, and write the file
numbas/settings.py
.The default answers for most of the questions apply only to multiuser instances; make the appropriate changes using the paths described in the earlier steps.
If you’ve followed these instructions exactly, you should use the following values:
Path of the Numbas compiler ../numbas_runtime
Which database engine are you using? sqlite3
Where are static files stored? static/
Where are uploaded files stored? media/
Where are preview exams stored? editor/static/previews/
Base URL of previews /static/previews/
If you make any mistakes, you can run the script again, or edit
numbas/settings.py
directly.Start the server:
python manage.py runserver
Open http://localhost:8000 in your web browser.
Ongoing maintenance¶
If you used git to clone the runtime and editor repositories, run the following commands to update your installation:
cd numbas_editor
git pull origin master
python manage.py migrate
pip install r requirements.txt
cd ../numbas_runtime
git pull origin master
pip install r requirements.txt
The admin site, where you can manually edit entries in the database, is at http://localhost:8000/admin.
Installing on a web server¶
Follow these instructions to set up an instance of the editor available to more than one person, over the web.
Installing the Numbas editor on Ubuntu¶
These are outline instructions on setting up the Numbas editor with a backend MySQL database.
The Numbas editor uses Django, a web framework written in the Python programming language. Django has many configuration options, which we won’t detail here. For more information, consult the Django documentation.
Note
The following instructions are for a server running Ubuntu Xenial (16.04) or newer.
Essential package installation¶
Packages that would be installed as part of a standard Ubuntu install are not listed.
Install Apache, Git, Apache WSGI module, MySQL and Python 3 using the
apt
packaging system:aptget install apache2 apache2dev gitcore mysqlserver \ mysqlcommon python3 acl libmysqlclientdev pythondev \ libapache2modwsgipy3 pythontk tcldev tkdev
Enable
mod_wsgi
, if it’s not already:a2enmod wsgi
Virtualenv¶
Rather than rely on the systemwide Python executable and libraries, a more flexible approach is to use virtualenv, which is a tool to create an isolated Python environment.
Create a user group which will have access to the virtualenv, and add yourself to it:
groupadd numbas usermod your_username a G numbas,wwwdata
You might need to start a new terminal, or log out and back in, for the group change to take effect.
Install Pip:
aptget install python3pip
Install virtualenv:
pip3 install virtualenv
Create the virtualenv in a suitable location:
mkdir /opt/python setfacl dR m g:numbas:rwx /opt/python virtualenv /opt/python/numbaseditor
Activate the virtualenv:
source /opt/python/numbaseditor/bin/activate
(This ensures that subsequent python packages are installed in this isolated environment, and not in the system environment.)
Database¶
Open the MySQL client:
mysql
Create a MySQL database called
numbas_editor
:create database numbas_editor;
Create a database user and grant privileges on
numbas_editor
database, with a password of your choice:grant all privileges on numbas_editor.* to 'numbas_editor'@'localhost' identified by 'password';
Create directories and set permissions¶
Create the following directories outside the web root, so they’re not accessible to the public:
mkdir /srv/numbas mkdir /srv/numbas/compiler mkdir /srv/numbas/media mkdir /srv/numbas/previews mkdir /srv/numbas/static
Set the correct ownership and permissions:
cd /srv/numbas chmod 2770 media previews chmod 2750 compiler static chgrp wwwdata compiler media previews static setfacl dR m g::rwX media previews setfacl dR m g::rX compiler static
Clone the editor and compiler repositories¶
Clone the Numbas repository:
git clone git://github.com/numbas/Numbas /srv/numbas/compiler
Clone the editor under the webroot directory:
git clone git://github.com/numbas/editor /srv/www/numbas_editor
Install the Python module dependencies of the editor (in the virtualenv):
pip install r /srv/www/numbas_editor/requirements.txt pip install r /srv/numbas/compiler/requirements.txt pip install mysqlclient mod_wsgi
Configuration¶
Run the “first setup” script:
python first_setup.py
This will configure the editor based on your answers to a few questions, and write the file
numbas/settings.py
.If you’ve been following these instructions exactly, you can accept the defaults for each question.
If you make any mistakes, you can run the script again, or edit
numbas/settings.py
directly.Create the apache config file and enable the site.
Edit
/etc/apache2/sitesavailable/numbas_editor.conf
with contents similar to that inthis prepared config file
. If following these instructions exactly, then you only need to change the lines containingServerName
andServerAdmin
.Enable the configuration:
a2ensite numbas_editor.conf service apache2 reload
Point a web browser at the server hosting the editor.
Ongoing maintenance¶
To keep the editor up to date, run the following script:
source /opt/python/numbaseditor/bin/activate
cd /srv/numbas/compiler
git pull origin master
pip install r requirements.txt
cd /srv/www/numbas_editor
git pull origin master
python manage.py migrate
python manage.py collectstatic noinput
pip install r requirements.txt
touch web/django.wsgi
Note that if any changes are made to the editor code, including
editing the settings files, then for the web server to recognise
these changes you must either run the command touch web/django.wsgi
,
or restart the Apache server.
Upgrading¶
Upgrading to Numbas 2.0¶
Upgrading to Numbas 2.0 from an earlier version is a straightforward process, but can take a long time and disk space if you have a very large database.
Follow the instructions below, using a shell in your numbas_editor
directory.
Remove
editor/templates/index.html
 Numbas 2.0 looks for your custom welcome message ineditor/templates/index_message.html
.Get the latest code:
git pull
Upgrade Python libraries:
pip install upgrade r numbas/requirements.pip``
Migrate the database (this could take a while):
python manage.py migrate
Copy
editor/templates/index_message.html.dist
toeditor/templates/index_message.html
, and customise to your liking.
That’s it!
If you have any problems, email numbas@ncl.ac.uk.
Upgrading from Numbas 2.0 to 3.0¶
Follow the instructions below, using a shell in your numbas_editor
directory.
Get the latest code:
git pull
Upgrade Python libraries:
pip install upgrade r requirements.txt
Run the new setup script. It will use your existing settings and perform the rest of the upgrade jobs.
python first_setup.py
The editor now has “terms of use” and “privacy policy” pages. You must edit those:
editor/templates/terms_of_use_content.html
andeditor/templates/privacy_policy_content.html
.Finally, get the latest code in your Numbas
compiler
directory:cd ../compiler git pull
That’s it!
If you have any problems, email numbas@ncl.ac.uk.
Upgrading from Numbas 3.0 to 4.0¶
Follow the instructions below, using a terminal in your numbas_editor
directory.
Get the latest code:
git pull
Upgrade Python libraries:
pip install upgrade r requirements.txt
Run the setup script. It will use your existing settings and perform the rest of the upgrade jobs.
python first_setup.py
Edit the file numbas/settings.py and add the following line:
LOGOUT_REDIRECT_URL = '/'
Finally, get the latest code in your Numbas
compiler
directory:cd ../compiler git pull
That’s it!
If you have any problems, email numbas@ncl.ac.uk.