Maths with QTI – QTI XML Structure and Building Blocks Resource

We have recently started using QTI, specifically Uniqurate and QTIWorks, to write maths questions for delivery to students. Uniqurate can be used to write basic questions, including maths questions with numerical answers and simple randomisation of values. However, to incorporate more complex randomisation, e.g. randomising variable letters, to allow mathematical expressions to be given as answers and to do various other more complex things with maths questions, it is necessary to write (or, preferably, modify someone else’s!) QTI XML. This can get quite complicated and I have found some aspects of it difficult to get stuck into. I find that I know that something is possible, but it can take some time to pin down exactly how to do it, and I usually copy code from other questions. (Many thanks to Dr Sue Milne from ELandWeb for providing extensive help, both by giving access to her questions and answering many QTI-related queries)

One thing that I keep wishing for is a resource containing reusable blocks of QTI code that could be used to build a question. I believe that such a resource does not currently exist, so I have decided to start to write one, the links to which can be found below.

At this point I should make the disclaimer that I am still early on in my QTI journey, so I am no expert, and can by no means guarantee that this resource will be correct, but I will try to improve and extend it as I get to know the QTI specification better. The posts based on the XML snippets that I have been using, and therefore they are far from being a complete resourse. However, I hope they are useful to anyone getting started with QTI. Please feel free to suggest additions and corrections.

  1. QTI XML Basic Structure
  2. Variable Declarations
  3. Template Processing
  4. Item Body
  5. Response Processing
  6. Solution and Hint
  7. Modifying assessment.xml (for Assessments created in Uniqurate)

Maths with QTI – QTI XML Basic Structure

Please note that this is a work in progress!

This is the first of my QTI XML Building Blocks posts, where I will give the basic structure of an assessment item in a QTI XML file, that can be used as a framework that can be filled in with the building blocks that I will cover in future posts. This is very much a work in progress and I can’t promise everything is correct. At this stage I am just trying to create something that is useful to me, and putting it out there in case it is useful to anyone else!

So, here is the basic structure of a QTI XML document (or the basic structure I’ve been using/copying for writing questions):

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

<!-- Define question properties -->
<!-- Some of these are obvious, others are XML namespace definitions - not all of these are generally needed 
   adaptive - if set to false, only one attempt is allowed, so this is best for summative items. If set to true, multiple attempts are allowed and the feedback/outcomes can be changed, and this is better for formative items, where a user can have multiple goes. This should not be confused with an adaptive test, where the questions presented change depending on a user's answers to previous questions, although a similar thing can be achieved within an adaptive item.
-->
<assessmentItem xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1"
   xmlns:m="http://www.w3.org/1998/Math/MathML"
   xmlns:xi="http://www.w3.org/2001/XInclude"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:ma="http://mathassess.qtitools.org/xsd/mathassess"
   xsi:schemaLocation="http://www.imsglobal.org/xsd/imsqti_v2p1 imsqti_v2p1.xsd http://mathassess.qtitools.org/xsd/mathassess mathassess.xsd">
   xml:lang="en"
   adaptive="true"
   timeDependent="false"
   identifier="questionidentifier"
   title="Question Title">

   <!-- VARIABLE DECLARATIONS -->
   <!-- Here we define all of the variables that are going to be used in the question -->

   <!-- Response Declarations -->
   <!-- These are the variables used in response processing, including those for storing the response(s) given by the user -->
   <responseDeclaration identifier="RESPONSE" cardinality="single" baseType="integer"/>

   <!-- Outcome Declarations -->
   <!-- These are the variables used for returning an outcome to the user, e.g. score, feedback -->
   <outcomeDeclaration identifier="SCORE" cardinality="single" baseType="integer"/>

   <!-- Template Declarations -->
   <!-- These are the variables used for creating the question, e.g. the variables used for randomising values within a question -->
   <templateDeclaration identifier="iA" cardinality="single" baseType="integer" mathVariable="true"/>

   <!-- TEMPLATE PROCESSING -->
   <templateProcessing>
      <!-- Here template variables are assigned values, constraints are defined etc -->
   </templateProcessing>

   <!-- ITEM BODY -->
   <itemBody>
      <!-- The itemBody contains the content of the item, including the question, interactions, feedback sections (which are initially hidden) etc  -->
   </itemBody>

   <!-- RESPONSE PROCESSING -->
   <responseProcessing>
      <!-- Here the user's response is assessed, compared the correct answer etc, and outcome variable, e.g. score and which feedback to show, are set -->
   </responseProcessing>
</assessmentItem>

Maths with QTI – Help Guide for Maths Entry Questions

This is intended as a simple guide to entering mathematical expressions as answers to questions delivered using QTIWorks. Any comments about its usefulness/helpfulness would be most welcome.

Note that you can also view an input hints box by clicking on the blue question mark symbol help_questionmark next to the maths input box. You can also watch a brief video showing you how to enter mathematical answers.

This guide contains the following sections:

The Maths Input box ^ Top

When a mathematical expression is required as an answer to a question, a text box within a larger grey box is shown. When text is typed into the text box, it is interpreted mathematically, and the resulting mathematical expression is shown:

mathsinputbox_mod

If you click on the blue question mark symbol help_questionmark, an input hints box will pop up.

Basic Operators (+ – * / =) ^ Top

The basic mathematical operators can be represented by words or symbols, as shown in the table below.

Operation Symbol Word
Addition +
Subtraction
Multiplication * times
Division / divide
Equals =

note that multiplication is implied between a coefficient and a variable, e.g. 2x = 2*x, and between consecutive variables, i.e. letters, unless the letters make up a special character, e.g. pa = p*a, but pi = π, not p*i.

Other Operators (± > ≥ < ≤ ≠) ^ Top

Other operatores, e.g. comparison operators, can be represented as shown in the table below.

Operation Input Interpretation
Plus or minus +- ±
Greater than > >
Greater than or equal to >=
Less than < <
Less than or equal to <=
Not equal !=

Precedence (order of operations) ^ Top

The order of precedence, i.e. the order in which operations are performed/interpreted, follows the usual rules:

  1. brackets
  2. roots and exponentials
  3. multiplication and division
  4. addition and subtraction
Input Interpretation Notes
2+3*4 precedence_nobrackets equals 14
2+(3*4) precedence_unnecessarybrackets equals 14, brackets are unnecessary
(2+3)*4 precedence_brackets equals 20, brackets are required

Special Symbols and Functions ^ Top

Generally, letters just represent variables, and multiplication between consecutive letters is implied (see Basic Operations above). However, there are certain letters or words that have special meaning, as follows:

Letter/Word Meaning
e e, the natural exponential, 2.71828…
i the imaginary number, √-1
alpha…lambda…pi…etc Greek letters, α, λ, π etc
log logarithm function
ln natural logarithm function
sin, cos, tan trigonometric functions
cap, cup, in, not, notin, subset, subseteq, to,
vee, wedge…and probably others
Logic and Set Theory operators

Fractions (a/b) ^ Top

Use the divide symbol,  ‘/’, between the numerator (top) denominator (bottom) of a fraction. Brackets may be needed to give the correct numerator and denominator.

Input Interpretation
1/2 half
2x+1/3x+2 fraction_no_brackets
(2x+1)/(3x+2) fraction_brackets

Brackets (a(b+c)) ^ Top

Brackets can be used as they normally would when writing an expression.

Input Interpretation Notes
sin(2x+30)  brackets_sin  brackets not needed for sin of single value, e.g. sinx gives sinx
5(x+1)(2x-3)  brackets_2
3(2x-(2-y))  brackets_nested equivalent to 3(2x-2+y)

Powers (x^a) ^ Top

Use ^ (hat/caret symbol) to represent powers:

Input Interpretation Notes
x^2 powers_xsquared    
x^(1/3) powers_xtothird fractional powers need brackets
x^-1 powers_xtominus1 negative powers do not need brackets
e^(x(2x+1)) powers_expbrackets
e^x(2x+1) powers_expnobrackets

Roots (sqrt(x) or x^(a/b)) ^ Top

Only a square root can be represented with the root symbol. All other roots must be represented as fractional powers:

Root Input Interpretation
Square root (√x) sqrtx or sqrt(x) roots_sqrtx
Cube root (∛x) x^(1/3) roots_cubertx

Subscripts (x_a) ^ Top

Use _ (underscore) to give a subscript (similar to using ^ for powers/superscripts)

Input Interpretation
x_1 subscript_x_1
y_a subscript_y_a

“Sorry, I could not make sense of your input” ^ Top

You will see this message in a number of situations (including, but not limited to):

  • When you have an operator (e.g. + – * / ^ _ =), that does not have a value/variable before and/or after it, e.g. ‘1+’, ‘*3’, ‘x/’, ‘y^’
  • When you have two consecutive operators, e.g. ‘+*’
  • When you have opened a bracket and not (yet) closed it, e.g. ‘2(x+3’

If you see this message when you believe you have entered a complete expression, make sure you check your expression carefully, in particular that you have closed all brackets.

CakePHP-Mailchimp-datasource 1.3 Read Method

If anyone’s still using CakePHP v1.3 of this brilliant datasource which allows you to treat data on subscribers in MailChimp as if they were in a local model, I had to make a few changes to make it work with v1.3 of the MailChimp API.

 
function read($model, $queryData = array()) {
 $url = $this->buildUrl('listMemberInfo', $queryData['conditions']['emailaddress']);
 $response = json_decode($this->connection->get($url), true);
 if(isset($response['errors'])&&$response['errors']>0) { //this is how errors are indicated
 return false;
 }
 return $response['data']; //allows find('first') to return $response['data'][0]
 }

WordPress: Improvement to Form Manager plugin when used with Members plugin

As mentioned in my earlier post, the WordPress Form Manager and Member’s plugins integrate fantastically. However, one thing that didn’t quite perfectly was that if a user was allowed to view the submission data for forms (the ‘

This is because, by default, clicking on the name of a form takes you to the edit/design page, whether or not you are allowed to edit the form. Therefore, if you are not allowed to edit the form, it doesn’t show the page, and you see nothing except the tabs for the actions that you are allowed to access, in this case the “Submission Data” tab. To see the submission data, you then have to click on this tab to view the data. Obviously, this second click is annoying, and the blank page is ugly/confusing.

Thankfully, this issue was quite easy to fix, by replacing line 155 of wordpress-form-manager/pages/main.php with the following code:

<strong>
   <?php if(!$fm_MEMBERS_EXISTS || current_user_can('form_manager_forms') || current_user_can('form_manager_data')) { ?>
      <a class="row-title" href="<?php
      //If the user can edit forms, take them to the edit page, as usual
      if(!$fm_MEMBERS_EXISTS || current_user_can('form_manager_forms')) { 
         echo get_admin_url(null, 'admin.php')."?page=fm-edit-form&sec=design&id=".$form['ID'];
      }
      //Otherwise, if the user can view the data, take them to the data page
      else if(current_user_can('form_manager_data')) { 
         echo get_admin_url(null, 'admin.php')."?page=fm-edit-form&sec=data&id=".$form['ID'];
      }
   ?>"><?php echo $form['title'];?></a>
   <?php } 
   //If user has no form permissions, do not create a link
   else { 
      echo $form['title']; 
   }  ?>
</strong>

Basically this just means that:

  • If the Members plugin isn’t installed, the link goes to the edit/design page
  • If the user can edit forms, the link goes to the edit/design page
  • If the user can’t edit forms but can view data, the link goes to the submission data page
  • If the user can’t edit forms or view data (i.e. they can do nothing with individual forms), then the form name isn’t made into a link

I hope this is a robust improvement – it seems to work well for me, and will prevent my ‘view data only’ users from getting annoyed/confused by the form link taking them to the wrong place.

WordPress Form Manager and Members plugins integrate brilliantly

We’ve been working with the WordPress Form Manager plugin for a while, and have found it an excellent and flexible way to create forms in WordPress (thanks Campbell Hoffman). However, I was initially struggling when trying to change the way the permissions worked within the plugin.

By default, only site administrators get to see the forms menu item in the Dashboard, and only they can edit forms, view submission data etc. I wanted to allow other roles (e.g. Contributors) to view submission data, but, ideally, not to edit forms, change advanced form settings etc, or edit posts etc. Therefore, I started looking around in the Form Manager plugin code to see if I could change things to allow different roles to do different things and was getting confused by things like the $fm_MEMBERS_EXISTS variable. What I should have done, as always, is look at the docs for the plugin, where I would have found (and eventually did find) this: http://www.campbellhoffman.com/form-manager-faq/#how-do-i-restrict-access-to-different-parts-of-form-manager-members

It turns out that the Form Manager plugin integrates with Justin Tadlock’s Member’s plugin, which in itself seems like an excellent plugin, allowing you to change the capabilities associated with different roles, create your own roles and more. As an aside, users, roles and capabilities in WordPress can be confusing, but Justin’s post on the what they all mean makes it much less so.

Therefore, combining these two plugins allowed me to create a new role that has very limited capabilities. Alongside the standard ‘read’ capability, all they can do is view the list of available forms (the ‘form_manager_main’ capability), view the submission data table (‘

In conclusion, I would say the Members plugin is a ‘must have’ if you want something other than the standard roles offered by WordPress and the Form Manager plugin, of which I was already a fan, is made all the better thanks to its ability to integrate with Members.