Manual for writing CBM Selftest Exercise Files
Tony Gardner-Medwin, Physiology (NPP), UCL, London
QUERIES: cbm@tmedwin.net     Last edit: July 2019

Introduction

Exercise files are plain text files that can be edited with any wordprocessor. They must be saved as ordinary text, which with WORD requires that you specify this under "Save As...". The filename must have an extension .js (e.g. mytestfile.js). Each file may contain a sequence of SECTIONS (each beginning with a function S(...); - see below), which are normally presented to the student in order, though they can also be selected from a section index. Each section may just contain information or explanatory material (shown as "INFORMATION" in the index) or it may contain questions, in which case it is shown as a numbered SECTION in the index.  The exercise format is very flexible, so some of the options may require care, but the basics used in most exercises are actually very simple. The text needs to conform to fairly strict requirements, set out here.

A simple example file

Here is a complete but simple file that works fine. You can try running it here. It has just two SECTIONS, the first with several fairly obvious different question types (described in more detail below). The second section contains a set of MCQ options that are used repeatedly in several questions (known as "Extended Matching Questions"). Note that the file includes lots of comments that are simply to help understand how it works and are ignored when it runs as an exercise. Lines beginning // and everything following // on a line are ignored by the program.

TITLE("CBM Demo File"); //Title to be shown at top of Window

//1st Section heading
S("Questions about Britain","Various question types");    // This heading will be shown along with each question in this section. The second string ".." is in smaller type.

// True/False Question
Q("All of Great Britain lies further North than Paris",T); // The specified answer is True.
E("Yes. Even the Channel Islands (not part of GB, though dependencies) lie further North than Paris.");

//Text answer Q
Q("What is the capital of England?");    // A question requiring a text answer
A("London");         //This is one acceptable answer, and being the first it is shown as the model answer
A("Londres","Yes, but the English name is London");      //a different acceptable answer with a special explanation
A("lond* ");          //accepts anything beginning with lond (NB by default, the checking of the reply is case insensitive).

// A multiple choice Question (the students chooses just one of the options as correct)
Q(MCQ,"Which is the capital of Scotland?"); 
MC("Glasgow");
MC("Edinburgh");
MC("Stirling");
A(2);  // the correct answer is the second option listed above
I(1,"This is not the capital, but it is the largest city"); // this picks up a particular incorrect response (option 1) and gives a special explanation when it is chosen.

// A multiple response Question
//  NB the student is asked to select two options in this case, one at a time, and with confidence expressed for each choice.
Q(MRQ,2,"Which two of these towns has a cathedral?");  
MC("Chester");
MC("Gloucester");
MC("Banbury");
MC("Bath");
A(1); A(3);

// A Multiple Response Q marked all in one go. Confidence is expressed that the entire set of choices is correct.
// NB the Q text could include, if you want, an indication of how many ticks the correct selection would include
Q(MRQ,0,"Make an exact selection showing which of these towns is on the coast"); 
IMG("demouk.png"); //Graphic shown with Q
MC("Birmingham");
MC("Southampton");
MC("Leeds");
MC("Liverpool");
MC("Nottingham");
A(2);  A(4);
E("Liverpool and Southampton are both historically very important ports; the others are important inland industrial towns."); //Explanation
IMG("demoports.png"); //Graphic shown with feedback

// Another text question, but with answers that may be given in numeric form.
Q("How many separate countries or provinces make up the UK?");
A("4");  // model answer
A("four"); //allows text version
A("{4}  * ");  // A bit unnecessary in this case! - but would allow as correct '4.0 countries'  (any format of 4 (+1%) with or without a following word).
E("They are England, Scotland, Wales and Northern Ireland: The \"United Kingdom of Great Britain and Northern Ireland\" . It does not include the Channel Islands or the Isle of Man but for VAT purposes the Isle of Man is treated as part of the UK. ") // Explanation to be shown after the student's response has been marked.

//A question with a range of quantities (number + units) permissible as correct answers
Q("British shops sometimes still use the 'pound' as a unit of mass. How many kg is one pound.?");
A("0.454 kg");  // The model answer
A(" {0.45 0.46} * ");  //gives a permissible range, and the wild card * allows any or no unit, since the unit was specified in the question.
A(" {450 460}  g* ");  //also accepts if a student gives the correct answer, but in grammes

SET("QLAST=1;"); //In the next section show Q text after everything else
S("EMQ questions","These are towns of historic significance in England")   // New section: EMQ = "extended matching questions". Several Qs use the same options. A popular format in clinical courses.
// The questions are displayed one at a time. Options may be correct for any number of the questions.
MC("Bath"); //1
MC("Bristol"); //2
MC("Chester"); //3
MC("Ironbridge"); //4
MC("Liverpool"); //5
MC("Manchester"); //6
MC("Newcastle"); //7
MC("Stoke"); //8
X("Which one of the above options is the best choice for the following description?");  //text shown below the options
Q(MCQ,"The heart of the pottery industry");
A(8);
Q(MCQ,"Called Deva in Roman times");
A(3);
Q(MCQ,"Familiar to Jane Austen");
A(1);
Q(MCQ,"Where the industrial revolution began");
A(4);

...............

Most Selftest files are actually simpler than this one - typically they have a lot of questions,  and perhaps many sections, but with only a few question types.

What are the individual lines in a file?

Technically, the file is a series of what are called 'function calls' , with a name and then information in brackets about what is to be done:
  NAME(....); 
Each function call is terminated with a semicolon, and usually it is best to put just one call on a line of the file - though there can be more. Function calls must not contain a 'line-break' or 'paragraph' marker, though there is no limit to the length of the text within them. This is just like a 'paragraph' in a WORD document. 

The text in a function call may be very long, and a wordprocessor may  'wrap' such text so that it appears on successive lines on the screen or in print. Some editors (e.g. Windows NOTEPAD and WORDPAD) allow you to turn off this 'word-wrap' so you can easily see if your text is split by paragraph marks. In WORD you can display paragraph marks (by checking the box under Tools - Options - View) or search for them (designating them as ^p).

This restriction, that the text in a function call is all on one line, doesn't mean that when it is shown on the screen it must be just a single paragraph. The text can contain instructions for line breaks and new paragraphs, bold and italic fonts etc. as in HTML (hypertext markup language) which is what is used in webpages.  The text can be as versatile as a webpage.  But note that whereas HTML normally ignores line breaks, these are not allowed in function calls.

The file must be saved as a plain text file with the extension .js , for example C:\mywork\myfile.js .  If you write it in WORD, you must save it as "Text Only" (Not "Text with line breaks". NB Sometimes wordprocessors add a tiresome .txt extension to the name you specify (e.g. myfile.js.txt ). It's usually obvious if  this happens. What you have to do is close the file and, in Explorer, rename it -  deleting the ".txt" part.  Usually when you load the file and resave it this problem doesn't arise again.

General Notes:  You can include blank lines and spaces for readability. Everything on a line after // is ignored, so can be used for comments. Function calls may include within the brackets several different things (e.g. numbers or text strings) separated by commas, and following the format shown above and the rules below. The text may contain single quotes or apostrophes (') but not double quotes (except as \" -- see below). In general you don't need to learn HTML, but can use the AUTHORING TOOL on the web site to deal with these kinds of things automatically. For more info,  see >Writing Text   below).

Specifications

File Title
There can be a single title specified for the whole file, shown at the top of the Index:
TITLE("..") ;
This line can appear anywhere in the file, but normally at the start. If more than one title is specified, only the last has any effect.


Writing Text 
Text to be shown is always enclosed within double quotes "....." and must not itself include either double quotation marks or line-breaks (paragraph marks).  Single quotation marks are fine, and double quotation marks can actually be specified to appear on screen - but they must be preceded by \. For example, a T/F question might be written as either:
Q("It is a compliment if someone says your name is 'mud' ?", F);
Q("It is a compliment if someone says your name is \"mud\" ?", F);
Line breaks to appear on screen are specified by the string <br> . New paragraphs (with extra spacing) are specified with <p>.
Those familiar with HTML (the markup language for web sites) will recognise these as HTML conventions. Text fields can use any HTML conventions. Other useful examples are for subscripts and superscripts (e.g. H<sub>2</sub>O or H<sup>+</sup> where, for example  <sub> turns on and </sub> turns off subscripting.

Writing Filenames and  Paths
Filenames and paths (including the route to the directory or folder with the path) are specified to display images or url links to required files. When writing paths, the character \ must be replaced by  / .  For example, "..\mylogo.gif" or "pics\pic32.jpg"  must be written "../mylogo.gif"or "images/pic32.jpg", each indicating a path of the desired image relative to the directory in which the source file will reside..

Sections
The file is divided into Sections, identified by
S("..text.."); or
S("subtitle"," ..text.."); or
S("REPEAT","..text.."); or
S("REPEAT","subtitle"," ..text..");
The information is shown for every screen throughout the Section, till the next S(); or the end of the file.
If S(); is followed by questions Q(); (see below) then it is assigned a section number, 1,2,...
If S(); is followed by another S(); before any Qs, then it is not numbered and is shown differently in the index as 'Information'.
If the first field in S(); is "REPEAT", then the questions within this section will be repeated indefinitely (with different randomisations if these are specified - see below) until the student clicks on 'New Section.  If this facility is used, it is important to inform the student that this is the case.
X("..text..");  defines line/s of text to show below the display of MCQ options in any MCQ or MRQ Qs in the Section
ES("..text..");  defines explanatory text to display only after completion of all Qs in a section, before going to the next section 
Sections with questions are sequentially numbered. If one or more sections with questions are removed from an exercise, the original numbering can be retained by replacing the missing sections with a section (without questions) with a third numerical element:
S("subtitle"," ..text..",n);
where n is the number by which to increment the number of the next section with questions.

Questions
Question types are described later, but they are all identified by a line of the form:
Q(.....);
Questions within a section are numbered 1,2,... so that each Q is identified by 2 numbers, e.g. as S5,Q4
If a question is removed from an exercise, the original numbering can be retained by replacing it with a line
Q("blank");
in the sequence of questions, and this question will not be shown.

Answers
For most question types, the correct answer or answers to a question are indicated in one or more lines of the form:
A(.....);
This must come after the corresponding question line Q(..), either before or after any multiple choices specified.
For multiple choice Qs, the A(); line may be written either for example as A(3); or A("3"); to indicate the correct choice is the third option.
For  T/F questions, the correct answer is given at the end of each Q(..) line: Q("text",T); or Q("text",F);
More detail will be given below.

Explanations

Explanations for individual questions
Explanation to be shown after a student has replied or pressed 'No Reply' is identified in a line containing the text (...) of the form:
E(".....");
This comes after the corresponding Q(); line (and may be before or after any associated A(); lines).

Explanation for a whole Section.
Sometimes it is preferable to delay giving an explanation until after all questions in a section have been completed, since explanation may give away information asked in other questions. This can be specified in either of two ways:
(1) An E() line placed after S() and before the first question definition (Q() line).
(2) A line  ES(".....");  placed anywhere before the next S() line (e.g. after all the questions, corresponding to when it will be displayed).
ES() overwrites any explanation previously defined for the same section with E() or ES().
If the student skips some or all questions in a section (e.g. by clicking 'Next Section'), the Section Explanation will not be displayed.

Conditional Explanations for questions
An explanation about a question can be made to show only if the student attempts an answer (i.e. not if they click 'No Reply'), by using
C("....."); instead of E(".....");  after a Q(); definition.
If C(); is used, E(); fields may precede or follow the C(), or both. The text will be shown on separate lines in the corresponding order. The availability of a conditional explanation is indicated on screen by the letters ex below the question, which if clicked as a link explain what this means.
C(); lines may have 2 text fields :
C(".. explanation if reply is correct..", ".. explanation if reply is wrong..");
Only the first is shown if the student's reply is correct, and only the second if it is wrong. In both cases, any unconditional explanation text (E()) is also shown (before and/or after the conditional explanations).

An image specified after E(); or C(); or CT(); is shown with whatever text is displayed. If an image is to be shown as sufficient explanation for a T/F question, without any text, it must be preceded by a blank E(""); line. Otherwise it will be shown along with the question itself. Conditional showing of images, conditional on a reply, is not implemented. [NB the blank E(""); is not necessary with other Q(); formats than T/F (below), because an IMG(); line coming after an answer definition A(); is always a part of the explanation.]

[A minor variant of C(...); is available, convenient for compatibility with some existing exercise formats using T/F questions. This interprets the order of two explanations differently, making them dependent on whether the student has entered T or F, not on whether this reply is right or wrong:
CT(".. explanation if student enters T..", ".. explanation if student enters F.."); ]

Images
Graphics or pictures are identified by a line:
IMG("..name..");
The name text is normally just a file name (e.g. IMG("pic4.jpg");) if the file is in the same folder as the exercise file, but it can include a path relative to this (e.g.
IMG("graphics/pic4.jpg");
or a full URL:
IMG("http://www.mywebsite/myfolder/mypic.png");
Note that directories are delimited by / not \. Here are some rules about Graphics:
Supplementary Material opened in a separate window
A filename, path,  URL or graphic can be opened in a supplementary window with the line :
SUPPL("..url..","..description..");
The window should open immediately on top, replacing any material already in a supplementary window.  (Only one supplementary window  is available.)  The decription is shown on the main window as a link, that if clicked reopens the supplementary window if closed, or brings it to the top.  The supplementary window is associated with a section, question or explanation according to the position of the SUPPL(); line in the file, in the same way as for IMG(). It is closed automatically when these conditions no longer apply.

True/False Questions

These are defined by a line that gives both the question and the T/F answer :
Q("..question text..", T); or Q("..question text..", F);
Any image to be shown with this particular Q can be specified with a following IMG(); line (see above).

MCQ (multiple choice) questions
These offer a set of possible responses, one of which is to be entered as the (or a) correct answer. The possible formats are:

Q(MCQ,".. question text..");
IMG("..");  [optional]
MC(".. text for option 1.." [ , "..comment to be shown whenever this option is selected.." ] );
MC(".. text for option 2.." [ , "..comment to be shown whenever this option is selected.." ] );
MC(".. text for option 3.." [ , "..comment to be shown whenever this option is selected.." ] );  .....
A(n);
The line A(n) defines a correct answer. If more than one answer is to be accepted as correct, then additional lines A(m); etc. can be added. If an IMG line appears after Q(); and before A(n), this image is shown with the question. If one appears after the first A(n), it is shown by way of explanation, along with any E(); or C(); text. NB  images shown as explanations cannot be made conditional on particular responses. Comments for particular options are optional.
[ Alternative formats for specifying options and comments, used in some exercises but normally less readable, are:
M(".. text for option 1..");
M(".. text for option 2..");
M(".. text for option 3.."); ....
or
M(".. text for option 1..", ".. text for option 2..", ".. text for option 3.." [,...] );
and
MFB(".. comment for option 1..");
MFB("..
comment for option 2..");
MFB(".. comment for option 3.."); ....
or
MFB(".. comment for option 1..", ".. comment for option 2..", ".. comment for option 3..", .....); 
Note that for MFB(); any options without comments must be included with blank text ("") to preserve the sequence.  ]

A note on explanations and comments for individual questions and responses
Explanations for any form of question can always be defined by E(); or C(); (see above). In addition, comments for specific chosen options in MCQ questions can be defined by MC(); or MFB(); lines as just described.  Note that if this is done for options that are reused for a whole set of MCQ questions (sometimes called Multiple Extended Question Sets), then the defined comment will be shown whenever the option is selected, regardless of the question. For example, the definition:
MC("Paris"  , "Paris is the capital of France");
will give this comment whenever Paris is selected as the reply in a sequence of questions that might ask for the capitals of several different countries. Often you may want the comment for a particular response to be different depending on the question context. When the reponse is a correct one defined by A(n), the comment can be included as an extra field within the A(); that defines it, e.g. :
A(n, "Well done, that is the best answer. "); , or
A(m, "OK, but actually ....  is a better answer, because ..... ");
If the response prompting the comment is incorrect, then it can be defined using I(); instead of A():
I(k, "Lots of people think this is the answer, but it isn't because .... ");
After the student responds, all the correct options are shown bold and underlined on the list, together with any general explanantion (E(); or C()) and any specific comments for the student's response.

MRQ (multiple response) questions
Like MCQs, these offer a set of options. But the student is asked to indicate more than one as correct responses. [For example, "Which three of the following cities are in Europe?"....] The format is:
Q(MRQ, z ,".. question text..");
MC(..);
MC(..);
MC(..);    /
/ same as for MCQ, above
A(i); A(j); A(k);
where z is the number of options the student should enter (one at a time, each with a separate confidence judgement and mark awarded), and i,j,k are allowable correct options.  There must be at least z allowable correct options specified, but there may be more. Note that if z=1, then the MRQ is formally identical to an MCQ question:
Q(MRQ, 1 ,".. question text.."); is equivalent to:
Q(MCQ ,".. question text..");
Note that with an MRQ, a student may be confident about some options and unconfident about others, so they are marked separately. The student is told how many to enter at the start, and cannot enter more than this number (z), though s/he can enter fewer by pressing No Reply at any stage.The maximum number of marks obtainable for an MRQ is 3z.

MRQ Explanations are defined in the same way as for an MCQ, above. An E(); explanation line is shown only after all z entries are complete or No Reply is pressed. The response-specific explanations are shown after each selection is made.

Re-using the multiple options for MCQs and MRQs
If the same set of options MC(..) are to be used for several questions, they can be specified after the section definition S(), and before any of the Questions. Then any Q(MCQ,...) or Q(MRQ,....) lines within the section, not followed by their own option definitions, will use the options defined for the Section. Thus you might define a set of cities, and ask : 'Which 3 are in Europe?", "Which two are capitals?", "Which four are the largest?",  "Which, if any, are largely Muslim?", etc..

Open-ended (unknown number) MRQ questions 
These are entered as MRQ questions with z=0. The student may then click any number of options (or none) from the list, to identify a  correct set of  responses for which there is a single confidence judgement that the selection is an exact match to the correct answer.  The reply is marked correct only if the entered options correspond exactly with the defined correct answers.  Any comments for individual responses the student makes (as defined in MC, MFB, A or I lines), as well as unconditional (E) or conditional (C) explanations, will be shown. If the correct response would be to select none of the options, this is indicated by the answer line A(0); A(0) is not legal for other forms of MRQ or MCQ questions. Text included with A(0)  (i.e. in the form A(0,"..text..") is ignored.

'How-Many?' MRQ questions (not implemented yet)
The idea here would be to present the usual M(); options, but to ask and mark on the basis simply of how many of the options were covered by the question. The response would then show which ones. Format not decided.

Text Response Questions
The question format is :
Q(".. question text..");
followed by any number of answer definitions, checked against a reply until a match is found :
A(".. answer text.." [,"optional conditional explanation text"[,optional code number]] ); // a match is marked correct and any conditional explanation text is then shown.
I(".. answer text..", "conditional explanation text" [,optional code number]); // a match is marked incorrect and conditional explanation text is then shown. NB The only reason to use I(); is to show special explanation text conditional on particular identifiable mistakes.
Explanation text E(..) or conditional explanation text C(..) or C("text if correct" , "text if incorrect") can be specified in the same way as for T/F questions (above). Such lines come after the answer definitions.
    The first A(); answer text is shown as the 'model answer'. Any number of subsequent A(); or I(); lines can be included for alternative correct answers, or incorrect ones deserving special explanation. Matching is normally case insensitive, unless the answer text is preceded by ` If the answer text is preceded by < or > then, respectively, a match is found if the reply text is contained within the answer text, or if it contains the answer text as a string. Wildcard elements are acceptable: ? (matching any single character) or * (matching any reply that matches the answer text up to the previous character in the answer text). Unless the answer text is a phrase between single quotes [ 'match this phrase' ] matching is only with the first word in the reply, up to any space. Several strings of answer text may be included within a single A(), separated by spaces (no commas), and checked in turn.
Special features: Within a reply, tabs convert to spaces, double (or more) spaces convert to single spaces. 'mm Hg' converts to 'mmHg'. If the line STRIP=1; is present in the file since the last S(), then the reply is completely stripped of all spaces before checking against answer texts. [This can be cancelled before the next S(); by STRIP=0;]. The current value of STRIP can be over-ridden for a particular A(..) by including an optional code number n. If n is odd strip is carried out, otherwise not  (i.e. strip= n&1).  An example of the use of STRIP would be to accept any form of the answer "E = mc^2" entered with or without spaces:
A("E = mc^2","",1);

Numerical Answers
Questions with numerical answers are the same as Text Response Questions. The only difference is in particular A(); lines, which may be used to match numerical replies, however entered, within a defined range.
A("{x y}"); //matches any number between x and y (inclusive).
A("{x"); or A("{x}"); //matches any number within a set tolerance (default 1%) of x.
A("{x y} *"); or A("{x *"); or A("{x} *"); //match the defined numbers even if followed by an additional string.
Thus Q("2+2="); A("{4 *");would accept as correct the reply 4 kg, while Q("2+2="); A("{4 "); would only accept a simple number, like 4 or 4.0 with no units.
    Tolerance for a question or for all the questions in a section, can be set by including " TOLERANCE = t; " within a SET(); command before the relevant S(); or Q(); (see below for SET()). This would set the tolerance to +/-t%
    Numerical replies can be entered in standard forms, e.g, 9.65E4 or 96500 or 96.5x10^3, but not as more general expressions (e.g. 120/5 or 10^0.3). Commas are ignored, and decimal points must be entered as . [stop] not , [comma]. Invalid numerical syntax in a reply will often be rejected with a request for a valid reply, but may simply be counted wrong (with an indication how it has been interpreted).

Quantity Answers
Answers that need to have both a numerical component and correspondingly correct units can be defined by including a numeric definition in answer text, followed by one or more text strings for acceptable prototypes to match to units in the reply. Thus a set of answer definitons might be:
A("{50 mph mi/h* miles/h*"); A({80 kph km/h* "); A({80,000 m/h"); etc.

Annotating a file with comments
Comments in a file (to be ignored by the interpreting program when reading the file) can be entered with // or /*.....*/
Where // appears on a line (as long as it isn't within a text field within double quotes, above) then anything after that, to the end of the line, is ignored
Likewise, everything between /* and the next */ is ignored, regardless of whether there are line breaks in between.

Combining separate instructions for convenience, on one line
Normally, new components of the file, like S(....); or Q(....); are written each on a new line. If they are, then strictly, they don't need the final semicolon.
If the semicolon is included however, separate components can be combined onto one line. This can make it easier to read the file:
Q("Which country led the operation?"); A("USA"); A("America"); A(" 'United St* ' ");

MORE ADVANCED ISSUES

Setting Parameters
SET("...javascript text....");  or
RET("...javascript text....");  or
These two lines differ only in when they are implemented.  Each line can define one or more instructions, which are stored with (in the case of SET) the next S(); or Q(); line or (in the case of RET()) the last preceding S(); or Q(); line. They are then acted on whenever the corresponding Section or Question is embarked on. Note that RET(); acts in a sense retrospectively, since it is implemented at a time corresponding to a point earlier than its position in the file, and the defined parameters (e.g Z[i], see below) may be used in earlier section or question text.  A SET() or RET(); line associated with a section is implemented each time the section begins (i.e., it is not performed over again for each Q(); in the section, so randomly defined parameters will remain constant throughout the section, unless redefined.). NB multiple instructions in a single SET(); or RET(); line must be separated by semicolons. The following sets of lines are all equivalent. (NB Z[0] to Z[99] are the names of variables that you can set, explained below):
SET(" Z[0]=selrand(3,9); Z[1]=8; Z[2]=Z[0]*Z[1]; ");
S("Section x");

S("Section x");
RET(" Z[0]=selrand(3,9); Z[1]=8; Z[2]=Z[0]*Z[1]; ");

SET("Z[0]=selrand(3,9);";
SET(" Z[1]=8;");
SET(" Z[2]=Z[0]*Z[1]; ");
S("Section x");

SET(" Z[0]=selrand(3,9);";
S("Section x");
RET(" Z[1]=8;");
RET(" Z[2]=Z[0]*Z[1]; ");
The following parameters have default values that will be used for each section unless changed by a SET(); line before S(); or a RET(); line after S();. It will revert to the default for following sections unless set again. The default values for the whole file can be changed before the first section by lines setting their value directly (not using SET();). If this is done, then don't subsequently use SET() to change it again, or the results may be unpredictable, dependent on which sequence of sections the the student may open.
RANDSEL=z; //RANDSEL is, by default zero. If it is set to a positive integer z (>1), then only a random selection of the questions (one from each successive set of z within the section), will be displayed. This effect lasts only for one section at a time. RANDSEL must be set within a SET(); line before the section definition S().
RANDSEQ=x; //RANDSEQ is, by default zero. If it is set to x=1, then the display order for questions within the section is randomised. As for RANDSEL above, this applies only for the current section.

MCQRAND=x; //MCQRAND is, by default zero. If it is set to x=1, a set of MCQ or MRQ options specified for individual Qs (after Q()) are displayed in random order.

EMQRAND=x; //EMQRAND is, by default zero. It affects whether MCQ or MRQ options specified after S(); are displayed in random order. These are usually options to be reused for several Qs in a section (EMQs) and though the order is randomised at the start of the section, it is not re-randomised for each Q in the section. 

MROWS=n; //MROWS is the number of rows of multiple choice options displayed in MCQ and MRQ questions (default=6). If there are more options than MROWS, then they form new columns. If MROWS=1, then the options are displayed in a single row horiaontally, which will spill over to new rows if there are too many options for one line.

QLAST=x; // QLAST is by default zero. If it is set to x=1, the Question Text for a MCQ or MRQ will be placed last, after the options and after any extra Section text X("...") shown after the options. By default, the Question text is shown above the options.
Multiple instructions within a SET(); command must be separated by semicolons (;) with no line breaks, and enclosed as a group within double quotes. For example :
      SET("RANDSEL=2; RANDSEQ=1; ");
would result in the following S(); being implemented by choosing at random one from each successive pair of questions, and presenting them in random order.

Randomised and calculated numerical parameters
Randomised parameters can be used in questions. 100 parameters can be defined and used at any one time: members of an array Z[i] for i between 0 and 99. The SET(); command is used to calculate these parameters.. Examples of instructions that can be used to calculate the parameters are:

Z[1]=2+2; // sets Z[i]=4
Z[3]=Z[0]*Z[1] + 3*Z[2]; // ues previously set values
Z[4]=Z[ Z[3] ]; // uses a previously set value as an index
if(Z[0]>0.1) Z[1]=Z[0]; else Z[1]=0;  // uses javascript statements to define Z[1] in a chosen manner 
Z[2]=Math.pow( Z[1] , 0.5); // uses a javascript function to take the square root of Z[1]
Z[2]=Math.abs( Z[1] ); // another common javascript function to take the absolute value of Z[1]
Z[0]=selrand (1, 6); // generates a random integer between 1 and 6 (inclusive)
Z[0]=selrand (1, 6, 0.2); // generates a random number from those between 1 and 6 (inclusive), separated by steps of 0.2 (i.e. one of the set 1,1.2,1.4,...6.0)
Z[0]=selrand (-5, 5 , 1, 0 ); // generates a random integer between -5 and 5 (inclusive), but excluding zero.
Z[0]=selrand (-5, 5 , 0.01, 0, 0.5 ); // generates a random number -5 and 5 (to 2 decimal places) inclusive), but excluding numbers within +/- 0.5 of 0.00. In this kind of example, if the last number is omitted (giving the range of values to exclude) then its default value is taken to be 1.0E-6.
Arrays of values, for statistical purposes
You can define a special array of values (of any size) called ZZ1 , for use in a section  like this:  SET(" ZZ1=[1,6,8,1,3,4,5]; ");
By giving the instruction Stat();  several statistical parameters are calculated from the array:
     STAT.n , STAT.mean ,  ZZ2, STAT.median, STAT.stdev, STAT.variance
The variance is calculated as the unbiassed estimate of the variance of the population (Mean squared deviation from the sample mean / (1-1/n)), and the standard deviation as the square root of this estimated variance..
A sorted array of the values, in ascending order, is also calculated, called ZZ2
Example:
SET("ZZ1=[selrand(1,50),selrand(1,50),selrand(1,50)]); Stat(); Z[0]=STAT.n; Z[1]=STAT.median; ");
S("Data = Z[Z1]");
Q("What is the median value?");
A("{Z[1]}");
E("First sort the Z[0] data values according to value: Z[Z2] <br>and then pick the middle value: Z[1]");
Substituting randomised parameters into text
Whenever the string Z[i] is encountered in the text for a section, question, answer, explanation or IMG(); command, it is replaced (recursively) with the corresponding value (shown to, at maximum, 4 significant digits). The fact that it is recursive means that Z[Z[0]] will, for example if Z[0]=3, be replaced first by Z[3] and then by whatever value Z[3] has currently. There must be no spaces within Z[i]. A choice of a graphic file can be made dependent on a value, by using numbers in the filenames. For example, IMG("picZ[2].gif"); would look for pic1.gif or pic2.gif etc. depending on the value of Z[2]. Substitution of calculation of intermediate values in a calculation into explanation text can help to explain the steps in a calculation. For example,
SET("Z[0]=selrand(3, 8, 0.1); Z[1]=Math.pow(10,-Z[0]); Z[2]=Z[1]*1000; ");
Q("What is the H+ concentration (in mM) corresponding to pH=Z[0] ?");
A("{Z[2] mM"); A("{Z[2] ");
I("{Z[1] * ","You gave the concentration in M units, not mM");
E("pH=Z[0] means that the H+ concentration is 10<sup>-Z[0]</sup> M, which is Z[1] M. To convert to mM you need to multiply the value by 1000, giving Z[2] mM. ");
You can quote all of the values in the special arrays ZZ1, ZZ2 (see Arrays, above) by placing Z[Z1] or Z[Z2] in the text. 

Lines in a file that set defaults for the exercise, or affect the interpretation of subsequent file lines
To act in the way described below, these instruction lines must appear as separate lines in the file (not within SET()), and without quote marks (").
SHOWALL=1;//this can be used at the start of a file to make all conditional explanations be displayed unconditionally, largely for test purposes.
RANDSEL=z; // This (just once in a file, normally at the start) sets so that one of every z questions in a section is selected at random for display, throughout the whole exercise (provided RANDSEL is not reset in a SET(); command (see above).
RANDSEQ=1; //This (just once in a file, normally at the start) sets so that questions are presented in random sequence throughout the whole exercise (as long as RANDSEQ is not reset by a SET(); command (see above).
MCQRAND=1;//sets so MCQ options defined in individual questions (after Q()) are shown in random order
EMQRAND=1;//sets so EMQ options (MCQ or MRQ options defined for a whole section, after S()) are shown in random order, but not re-randomised for different Qs.
MROWS=n;//sets number of rows of options in MCQ, MRQ questions
MRAND=1; //sets so that MCQ, MRQ options are presented in random order
STRIP=x;// STRIP is, by default, zero. If set to x=1, then answer text in subsequent A(...) lines for text responses and the corresponding entries made by a student will be stripped of all spaces before a check is made for a match. For example A("x + y"); would allow a match with 'x+y' or 'x +y' or 'x+ y' or 'x + y'. STRIP must be reset to 0 if it is no longer to apply to subsequent A(...) lines in a file. STRIP can be switched back and forth between 1 and 0 in a file, each time affecting only the subsequent lines in the file.
IMGCASE=n; // 0(default) image filenames are case-sensitive 1=convert to lower 2=convert to upper case filenames
USECONF=n; 1(default) =use CBM, but student can switch this off (to -1) or on //0: no CBM //2: CBM unchangeable
FB=n; // 1(default) shows feedback, though student can switch this off (to -1) or on. FB=0: no feedback. FB=2: shown only for Qs with explanations
FINI=""; // relative url to go to after a submission (default="menu.htm").     ="CLOSE" = close window ="CLEAR" = wipe subwindow and put up message ="RESTART" = start a new session
MAX=n; // Submit results after completion or viewing and skipping n questions if n>0 (default: n=0)
EXAMMODE=n; //This (set before any sections) determines various aspects of function. The default is EXAMMODE=0; EXAMMODE=15 (for 1+2+4+8) is a typical exam mode, where the set value n is the sum of numbers for the required actions:
  // 1: Omit options to view index, comments, or to repeat Qs, change CBM use, etc.
  // 2: Omit 'No Idea' from response options
  // 4: Don't show whether answers were correct, or the mark awarded
  // 8: Omit cumulative mark display
(advanced options) :
  // 16: allow student to click to view cumulative score so far
  // 32: record sequence of Q presentations, if randomised.
FB_SWITCH=c; If FB_SWITCH>-1 (default) Pseudo-random assignment of students to see or not see immediate feedback after responses, according to whether character number c in the student's userid (starting with c=0 for the first char) is odd or even in the alphabet. If the character has an odd code, the component 4 of EXAMMODE previously set (or 0 by default=0) is reversed (i.e. switched on or off). Other components of EXAMMODE are unaffected. By changing the component 4 in the setting of EXAMMODE in a different exercise file, whether a particular student sees feedback or not will be reversed.
MODE=n; //may be set by run.htm for mobiles, or in exercise. 0(default) = can use keyboard for TF Qs 1=no kbd options for TF 2= no kbd focus

INST="....";//OBSOLETE Sets a default for the institution field in a submission.
STATUS=n; //OBSOLETE Sets a default index for the status field in a submission.
TOPIC=n; //OBSOLETE Sets a default index for the topic field in a submission.

Alternative formats
These formats are not encouraged. They are mainly to aid compatiility with other systems, and may appear in some existing files.
T/F questions may be entered : Q(T, ".. question text .."); or Q(F, ".. question text ..");
MCQ questions may be entered as Q( ".. question text ..", MCQ);
Unconditional explanations (normally E(..) ) may alternatively be added as an extra comma separated field within Q() (for all question types), after the defining fields.
Conditional explanations (normally C(..) ) may alternatively be added as second (or second and third) extra comma separated fields within Q(), for all question types, after the defining fields.
U() is equivalent to E(), and MQ is equivalent to MCQ
A(Ma); A(Mb); etc. are equivalent to A(1); A(2); etc. in MCQ and MRQ questions.