Table of Contents

YourWay Math Academy Question Writing Guide

Writing Questions

The YourWay Math Academy question format is based on PHP.

Question Parts

A question is formed in several parts:
  • Description: A description of the question. This is not shown to students
  • Use Rights: The rights you wish to grant other people (you always have full rights). Options are:
    • Private: Only you can use the question
    • Use, no modification: Anyone can use the problem, but only you can modify the problem. Anyone can add library assignments, but cannot remove assignments.
    • Use, allow modification: Anyone can use or modify the problem.
  • Libraries: The question libraries you wish to include this question in
  • Question type: The type of question.
  • Common control: General definitions needed for both display and scoring
  • Question control: Definitions only needed for question display
  • Question text: The actual question display. This section should be HTML based, but can include variables defined in the common or question control. For convenience, a blank line is automatically interpreted to be a paragraph break. Use of < and > signs are usually handled ok, but use of the HTML &lt; and &gt; are recommended in their place.
  • Answer: Code defining the answer
Note: All control code can be placed in the "Common Control" box; the Question Control and Answer sections do not have to be used.

Basic Control Syntax

Lines of the common control, question control, and answer sections usually take the form of variable definition. In YourWay Math Academy, variables are identified with a dollarsign ($) prefix. For example, $a is the variable a. Most lines will take one of these forms:

  • $var = number. Example: $a = 3
  • $var = calculation. Example: $a = 3*$b*$c
  • $var = function. Example: $a = showplot("sin(x)")
  • $var = randomizer. Example: $a = rand(-5,5)

Variable Types

There are a few types of variables:

  • A number: $a = 15. A calculation like $a = 3^2 will also result in a number
  • An array: $a = array(6,8,10). This is a collection of variables. You can reference the parts using an index (note that arrays are zero-indexed), so $a[0] = 6.
  • A string: $a = "hi there".
  • Boolean: $a = true

Note that numbers are not in quotes, and strings are in quotes. When you use the double-quote mark (") to define a string, you can interpolate variables into the string. Example:

$a = 3
$b = 5
$str = "What is $a/$b"

In this example, $str now contains "What is 3/5".

Note: Strings in single quotes will not interpolate variables.
Warning: Strings are interpolated literally, so if you had $a = -4 and then defined $b = "$a^2" you would end up with "-4^2", which may not be what you intended. Use explicit parentheses in these cases.

Array assignment

In some cases you want to define several variables at once. There are two ways to do this:

  • $var1,$var2 = arrayfunction. Example: $a,$b = diffrands(-5,5,2)
  • $ar = arrayfunction. Example: $ar = diffrands(-5,5,2)

In the first example, variables $a and $b each take on a single value. In the second example, the variable $ar is an array; the elements can be accessed as $ar[0] and $ar[1] (note that arrays are zero-indexed). If you use this approach, enclose the variable reference in parenthesis in calculations, like $new = ($ar[0])^2, and in curly brackets inside strings, like $string = "there were {$ar[0]} people".

// Method 1: assign to separate variables
$a,$b = diffrands(-5,5,2)

// Method 2: assign to an array variable
$ar = diffrands(-5,5,2)

// Access individual elements with $ar[0], $ar[1]
$first = ($ar[0])
$sum = ($ar[0]) + ($ar[1])

// Literal array definition
$colors = array("red","green","blue")

You can also literally define an array using the "array" function. Examples: $ar = array(2,3,4,5), or $ar = array("red","green","blue")

You can also use a shorthand notation for an array, using square brackets. Example: $ar = [2,3,4,5].

Working with Strings

If needed, you can concatenate (combine) two strings using the . operator. Example:

$a = "string one "
$b = "string two"
$both = "$a$b"

// Variable interpolation in strings
$n = rand(1,10)
$msg = "The number is $n"

If you have a long command to type, you can put a & at the end of a line to specify it continues on the next line. Example:

$questions = array("this is choice 1",&
"this is choice 2")

If defining a string for display, you can put a && at the end of a line to specify it continues on the next line and insert an HTML line break. Example:

$showanswer = "Do this first. &&
Then do this."

will be interpreted as:

$showanswer = "Do this first. <br/>Then do this."

Comments

You can insert comments in your code by starting the comment with two forward slashes: //this is a comment. Typically it's best to put comments on their own line, but they can also be placed after a line of code.

Conditionals

Any assignment line can be followed by one of two conditionals: where or if.

where is used to repeat the previous assignment if the condition provided is not met. The where condition is almost exclusively used with array randomizers. Example: to select two different numbers that are not opposites:

$a,$b = diffrands(-5,5,2) where ($a+$b!=0)

if is used to make an assignment conditional. For example:

$a = rand(0,1)
$b = "sin(x)" if ($a==0)
$b = "cos(x)" if ($a==1)

Note the use of double equal signs (==) for testing equality. A single equal sign (=) will make an assignment (change the value of $a in this example) and return true, which is probably not what you intended to do.

Comparison operators available for if and where statements:

  • == Equal to
  • != Not equal to
  • > Greater than
  • < Less than
  • >= Greater than or equal to
  • <= Less than or equal to

To do compound conditionals, use || for "or", and && for "and". For example:

$a = nonzerorand(-9,9) where ($a!=1 && $a!=-1)

The if condition can also be used before or after a code block like this:

$a = rand(0,1)
if ($a==0) {
   $b = 1
   $c = 2
}

or

$a = rand(0,1)
{
   $b = 1
   $c = 2
} if ($a==0)

When "if" is used before a block of code, it can optionally be followed with "elseif" and/or an "else" statement, like this:

$a = rand(0,5)
if ($a==0) {
   $b = 1
} elseif ($a==2) {
   $b = 3
} else {
   $b = 2
}

"where" can also be applied to a block of code:

{
  $a = rand(-5,-1)
  $b = rand(1,5)
} where ($a+$b !==0)

Loops

There are several looping macros (such as calconarray) that can meet most needs. For more general use there is a for loop:

for ($i=a..b) { action }

Here a and b represent whole numbers or variables. Expressions are not allowed.

Examples:

$f = 0
for ($i=1..5) { $f = $f + $i }

$a = rands(1,5,5)
$b = rands(1,5,5)
for ($i=0..4) {
  $c[$i] = $a[$i]*$b[$i]
}

Conditions can be used inside a for loop, but not outside without explicit blocking

for ($i=1..5) {$a = $a+$i if ($i>2) }     WORKS
for ($i=1..5) {$a = $a+$i} if ($a>2)     DOES NOT WORK
{for ($i=1..5) {$a = $a+$i} } if ($a>2)    WORKS

Randomizers

Note on macros: The descriptions below explain macros available and the arguments the functions should be called with. Arguments in [square brackets] are optional arguments, and can be omitted. For all randomizers, all bounds (min,max) are inclusive.

Single result randomizers:

  • rand(min,max): Returns an integer between min and max
  • rrand(min,max,p): Returns a number between min and max in steps of p. Example: rrand(2,5,.1) might return 3.4. rrand(2,5,.01) might return 3.27. rrand(2,8,2) might return 6
  • nonzerorand(min,max): Returns a nonzero integer between min and max
  • nonzerorrand(min,max,p): Returns a nonzero real number between min and max in steps of p
  • randfrom(list or array): Return an element of the list/array. Examples of lists: "2,4,6,8", or "red,green,blue"
  • randname(),randmalename(),randfemalename(): Returns a random first name
  • randnamewpronouns([option]): Returns a random first name with pronouns in the order: subjective, objective, possessive (singular), possessive (plural), reflexive. Can set option to 'neutral' for they/them/their/theirs/themself pronouns. Use: $name,$heshe,$himher,$hisher,$hishers,$himherself = randnamewpronouns()

Array randomizers (return multiple results):

  • rands(min,max,n,[order]): Returns n integers between min and max. Can set order to 'inc' or 'dec' to sort the values.
  • rrands(min,max,p,n,[order]): Returns n real numbers between min and max in steps of p. Can set order to 'inc' or 'dec' to sort the values.
  • nonzerorands(min,max,n,[order]): Returns n nonzero integers between min and max. Can set order to 'inc' or 'dec' to sort the values.
  • nonzerorrands(min,max,p,n,[order]): Returns n nonzero real numbers between min and max in steps of p. Can set order to 'inc' or 'dec' to sort the values.
  • randsfrom(list/array,n,[order]): Return n elements of the list/array. Can set order to 'inc' or 'dec' to sort the values.
  • jointrandfrom(list/array,list/array,[list/array,...]): Returns one element from each list, where the location used in each list is the same
  • diffrands(min,max,n,[order]): Returns n different integers between min and max. Can set order to 'inc' or 'dec' to sort the values.
  • diffrrands(min,max,p,n,[order]): Returns n different real numbers between min and max in steps of p. Can set order to 'inc' or 'dec' to sort the values.
  • diffrandsfrom(list/array,n,[order]): Return n different elements of the list/array. Can set order to 'inc' or 'dec' to sort the values.
  • nonzerodiffrands(min,max,n,[order]): Returns n different nonzero integers between min and max. Can set order to 'inc' or 'dec' to sort the values.
  • nonzerodiffrrands(min,max,p,n,[order]): Returns n different nonzero real numbers between min and max in steps of p. Can set order to 'inc' or 'dec' to sort the values.
  • jointshuffle(list/array1,list/array2,[n1,n2]): Shuffles two lists/arrays in a way that retains respective order. In n1 is provided, n1 elements from each shuffled array will be returned (like a joint version of diffrandsfrom). If n2 is also provided, n1 elements of list/array1 and n2 elements of list/array2 will be returned.
  • singleshuffle(list/array,[n]): returns a shuffled version of a list/array. If n is provided, it behaves identically to diffrandsfrom
  • randnames(n),randmalenames(n),randfemalenames(n): Returns n random first names
  • randcity([country]),randcities(n, [country]): Returns one or n random US or Canadian city names. Argument country can be set to "USA" or "Canada". The default is "USA".
  • randstate([country]),randstates(n, [country]): Returns one or n random US state or Canadian province names. Argument country can be set to "USA" or "Canada". The default is "USA".
  • randcountry(),randcountries(n): Returns one or n random country names
  • randpythag([min,max]): Return a Pythagorean triple. min/max default to 1 to 100

Graph/Table Macros

The following macros create graphs or tables:
  • showarrays(string,array,[string,array]...,[options]): Creates a tabular display of the data in the array(s) as column(s), with the strings as column headers. Alternatively you can call this function with arguments showarrays(array of column headers, array of data arrays, [options]). Options can be a string = "c", "r", or "l" to center, left-align, or right align data, or can be an array with $opts["align"] for alignment, and $opts["caption"] to add a caption to the table. To align each column differently, provide a a string with a character for each column, like "rcc"
  • showdataarray(array,[columns]): Creates a tabular display of the data in the array with no headers. Data is presented in one column unless second argument is provided, in which case the data will be distributed over the specified number of columns.
  • horizshowarrays(string,array,[string,array]...): Creates a tabular display of the data in the array(s) as row(s), with the strings as row labels. Does not text wrap, so only use for small data sets.
  • showrecttable(data array of arrays,columnlabels,rowlabels,[format]): Creates a tabular display of a 2x2 data table, where $data[0] is the first row of the table. The rowlabels and columnlabels are arrays of labels. format = "c", "r", or "l" to center, left-align, or right align data.
  • showplot(...) — Generates a graph image.
    showplot( funcstrings, xmin, xmax, ymin, ymax, labels, grid, width, height )
    funcstrings window display
    Full Parameter Reference

    funcstrings

    A single string or an array of strings. Each string uses one of three formats:

    1. Function — plot a curve

    "function, color, min, max, startmarker, endmarker, width, dash"
    • function: a function of x (e.g. cos(x)), a parametric function of t (e.g. [sin(t),cos(t)]), or a vertical line (e.g. x=1)
    • color: black, red, orange, yellow, green, blue, purple
    • min, max: input range for the variable. Exclude discontinuities with ! — e.g. -5,5!0!2
    • startmarker, endmarker: "open", "closed" (dots), "arrow", or omit for none
    • width: line width in pixels
    • dash: "dash" for dashed line, omit for solid
    • Examples: "cos(x),red"   "x^2,,-2,2,open,closed"   "[t^2,t/3],blue,0,5,,,2,dash"   "1/x,black,-5,5!0"   "x=1,red,,,,,,dash"

    2. Dot — draw a point

    "dot, x, y, style, color, label, labelloc"
    • dot: the literal word dot
    • x, y: coordinates of the dot
    • style: "open" or "closed"
    • color: black, red, orange, yellow, green, blue, purple
    • label: text label for the dot
    • labelloc: above, below, left, right, aboveleft, etc.
    • Examples: "dot,3,4"   "dot,1,1,open"   "dot,3,3,,blue,A"

    3. Text — place a label

    "text, x, y, label, color, location, angle"
    • text: the literal word text
    • x, y: coordinates for the label
    • label: the text string to display
    • color: black, red, orange, yellow, green, blue, purple
    • location: above, below, left, right, aboveleft, etc.
    • angle: rotation in degrees (0, 90, 180, 270)
    • Examples: "text,2,4,Cars"   "text,4,0,Hours,below"

    Window & Display Parameters

    • xmin, xmax, ymin, ymax: Graphing window. Defaults to −5 to 5. Use "0:-n" for xmin/ymin to show gridlines only after 0 while still spacing to −n (alternative to addplotborder for first-quadrant graphs).
    • labels: axis label spacing. Defaults to 1. Set to "off" or 0 for none. Use "xlbl:ylbl" for different spacing on each axis.
    • grid: grid line spacing. Defaults to 1. Set to "off" or 0 for none. Use "xgrid:ygrid" for different spacing on each axis.
    • width, height: graph dimensions in pixels. Defaults to 200×200.

Interactive Graph Builder

Configure parameters and see the result live

Window Settings
Functions
Dots
Text Labels
Enable Math to render equations using ASCIIMath notation (e.g. y=sqrt(x), x^2+1)
Lines & Arrows
Shapes (Circles, Rects, Arcs...)
Slope Field
Raw Commands
Enter arbitrary ASCIIsvg commands, one per line (e.g. circle([0,0],2))
Click "Update Preview" to render
  • mergeplots($plot1, $plot2, [$plot3, $plot4, ...]): Merges multiple plots into one. Usually not necessary, since showplot can accept an array of funcstrings, but occasionally useful when adding to a graph generated by another function. The grid and border from the first graph is used. To avoid weird behavior, try to ensure all plots were drawn using the same grid.
  • addfractionaxislabels(plot,step): Adds labels along the horizontal axis in steps of step to a plot created with showplot. Step is a fraction like "1/4", or a pi multiple, like "pi/4" or "2pi". When using this, make sure to set the showplot x-axis label spacing larger than the domain to prevent the default labels from showing.
  • addlabel(plot,x,y,label,[color,loc,angle]): Adds a label to a plot created with showplot.
    • plot: The plot created with showplot
    • x,y: The coordinates for the label
    • label: The string label itself. MathML cannot currently be displayed in labels
    • color: Label color. Defaults to black.
    • loc: By default, the label is centered at the x,y coordinates. Use "left" to display the string to the left of the point, "right" to the right, "below" for below the point, "above" for above the point.
    • angle: Angle to rotate text.
  • addlabelabs(plot,x,y,label,[color,loc,angle]): Adds a label to a plot created with showplot. Parameters are the same as with addlabel, except x and y here are pixel values on the picture rather than values relative to the axes.
  • addplotborder(plot,left,[bottom,right,top]): Changes the pixel width of border (default 5) around a plot. Labels will show within the border. Typically used to add room for labels to show.
  • adddrawcommand(plot,commands): Inserts arbitrary asciisvg drawing commands into an existing plot created with showplot or other drawing tools.
  • showasciisvg(string,[width,height,alttext]): If you know the ASCIIsvg language, this will set up an svg with "string" as the script. optionally you can specify the width and height (in pixels) for the svg. For accessibility, you should always try to include alttext, which is text that displays to people requesting non-visual alternatives.
  • replacealttext(image or graph, alttext): Replaces the alt text (alt tag) in the image or graph with the specified text. This alt text will replace the autogenerated textual description for graphs produced by showplot.
  • changeimagesize(image or graph, width, [height]): Changes the display width for an image. Note this doesn't resize the file itself, just changes the display size - it's always better to resize the original image file.
  • textonimage(img,text,left,top[text,left,top,left,...]): Overlays text over an image. Image can be a URL or the variable for an uploaded image. Specify the text string, and offset in pixels from the top left corner. Can specify multiple strings to overlay. textonimage is not screenreader-friendly, so it's recommended you provide an alt text on the image, which will be read to the screenreader instead of the image and any layered text.
  • addimageborder(image, [border width, margin]): Adds a border to an image uploaded in the question editor. Border width (default 1) and whitespace margin (default 0) can be specified.
  • arraystodoteqns(xarray,yarray,[color]): Converts an array of x-values and y-values into a form that can be used in showplot.
  • connectthedots(xarray,yarray,[color,thickness,startmarker,endmarker]): Converts an array of x-values and y-values into a form that can be used in showplot to create a series of lines connecting the (x,y) pairs
  • arraystodots(xarray,yarray): Converts an array of x-values and y-values into a form that can be used in the Drawing answer type
  • gettwopointlinedata(stuans, [xmin, xmax, ymin, ymax, drawing width, drawing height]) or gettwopointlinedata(stuans, [grid, snaptogrid]): Takes a $stuanswers from a drawing question and pulls out the two-point line data. Returns an array of lines, each of form array(x1,y1,x2,y2) giving the coordinates of the two points used.
  • gettwopointdata(stuans, type, [xmin, xmax, ymin, ymax, drawing width, drawing height]) or gettwopointdata(stuans, type, [grid, snaptogrid]): Takes a $stuanswers from a drawing question and pulls out the two-point data for the given curve type. Type should be one of 'line', 'lineseg', 'ray', 'parab', 'horizparab', 'sqrt', 'cubic', 'cuberoot', 'rational', 'exp', 'log', 'sin', 'cos', 'abs', 'vector', 'circle','ellipse'. Returns an array of curve data, each of form array(x1,y1,x2,y2) giving the coordinates of the two points used. They are returned in the order clicked. For example, with 'parab' type, the first point is the vertex and the second point is an arbitrary point. Can use type 'circlerad' to return array(x-center,y-center,radius) or 'ellipserad' to return array(x-center,y-center,x-radius,y-radius).
  • getdotsdata(stuans, [xmin, xmax, ymin, ymax, drawing width, drawing height]) or getdotsdata(stuans, [grid, snaptogrid]): Takes a $stuanswers from a drawing question and pulls out the closed dots data. Returns an array of dots, each of form array(x1,y1) giving the coordinates of the dot.
  • getopendotsdata(stuans, [xmin, xmax, ymin, ymax, drawing width, drawing height]) or getopendotsdata(stuans, [grid, snaptogrid]): Takes a $stuanswers from a drawing question and pulls out the open dots data. Returns an array of dots, each of form array(x1,y1) giving the coordinates of the dot.
  • getlinesdata(stuans, [xmin, xmax, ymin, ymax, drawing width, drawing height]) or getlinesdata(stuans, [grid, snaptogrid]): Takes a $stuanswers from a drawing question and pulls out the lines data, which includes polygons. Returns an array, with an element for each line/curve draw. Each of those elements will be an array of points on that line/curve. Each of those points is array (x,y).
  • getineqdata(stuans, [type, xmin, xmax, ymin, ymax, drawing width, drawing height]) or getineqdata(stuans, [grid, snaptogrid]): Takes a $stuanswers from a drawing question and pulls out the inequalities data for the given curve type. Type should be one of 'linear' or 'quadratic'. Returns an array of curve data, each of form array(style,x1,y1,x2,y2,x3,y3) giving the coordinates of the three points used. They are returned in the order clicked. style will be either 'ne' for strict inequality (dashed line), or 'eq' for inequality with equality (solid line).
  • getsnapwidthheight(xmin, xmax, ymin, ymax, drawing width, drawing height, snaptogrid): Takes drawing grid info and a snaptogrid value or string, and returns an array(width,height) giving a closeby drawing width and height that will guarantee that the snaptogrid values fall on exact drawing pixel locations.

Format Macros

The following macros help with formatting values for display:
  • makepretty(string or array of strings): Changes double add/subtract signs to a single sign.
  • makeprettydisp(string or array of strings): Does makepretty (see above) and backquotes the string for math display
  • polymakepretty and polymakeprettydisp: Like makepretty, but for polynomials. Cleans up 0*, 1*, ^1, and ^0 to make the polynomial look nicer. This function can do weird things for equations that are not simple polynomials, so test well
  • makexpretty and makexprettydisp: (deprecated - use makexxpretty instead) Like makepretty, but the X-tra version - attempts to clean up things like 1*, 0*, etc. This function will often cause weird things to happen, so test well
  • makexxpretty and makexxprettydisp: Like makepretty, but the X-tra version - attempts to clean up things like 1*, 0*, x^1, x^0, etc. Can occasionally cause strange output, so be sure to test. Handles things better than the older makexpretty, but does not always produce 100% identical output. This function cannot handle |x| notation; use abs(x) instead.
  • numtowords(number,[addth, numwithTh, addcommas): Creates a string containing number written out in words.
    numtowords(1203) returns "one thousand two hundred three"
    numtowords(1203,true) returns "one thousand two hundred third"
    numtowords(1203,false,true) returns "1023rd"
    numtowords(1203,false,false,true) returns "one thousand, two hundred three"
  • fractowords(numerator,denominator,[options]): Creates a string containing fraction numerator/denominator written out in words. By default, fractions will be reduced to integers if possible, and pos/neg signs will be reduced. Options is a string that can include combinations of 'mixed' or 'literal', and 'over' or 'by'. Using 'over' or 'by' will connect numerator and denominator with that word. Using 'mixed' will output a mixed number, and 'literal' overrides the default simplifications. Does not allow division by zero. If 'over' and 'by' both used, defaults to 'over'. If 'mixed' and 'literal' both used, defaults to 'mixed'.
    fractowords(5,-2) returns "negative five halves"
    fractowords(6,3) returns "two"
    fractowords(-7,4,'mixed') returns "negative one and three fourths"
    fractowords(-7,4,'mixed over') returns "negative one and three over four"
    fractowords(6,3,'literal') returns "six thirds"
    fractowords(6,3,'literal over') returns "six over three"
  • numtoroman(number,[uppercase]): Converts a number 0.5-3999.5 to a roman numeral string. Defaults to uppercase; set second parameter to false to produce lowercase
  • prettyint(number): Adds commas in thousands spaces of integers. Example: prettyint(1234) will return "1,234". The result is a string, which can only be used for display, not in calculations
  • prettyreal(number,decimals,[comma]): Adds commas in thousands spaces of number, and displays the value to a fixed number of decimals places (rounding if needed). Example: prettyreal(1234.567,2) will return "1,234.57", and prettyreal(1.8,3) will return "1.800". The result is a string, which can only be used for display, not in calculations. By default adds a comma as a thousands separator; set comma to "" to override.
  • prettysmallnumber(number, [space]): Prevents very small numbers from being displayed as scientific notation. Set space to true to add space in groups of 3, like 0.000 000 02
  • prettysigfig(number,sigfigs,[comma,choptrailingzeros]): Rounds number to sigfigs significant figures. By default it adds commas in thousands spaces; set comma to "" override. Set choptrailingzeros to true to chop trailing zeros from the decimal part, even if significant. This is for display; to round a number for calculations, use roundsigfig.
  • makescinot(number,[decimals,format]): Converts number to scientific notation. If provided, rounds mantissa to decimals places. Can specify format: "*" "E" as alternative to default cross.
  • prettytime(value,informat,outformat): Creates a nice representation of a time. Informat can be 'h', 'm', or 's' designating whether value is hours, minutes, or seconds. Outformat can be any combination of these to specify output. For example, 'hm' will return "__ hours and __ minutes". Outformat can also be 'clock' which returns 3:42pm, or 'sclock' which returns 3:42:15pm
  • dispreducedfraction(numerator,denominator,[doubleslash,variable in numerator]): Takes two numbers as numerator and denominator of a fraction, returning a display form of the fraction, reduced to lowest terms. Suitable for $showanswer. Set doubleslash to true to produced "3//4" rather than "3/4". Set variable in numerator to put a variable in the numerator, such as pi.
  • makereducedfraction(numerator,denominator,[doubleslash,variable in numerator]): Same as dispreducefraction, but not already in display form
  • decimaltofraction(decimal,[format,maxden]): Converts a decimal to a fraction. Can use format="mixednumber" to get a mixed number rather than improper fraction. Only works for denominators up to maxden (default 5000)
  • htmldisp(string,[variables]): Uses HTML instead of the math typesetter to display simple exponents and subscripts, and to italicize variables
  • formatcomplex(real,imag): Creates a string like "2+i" from the real and imaginary parts.

String Macros

These macros help with working with strings:
  • stringappend(value,string): Appends string to value. If value is an array, string is appended to each element of the array
  • stringprepend(value,string): Same as stringappend, but prepends string to value
  • today([string]): Returns today's date, like "July 3, 2008". Can change format using string (see http://us2.php.net/manual/en/function.date.php for formats)
  • stringpos(needle,haystack): Finds the position of the string needle in the string haystack. Returns -1 if needle is not found
  • stringlen(string): returns the character count in the provided string
  • stringclean(string,mode): mode 0: trims leading and trailing whitespace. mode 1: removes all whitespace. mode 2: removes all non-alphanumeric characters.
  • substr(string,start,[length]): grabs the part of the string from the start index with given length. If length is not specified, it cuts from the start index to the end of the string.
  • strtoupper(string): make all characters in the string upper case
  • ucfirst(string): makes the first character in the string upper case
  • strtolower(string): make all characters in the string lower case
  • substr_count(haystack,needle): Find the number of occurrences of needle in the string haystack
  • str_replace(search,replace,string): Replace all occurrences of search in the string with replace. Search and replace can be arrays.

Array Macros

These macros are for working with arrays:
  • listtoarray(list): Converts a list, like "1,2,3,4" or "cat,dog,rabbit" to an array
  • explode(symbol, string): Converts a string to an array, breaking it apart on the given symbol.
  • arraytolist(array): Converts an array to a list
  • calclisttoarray(list): Converts a list of calculations, like "2^2,3^5,7/2" to an array, evaluating the calculations along the way.
  • stringtoarray(string): Converts a text string to an array of characters
  • fillarray(value,num,[start]): Creates an array with num entries, all of which are the same given value. Array indexing starts at 0 unless specified
  • sortarray(list/array,[dir]): Sorts an array from lowest to highest value. To sort in reverse order, give the option second parameter as "rev"
  • jointsort(array,array,[array,...]): Jointly reorders two or more arrays based on a lowest-to-highest sort of values in the first array
  • consecutive(min,max,[step]): Creates an array of consecutive numbers, starting at min and ending at max, in increments of step. Step is optional; it defaults to 1.
  • calconarray(array,calculation): Returns an array, performing the given calculation on each element of the given array. Use "x" as the variable to represent each element of the array. Example: $b = calconarray($a,"x^2") will create an array that is the square each element of the array $a.
  • multicalconarray(calculation,varslist,var1array,var2array,etc.) Returns an array, performing the given calculation on each set of elements from the given arrays. Allows multivariable calculations. Example: $z = multicalconarray("x*y^2","x,y",$xs,$ys)
  • calconarrayif(array,calculation,ifcondition): Like calconarray, but allows you to specify a condition for each element for whether to do the calculation. Example: $b = calconarrayif($a,"x+.1","floor(x)==x") will add .1 to all whole numbers in the array, and leave the other elements unchanged.
  • subarray(array,params): Creates a new array as a subset of the specified array. The params can take several forms:
    • subarray($a,2,4,6): creates an array from $a[2], $a[4], and $a[6]
    • subarray($a,"1:3","6:8"): create an array from $a[1] through $a[3], and $a[6] through $a[8]
    • subarray($a,$b): creates an array from entries in $a with indexes specified in $b. So if $b = array(2,4,6), this would return $a[2], $a[4], and $a[6]
  • joinarray(array,symbol): Convert an array to a string, joining elements with the given symbol
  • mergearrays(array,array,[array,...]): Combines two or more arrays into one long array
  • unionarrays(array,array): Unions two arrays, preventing duplicates, into a new array
  • intersectarrays(array,array): Finds the intersection of two arrays
  • diffarrays(array1,array2): Returns all elements in array1 that are not also in array2
  • array_unique(array): Returns the array, stripping duplicate values
  • array_values(array): Returns the values of an array, reindexing with consecutive numeric indices.
  • count(array): Counts the number of entries in the array
  • sumarray(array): Adds the entries in an array
  • in_array(needle,haystack): Checks if value needle is in array haystack. Returns true or false
  • arrayfindindex(needle,haystack): Returns the index in the array haystack of the value needle. If there are multiple matches, it only returns the first.
  • arrayfindindices(needle,haystack): Returns an array of indices in the array haystack of the value needle.
  • array_flip(array): Reverses a one-to-one array, so indexes become values and values become indexes

General Macros

These macros are fairly general purpose:
  • ifthen(condition,trueval,falseval): Takes a comparison condition, and returns the trueval if the condition is true and the falseval otherwise.
  • formhoverover(label,tip): Creates a hover-over definition or other tip
  • formpopup(label,content,[width,height,style,scrollbars]): Creates a link or button leading to a popup window. Content can be a web address, or HTML content to put directly into the popup. Style can be "link" or "button". Scrollbars defaults to false - set true for scrollbars.
  • forminlinebutton(lable,content,[style,outputstyle]): Creates a link or button that when clicked will reveal hidden content. Content can be any valid HTML. Style can be "link" or "button". Outputstyle can be "inline" or "block". Block will allow any HTML, but will be displayed on a new line. Use "inline" to have text stay on the same line.
  • makenumberrequiretimes(array/list): Takes an array or list of numbers and generates a string suitable for use as a $requiretimes. Writes the string so that every number in the array must show up in the student answer. Automatically detects and adjusts for number overlaps (like 2 appearing in 32).
  • ABarray(start, num): Produces an array of strings of the form [AB#] which will get replaced with answerboxes if placed in the question text. start is the first value used, and num indicates the number of entries to create. ABarray(5,2) will output array("[AB5]","[AB6]"). This macro is often used in conjunction with the showarrays macro.
  • scoremultiorder(stua, answer, swap, type, [weights]): In a multipart question, allows questions or groups of questions to be scored in any order. Works for types 'number', 'string', 'calculated', 'numfunc', 'complex', 'calccomplex', 'ntuple', and 'calcntuple'. Note: Use of the "list" option for individual question types is strongly recommended over using this function if you're just asking for multiple answers.
    • Use like $answer=scoremultiorder($stuanswers[$thisq],$answer,'0;1','number')
    • stua: For numeric types, $stuanswers[$thisq] should be the first argument. For calculated types, $stuanswersval[$thisq] should be the first argument.
    • answer: The second argument is always $answer. This function must be used after $answer is already defined.
    • swap: The third argument shows what entries should be swappable. It can be a string or array of strings. Examples:
      • '0;1' would say answers index 0 and 1 should be swappable
      • '0;1;2' would say answers index 0,1,and 2 should be swappable
      • ['0;1','2;3'] would say answers index 0 and 1 should be swappable, and 2 and 3 should be swappable
      • '0,1,2;3,4,5' would say answers with indices 0,1,2 should be swappable as a group with the answers with indices 3,4,5. Comparison is only made on the first entry to decide whether to swap the groups.
    • type: should be the question part short name, like 'number' or 'calccomplex', for the entries that can be swapped.
    • weights: optionally, you can include your answeights to have them swapped to. In that case, use the form $answer,$answeights=scoremultiorder($stuanswers[$thisq],$answer,'0;1','number',$answeights)

Math Macros

These macros are used for mathematical calculations:
  • sin(t), cos(t), tan(t), sec(t), csc(t), cot(t): The usual trig functions
  • arcsin(v), arccos(v), arctan(v): The inverse trig functions
  • abs(v): Absolute value
  • gcd(a,b): Greatest common divisor of a and b
  • lcm(a,b): Least common multiple of a and b
  • sgn(a): Returns the sign of a, as -1, 0, or 1.
  • v!: Factorial, like $a = $b!
  • evalfunc(func,vars,val1,val2,..): Evaluates a function given the variables and values for each variable. For example evalfunc("x^2*y","x,y",2,3) will evaluate x^2*y with x=2, y=3
  • evalnumstr(expr): Evaluates a string representation of a numerical expression, like "(2pi)/3", to a decimal. Avoid using this in place of direct calculation in most cases, but it can be handy if you already have generated the string for display but then need to do a calculation with it.
  • See also: calconarray and multicalconarray in the Array Macros section

Conditional Test Macros

These macros are used to test various conditions. They typically return true or false, depending on whether the desired condition is met.
  • getstuans($stuanswers, $thisq, [part number]): Pass this function the $stuanswers or $stuanswersval arrays, $thisq for the question number, and a part number (omit if it's a single part question) and this will return the corresponding value. Use of this function is recommended over directly accessing the array, as this function accounts for undefined values in a way that won't trigger errors.
  • stuansready($stuanswers, $thisq, array of part numbers, [anstypes]): Before using student answers, you need to check to make sure the student has actually answered them. Pass this function the $stuanswers or $stuanswersval arrays, $thisq for the question number, and an array of part numbers, and it will check to make sure a non-blank answer has been provided for all of the part numbers. A part number can also be given as "1 or 2" if answering either part is sufficient. To allow a blank answer, prefix a part number with a tilde. It is good to wrap any multipart or conditional code using student answers in an if block using stuansready as the condition. It is advisable to pass $anstypes as a 4th input, which allows the function to handle special cases like matrices better.
  • comparenumbers(a,b,[tol]): Compares numbers or numerical expressions a and b to see if there are equivalent to the specified tolerance. Set tol to specify the relative tolerance (defaults to .001), or prefix with | for an absolute tolerance.
  • comparentuples(a,b,[tol],[option]): Compares ntuples or calcntuples a and b to see if they are equivalent to the specified tolerance. Set a single tol to specify the relative tolerance for all entries in ntuple (defaults to .001), or prefix with | for an absolute tolerance, such as "|0.5". Can make tol an array (or list) to apply by element to the ntuple. By default, function compares the parentheses/brackets containing the ntuple. Can give option "ignoreparens" to only compare the entries in the ntuple, so (a,b) would be considered equivalent to [a,b].
  • comparefunctions(a,b,[vars,tol,domain]): Compares functions a and b to see if they are algebraically equivalent. Set vars to a list of variables (defaults to 'x'). Set tol to specify the relative tolerance (defaults to .001), or prefix with | for an absolute tolerance. Set domain to "xmin,xmax" to specify a domain for comparison, or "xmin,xmax,integers" to restrict domain to integer values.
  • comparelogic(a,b,vars): Compares two logical statements, written using ^^ for and, vv for or, ~ for not, -> or => for conditional, and <-> or <=> for biconditional. vars should be a list or array of variables in the statements.
  • is_numeric(str): Checks if the string represents an integer or decimal number.
  • scorestring($answer,$showanswer,words,$stuanswers,$thisq,[partn, highlight]): This function checks to see if the words in the list/array "words" appear in the student's answer. If they all appear, it redefines $answer so the student's answer is marked correct. $showanswer is also redefined to show the original $answer with all the required words highlighted. You can turn off the highlighting by setting the optional highlight parameters to false.
    For multipart questions, include the part number as an additional parameter. Usage for single part questions (where $words is predefined earlier in the code):
    $answer,$showanswer = scorestring($answer,"",$words,$stuanswers,$thisq)
    Usage for multipart questions (again where $words is predefined). This is example is for part 2:
    $answer,$showanswer = scorestring($answer,$showanswer,$words,$stuanswers,$thisq,2)

Feedback Macros

These macros are used to select and format feedback messages to students. They return a string which can be placed in the question text.
  • getfeedbackbasic(correct msg, incorrect msg, $thisq, [partnum]): Generates a feedback string based solely on whether the question was scored correct or not. Provide the correct and incorrect messages to display, and provide $thisq. Give a part number for multipart questions to get part-based feedback.
  • getfeedbacktxt(stuans, feedbacktxt, ans): Gives feedback on multiple choice questions.
    stuans should be the student answer, obtained from $stuanswers[$thisq] for single part questions, or using the getstuans macro for multipart.
    feedbacktxt is an array of feedback responses, corresponding in array order to the $questions, so feedbacktxt[1] is the feedback if the student selects $questions[1] as their answer.
    ans is the correct answer; you can usually pass $answer if it's been defined already.
  • getfeedbacktxtessay(stuans, feedbacktxt): Gives feedback on essay questions. stuans should be the student answer, obtained from $stuanswers[$thisq] for single part questions, or using the getstuans macro for multipart. It is not actually evaluated or compared - it is only needed to see if the student has entered a response or not. Once the student has entered any response, feedbacktxt will be returned.
  • getfeedbacktxtnumber(stuans, partialcredit, feedbacktxt, defaultfeedback, [tol]): Gives feedback on number questions.
    stuans should be the student answer, obtained from $stuanswers[$thisq] for single part questions, or using the getstuans macro for multipart. For Calculated type questions, be sure to use $stuanswersval.
    partialcredit is an array or list of form array(number, score, number, score, ... ) where the scores are in the range [0,1].
    feedbacktxt is an array of feedback messages, corresponding in array order to the order of the numbers in the partialcredit list.
    defaultfeedback is the default incorrect response feedback
    Set tol to specify the relative tolerance (defaults to .001), or prefix with | for an absolute tolerance.
  • getfeedbacktxtcalculated(stuans, stuansval, partialcredit, feedbacktxt, defaultfeedback, [answerformat, requiretimes, tol]): Gives feedback on calculated number questions.
    stuans should be the student answer, obtained from $stuanswers[$thisq] for single part questions, or using the getstuans macro for multipart.
    stuansval should be the numerical value of the student answer, obtained from $stuanswersval[$thisq].
    partialcredit is an array or list of form array(number, score, number, score, ... ) where the scores are in the range [0,1].
    feedbacktxt is an array of feedback messages, corresponding in array order to the order of the numbers in the partialcredit list.
    defaultfeedback is the default incorrect response feedback
    answerformat can be a single answerformat to apply to all expressions, or an array with each element applied to the corresponding expression
    requiretimes can be a single requiretimes to apply to all expressions, or an array with each element applied to the corresponding expression
    Set tol to specify the relative tolerance (defaults to .001), or prefix with | for an absolute tolerance.
    Example: getfeedbacktxtcalculated($stuanswers[$thisq], $stuanswersval[$thisq], array("1/2",1,"1/2",.5), array("Correct", "Right value, but give your answer as a fraction"), "Incorrect", array("fraction","")) will check the students answer against the answer "1/2" twice, the first time applying the "fraction" answerformat, and the second time not.
  • getfeedbacktxtnumfunc(stuans, partialcredit, feedbacktxt, defaultfeedback, [vars, requiretimes, tol, domain]): Gives feedback on numfunc (algebraic expression/equation) questions.
    stuans should be the student answer, obtained from $stuanswers[$thisq] for single part questions, or using the getstuans macro for multipart.
    partialcredit is an array or list of form array(expression, score, expression, score, ... ) where the scores are in the range [0,1].
    feedbacktxt is an array of feedback messages, corresponding in array order to the order of the numbers in the partialcredit list.
    defaultfeedback is the default incorrect response feedback
    vars should be a list of variables used in the expression. Defaults to "x"
    requiretimes can be a single requiretimes to apply to all expressions, or an array with each element applied to the corresponding expression
    Set tol to specify the relative tolerance (defaults to .001), or prefix with | for an absolute tolerance.
    Set domain to limit the test domain. Defaults to "-10,10"

Using Other Macros

If an YourWay Math Academy administrator has installed other Macro Libraries, you can load a macro library by entering the line loadlibrary("list of library names") at the beginning of the Common Control section.

Examples: loadlibrary("stats") or loadlibrary("stats,misc")

Click on the "Macro Library Help" link in the question editor to get a list of installed macro libraries and the macros available in each library

Math Entry

YourWay Math Academy uses ASCIIMath for math entry. In question text or inside strings that will be displayed in the question text, wrap expressions to be rendered in the backtick/grave symbol, like `x^2`. That key is usually located on the same keyboard button as the tilde.

For calculations, a limited subset is available:

SymbolMeaning
* / + -Multiply, divide, add, subtract
^Powers. 2^3 = 8.
e, piThe standard constants
%Modulus (remainder after division. 5%2 = 1)
mod(p,n)Modulus. This version gives positive results for modulus of negative numbers.
!Factorial
sqrtSquare root
sin,cos,tan,cot,sinh,coshStandard trig function. Be sure to enter as sin(2), not sin 2
arcsin,arccos,arctan,arcsinh,arccoshInverse trig functions.
sin^-1, cos^-1, tan^-1Alternative entry for inverse trig functions. Use like sin^-1(0.5)
lnNatural Logarithm base e
logCommon Logarithm base 10
absAbsolute Value. Note that while abs() is used for calculations, you may prefer to use | brackets for display
round(n,d)round number n to d decimal places
roundsigfig(n,s)round number n to s significant digits. This is for calculations; if you need a value for display and want to ensure trailing 0's display, use prettysigfig
floor,ceilfloor/ceiling: integer below/above given number
min,maxmin or max of the passed values. Can be used as min($a,$b,$c) or min($arrayvariable).

For display only, the full ASCIIMath language is available (which includes support for a limited subset of LaTeX). For more info, see the ASCIIMath syntax.

Common options to all types

All question types can support these options:

Hints

For a single question (not multipart), to use hints, in the common control (or question control) section define the array $hints where:

$hints[attempt number] = "hint text"

For example:

$hints[0] = "This will show on first display"
$hints[1] = "This will show on second attempt (after 1 missed attempt)"
$hints[2] = "This will show on third and subsequent attempts, since no later values have been defined"

It is fine, for example, to not define $hints[0] if you want nothing to display initially.

Then in the question text, place the location of the hint using the variable $hintloc.

In multipart questions, you can follow the process above if you just want a single strand of hints for the entire problem. If you want per-part hints, define the $hints array as:

$hints[question part number][attempt number] = "hint text"

Then in question text, place each hint using $hintloc[question part number]

To have the hint to display based on a set of previous answers, you can use:

$hints[question part number][attempt number] = array("hint text", [part num1, part num 2])

This will display the hint after all the parts listed have had the required attempts or are correct.

To override the default Hint: text, set $hintlabel.

Help references

To provide help of some sort for a question (typically, links to videos, book references, etc), define $helptext in the common control section. Any text assigned to this variable will show above the answer box entry tips. The display of this text is controlled by the same "show hints?" option that controls the display of hints described above.

Referencing Student Answers

To create multipart questions that are graded on consistency, or to create a set of lab-type problems that rely on student-provided data, you can reference students' previous answers in your question code. You will only be able to reference the student answer to some question types

  • $stuanswers[N] will refer to the student's answer on question N (not zero-indexed: N=1 is question 1)
  • $stuanswers[N][P] will refer to the student's answer on question N, part P (if multipart)
  • $stuanswers[$thisq][P] will refer to the student's answer on the current question, part P
  • $stuanswers[$thisq-1] will refer to the student's answer on the previous question
  • $stuanswersval[$thisq] or $stuanswersval[$thisq][P] will contain the numerical value of Calculated question types.

Notes (important!):

1) If the student has not answered the question, then $stuanswers[N] === null, with the exception of drop-down select questions, where $stuanswers[N] == "NA" if no selection is made. If used in an equation, it will take on the value 0. To prevent divide-by-zero errors and to prevent students from exploiting this, it is highly recommended that you do something like:

$a = $stuanswers[$thisq][0]
$a = rand(1,100) if ($a===null)

Perhaps also include: $warning = "You MUST answer question 1 before this question" if ($a===null), then put $warning in the question text.

2) If you use $stuanswers in your $answer, $showanswer will generally not be defined. If you follow the advice in #1 above, then your $showanswer will reflect the random number assigned to $a. For this reason, it is highly recommended that you custom define the $showanswer.

3) If using the $stuanswers array in a string or in the Question Text, you must enclose it with curly brackets: Your answer was {$stuanswers[0][0]}. If using it directly in a calculation, enclose it in parentheses just to be safe.

4) $stuanswers[$thisq] is defined for question scoring, but may not be for question display.

5) You can use the function getstuans($stuanswers,N,P) to retrieve a student answer value. This method bypasses some strange things that happen when there is a multipart question with only one part, so is recommended.

6) You can use the function stuansready($stuanswers,$thisq,[p1,p2,...]) to determine if the parts have been answered, instead of checking for null.

Other Reference Variables

A few other special purpose variables can be referenced:

  • $scorenonzero: This variable is only available on display, not during scoring. $scorenonzero[$thisq] (or $scorenonzero[$thisq][partindex] for multipart) will be -1 if the question is unanswered, 0 if the score is zero, and 1 if the score is anything above 0.
  • $scoreiscorrect: This variable is only available on display, not during scoring. $scoreiscorrect[$thisq] (or $scoreiscorrect[$thisq][partindex] for multipart) will be -1 if the question is unanswered, 1 if the score (before any penalties) is perfect, and 0 otherwise.
  • $attemptn: This variable holds the attempt number of the current attempt. 0 is the initial attempt, 1 is the next attempt, etc.
  • $partattemptn[part number]: For multipart questions, this holds the attempt number on each part.
  • $requestclearla: If you set $requestclearla=true in your code, it will request the display to clear out the student's last answer. This might be useful if your question branches based on attempt count. Example: $requestclearla = true if ($attemptn==2 && !$scoreiscorrect[$thisq])

Reusing Code

You can import in the Common Control code from another question using

includecodefrom(questionid)

where questionid is the ID number of the question you want to import the code of. In the source question, the variable $included will automatically be set to true when the question has been included, so it can be used to determine if the question has been imported into another question, or is running independently.

For example, in the master/source question, you might use the code:

if (!$included) {
 $type = rand(0,4)
}
do stuff here

In a question using this code, you could limit to a specific type using:

$type = 0
includecodefrom(1234)

Question text can be also brought in from another question by using

includeqtextfrom(questionid)

somewhere in the Question Text portion of the question.

Question Types

The question types available are:

Number

The student is asked to enter a number (integer, decimal, or scientific notation). The answer is compared to a given tolerance. Can also accept DNE, oo (Infinity), and -oo (Negative Infinity) as answers.

Required Variables

$answer = a number or calculation resulting in a number, like $answer = 5
Defines the answer. Define multiple acceptable answers in a string separated by or: $answer = "3 or 5 or 7". Alternatively, you can provide an interval notation range of acceptable answers, like $answer = "(2,5]". Providing a range will override any tolerances set. If $answerformat is set for list answers, then this should provide a list of correct answers, like $answer = "1,2,3".

Optional Variables

$reltolerance = a decimal value
Defines the largest relative error that will be accepted. If this is not set, a relative error of .001 (.1%) is used by default.
$abstolerance = a number
Defines the largest absolute error that will be accepted. This will override the use of $reltolerance
$reqdecimals = a number
Defines the minimum decimal accuracy required (ie 2 for two decimal places). This will put a message in the answer tips stating the decimals required. If neither $abstolerance or $reltolerance is set, this will set the tolerance, otherwise the provided tolerance will be used (even if it doesn't agree with the $reqdecimal setting).

$reqdecimals = "=2" can be used to require exactly 2 decimal places in the answer, regardless of how the value rounds (so 3.5 would get marked wrong when the answer is 3.50 if "=2" is used). If you use the "=2" form, it will also round your $answer if needed for the $showanswer.
When the "=2" form is used, it overrides both $reltolerance and $abstolerance, and by default tests that the student answer exactly matches the correct answer ($abstolerance=0). To override the tolerance use +- in the setting, like this:
$reqdecimals = "=2+-.01" checks for exactly 2 decimals, but allows the answer to have an absolute error of .01
$reqdecimals = "=2+-1%" checks for exactly 2 decimals, but allows the answer to have an relative error of 1% (equivalent to $reltolerance = .01)
$reqsigfigs = a number
Defines the significant figure accuracy required. Use $reqsigfigs = 2 for at least 2 sig fig accuracy, or $reqsigfigs = "=2" to require exactly 2 sig figs in the answer, or $reqsigfigs = "[2,3]" to require 2 or 3 sigfigs. This will put also a message in the answer tips stating the significant figures required. If you use the "=2" form, it will also round your $answer if needed for the $showanswer.
This setting overrides both $reltolerance and $abstolerance, and by default tests that the student answer rounded to the specified sigfigs matches the correct answer. To override the tolerance use +- in the setting, like this:
$reqsigfigs = "=2+-.01" checks for exactly 2 sigfigs, but allows the answer to have an absolute error of .01
$reqsigfigs = "=2+-1%" checks for exactly 2 sigfigs, but allows the answer to have an relative error of 1% (equivalent to $reltolerance = .01)
$answerformat = "list", "exactlist", "orderedlist", "integer, "units", "nosoln", or "nosolninf"
  • Answerformats can be combined, like $answerformat = "nosoln,list"
  • $answerformat = "list", "exactlist", or "orderedlist" specifies that a list of answers is expected.
  • If $answerformat="list", then duplicate values are ignored.
  • If $answerformat="exactlist", then duplicate values are not ignored.
  • If $answerformat="orderedlist", the list must be in the same order and contain identical counts of values.
  • $answerformat = "integer" changes the entry hint to only indicate integers, and rejects answers that contain decimals (except it does allow 2.0 instead of 2)
  • $answerformat = "units" adds unit checking. Supply the answer like $answer = "3 kg/m^2". The student's answer can be in other equivalent units, so "300 cm" is considered equivalent to "3 m". The answer must be in the format [decimal number]*[unit]^[power]*[unit]^[power].../[unit]^[power]*[unit]^[power]..., though multiplication can be implied. Note that the units do not require mathematically-proper parens around the denominator. The decimal number can include basic scientific notation in 3E5 or 3*10^5 formats. Note that tolerances are scaled to the unit, so $answer = "3m" with $abstolerance = .1 would mean .1 meters, so "310cm" would still be within tolerance. If $reqsigfigs is set, the specified number of sigfigs will need to be present in the student's answer, regardless of units.
  • $answerformat = "nosoln" or "nosolninf" adds a list radio buttons for "no solutions" and optionally "infinite solutions". $ansprompt can override the default statements like this: $ansprompt = "One value, x=;No values;Many values"
$partialcredit = array(number,score,[number,score,...])
Allows you to specify partial credit for other answers. The array should be given in the form array(number,score,number,score,...), where number is the value to compare to the student answer, and score is a proportion between 0 and 1 to award as partial credit. Note this currently only works for single number answers; "or" and list answers are not supported.
$ansprompt = string
A string that will be displayed in front of the input box. Example: $ansprompt="y="
$displayformat = "alignright"
Aligns the text in the answer box to the right side
$answerboxsize = number
Determines the number of characters space provided for entry of an answer. Defaults to 20.
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the question input box in that location
$showanswer
The answer to show to students (if option if available). Defaults to $answer. Use this to give a detailed answer, or a rounded off answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Calculated

A student is asked to enter a number or a calculation, like 2/3, 5^2, or sin(2). Can also accept DNE, oo (Infinity), and -oo (Negative Infinity) as answers.

Required Variables

$answer = a number or calculation resulting in a number
Defines the answer. Define multiple acceptable answers in a string separated by or: $answer = "3 or 5 or 7". Alternatively, you can provide an interval notation range of acceptable answers, like $answer = "(2,5]". Providing a range will override any tolerances set

To have the answer display as a rendered expression, provide the answer as a string. For example, if you want the answer to show as 24 then you'd specify $answer = "2^4". If you specified $answer = 2^4, the answer would display as 16.

Optional Variables

$answerformat = "fraction", or one of the other options below.
Specifies answer format options. Some can be combined in a list, like this: $answerformat="nodecimal,notrig".
  • Base format types: only use at most one of these at a time
    • fraction: requires the answer to be a single fraction (like 10/6, 1/3, or 5)
    • reducedfraction: a reduced fraction (like 5/3 or 5)
    • mixednumber: a reduced mixed number (like 2 1/2 or 2_1/2, or 2/3 or 5)
    • mixednumberorimproper: a reduced mixed number or improper fraction (like 2 1/2 or 5/2)
    • sloppymixednumber: a mixed number (will take 5/2, 2 1/2, even 1 3/2)
    • scinot: scientific notation (like 2.3*10^4)
    • scinotordec: scientific notation (like 2.3*10^4) or decimal value
    • fracordec: a single fraction or decimal value. Can be combined with "allowmixed" to also allow mixed numbers.
    • decimal: requires the answer to be an integer or decimal value
  • Mix-ins: You can add these as needed to modify what's allowed
    • allowunreduced: can be combined with "mixednumber" or "mixednumberorimproper" to allow unreduced fractional parts
    • allowxtimes: allows the use of x for multiplication (like 23x10^2 for 23*10^2), typically in combo with the "scinot" format
    • nodecimal: require an answer without decimals (also disallows 10^-2 and 3E-2)
    • notrig: require an answer without trig functions (sin,cos,tan,sec,csc,cot)
    • allowmixed: will enable support for mixed numbers (like 2 1/2) in answers
    • allowdegrees: will enable the use of the degree symbol to designate degrees, so sin(30degree)=1/2.
    • noval: tells the answer preview to not compute a decimal equivalent (deprecated - this option is now enabled by default)
    • showval: tells the answer preview to display a decimal equivalent
    • sameform: requires the student's answer be in the "same form" as the correct answer. This means exactly the same, except for commutation of addition and multiplication, multiplication by 1, implicit multiplication, and extra parentheses. Use with caution.
  • List options: only use at most one of these at a time
    • list: a list of answers is expected - ignores duplicate values (1,1,2 is equivalent to 1,2)
    • exactlist: a list of answers is expected - does not ignore duplicates
    • orderedlist: a list of answers is expected - order is important, and duplicates are not ignored
  • Special options:
    • nosoln: adds radio buttons for "no solutions". Use $answer="DNE" if the answer is no solutions.
    • nosolninf: adds radio buttons for "no solutions" and "infinite solutions". Use $answer="DNE" or $answer="oo" respectively if needed.
    • To override the default "no solutions" and "infinite solutions" wording, you can define $ansprompt as a list of semicolon-delimited strings to override the default wording. For example,
      $ansprompt = "One value, x=;No values;Many values"
$formatfeedbackon = true
Turns on "right answer, wrong format" feedback on the question
$reltolerance = a decimal value
Defines the largest relative error that will be accepted. If this is not set, a relative error of .001 (.1%) is used by default.
$abstolerance = a number
Defines the largest absolute error that will be accepted. This will override the use of $reltolerance
$reqdecimals = a number
Defines the decimal accuracy required (ie 2 for two decimal places). This will put a message in the answer tips stating the decimals required. If neither $abstolerance or $reltolerance is set, this will set the tolerance, otherwise the provided tolerance will be used (even if it doesn't agree with the $reqdecimal setting).
$reqsigfigs = a number
Defines the significant figure accuracy required. Only valid for "decimal", "scinot", and "scinotordec" $answerformat options. Use $reqsigfigs = 2 for at least 2 sig fig accuracy, or $reqsigfigs = "=2" to require exactly 2 sig figs in the answer, or $reqsigfigs = "[2,3]" to require 2 or 3 sigfigs. This will put also a message in the answer tips stating the significant figures required. If you use the "=2" form, it will also round your $answer if needed for the $showanswer.
This setting overrides both $reltolerance and $abstolerance, and by default tests that the student answer rounded to the specified sigfigs matches the correct answer. To override the tolerance use +- in the setting, like this:
$reqsigfigs = "=2+-.01" checks for exactly 2 sigfigs, but allows the answer to have an absolute error of .01
$reqsigfigs = "=2+-1%" checks for exactly 2 sigfigs, but allows the answer to have an relative error of 1% (equivalent to $reltolerance = .01)
$requiretimes = a list, like "^,=3,cos,<2"
Adds format checking to the student's answer. The list can include multiple checks, which come in pairs. The first is the symbol to look for. The second describes what is acceptable. For example, in the string shown above, the symbol "^" would be required to show up exactly 3 times, and "cos" would be required to show up less than 2 times.
Be aware that if you search for "5,=1", it will match both 5 and 15 and 2.5, since all three strings contain a 5. When searching for numbers, you can avoid this by putting a "#" before the number, like "#5,=1", which would match the 5 but not 15 or 0.5. Beware this type of search ignores signs.
You can use just "#" in the symbol location to match any number (including decimal values); 3.2^5 would match twice.
You can match either of two symbols by putting || between them, like ".5||1/2,>0"
You can use a regular expression by putting in the symbol location "regex:expression"
You can put "ignore_commas,true" at the beginning of the $requiretimes to ignore commas in the answer
You can put "ignore_symbol,$" (or some symbol other than $) at the beginning of the $requiretimes to ignore that symbol in the answer
$requiretimeslistpart = a list, in the same format as $requiretimes
Similar to $requiretimes, but this check is applied to each element of the answer list when a list $answerformat is used, where $requiretimes would be applied to the entire list of answers. To apply different $requiretimes to each element of the $answer list, separate them with semicolons, like "pi,=1;/,=1;;"
$ansprompt = string
A string that will be displayed in front of the input box. Example: $ansprompt="y="
$answerboxsize = number
Determines the number of characters space provided for entry of an answer. Defaults to 20.
$hidepreview = true
Hides the Preview button. Could be useful in multipart questions, or if you're only asking for a simple response, like a fraction
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the question input box in that location
$showanswer
The answer to show to students (if option if available). Defaults to $answer. Use this to give a detailed answer, or a rounded off answer.
$previewloc (In Question Text)
Where you want the preview button to be located. Defaults to after the entry box if not placed in question text.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Multiple-Choice

A student is asked to select the correct answer from those given. The order of choices is automatically randomized.

Required Variables

$questions (or $choices) = an array of choices
Defines the choices. If you use $choices, don't define $questions
$answer = the index into $questions that contains the correct answer
Defines the answer. Remember that arrays are zero-indexed, so if $questions = array("correct","wrong","wrong"), then $answer=0. Define multiple acceptable answer indices in a string separated by or: $answer = "0 or 1".

Optional Variables

$displayformat = "horiz", "select", "2column, "3column", or "inline"
Will lay out the choices horizontally, as a select box, in multiple columns, or inline with text rather than using the default vertical layout
$noshuffle = "all" or "last" or "last2"
If $noshuffle="all", then the $questions array will not be randomized (shuffled). If $noshuffle = "last", then the $questions array will be randomized, except for the last element. This is for options like "None of the above". You can use "last2" or "last3" to randomize all but the last 2 or 3 elements.
$partialcredit = array(index,score,[index,score,...])
Allows you to specify partial credit for other answers. The array should be given in the form array(index,score,index,score,...), where index is the index in $questions, and score is a proportion between 0 and 1 to award as partial credit. For example, if $answer = 0 and $partialcredit = array(2,.3), then the student would get full credit for selecting the item corresponding with $questions[0], and 30% credit for selecting the item corresponding with $questions[2]. All other answers would receive 0 credit.
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the choice list in that location
$showanswer
The answer to show to students (if option if available). Defaults to the text of the correct answer. Use this to substitute a detailed answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Multiple-Answer

A student is asked to select all the choices given that are correct. The order of choices is automatically randomized.

Required Variables

$questions (or $choices)= an array of questions
Defines the choices. If you use $choices, don't define $questions
$answers = a list of the indexes into $questions that contain the correct answer
Defines the answers. Remember that arrays are zero-indexed, if $questions = array("correct","correct","wrong"), then $answers="0,1". Or there are more than one correct combination, separate with or, like $answers = "0,1 or 0,3"

Optional Variables

$scoremethod = "answers" or "allornothing" or "takeanything"
By default, the total points possible are divided by the number of questions, and partial credit is lost for each correct answer missed and each wrong answer selected. If $scoremethod="answers" is set, then the total points possible are divided by the number of answers (tougher grading scheme). If $scoremethod="allornothing", then the student will only get credit if every piece is correct (no partial credit). if $scoremethod="takeanything", full credit will be given for any response.
$displayformat = "horiz", "2column, "3column", or "inline"
Will lay out the choices horizontally, in multiple columns, or inline with text rather than using the default vertical layout
$noshuffle = "all"
If $noshuffle="all", then the $questions array will not be randomized (shuffled)
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the choice list in that location
$showanswer
The answer to show to students (if option if available). Defaults to the text of the correct answers. Use this to substitute a detailed answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Matching

A student is asked to match answers with questions

Required Variables

$questions = an array of questions
Defines the questions - these will be on the left with entry boxes
$answers = an array of answers
Defines the answers - these will be on the right and lettered

Optional Variables

$matchlist = a list of the indexes into $answers that contain the match to each question.
Defines correct matches. By default, it is assumed that each element of $questions is matched one-to-one with the corresponding element of $answers (in other words, that $answers[0] is the answer to $questions[0]).
$matchlist allows you to define one-to-many matches. Example: if $questions=array("cat","dog","quartz") and $answers=array("animal","mineral"), then $matchlist = "0,0,1"
$questiontitle = string
Displays a title above the list of questions. For example, if $questions was a list of states, then $questiontitle="States" would be appropriate
$answertitle = string
Displays a title above the list of answers
$noshuffle = "questions" or "answers"
Retains original order of questions or answers, and only shuffles the other. By default, both lists are shuffled
$displayformat = "select" or "2columnselect"
Only displays the $answers, with select boxes next to each containing the $questions. This should only be used with pure text $questions.
$scoremethod = "allornothing"
Setting "allornothing" will mean no partial credit is given, and the student must match all parts correctly to get credit.
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place matching questions and answers in that location
$showanswer
The answer to show to students (if option if available). Defaults to the list of correct matches. Use this to substitute a detailed answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Function

A student is asked to enter a function

Required Variables

$answer = string
Defines the answer function, entered as a string. For example, $answer="2sin(x)". You can specify multiple acceptable answers by separating with "or", like $answer="x^2 or x^4"
Note: The system will accept any algebraically equivalent answer. To only allow answers of a specific format, you'll also need to define $requiretimes (see below).

Optional Variables

$variables = string
A list of all variables in the function (including letters representing constants). Defaults to "x". Can use "f()" to indicate a symbol represents a function.
$domain = "inputmin,inputmax"
Defines the domain on which to compare the given answer and correct answer functions. The same domain applies to all variables. An option third list element "integers" can be given, which limits the domain to integer values. The domain defaults to real numbers from -10 to 10. If using multiple variables, can extend domain to define domain for each variable separately. Example: $variables = "x,y"; $domain = "0,5,20,25"
$requiretimes = a list, like "^,=3,cos,<2"
Adds format checking to the student's answer. The list can include multiple checks, which come in pairs. The first is the symbol to look for. The second describes what is acceptable. For example, in the string shown above, the symbol "^" would be required to show up exactly 3 times, and "cos" would be required to show up less than 2 times. You can use "#" in the symbol location to match any number (including decimal values); 3.2x+42y would match twice.
You can use a regular expression by putting in the symbol location "regex:expression"
You can match either of two symbols by putting || between them, like "x^-3||/x^3,>0"
Include "ignore_case,false" to make the search case sensitive. Include "ignore_symbol,$" (or some symbol other than $) at the beginning of the $requiretimes to ignore that symbol in the answer
Note that commas are ignored by default with Function type, and a basic exponent like x^(-3) is converted to x^-3 before the check.
$answerformat = "equation" or "inequality" or "toconst" or "scalarmult" or "nosoln" or "nosolninf" or "sameform" (can combine, like "equation,nosoln")
By default, the student answer is expected to be an expression, and be equivalent (at points) to the specified answer. This option changes this behavior.
"equation": Specifies that the answer expected is an equation rather than an expression. The given answer should also be an equation. Be sure to specify all variables in the equation in $variables. This may fail on equations that are near zero for most values of the input; this can often be overcome by changing the $domain
"inequality": Specifies that the answer is expected to be an inequality rather than an expression. The given answers should also be an inequality. Be sure to specify all variables in the equation in $variables. This may fail on equations that are near zero for most values of the input; this can often be overcome by changing the $domain
"toconst": Specifies that the answer provided by the student is allowed to differ from the specified answer by a constant for all inputs. Appropriate for comparing antiderivatives. This may fail on expressions that evaluate to very large values or raise numbers to very large powers.
"scalarmult": Specifies that the answer provided by the student is allowed to differ from the specified answer by a scalar multiple.
"nosoln" or "nosolninf" adds a list radio buttons for "no solutions" and optionally "infinite solutions". $ansprompt can override the default statements like this: $ansprompt = "One function, f(x)=;No such function exists"
"sameform": requires the student's answer be in the "same form" as the correct answer. This means exactly the same, except for commutation of addition and multiplication, multiplication by 1, implicit multiplication, and extra parentheses. (2x-3)(5-x) would be "sameform" as (-1x+5)(2*x-3), but 2/4x and 1/2x and 0.5x would not be "sameform". Use with caution.
$partialcredit = array(string,score,[string,score,...])
Allows you to specify partial credit for other answers. The array should be given in the form array(string,score,string,score,...), where string is the expression to compare to the student answer, and score is a proportion between 0 and 1 to award as partial credit. Note this currently only works for single expression answers; "or" answers are not supported.
$formatfeedbackon = true
Turns on "right answer, wrong format" feedback on the question
$reltolerance = a decimal value
Defines the largest relative error that will be accepted. If this is not set, a relative error of .001 (.1%) is used by default.
$abstolerance = a number
Defines the largest absolute error that will be accepted. This will override the use of $reltolerance
$ansprompt = string
A string that will be displayed in front of the input box. Example: $ansprompt="y="
$answerboxsize = number
Determines the number of characters space provided for entry of an answer. Defaults to 20.
$hidepreview = true
Hides the Preview button. Could be useful in multipart questions, but generally not recommended
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the question input box in that location
$showanswer
The answer to show to students (if option if available). Defaults to makeprettydisp($answer).
$previewloc (In Question Text)
Where you want the preview button to be located. Defaults to after the entry box if not placed in question text.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

String

A student is asked to enter a string (a word or list of letters).

Required Variables

$answer = a string
Defines the answer. Multiple acceptable answers can be entered using "or". Example: $answer = "dog or cat"

Optional Variables

$strflags = string of flags, like "ignore_case=1,trim_whitespace=0"
Determines how the string will be compared. Set to 1 to turn on, 0 for off. Flags are:
  • ignore_case: ignores capitol/lowercase differences
  • trim_whitespace: trims leading and ending whitespace (spaces)
  • compress_whitespace: compresses multiple spaces to one space and trims
  • remove_whitespace: removes all whitespace (spaces)
  • ignore_order: treats ABC and CBA as equivalent
  • ignore_commas: removes commas
  • partial_credit: awards partial credit based on Levenshtein distance between strings
  • allow_diff=n: gives full credit for answers with Levenshtein distance between strings ≤ n
  • in_answer: gives credit if $answer is contained anywhere in the student answer
  • regex: interprets $answer as a regular expression (pattern) to evaluate the student's answer. For example, $answer="cost.*increas" will give credit if the word cost appears before increas in the student's answer. $answer="increas|ris" will accept any of the following: increasing, increases, rising, or risen etc.
  • special_or: use *or* for separating answers rather than or.
  • ignore_symbol=sym: Unlike the other flags, this is not an on/off flag. Set this equal to a symbol to ignore that symbol in student answers. This flag can be used multiple times with different symbols.
By default, compress_whitespace and ignore_case are On. Only one of partial_credit, allow_diff, in_answer or regex may be used at a time.
$scoremethod = "takeanything" or "takeanythingorblank" or "submitblank"
"takeanything" or "takeanythingorblank" sets the problem to give full credit for any answer. "takeanythingorblank" also counts blank answers as correct. "submitblank" will cause blank answers to get submitted for scoring (new system only).
$answerformat = "list" or "logic"
"list" specifies that a list of answers is expected. Renders ignore_commas unnecessary. Cannot be used with partial_credit flag. Duplicates are not ignored.

"logic" enables a separate grading algorithm for logic statements, ignoring $strflags. The $answer should be given using vv for or, ^^ for and, ~ for not, => for conditional, and <=> for biconditional. Parens are supported, but no other symbols. The variables used in the logic expression must be declared by defining $variables.
$displayformat = "usepreview" or "typeahead" or "usepreviewnomq"
"usepreview" enables mathquill entry for mathematical answers.
"usepreviewnomq" adds a preview button for previewing mathematical answers in asciimath.
"typeahead" will enable an auto-suggest list of options once the student has typed at least two letters of the word. Provide the auto-suggest list in the variable $questions.
$variables
When $answerformat="logic" is used, define the $variables in the logic statement, like "p,q"
$ansprompt = string
A string that will be displayed in front of the input box. Example: $ansprompt="type: "
$answerboxsize = number
Determines the number of characters space provided for entry of an answer. Defaults to 20.
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the answer entry box in that location
$showanswer
The answer to show to students (if option if available). Defaults to the text of the correct answer. Use this to substitute a detailed answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Essay

A student is asked to enter a free-response answer. The essay type is not automatically graded.

Required Variables

None - the essay type is not computer graded.

Optional Variables

$answerboxsize = "rows" or $answerboxsize = "rows,columns"
Determines size of space provided for entry of an answer. Defaults to 5 rows, 50 columns.
$displayformat = "editor"
Use the rich text editor for the essay answer box.
$scoremethod = "takeanything" or "takeanythingorblank"
Sets the problem to give full credit for any answer. The latter also counts blank answers as correct.
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the essay box in that location
$showanswer
The answer to show to students (if option if available). Defaults to the text of the correct answer. Use this to substitute a detailed answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Writing

The Writing question type is designed for essay and long-form writing assignments with enhanced features for academic integrity, rubric-based grading, and AI-assisted feedback. Unlike the basic Essay type, Writing questions include activity tracking, paste monitoring, and integration with the enhanced rubric system. Writing questions are not automatically graded by default but can use AI to suggest grades based on rubrics, or can be configured for automatic scoring.

Note: Writing questions can only be used as standalone questions. They cannot be used as a part type within Multipart or Conditional questions, because the rubric integration, self-assessment, AI formative feedback, and activity tracking features require a dedicated question context. If you need a text input within a multipart question, use the Essay type instead.

Required Variables

None - the writing type requires manual or AI-assisted grading by default.

Optional Variables - Editor Display

The editor includes a fullscreen button that students can use to expand the editor to fill the screen, providing more space for longer writing tasks.

$showWordCount = true or false
Show a live word count display in the toolbar. If word limits are set, they will be shown in the tooltip. Defaults to true.
$showThesaurus = true or false
Enable the built-in thesaurus tool. Students can select a word and click the thesaurus button to see synonyms (uses Merriam-Webster API). Defaults to true.
$showDictionary = true or false
Enable the built-in dictionary tool. Students can select a word and click the dictionary button to see definitions (uses Merriam-Webster API). Defaults to true.

Optional Variables - Toolbar Customization

$toolbarAllowMath = true or false
Override profile setting to enable/disable math formula insertion.
$toolbarAllowMedia = true or false
Override profile setting to enable/disable image/media embedding.
$toolbarAllowTables = true or false
Override profile setting to enable/disable table insertion.
$toolbarAllowFormatting = true or false
Override profile setting to enable/disable text formatting (bold, italic, underline, etc.).
$toolbarAllowLinks = true or false
Override profile setting to enable/disable hyperlink insertion.
$toolbarAllowLists = true or false
Override profile setting to enable/disable bullet and numbered lists.

Optional Variables - Word Limits

$minWords = number
Minimum word count requirement. If set, displays a warning when below the minimum. Used for scoring validation with certain score methods.
$maxWords = number
Maximum word count limit. If set, displays a warning when exceeded.

Optional Variables - Activity Tracking

$pastePolicy = "allow", "track", or "block"
Controls how pasted content is handled:
  • allow: No restrictions, minimal tracking
  • track: Allow paste but log events and flag suspicious activity for teacher review (default)
  • block: Block external paste, allow only internal copy/paste within the editor
A status indicator is shown to students when tracking is active.
$autoSaveInterval = number
Auto-save interval in seconds. Drafts are saved automatically at this interval and on submit. Set to 0 to disable auto-save. Defaults to 30 seconds.

Optional Variables - Rubric & Self-Assessment

$rubricId = number
ID of a rubric (from the enhanced rubric system) to associate with this question. The rubric will be displayed during grading and can be used for AI-assisted grade suggestions. Find rubric IDs at Course > Rubrics.
$allowSelfAssess = true or false
Enable student self-assessment using the associated rubric. Students can evaluate their own work against the rubric criteria before submitting. Requires $rubricId to be set. Defaults to false.

Optional Variables - Scoring

$scoremethod = "takeanything", "takeanythingorblank", or "wordcount"
Sets automatic scoring behavior:
  • (not set): Default manual grading. Blank responses get 0, non-blank responses require teacher review.
  • takeanything: Full credit for any non-blank response. If $minWords is set and the response is below the minimum, partial credit is given based on the word count ratio (wordCount / minWords).
  • takeanythingorblank: Full credit for any response, including blank responses.
  • wordcount: Score based on meeting $minWords. Full credit if word count meets minimum, partial credit (wordCount / minWords) if below, zero if blank. Requires $minWords to be set.
$answer = string
The model answer to display when students view the answer (if the option is available). Can include HTML formatting. This is shown as the "correct answer" in review contexts.
$showanswer = string
Alternative to $answer. The answer to show to students. Use this to provide a model response or detailed answer explanation.

Optional Variables - Accessibility & Display

$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders. Appended to the question identifier.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the writing editor in that location instead of the default position.
$hidetips = true
Hides the question entry tips that display by default.

Activity Tracking

When using $pastePolicy = "track" or "block", the system automatically tracks:

  • Paste events: Whether content was pasted from external sources vs internal copy/paste, character counts, and content hashes
  • Typing sessions: Start/end times and character counts typed
  • Focus/blur events: When the student leaves and returns to the editor
  • Draft versions: Automatic saves with full content history

The system automatically flags responses that appear suspicious (e.g., high external paste ratio). Teachers can view the activity timeline, draft history, and flagged responses in the grading interface.

Writing Settings Helper

The question editor includes a "Writing Settings Helper" panel that provides a visual interface for configuring Writing question options. Click the panel header to expand it.

  • Quick Presets: Select from pre-configured templates (Academic Essay, Reflection Journal, Exam Response, Creative Writing, Minimal) to quickly populate common settings
  • Visual Controls: Configure all options using dropdowns, checkboxes, and text inputs without needing to remember variable names
  • Apply Settings to Code: Click this button to generate properly-formatted PHP code with helpful comments and inject it into the Common Control editor
  • Rubric Sync: When you select a rubric from the Rubric Selection dropdown, the "Include $rubricId in code" option automatically syncs

Administrators can manage system-wide presets at Admin > Writing Presets.

Rubric Integration

There are two ways to associate a rubric with a Writing question:

  1. Using the Rubric Selection dropdown (recommended):
    • In the question editor, find the "Rubric Selection" section (appears when Writing type is selected)
    • Select a rubric from the dropdown (organized by My Rubrics, Shared Rubrics, Templates)
    • Optionally check "Enable student self-assessment"
    • If using the Writing Settings Helper, check "Include $rubricId in code" to also set the variable
    The rubric assignment is stored in the database (imas_rubric_assignments table) separately from the code.
  2. Setting $rubricId in code:
    • Create a rubric at Course > Rubrics (or /course/addrubric2.php)
    • Note the rubric ID from the rubric list
    • Set $rubricId in your question code to the rubric ID
    • Optionally enable $allowSelfAssess = true for student self-evaluation

Both methods work, and you can use both together. The UI method is recommended for ease of use, while the code method gives you more control and makes the rubric assignment visible in the code.

When a rubric is attached, the grading interface shows the rubric with clickable score levels. AI can suggest which levels to select based on the student's response.

AI Features (Teacher)

When AI is enabled in the site configuration, teachers can:

  • Request AI-suggested rubric level selections with explanations for each dimension
  • Get AI-generated writing feedback on grammar, style, and structure
  • View AI confidence scores and suggested improvements

Note: AI suggestions are advisory only. Teachers must review and approve all grades.

AI Formative Feedback (Student)

When enabled, students can request AI-powered formative feedback on their writing before final submission. This helps students improve their work through constructive feedback without affecting their grade.

$aiFormativeEnabled = true or false
Enable the "Get AI Feedback" button for students. When clicked, the AI analyzes the student's response against the rubric criteria and provides structured feedback including:
  • Suggested rubric level selections (highlighted on the rubric display)
  • Overall feedback summary
  • Identified strengths
  • Areas for improvement
Requires $rubricId to be set and AI to be enabled in site configuration with the student_formative feature flag. Defaults to false.
$aiAllowChat = true or false
When AI formative feedback is enabled, this controls whether students can ask follow-up questions about the feedback. Students can have a conversation with the AI to better understand the feedback and how to improve. Defaults to true (when $aiFormativeEnabled is true).

Important: AI formative feedback is purely advisory and does not affect grades. All sessions are logged for teacher review, allowing instructors to see how students engaged with the feedback during their learning process.

AI Calibration Exemplars

Teachers can add exemplar responses to help calibrate AI feedback for specific questions. Exemplars are example student responses with teacher-assigned rubric scores that teach the AI what different quality levels look like for this particular question.

Benefits:

  • More consistent AI scoring aligned with your expectations
  • AI learns from concrete examples rather than just rubric text
  • Particularly useful for subjective or nuanced criteria

How to Add Exemplars:

  1. Open the question editor and save the question (exemplars require a saved question)
  2. Select a rubric in the Rubric Selection section
  3. Click the "Manage Exemplars" button that appears
  4. Add example responses with:
    • Response text - A sample student response
    • Scores - Select the appropriate level for each rubric dimension
    • Rationale (optional) - Explain why you gave these scores

Best Practices:

  • Add 2-3 exemplars covering different quality levels (e.g., high, medium, low)
  • Include rationale to help the AI understand your reasoning
  • Focus on exemplars that illustrate edge cases or common scoring decisions
Example — With AI Formative Feedback
$pastePolicy = "track"
$showWordCount = true
$showThesaurus = true
$minWords = 200
$maxWords = 1000
$rubricId = 5
$allowSelfAssess = true
$aiFormativeEnabled = true
$aiAllowChat = true

$question = "Write an argumentative essay on the topic of climate change policy.
Use evidence to support your position."
Example — Basic Essay
$showWordCount = true
$minWords = 250
$maxWords = 500

$question = "Write a short essay (250-500 words) describing your favorite book."
Example — Tracked Assessment with Rubric
$pastePolicy = "track"
$showWordCount = true
$showThesaurus = true
$minWords = 250
$maxWords = 1000
$rubricId = 5
$allowSelfAssess = true

$answer = "A strong persuasive essay includes a clear thesis, supporting evidence,
and addresses counterarguments. The conclusion should reinforce the main argument."

$question = "Write a persuasive essay arguing for or against the use of
renewable energy sources. Your essay should include an introduction with
a clear thesis statement, at least three body paragraphs with supporting
evidence, and a conclusion that reinforces your argument."
Example — Auto-Scored Reflection
$scoremethod = "wordcount"
$minWords = 100
$showWordCount = true
$toolbarProfile = "basic"
$pastePolicy = "allow"

$question = "Reflect on what you learned in this module. Write at least 100 words."
Example — Minimal Journal Entry
$scoremethod = "takeanything"
$toolbarProfile = "minimal"
$showThesaurus = false
$pastePolicy = "allow"

$question = "What is one thing you are grateful for today?"

Drawing

Drawing questions require the student to draw one or more lines/curves or dots. Dots are graded right/wrong. Lines/curves are graded based on the deviation of the drawn line from the correct line.

Required Variables

$answers = a string or array of strings describing the points or curves to be drawn
Curves: "f(x)" like "x^2+3".
Line segments or rays: "f(x),xmin,xmax", like "x+1,-3,2" or "x+1,-oo,3"
Dots: "x,y" for closed dots, "x,y,open" for open dots, like "2,3"
See below for additional entry formats for other curves when using "twopoint" drawing.
When using twopoint drawing, you can preface an answer with "optional", like "optional,2,3", to indicate that drawing element is not required, but shouldn't mark down the score if present.

Recommended Variables

$answerformat = "twopoint", "polygon", "inequality", "numberline", or (for the older tools), "line,lineseg,dot,opendot"
Limits the drawing tools available to students. Defaults to the older drawing tools "line,dot,opendot".

$answerformat="twopoint" will use a different set of drawing tools for specific shapes that all use two control points to define the shape. It is strongly recommended you use these instead of the older tools.

  • $answerformat="twopoint" will use a default tool set of line, parabola, absolute value, circle, and dot tools
  • You can limit or expand the tools by specifying them: e.g. $answerformat = "twopoint,line,parab". Valid values are:
    • line (lines)
    • lineseg (line segment)
    • ray (rays)
    • parab (vertical parabolas)
    • horizparab (horizontal parabolas)
    • cubic (a(x-h)^3+k style cubics)
    • abs (absolute value)
    • circle (circles)
    • dot (open and closed dots)
    • sqrt (square root)
    • cuberoot (cube root)
    • trig (sin and cos)
    • vector (position or displacement vectors)
    • exp (exponential with horizontal asymptote at y=0)
    • genexp (exponential with any horizontal asymptote)
    • log (logarithm with vertical asymptote at x=0)
    • genlog (logarithm with any vertical asymptote)
    • rational (linear/linear rational)
    • ellipse (ellipses)
    • hyperbola (vertical or horizontal hyperbolas)
  • For lines, vertical parabolas, absolute values, square roots, cubics, cuberoots, sines, cosines, exponentials, logs, and rationals (linear/linear only) give $answers as a function of x, like "2(x-1)^2+3"
  • For line segments and rays, given $answers as a function with domain, like "2x+4,-oo,3", or for vertical line segments use x= and give the range, like "x=4,-2,3"
  • For dots give $answers as "x,y", or "x,y,open" for open dots
  • For circles, give $answers as "circle,x,y,radius", like "circle,2,-1,3"
  • For ellipses, give $answers as "ellipse,x,y,x_radius,y_radius", like "ellipse,1,2,4,2"
  • For hyperbolas of form (x-h)^2/a^2-(y-k)^2/b^2=1, give $answers as "horizhyperbola,h,k,a,b"
  • For hyperbolas of form (y-k)^2/a^2-(x-h)^2/b^2=1, give $answers as "verthyperbola,h,k,a,b"
  • For horizontal parabolas give $answers as "x=equation", like "x=2(y-1)^2-3".
  • For vertical lines give $answers as "x=number", like "x=3".
  • For vectors, give $answers as "vector, x_start, y_start, x_end, y_end" for position vectors, or "vector, dx, dy" for displacement vectors

$answerformat = "polygon" can be used for drawing a single polygon; give $answer as array of points in order joined with edges.

$answerformat = "closedpolygon" can be used for drawing a single polygon that is closed; the enclosed area will be shaded and the drawing terminate when the shape is closed. The format is the same as "polygon", except make sure the first and last entry of your $answers array are identical.

$answerformat="inequality" will use a set of drawing tools for graphing linear inequalities in two variables. Give $answers for non-vertical lines in form like ">=3x+4", "<5x+4", and "x<=3" for vertical lines.

$answerformat="inequality,parab" will use a set of drawing tools for graphing quadratic inequalities in two variables. Give $answers in form like ">=x^2-4", "<x^2+1". Use $answerformat="inequality,both" to turn on lines and parabolas.

$answerformat="inequality,abs" will use a set of drawing tools for graphing absolute value inequalities in two variables. Give $answers in form like ">=abs(x-3)+4", "<3abs(x)". Use $answerformat="inequality,line,abs,parab" or some combo to turn on multiple tools.

$answerformat="numberline" will use a set of drawing tools for graphing inequalities or points in one variable on a number line. Give $answers as dots and line segments, or use the intervalstodraw function from the interval macro library to form the $answers array.

$answerformat can also be used to limit the older tools: $answerformat = "line", or $answerformat = "line,dot"

$snaptogrid = spacing
Turns on snapping, where points will jump to a grid. $snaptogrid = 1 will jump to the nearest integer. $snaptogrid = 0.5 will jump to the nearest .5. $snaptogrid = "2:4" will jump to the nearest 2 in the x and 4 in the y. Does not have to match the actual grid line spacing. Be aware that due to pixelation, the snapping may not land on exact values correctly. This is usually corrected for automatically, but it sometimes fails if the correction would be too large. In that case, use the getsnapwidthheight macro to compute an imagewidth and imageheight that will be pixel accurate.

Optional Variables

$grid = "xmin,xmax,ymin,ymax,xscl,yscl,imagewidth,imageheight"
Defines the grid to be drawn on. Defaults to "-5,5,-5,5,1,1,300,300". You can set all or just some of the values. For example, to just set the window, you could use "0,10,0,10"
If using $answerformat="numberline", set ymin and ymax to 0.
If desired, you can set separate label and grid spacing using "xmin,xmax,ymin,ymax,xlabelspacing:xgridspacing,ylabelspacing:ygridspacing,imagewidth,imageheight". You can specify axis labels using "xmin,xmax,ymin,ymax,xlabelspacing:xgridspacing:xaxislabel,ylabelspacing:ygridspacing:yaxislabel,imagewidth,imageheight". To create first quadrant graphs, use "0:-n" (for some value of n) for xmin and/or ymin to only have gridlines and labels after 0, while still using -n to adjust spacing.
$background = equation or array of equations, using the showplot macro format
Define a graph to display in the background, to be drawn on top of. Example: $background = "x^2,red".
You can also set $background a string of asciisvg commands prefaced with "draw:", like "draw:line([1,1],[3,3]);". Note that initPicture and axes will already have been called, so do not include them.
You can also set $background to "none" to remove axes and the grid.
$partweights = array or list of weights
Defines grading weight for each line or dot in $answers. Example: $partweights = ".5,.25,.25". Defaults to equal weights on each line or dot.
$reltolerance = tolerance scaling factor
Scales the grading tolerance. Defaults to 1. Set $reltolerance = 2 to make the grading twice as tolerant; $reltolerance = 0.5 to make grading half as forgiving
$abstolerance = grading cutoff
Sets all-or-nothing grading. If score < $abstolerance, the student receives 0 for the question (note: score is between 0 and 1). Otherwise the student will receive full credit. Not set by default.
$scoremethod = "takeanything", "direction", "relativelength"
When "takeanything" is used, this will give full credit for any non-blank answer. This might be of use with the freehand drawing option.
"direction" and "relativelength" are only used for vectors. "direction" will score the initial point and direction for position vectors, but not length, and will only score direction for displacement vectors. "relativelength" will score like "direction", but will also check that the drawn vectors have correct lengths relative to each other.
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the question input drawing tool in that location
$showanswer
The answer to show to students (if option if available). Defaults to the text of the correct answer. Use this to substitute a detailed answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

N-Tuple

N-Tuple questions require the student to enter an n-tuple or list of n-tuples. This can be used for coordinate points, vectors, or any other n-tuple of numbers.

Required Variables

$answer = a string containing an n-tuple or list of n-tuples
Defines the answer n-tuple or list of n-tuples. N-tuples can be any dimension, but must be surrounded by any of: (), [], {}, <>. Examples: $answer = "(1,2)", $answer = "<2,3,4>,<1,5,7>", $answer = "(1,2) or (1,3)"

Optional Variables

$displayformat = "point", "pointlist", "vector", "vectorlist", "list"
Changes the answer entry tips (does NOT change how the question is graded). For points, entry like (2,3) is specified. For vectors, entry like <2,3> is specified.
$scoremethod = "byelement"
By default, the whole n-tuple must be correct to receive any credit. Set $scoremethod = "byelement" to give partial credit if only some elements of the n-tuple are correct.
$reltolerance = a decimal value
Defines the largest relative error that will be accepted. If this is not set, a relative error of .001 (.1%) is used by default.
$abstolerance = a number
Defines the largest absolute error that will be accepted. This will override the use of $reltolerance
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the question input drawing tool in that location
$showanswer
The answer to show to students (if option if available). Defaults to the text of the correct answer. Use this to substitute a detailed answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Calculated N-Tuple

Calculated N-Tuple questions require the student to enter an n-tuple or list of n-tuples. This can be used for coordinate points, vectors, or any other n-tuple of numbers. This is identical the the N-tuple answer type, but allows students to enter mathematical expressions rather than just numbers, such as (5/3, 2/3).

Required Variables

$answer = a string containing an n-tuple or list of n-tuples
Defines the answer n-tuple or list of n-tuples. N-tuples can be any dimension, but must be surrounded by any of: (), [], {}, <>. Examples: $answer = "(1/3,2)", $answer = "<2,3,4>,<1,5,7>", $answer = "(1,2) or (1,3)"

Optional Variables

$displayformat = "point", "pointlist", "vector", "vectorlist", "list"
Changes the answer entry tips (does NOT change how the question is graded). For points, entry like (2,3) is specified. For vectors, entry like <2,3> is specified.
$answerformat = "scalarmult", "fraction", "reducedfraction", "mixednumber", "scinot", "fracordec", "nodecimal", "notrig", "nosoln", "nosolninf"
"scalarmult" will accept any answer that is a scalar multiple of the correct answer.
The other options require each component of the answer to be a single fraction (like 10/6), a reduced fraction (like 5/3), a reduced mixed number (like 2_1/2), scientific notation (like 2.3*10^4), a single fraction or decimal, an answer without decimals (also disallows 10^-2 and 3E-2), or an answer without trig functions (sin,cos,tan,sec,csc,cot). Multiple options can be specified like $answerformat="nodecimal,notrig".
$answerformat = "nosoln" or "nosolninf" adds a list radio buttons for "no solutions" and optionally "infinite solutions". $ansprompt can override the default statements like this: $ansprompt = "One value, x=;No values;Many values"
$scoremethod = "byelement"
By default, the whole n-tuple must be correct to receive any credit. Set $scoremethod = "byelement" to give partial credit if only some elements of the n-tuple are correct.
$reltolerance = a decimal value
Defines the largest relative error that will be accepted. If this is not set, a relative error of .001 (.1%) is used by default.
$abstolerance = a number
Defines the largest absolute error that will be accepted. This will override the use of $reltolerance
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the question input drawing tool in that location
$showanswer
The answer to show to students (if option if available). Defaults to the text of the correct answer. Use this to substitute a detailed answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Complex

Complex questions require the student to enter a complex number in a+bi form.

Required Variables

$answers = a string containing a complex number or list of complex numbers
Defines the answer. Example: $answer="3+2i"

Optional Variables

$answerformat = "list"
Specifies that the answer will be a list of complex numbers.
$reltolerance = a decimal value
Defines the largest relative error that will be accepted. If this is not set, a relative error of .001 (.1%) is used by default.
$abstolerance = a number
Defines the largest absolute error that will be accepted. This will override the use of $reltolerance
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the question input drawing tool in that location
$showanswer
The answer to show to students (if option if available). Defaults to the text of the correct answer. Use this to substitute a detailed answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Calculated Complex

Calculated Complex questions require the student to enter a complex number in a+bi form. This is identical to the Complex answer type, but allows students to enter mathematical expressions rather than just numbers, such as 1/3+sqrt(2)i.

Required Variables

$answer = a string containing a complex number or list of complex numbers
Defines the answer. Example: $answer="3+2i", $answer="2/3+1/3i". The answer must be given in a + bi format (so 2+3isqrt(2) or 5/2+i/3 will not work)

Optional Variables

$answerformat = "sloppycomplex", "fraction", "reducedfraction", "mixednumber", "scinot", "fracordec", "nodecimal", or "notrig"
Use "sloppycomplex" to allow the student to enter complex numbers in forms other than a+bi (allows 2+3isqrt(2) for example). Student answer must still only contain one i.
The other options requires the real and imaginary parts of the answer to be a single fraction (like 10/6), a reduced fraction (like 5/3), a reduced mixed number (like 2_1/2), scientific notation (like 2.3*10^4), a single fraction or decimal, an answer without decimals (also disallows 10^-2 and 3E-2), or an answer without trig functions (sin,cos,tan,sec,csc,cot). Multiple options can be specified like $answerformat="nodecimal,notrig".
$answerformat = "list" specifies that the answer will be a list of complex numbers. $answerformat = "nosoln" or "nosolninf" adds a list radio buttons for "no solutions" and optionally "infinite solutions". $ansprompt can override the default statements like this: $ansprompt = "One value, x=;No values;Many values"
$reltolerance = a decimal value
Defines the largest relative error that will be accepted. If this is not set, a relative error of .001 (.1%) is used by default.
$abstolerance = a number
Defines the largest absolute error that will be accepted. This will override the use of $reltolerance
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the question input drawing tool in that location
$showanswer
The answer to show to students (if option if available). Defaults to the text of the correct answer. Use this to substitute a detailed answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Numerical Matrix

The student is asked to enter a matrix of numbers (integer, decimal, or scientific notation). The entries are compared to a given tolerance.

Required Variables

$answer = string describing a matrix of numbers, or calculations leading to numbers
Defines the answer. Example: $answer = "[(1,2,3),(8/2,5,6)]" is a 2x3 matrix with first row: 1,2,3

Optional Variables

$answersize = "rows,cols"
Defines the size of the answer matrix. If this is supplied, the student will be provided with a grid of entry boxes in which to input the matrix. If this is not supplied, they will be required to enter the matrix using the ASCIIMath notation, like "[(1,2,3),(4,5,6)]"
$answerformat = "scalarmult" or "ref"
If "scalarmult" used, any scalar multiple of the correct matrix will be accepted.
If "ref" is used, any row echelon form matrix that is row equivalent will be accepted.
$reltolerance = a decimal value
Defines the largest relative error that will be accepted. If this is not set, a relative error of .001 (.1%) is used by default.
$abstolerance = a number
Defines the largest absolute error that will be accepted. This will override the use of $reltolerance
$scoremethod = "byelement"
By default, the whole matrix must be correct to receive any credit. Set $scoremethod = "byelement" to give partial credit if only some elements of the matrix are correct.
$displayformat = "det"
When $answersize is used, by default square brackets are used around the entry array. Set $displayformat = "det" to use vertical bars instead.
$ansprompt = string
A string that will be displayed in front of the input box. Example: $ansprompt="y="
$answerboxsize = number
Determines the number of characters space provided for entry of an answer. Defaults to 20. Will only be used if $answersize is not supplied.
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the question input box in that location
$showanswer
The answer to show to students (if option if available). Defaults to $answer. Use this to substitute a detailed answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Calculated Matrix

The student is asked to enter a matrix of numbers or calculations, like 2/3 or 5^2. The entries are compared to a given tolerance.

Required Variables

$answer = string describing a matrix of numbers, or calculations leading to numbers
Defines the answer. Example: $answer = "[(1,2,3),(8/2,5,6)]" is a 2x3 matrix with first row: 1,2,3

Optional Variables

$answersize = "rows,cols"
Defines the size of the answer matrix. If this is supplied, the student will be provided with a grid of entry boxes in which to input the matrix. If this is not supplied, they will be required to enter the matrix using the ASCIIMath notation, like "[(1,2,3),(4,5,6)]"
$answerformat = "scalarmult","ref","fraction", "reducedfraction", "mixednumber", "scinot", "fracordec", "nodecimal", or "notrig"
Requires the entries of the answer to be a single fraction (like 10/6), a reduced fraction (like 5/3), a reduced mixed number (like 2_1/2), scientific notation (like 2.3*10^4), a single fraction or decimal, an answer without decimals (also disallows 10^-2 and 3E-2), or an answer without trig functions (sin,cos,tan,sec,csc,cot). Multiple options can be specified like $answerformat="nodecimal,notrig".
If "scalarmult" used, any scalar multiple of the correct matrix will be accepted.
If "ref" is used, any row echelon form matrix that is row equivalent will be accepted.
$reltolerance = a decimal value
Defines the largest relative error that will be accepted. If this is not set, a relative error of .001 (.1%) is used by default.
$abstolerance = a number
Defines the largest absolute error that will be accepted. This will override the use of $reltolerance
$scoremethod = "byelement"
By default, the whole matrix must be correct to receive any credit. Set $scoremethod = "byelement" to give partial credit if only some elements of the matrix are correct.
$displayformat = "det"
When $answersize is used, by default square brackets are used around the entry array. Set $displayformat = "det" to use vertical bars instead.
$ansprompt = string
A string that will be displayed in front of the input box. Example: $ansprompt="y="
$answerboxsize = number
Determines the number of characters space provided for entry of an answer. Defaults to 20. Will only be used if $answersize is not supplied.
$hidepreview = true
Hides the Preview button. Could be useful in multipart questions, but generally not recommended
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the question input box in that location
$showanswer
The answer to show to students (if option if available). Defaults to $answer. Use this to substitute a detailed answer.
$previewloc (In Question Text)
Where you want the preview button to be located. Defaults to after the entry box if not placed in question text.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Interval

A student is asked to enter an interval notation answer. Example: (2,5]U(7,oo)

Required Variables

$answer = a string with the answer in interval notation
Defines the answer. Join multiple intervals with U for union. Example: $answer = "(-oo,4]U(3,oo)". Use DNE for empty set. Multiple acceptable answers can be entered using "or". Example: $answer = "(3,3) or [3,3]"

Optional Variables

$reltolerance = a decimal value
Defines the largest relative error that will be accepted. If this is not set, a relative error of .001 (.1%) is used by default.
$abstolerance = a number
Defines the largest absolute error that will be accepted. This will override the use of $reltolerance
$reqdecimals = a number
Defines the decimal accuracy required (ie 2 for two decimal places). This will put a message in the answer tips stating the decimals required. If neither $abstolerance or $reltolerance is set, this will set the tolerance, otherwise the provided tolerance will be used (even if it doesn't agree with the $reqdecimal setting).
$answerformat = "normalcurve" or "list"
"normalcurve" Changes the question to use a "shade the area under the normal curve" widget. Define $answer using the interval that should be shaded. Note that the shading tool only allows selection of z-values to 1 decimal place.
"list" will accept a list of comma-separated intervals like $answer="[2,3),(5,7)"
$scoremethod = "partialcredit"
By default, interval answers will be marked all right or all wrong. Setting $scoremethod = "partialcredit" will changing the scoring mode to give partial credit. (new assessment system only).
$ansprompt = string
A string that will be displayed in front of the input box. Example: $ansprompt="`x in`"
$answerboxsize = number
Determines the number of characters space provided for entry of an answer. Defaults to 20.
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the entry box in that location
$showanswer
The answer to show to students (if option if available). Defaults to the text of the correct answer. Use this to substitute a detailed answer.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Calculated Interval

A student is asked to enter an interval notation answer. Example: (2,5]U(7,oo). Values can be entered as calculations rather than numbers, like [2/5,sqrt(8)]. Can use $answerformat="inequality" to require the student to use inequalities rather than interval notation.

Required Variables

$answer = a string with the answer in interval notation
Defines the answer. Join multiple intervals with U for union, and oo for infinity. Example: $answer = "(-oo,4]U(9/2,oo)". Use DNE for empty set. Multiple acceptable answers can be entered using "or". Example: $answer = "(3,3) or [3,3]".

Optional Variables

$answerformat = "fraction", "reducedfraction", "mixednumber", "scinot", "fracordec", "nodecimal", "notrig", "list", or "inequality"
Requires the each value in the answer to be a single fraction (like 10/6), a reduced fraction (like 5/3), a reduced mixed number (like 2_1/2), scientific notation (like 2.3*10^4), a single fraction or decimal, an answer without decimals (also disallows 10^-2 and 3E-2), or an answer without trig functions (sin,cos,tan,sec,csc,cot). Multiple options can be specified like $answerformat="nodecimal,notrig".
$answerformat = "inequality" will require the student to enter an inequality rather than an interval. The instructor answer must still be given in interval notation (it will be reformatted to an inequality automatically for the Show Answer). Use $variables="y" to change the variable of the inequality.
"list" will accept a list of comma-separated intervals like $answer="[2,3),(5,7)". Does not work with "inequality".
$reltolerance = a decimal value
Defines the largest relative error that will be accepted. If this is not set, a relative error of .001 (.1%) is used by default.
$abstolerance = a number
Defines the largest absolute error that will be accepted. This will override the use of $reltolerance
$reqdecimals = a number
Defines the decimal accuracy required (ie 2 for two decimal places). This will put a message in the answer tips stating the decimals required. If neither $abstolerance or $reltolerance is set, this will set the tolerance, otherwise the provided tolerance will be used (even if it doesn't agree with the $reqdecimal setting).
$scoremethod = "partialcredit"
By default, interval answers will be marked all right or all wrong. Setting $scoremethod = "partialcredit" will changing the scoring mode to give partial credit. Note that answers not meeting $answerformat requirements will have deductions in addition to correctness checks. (new assessment system only).
$ansprompt = string
A string that will be displayed in front of the input box. Example: $ansprompt="`x in`"
$answerboxsize = number
Determines the number of characters space provided for entry of an answer. Defaults to 20.
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the entry box in that location
$showanswer
The answer to show to students (if option if available). Defaults to the text of the correct answer. Use this to substitute a detailed answer.
$previewloc (In Question Text)
Where you want the preview button to be located. Defaults to after the entry box if not placed in question text.
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Chemical Equation

A student is asked to enter a chemical formula, or use $answerformat="reaction" to ask for a reaction equation.

Required Variables

$answer = a string with the answer
Defines the answer, like "H_2O". Spaces are ignored. For reactions, use -> for a right arrow, and <-> for an equilibrium arrow, like "2H+O->H_2O".

Optional Variables

$answerformat = "reaction"
Use "reaction" if you're asking for a reaction equation.
$variables = a list of atoms
Define this to populate the equation editor with the specified atoms.
$answerboxsize = number
Determines the number of characters space provided for entry of an answer. Defaults to 20.
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the entry box in that location
$showanswer
The answer to show to students (if option if available). Defaults to the text of the correct answer. Use this to substitute a detailed answer.

Chemical Molecule Drawing

A student is asked to enter a sketch a molecule, using the Kekule drawing tool. If the student has enabled the keyboard-based drawing accessibility option, they will be presented with a textbox for them to write out a description instead.

Required Variables

$answer = "SMILES~~~CML"
Defines the answer, which includes the SMILES representation of the molecule, as well as the CML representation used for displaying the answer key. Use our answer generator to draw the answer and generate the $answer string. You can specify multiple acceptable answers separated by or, like "SMILES~~~CML or SMILES~~~CML"

Optional Variables

$displayformat (In Common Control)
Set to "condensed" to display the atom labels on the drawing.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the entry box in that location
$showanswer
The answer to show to students (if option if available). Defaults to a drawing of the correct answer. Use this to substitute a detailed answer.

File Upload

A student is asked to upload a file. The file upload type is not automatically graded.

Required Variables

None - the file upload type is not computer graded.

Optional Variables

$scoremethod = "takeanything" or "takeanythingorblank"
Sets the problem to give full credit for any answer. The latter also counts blank answers as correct.
$answerformat = "images", "canpreview", or a list of file extensions
Set a list of preferred file formats for the file selector. "images" is a shorthand for .jpg,.gif,.png,.jpeg. "canpreview" is a shorthand for image files, office files, and pdfs, which can be previewed inline. If listing file extensions, provide a comma separated list with leading periods, like ".pdf,.docx,.doc"
$readerlabel = string
A string that will be used as a visually hidden label on the input box for screenreaders.
$answerbox (In Question Text)
Using the variable $answerbox in the Question Text will place the file upload box in that location
$showanswer
The answer to show to students (if option if available).
$hidetips = true
Hides the question entry tips that display by default. This should only be used when a question type is being used in an unintentional way, or if the question type gives away critical info to the student.

Code

The Code question type embeds a full code editor (CodeMirror 6) with sandboxed execution directly in the assessment. Students write, run, and test code in their browser. It supports six languages with different editor layouts, optional test cases, static code checks for auto-scoring, and AI-powered progressive hints.

Note: Code questions are designed for use as standalone questions. While the "code" type can technically be used within Multipart or Conditional questions, the full-featured editor with multiple panels works best as a dedicated question. For embedding syntax-highlighted code in any question’s text, see the Code Samples in Question Text section below.

Code Questions › AI Authoring Reference — the Author-with-AI toolbar, the portable bundle format, and the template gallery →

Supported Languages

$codelanguage valueDisplay NameEditor LayoutDescription
javascriptJavaScriptSingle editor + consoleFull-width editor with console output below. Runs natively in the browser.
pythonPythonSingle editor + consoleFull-width editor with console output below. Runs via Pyodide (WebAssembly) entirely in the browser — no server-side Python needed. First run may take a moment to load.
p5jsp5.jsEditor + canvas previewEditor panel with a live canvas preview for creative coding and visualizations. Uses the p5.js library loaded from CDN.
htmlHTMLEditor + iframe previewSingle HTML editor with a live iframe preview.
htmlcssHTML + CSSStacked editors + previewHTML and CSS editors stacked vertically with a live iframe preview.
htmlcssjsHTML + CSS + JSTabbed editors + previewThree tabbed editors (HTML, CSS, JavaScript) with a live iframe preview.

Required Variables

None — the code type uses manual grading by default. Set $scoremethod = "auto" with $codechecks for automatic scoring.

Optional Variables — Language & Editor

$codelanguage = "javascript" | "python" | "p5js" | "html" | "htmlcss" | "htmlcssjs"
Selects the programming language and editor layout. See the table above. Defaults to "javascript".
$answerboxsize = "width,height"
Editor dimensions in pixels. Defaults to "600,550". Can also specify height only (e.g., "400"). Minimum: 300 width, 200 height.
$p5canvassize = "width,height"
p5.js only. Canvas dimensions in pixels. Defaults to "400,400". Can specify a single number for a square canvas.
$instructions = "HTML string"
HTML-formatted instructions displayed above the editor area, inside the editor container. Useful for brief guidance that should appear close to the editor rather than in the question text.

Optional Variables — Starter Code

$startercode = "code string"
Initial code shown when the student opens the question. For single-file languages (javascript, python, p5js, html). Use \n for line breaks within the string.
$startercode_html = "HTML code"
HTML starter code for multi-file languages (htmlcss, htmlcssjs). Appears in the HTML tab/editor.
$startercode_css = "CSS code"
CSS starter code for multi-file languages (htmlcss, htmlcssjs). Appears in the CSS tab/editor.
$startercode_js = "JavaScript code"
JavaScript starter code for htmlcssjs only. Appears in the JS tab.
Tip: You don’t need to write escaped strings by hand. The Code Settings Helper in the question editor provides visual code editors for each file — just paste your code in; it’s written into the control code automatically when you save the question.

Optional Variables — Scoring

$scoremethod = "manual" | "auto" | "takeanything" | "takeanythingorblank"
  • manual (default): Requires teacher grading. Non-blank submissions are flagged for review.
  • auto: Automatically scores based on $codechecks and/or $codetests (when $codetestscoring = true). Score is the weighted ratio of passed checks and tests.
  • takeanything: Full credit for any non-blank, non-starter submission.
  • takeanythingorblank: Full credit for any submission, including blank.
Note: Empty submissions and submissions identical to the starter code always receive a score of 0, regardless of the scoring method.

Optional Variables — Test Cases

Note: Test cases are available for JavaScript and Python only. By default, tests are a learning tool — students click “Run” to see if their code passes. When $codetestscoring = true, test results also contribute to the auto-score alongside code checks.
$codetests = JSON string
A JSON array of test case objects. Each object has "call" (the function call to execute), "expected" (the expected return value as a string), and an optional "weight" (numeric, default 1).
Example: $codetests = "[{\"call\":\"add(2,3)\",\"expected\":\"5\"},{\"call\":\"add(-1,1)\",\"expected\":\"0\",\"weight\":2}]"
$codevisibletests = JSON string
A JSON array of zero-based indices specifying which tests are visible to students. If not set, all tests are visible. Hidden tests still run when students click Run, but students only see the visible ones.
Example: $codevisibletests = "[0,1]" — shows only the first two tests, hides the rest.
$codetestscoring = true
When set, test results are included in the auto-score calculation. Tests execute client-side in the sandbox and results are submitted with the answer. If a student never clicks Run, all tests count as failed. The combined scoring formula is: score = (sum of passed check weights + passed test weights) / (sum of all check weights + all test weights)
Requires $scoremethod = "auto". Can be used together with code checks or on its own.

Optional Variables — Code Checks

Code checks perform static analysis of the student’s source code. They inspect the code text (not runtime output) and work with all languages. Code checks can serve as a feedback tool (with $showcodechecks) and/or as an auto-scoring source (with $codechecksscoring).

$codechecks = JSON string
A JSON array of check objects. Each check has a "type" and type-specific properties, plus optional "label" (custom display text) and "weight" (numeric, default 1). See the reference table below.
$codechecksscoring = true
When set, code checks are included in the auto-score calculation. Scoring formula: score = (sum of passed check weights) / (sum of all check weights)
Requires $scoremethod = "auto". Can be used together with test case scoring or on its own.
$showcodechecks = true
When true, displays a “Code Check Results” panel after submission showing which checks passed or failed with their labels. Helps students understand what they need to implement.
Backward compatibility: Existing questions with $codechecks and $scoremethod = "auto" but no $codechecksscoring flag will continue to work as before — code checks automatically participate in scoring. The explicit flags are only required when using the Settings Helper or when combining code checks with test case scoring.

Code Check Types Reference

TypeRequired PropertyWhat It Checks
contains_function "name": "funcName" Source defines a function with the given name.
JS: function name(), const name = () =>, etc.
Python: def name():
contains_class "name": "ClassName" Source defines a class with the given name.
contains_call "name": "funcName" Source calls the given function (e.g., funcName(...)).
contains_keyword "keyword": "text" Source contains the text (case-insensitive substring match).
not_contains "keyword": "text" Source does not contain the text (case-insensitive). Use to restrict forbidden approaches.
regex "pattern": "regexPattern" Source matches the regular expression pattern.
min_lines "count": number Source has at least this many non-empty lines.

All check types support optional "label" (custom student-facing text) and "weight" (numeric, default 1). For multi-file languages, add "file": "html" (or "css", "js") to check only that file.

Optional Variables — AI Hints

Progressive AI-powered hints guide students toward the solution without giving the answer away. Hints automatically escalate from vague (early) to specific (later) based on the student’s progress.

$codeHintsEnabled = true
Enables the “Hint” button in the editor toolbar.
$codeHintsMax = number
Maximum hints per attempt (1–10). Defaults to 3.
$codeHintsQuestionPrompt = "text"
Custom context for this specific question, appended to the AI system instruction. Use this to guide the AI’s teaching strategy.
Example: $codeHintsQuestionPrompt = "Guide students toward using recursion. Do not reveal the base case until the final hint."
Note: A course-level AI system prompt can be configured in Course Settings > AI Code Hints. The question-level prompt is appended to it. Teachers can view the full AI prompt and all hints given to a student when reviewing submissions (teacher transparency).

Optional Variables — Student Images

Attach images the student can reference in their own code (for example, copy a URL into an <img src="..."> tag). Images are uploaded to / chosen from the same media library used by Interactive2 questions, so they are reusable across questions. The easiest way to manage them is the Student Images panel in the Code Settings Helper (Upload image / Choose from library).

$codeimages = JSON string
An array of {url, name, media_id} objects. Students see these behind an “Images” button in the editor toolbar, which opens a panel listing each image (thumbnail, name, and a copy-able URL). The URLs are not inserted into the question source — surfacing them is the point, since using an image URL in markup is the skill being practiced.
Example: $codeimages = "[{\"url\":\"https://…/diagram.png\",\"name\":\"diagram\",\"media_id\":123}]"
Tip: Because these images live in the shared library, deleting one that a code question still uses is blocked — remove it from the question (Student Images panel) and save first.

Optional Variables — Accessibility & Display

$readerlabel = string
Visually hidden label for screenreaders. Defaults to “Code editor.”
$answerbox (In Question Text)
Using the variable $answerbox or the shorthand [AB] in the Question Text will place the code editor in that location.
$showanswer
The answer to show to students. Defaults to generic text since code answers vary.
$hidetips = true
Hides the question entry tips that display by default.

The Code Settings Helper

When the question type is set to “Code,” a Code Settings Helper panel appears in the question editor. It provides a visual interface for all the settings above:

  • Language dropdown
  • Syntax-highlighted starter code editors (one per file for multi-file languages)
  • Test case table with add/remove rows and visibility checkboxes
  • Code check table with type selection, properties, labels, and weights
  • Score method dropdown
  • AI hints toggle with max hints and custom prompt fields

Your settings are written into the Common Control code automatically when you save the question. You never need to write the escaped JSON strings by hand.

Author with AI

Above the helper is an Author-with-AI toolbar that can build or revise a whole Code question for you:

  • Draft / Adapt with AI — describe a question in a sentence and the built-in assistant fills in the whole helper (or adapts what’s already there). Requires an AI provider configured for the site.
  • Browse Templates… — a gallery of ready-made questions (JavaScript, Python, web, p5.js) you can drop in and edit.
  • AI Instructions + Copy My Code + Paste AI Response — round-trip the question through any AI chat (Claude, ChatGPT, Gemini) using a portable plain-text bundle: copy the instructions into your chat, work on the question there, then paste the reply back to fill the helper.
  • What’s New — recent changes to the Code authoring tools.
Full guide: see Code Questions › AI Authoring Reference for the toolbar in detail, the bundle format (the ===== SECTION ===== blocks the AI exchanges), and the template gallery.

Examples

Expand each example below to see a complete Common Control block for that language.

Example — JavaScript (Auto-Scored with Tests, Code Checks & AI Hints)

A function-writing question with visible + hidden test cases, weighted code checks, and AI hints.

// ========================================
// Code Question Settings
// ========================================
$codelanguage = "javascript"
$scoremethod = "auto"
$startercode = "function factorial(n) {\n  // Write your code here\n\n}\n\n// Test it out:\nconsole.log(factorial(5)); // Should print 120"
$answerboxsize = "600,400"
$codetests = "[{\"call\":\"factorial(0)\",\"expected\":\"1\"},{\"call\":\"factorial(1)\",\"expected\":\"1\"},{\"call\":\"factorial(5)\",\"expected\":\"120\"},{\"call\":\"factorial(10)\",\"expected\":\"3628800\"}]"
$codevisibletests = "[0,1,2]"
$codechecks = "[{\"type\":\"contains_function\",\"name\":\"factorial\",\"label\":\"Defines factorial function\",\"weight\":1},{\"type\":\"not_contains\",\"keyword\":\"Math.\",\"label\":\"Implements without Math library\",\"weight\":0.5}]"
$showcodechecks = true
$codeHintsEnabled = true
$codeHintsMax = 3
// ======== End Code Settings ========
Example — Python (Custom AI Hint Prompt)

A palindrome checker with hidden edge-case tests and a custom AI teaching strategy.

// ========================================
// Code Question Settings
// ========================================
$codelanguage = "python"
$scoremethod = "auto"
$startercode = "def is_palindrome(text):\n    # Write your code here\n    pass\n\n# Test it out:\nprint(is_palindrome('racecar'))  # Should print True\nprint(is_palindrome('hello'))    # Should print False"
$answerboxsize = "600,400"
$codetests = "[{\"call\":\"is_palindrome('racecar')\",\"expected\":\"True\"},{\"call\":\"is_palindrome('hello')\",\"expected\":\"False\"},{\"call\":\"is_palindrome('A man a plan a canal Panama')\",\"expected\":\"True\"}]"
$codevisibletests = "[0,1]"
$codechecks = "[{\"type\":\"contains_function\",\"name\":\"is_palindrome\"},{\"type\":\"contains_call\",\"name\":\".lower\",\"label\":\"Converts to lowercase\"},{\"type\":\"contains_call\",\"name\":\".replace\",\"label\":\"Removes spaces\"}]"
$showcodechecks = true
$codeHintsEnabled = true
$codeHintsMax = 5
$codeHintsQuestionPrompt = "Guide the student toward using .replace(' ', '') to remove spaces and .lower() to normalize case, then comparing the string to its reverse using slicing [::-1]. Do not reveal the slicing syntax until later hints."
// ======== End Code Settings ========
Example — p5.js (Canvas Preview, Manual Grading)

A creative coding question where students add a Player class to a Space Invaders game. Manual grading with AI hints.

// ========================================
// Code Question Settings
// ========================================
$codelanguage = "p5js"
$scoremethod = "manual"
$p5canvassize = "500,500"
$answerboxsize = "900,600"
$startercode = "let allAliens = [];\nlet allBullets = [];\n\nfunction setup() {\n  createCanvas(500, 500);\n  allAliens.push(new Alien(20));\n  allAliens.push(new Alien(80));\n  allAliens.push(new Alien(140));\n}\n\nfunction draw() {\n  background(20, 20, 40);\n  for (let i = 0; i < allAliens.length; i++) {\n    allAliens[i].display();\n    allAliens[i].move();\n  }\n  // TODO: Add player display and movement here\n}\n\n// TODO: Create a Player class here\n\nclass Alien {\n  constructor(x) {\n    this.x = x;\n    this.y = 20;\n    this.w = 40;\n    this.h = 40;\n    this.speed = 2;\n    this.direction = 0;\n  }\n  display() {\n    fill(0, 0, 255);\n    rect(this.x, this.y, this.w, this.h, 15);\n  }\n  move() { /* alien movement logic */ }\n}"
$codeHintsEnabled = true
$codeHintsMax = 5
$codeHintsQuestionPrompt = "Guide students toward creating a Player class with constructor, display, and move methods. Use triangle() for the ship shape and keyIsDown(LEFT_ARROW)/keyIsDown(RIGHT_ARROW) for movement."
// ======== End Code Settings ========
Note: loadImage() does not work in the sandbox because there is no filesystem. Use p5.js shape-drawing functions (ellipse, rect, triangle, circle, line, arc, etc.) instead of image files.
Example — HTML (Simple Preview)

A basic HTML page with live preview and take-anything scoring.

// ========================================
// Code Question Settings
// ========================================
$codelanguage = "html"
$scoremethod = "takeanything"
$startercode = "<!DOCTYPE html>\n<html>\n<head>\n  <title>My Page</title>\n</head>\n<body>\n  <h1>Hello World</h1>\n  <p>Add your content here.</p>\n</body>\n</html>"
$answerboxsize = "800,500"
// ======== End Code Settings ========
Example — HTML + CSS (Stacked Editors)

A styled card exercise with HTML and CSS editors side by side, plus code checks for required CSS properties.

// ========================================
// Code Question Settings
// ========================================
$codelanguage = "htmlcss"
$scoremethod = "auto"
$startercode_html = "<div class=\"card\">\n  <h2>Card Title</h2>\n  <p>Card content goes here.</p>\n</div>"
$startercode_css = ".card {\n  /* Add your styles here */\n}"
$answerboxsize = "900,500"
$codechecks = "[{\"type\":\"contains_keyword\",\"keyword\":\"border-radius\",\"label\":\"Uses border-radius\",\"file\":\"css\"},{\"type\":\"contains_keyword\",\"keyword\":\"box-shadow\",\"label\":\"Uses box-shadow\",\"file\":\"css\"}]"
$showcodechecks = true
// ======== End Code Settings ========
Example — HTML + CSS + JS (Tabbed Editors, Manual Grading)

An interactive component with three tabbed editors and manual grading.

// ========================================
// Code Question Settings
// ========================================
$codelanguage = "htmlcssjs"
$scoremethod = "manual"
$startercode_html = "<div class=\"component\" id=\"myComponent\">\n  <h2>My Component</h2>\n  <p>Replace this with your own content.</p>\n  <button id=\"actionBtn\">Click Me</button>\n</div>"
$startercode_css = "body {\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  min-height: 100vh;\n  margin: 0;\n  background: #f5f5f5;\n  font-family: Arial, sans-serif;\n}\n\n.component {\n  background: white;\n  border-radius: 8px;\n  padding: 20px;\n  max-width: 300px;\n  box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n}\n\n/* Add a hover effect below */"
$startercode_js = "// Add a click handler for the button\ndocument.getElementById('actionBtn').addEventListener('click', function() {\n  // Make something happen when clicked!\n\n});"
$answerboxsize = "900,500"
$codeHintsEnabled = true
$codeHintsMax = 3
// ======== End Code Settings ========

Interactive2

The Interactive2 question type is a fully custom interactive widget — animation, simulation, 3D visualization, physics demo — built from JavaScript that runs in a sandboxed iframe inside the student's browser. Scoring runs on the server in an isolated V8 sandbox. Use Interactive2 when no other question type can represent what you want the student to do: dragging a charge in a magnetic field, tuning a pendulum until its period matches, rotating a 3D molecule to match a target orientation, and so on.

Tip: Most Interactive2 questions are written with the help of an AI assistant. This section includes a Copy AI Prompt button that gives you a complete system prompt; paste it into Claude or ChatGPT followed by your question idea, and the AI returns code you can drop straight into the three editors.

Three code sections

An Interactive2 question has three separate editors in the question editor panel. They flow data through three stages of execution:

  1. Variables (PHP) — YourWay Math Academy-style PHP that runs server-side when the question is generated. Randomizes the problem. A variable like $length = rand(5, 15) / 10.0; becomes available in the UI code as CONFIG.length and in the scoring code as VARS.length. Standard PHP math (sin, cos, sqrt, sprintf, etc.) plus YourWay Math Academy helpers rand, rrand, rands, roundsigfig, decimaltofraction, getRoundNumber are available. The preprocessor rewrites bare piM_PI and eexp(1) — write them without parens.
  2. UI Code (JavaScript) — Runs in a sandboxed iframe in the student's browser. Four globals are in scope:
    • container — DOM element to render into.
    • CONFIG — frozen object of the PHP variables above.
    • STATE — mutable object. Writes auto-sync to the server every 2 seconds and on submit. Prior STATE is restored on reload. If you don't write to STATE, the student's work won't persist and scoring will see nothing.
    • qnId — question number as a string. Use it to make unique DOM IDs when more than one question may appear on the page.
  3. Scoring Code (JavaScript) — Runs on the server in an isolated V8 sandbox when the student submits. Students never see this code. Four globals:
    • VARS — the PHP variables.
    • RESPONSE — the student's STATE object.
    • SCORE — you set this to a number from 0 to 1.
    • FEEDBACK — you set this to a short string shown to the student.
    Five-second execution timeout. Handle missing keys defensively (RESPONSE.count || 0).

Sandbox rules (UI code)

  • No window.parent, no form submission, no top-level navigation.
  • allow-scripts allow-same-origin allow-modals are on (alert/prompt/confirm work).
  • The sandbox is served from the same origin as the main site, so same-origin fetches and relative URLs just work.

Multi-checkpoint scoring (one question → multiple graded parts)

A single Interactive2 question can ask the student to complete several independent sub-tasks and score each one separately. This is how you build multi-step problems — "identify the slope, then the y-intercept, then evaluate the line at a point" — without creating a native multi-part question. Each sub-task is called a checkpoint. Multi-checkpoint mode is opt-in: write a flat scoring block for single-score questions, or provide a checkpoints array when you want per-part grading.

How it works:

  • Each checkpoint has its own scoring code. The Settings panel exposes a "Checkpoints" editor where you add any number of checkpoints. Every one has an id, a human-readable label, an optional weight (default 1), a showAnswer string, and its own JavaScript scoring block.
  • Checkpoints share one STATE. The UI still uses the single STATE object. By convention, store each checkpoint's value under a key matching its id: if the checkpoint is id: 'slope', write STATE.slope. The server uses this convention to know which checkpoints the student actually attempted on this submit (see "Per-part tries" below).
  • Scoring code has an extra global: ATTEMPTED. In a checkpoint's scoring block the same sandbox as single-scoring applies (VARS, RESPONSE, SCORE, FEEDBACK) plus one addition: ATTEMPTED. Set ATTEMPTED = false when the student hasn't provided a value for this checkpoint (e.g. RESPONSE.slope is missing or empty). Unattempted checkpoints do not consume a try. RESPONSE is still the full STATE object — a checkpoint can cross-reference other checkpoints' inputs freely.
  • Per-part tries. The question's Tries setting applies per checkpoint. If Tries = 3 and the student gets the slope right on the first submit but the intercept wrong, only the intercept's try counter increments — they still have 2 more tries on the intercept without losing any on the slope.
  • Best-try-wins scoring. Each checkpoint's final score is the highest score across all its tries. If a student gets a checkpoint right, then edits and resubmits and gets it wrong, the earlier correct answer still counts. Total question score = weighted average of the per-checkpoint best scores.
  • Per-checkpoint visual indicators. Call addResultIndicator(el, checkpointId) from the UI code to attach a small status icon next to a prompt. The sandbox updates it automatically: green check for a correct last submit, red X for incorrect, yellow half-circle for partial credit, purple pencil when the student has edited since the last submit. No author code needs to update the icon — just place it once.

Authoring a checkpoint's scoring code:

// Example scoring block for a checkpoint with id "slope":
var expected = VARS.m;
var ans = (RESPONSE.slope == null) ? NaN : parseFloat(RESPONSE.slope);
if (!isFinite(ans)) {
  ATTEMPTED = false;      // don't burn a try
  SCORE = 0; FEEDBACK = 'Enter the slope.';
} else if (Math.abs(ans - expected) < 0.01) {
  SCORE = 1; FEEDBACK = 'Correct!';
} else {
  SCORE = 0; FEEDBACK = 'Not quite — look for the coefficient of x.';
}

The scoring code for all checkpoints runs in a single server request per submit — the sandbox batches them behind a single Cloud Function call, so adding more checkpoints has negligible latency cost.

When to use checkpoints vs. a single score: Use a single score when there's one correct outcome (did the pendulum's period hit the target? did the student assemble the molecule?). Use checkpoints when the question has distinct sub-answers the student should get separate feedback on, or when each sub-answer deserves its own tries budget.

Answer Review (server-rendered worked solution)

The Answer Review pane is a 4th, optional editor in the Interactive2 settings panel. It holds HTML (not JavaScript) that the platform renders server-side as a sibling of the iframe — only after the question is settled. Use it to publish a worked solution that uses the student's randomized values.

The AR block appears when every checkpoint is correct, OR every checkpoint is exhausted (tries used up with zero credit). Until then, the block is not in the DOM at all — nothing CSS-hidden, nothing for a determined student to inspect. Teachers always see the AR in course/testquestion2.php preview, with a yellow "Teacher preview" banner.

The AR pane also respects the assessment's Show answer setting and any per-question override — exactly like a standard detailed solution. If Show answer is set to Never, students never see the AR even after the question settles.

Variable interpolation. Variables from the Variables pane interpolate as $name:

<p>The slope is <strong>m = $m</strong>.</p>
<p>Substituting x = $xval gives y = $_y_at_x.</p>

The _-prefix convention. Every variable from the Variables pane is shipped to the iframe as CONFIG.<name> — readable from DevTools the moment the page loads. To keep an answer-key value out of CONFIG, prefix the variable name with an underscore:

$m = rand(-4, 4);              // visible in CONFIG (UI renders it)
$xval = rand(2, 7);             // visible in CONFIG
$_y_at_x = $m * $xval + $b;     // server-only — stripped from CONFIG

Underscore-prefixed variables are still available to the AR template (which runs server-side) and to scoring code (which receives the full $variables). Only the iframe's CONFIG is filtered.

Style hooks (no inline style strings needed): .i2-rule-of-thumb, .i2-big-idea, .i2-math-wrap, .i2-sum-hdr, .i2-sum-body, .i2-sum-ans. Math via $$..$$ (display) or \(..\) (inline).

See Interactive2 Stdlib Reference › Answer Review HTML for the full spec, allowed tags, error handling, and a worked example.

AR Chat (Socratic AI tutor below the worked solution)

Whenever a question has an Answer Review and AI services are configured for the site, a "Buddy" chat panel sits alongside the worked solution. On wide containers (≥ 1100px) the AR and chat render side by side — the chat sticks in the right column while the student scrolls the AR — and on narrower screens the chat collapses underneath as a normal block. Container queries decide, so the layout responds to the question's available width rather than the viewport.

The student can highlight any text in the worked solution — a step, an equation, a definition — and that selection becomes a quoted blockquote at the top of their next message. Enter sends; Shift+Enter inserts a newline. Replies render in markdown with KaTeX-rendered math. The AI can also embed [focus:<anchor-id>] markers inline to point at specific AR sections; the chat client renders each as a clickable pill that scrolls and spotlights the targeted div in ochre. Anchors auto-generate for .i2-sum-hdr / .i2-math-wrap / .i2-rule-of-thumb / .i2-big-idea; for precise control add data-i2-anchor="my-name" attributes in the AR HTML.

Step palette. Every .i2-sum-hdr in the AR also gets a leading colored numbered badge (8-color palette: Indigo, Emerald, Amber, Rose, Sky, Violet, Teal, Fuchsia — steps 9+ wrap). The AI is told the step list and prefers [step:N] over [focus:auto-step-N]; the chat pill renders in the same color as the matching AR badge, so a "Step 2" reference reads as a single visual idea rather than two disconnected artifacts. Authors don't write [step:N] — just structure your worked solution with .i2-sum-hdr headings and the system numbers + colors them. Badges render even when chat is disabled.

Default ON, opt out per question. The chat panel renders automatically whenever the AR renders. To hide it on a specific question, add to the Variables pane:

$interactive2_ar_chat_disabled = true;

Optional per-question knobs:

$interactive2_ar_chat_max_messages = 12;   // default 8 (range 1–20)
$interactive2_ar_chat_context = <<<'AR_CHAT_CTX'
Focus on chain-rule reasoning. Never give the closed-form derivative.
AR_CHAT_CTX;
$interactive2_ar_chat_starters = <<<'AR_CHAT_STARTERS'
Walk me through step 1
Why isn't the answer just $mass times $accel?
Give me a similar problem to try
AR_CHAT_STARTERS;

The starters block (max 4 lines) is the only source of suggestion chips. If you leave it blank, no chips appear — there is no auto-derive or static fallback. $variable syntax is interpolated against this version, so chips can reference per-version values. LaTeX delimiters \(..\), \[..\], $$..$$, and [latex]..[/latex] render via KaTeX in the chip itself; single $..$ is NOT a delimiter (clashes with $variable). The four AR chat settings round-trip through the Copy My Code / Paste AI Response buttons via a ===== AR CHAT ===== section, so the AI can propose chip wording and you can accept it with one paste.

For an end-to-end demo of every AR capability (multiple anchor kinds, an explicit data-i2-anchor, server-only _* answer-key vars, LaTeX-rendered starters, per-question teacher context), open the template gallery and load "AR Chat Showcase — Coulomb force" under the AI Chat category.

Security model. The AI sees the question prompt, the rendered worked solution, the student's last RESPONSE/STATE, and the FULL $variables — including _*-prefixed server-only keys (the answer key). The student NEVER sees any of that beyond what the AI chooses to say. The default system prompt forbids verbatim disclosure of _* variables and instructs the AI to respond Socratically (one focused question at a time, acknowledge what the student got right, never blurt the answer). The 8-message cap is the second line of defence. The conversation is logged server-side per (student, assessment, question) and survives page reloads; teachers can override the system prompt course-wide via Course Settings › "AI Interactive2 Answer Review Chat Instructions".

Sequential sections (unlock one part at a time)

By default every checkpoint is visible at once. For scaffolded questions — "answer Section 1, then Section 2 unlocks" — you can gate any DOM element on prior checkpoints being done. This mirrors the /// separator in native multi-part questions but works purely in the authored UI code.

Two attributes do all the work:

  • data-checkpoint="<id>" — Mark the DOM element that holds a checkpoint's input(s). Used by the section-state engine to know which checkpoint lives inside which section.
  • data-reveal-after="<id>" or data-reveal-after="<id1>,<id2>" — Put this on a section wrapper (typically a <fieldset>) that should stay hidden until the listed checkpoints are done. A comma-separated list means AND: every listed checkpoint must be done. A checkpoint counts as done when the student has scored it correctly or used up all their tries on it.

Minimal example — two sections, the second gated on the first's two checkpoints:

container.innerHTML =
  '<fieldset>' +
  '  <legend>Section 1 — Identify the coefficients</legend>' +
  '  <div data-checkpoint="slope">...slope input...</div>' +
  '  <div data-checkpoint="intercept">...intercept input...</div>' +
  '</fieldset>' +
  '<fieldset data-reveal-after="slope,intercept">' +
  '  <legend>Section 2 — Evaluate at a point</legend>' +
  '  <div data-checkpoint="evaluation">...evaluation input...</div>' +
  '</fieldset>';

What the student sees:

  • Only the current, unlocked section is visible. Gated sections are display:none until their gate opens.
  • The sandbox auto-applies section border colors: solid grey for done, blue (2px) for active (the first unlocked section with work remaining), dashed grey for pending (unlocked but later). Hidden sections stay invisible.
  • When the question contains two or more sections, a small "(X of Y)" counter is injected into each section's <legend> so the student knows where they are.
  • The Submit button relabels itself to "Submit Section" when the question uses data-reveal-after. Nothing extra to configure — the server detects the attribute in the UI code and tells the player to swap the label.
  • In the authoring preview (testquestion2.php), all sections are revealed at once so you can test each one without having to answer prior sections correctly. A blue banner at the top of the preview reminds you that students will see them one at a time.
What counts as a "section": Any <fieldset> or element with data-section that contains one or more [data-checkpoint] descendants. You don't have to use <fieldset>, but it pairs naturally with <legend> for section titles and the auto-injected counter.
Instant re-evaluation: Gates re-evaluate after every submit (the iframe reloads with fresh checkpoint scores). If you need to force a re-evaluation from custom JavaScript — e.g. your UI should reveal a section based on a condition that isn't a checkpoint — call window.__i2_applyRevealGates() and window.__i2_applySectionStates() from your UI code.

Tabbed and gallery section layouts

A long multi-checkpoint walkthrough (4–6 sections of instructions, hints, and inputs) becomes a lot of vertical scrolling inside the iframe. To keep the student focused on one section at a time, the question can opt into a different layout via a single line in the Variables block:

$interactive2_section_layout = 'tabs';     // or 'gallery', or omit for the default vertical stack

The toggle also lives in the Interactive2 Settings panel: when scoring mode is Multiple checkpoints, a Section layout dropdown appears next to the checkpoint editor with the same three values. Picking a value there writes the line into the Variables block for you on Apply.

What changes — and what doesn't:

  • UI code is unchanged. Each <fieldset> (or [data-section]) that contains a [data-checkpoint] becomes a tab/panel automatically. You don't write any tab markup.
  • STATE is shared across sections in every layout. A value the student typed in tab 1 is available to UI code, scoring code, and AR templates in every other section — data still passes between sections exactly like the default vertical layout.
  • Reveal-gates still apply. A section gated by data-reveal-after appears as a disabled (greyed, lock icon) tab/dot until its gate opens, so the student sees the full roadmap without being able to skip ahead. When the gate opens on the next Submit, the tab unlocks.
  • Status icons mirror the section state. Tabs show ✓ for done, the section number for active/pending, and a 🔒 for locked. Gallery dots use color (green for done, blue for the current section, grey otherwise).
  • Submit, scoring, and Answer Review behave identically. Submit posts the whole STATE to scoring; AR renders below the iframe once every checkpoint is settled.
  • Authoring preview flattens to vertical. In course/testquestion2.php, all sections render stacked so authors can see and test each section without paging through tabs. Students still see one section at a time.

When to pick which:

  • Default (vertical) — Best for 1–3 sections with short bodies. Keeps the linear narrative feel of the existing walkthrough templates.
  • Tabs — Best for 3–6 sections of moderate length. The full set is visible as a roadmap, students click between them, and the tab strip horizontally scrolls on phones.
  • Gallery — Best for 4+ sections, very long sections, or when phone use is the dominant case. One section at a time fills the iframe; Prev/Next buttons advance through unlocked sections.

Mobile behavior: The tab strip uses overflow-x:auto so students on narrow viewports can swipe the strip horizontally. The gallery's Prev/Next + dot indicators are sized to fit a phone-portrait viewport without wrapping.

Tab label font size

Tab labels render at 15px by default — the same size as body text and rendered math, so labels containing inline LaTeX (e.g. \vec{E} Field 1, \vec{F}_e\uparrow < \vec{F}_g\downarrow, PE → KE) sit comfortably alongside the question content. If a particular question has a long label that crowds the strip, or you want a slightly smaller/larger size for a stylistic reason, override per question with a single line in the Variables block:

$interactive2_tab_font_size = '14px';   // or '13px', '16px', '1.1em', etc. — omit for the 15px default

Accepts any numeric value with a px, em, rem, or % unit (bare numbers are treated as px). Only applies when $interactive2_section_layout = 'tabs'; — gallery dots have no labels and the default vertical layout has none either. The override field also appears in the Interactive2 Settings panel, in the same row as the Section layout dropdown, when Tabs is selected.

Smart hint visibility toggle

Any question whose UI Code renders <details> hint cards automatically gets a small 💡 Hints (N) button in the sandbox header. Clicking it bulk-opens or closes every <details> in the currently visible section/tab/panel — so a student peeking at the hints in tab 1 doesn't get tab 2's spoilers along with them. Per-card clicks still work and override the global state.

The button auto-hides itself when the question has zero <details> blocks, and goes disabled (greyed with a "No hints in this section" tooltip) when the currently visible scope has none. There's nothing to set up — write <details> blocks in your UI Code as usual and the toggle appears for free.

Opt-out for assessments. For quizzes, exams, and summative labs where revealing all hints at once would defeat the assessment, tick Disable the bulk hints toggle for this question in the Interactive2 Settings panel — or write directly in the Variables block:

$interactive2_hints_toggle_disabled = true;

Polarity matches AR Chat: default false means the toggle is ON; absence of the line means it's enabled.

Media files (images, audio, video)

Interactive2 questions reference media through stable placeholders — tokens like {{image:hero}}, {{audio:heartbeat}}, or {{video:demo}}. You write the placeholder in your code; the platform replaces it with a real URL at save time. You never paste raw Firebase URLs into question source, so renames and replacements just work. There are two equivalent places to add media:

From the editor (recommended for new questions). Open an I2 question in course/moddataset.php and you'll see a Media Library panel right above the Variables editor. Drop image / audio / video files there; each upload asks for a short reference name — e.g. hero, pendulum, fbd_demo. The tile then shows you the {{type:name}} token, and the Insert button drops it into whichever code editor was last focused (Variables / UI Code / Scoring / Answer Review). Click Pick from library… at the top of the panel to reuse a file you uploaded for another question — same picker as the test page, scoped to your media.

Use the placeholder in your code — the same way in UI Code and in Answer Review HTML:

// UI Code
container.innerHTML = '<img src="{{image:hero}}" alt="Heart diagram">';

// Answer Review HTML
<img src="{{image:hero}}" style="max-width:100%">

Save the question. The auto-linker scans every {{type:name}} in your saved code and inlines the matching file's URL. The save flash reports “Auto-linked N media placeholder(s)”. Same auto-link runs whenever you save — including after a Paste AI Response — so pre-staging media first lets the AI write code that references it by name. The Copy AI Prompt output even includes a read-only ===== MEDIA ===== section listing every reference + URL + tags so the AI knows what's available.

From the test page (write placeholders first, upload later). If you write or paste code that references media you haven't uploaded yet — very common with AI-drafted questions — just save it with the placeholders in place. Open the question in course/testquestion2.php and you'll see a Media slots panel listing each unresolved placeholder as an upload card. Drop a file on the card to upload + bind in one step, or click Library to pick an existing file. The file lands in your library with the placeholder's name as its reference name, ready to reuse elsewhere.

Both flows feed the same library — a file uploaded from the editor with reference name hero can be picked from the test page later, and vice versa. If you upload bytes that are already in your library (same SHA-256), the platform skips the duplicate upload and assigns the new reference name to the existing row.

See Media files in the Interactive2 reference for the full walkthrough, including dedup details, the rename flow, and Answer Review patterns.

What is a "library"?

For non-programmers: A library is a pre-built toolkit that does one specific thing really well. Think of it like an app on your phone — one for maps, one for photos, one for drawing. When you're building an Interactive2 question, you tick a box to say "this question needs the 3D drawing tool" or "this question needs the math-typing tool", and that tool becomes available for the question to use. You don't have to write the tool yourself; you just opt in. The Copy AI Prompt button generates question code that already knows how to use each library, so you usually don't have to touch JavaScript at all — you describe what you want and the AI writes the code.

The Interactive2 Settings panel has a Libraries checkbox picker. Checked libraries are loaded automatically before your question runs, so the code you (or the AI) write can just use them. Every library is self-hosted on the YourWay Math Academy server — they keep working even when students are on networks that block internet CDNs (ad blockers, managed school networks, corporate firewalls).

The 13 built-in libraries

Expand each one below for a plain-English explanation and example questions teachers have built with it.

three.js — 3D scenes (rotate, zoom, lighting)

Draws anything 3D — spheres, boxes, complex meshes, lighting, shadows. Students can drag to rotate the scene and scroll-wheel to zoom. If your question involves anything in three dimensions, this is the library.

Example questions: 3D right-hand rule (identify the force direction), magnetic field lines around a bar magnet with flowing particles, rotatable molecular models, vectors in 3D space, coordinate-system exercises, cross-section of a solid.

matter.js — 2D physics (gravity, collisions, springs)

A real 2D physics engine. Objects have mass, gravity, friction, bounciness; they collide with each other and obey Newton's laws. Set up the scene and the engine simulates the rest.

Example questions: projectile motion (launch a ball over a wall to hit a target), pendulum period measurement, draggable block on an inclined plane, Newton's cradle, Rube Goldberg machines, simple machines (levers, pulleys).

p5.js — 2D animations and creative coding

A simple 2D drawing/animation library designed for artists and beginners, not just engineers. Great for procedural graphics, particle effects, wave patterns, and anything where you want to animate pixels frame-by-frame.

Example questions: two-source wave interference patterns, Lissajous figures, fractal tree generator, fluid-dynamics sketch, Fourier-series builder (hear the waves), visual rhythm/beat identification.

math.js — Symbolic math (parse expressions, take derivatives)

The only library here that genuinely understands math. You can feed it a string like "x^2 + sin(x)" and it turns that into a computable expression, or takes its derivative symbolically, or does linear algebra, or works with complex numbers.

Example questions: derivative matcher (student types their f'(x), app checks against the true derivative), expression graphing, equation solver, matrix transformations, complex-number arithmetic trainer.

Chart.js — Simple charts (bars, lines, scatter, pies)

Quick, beautiful standard charts with built-in tooltips, legends, and animations. If you need a scatter plot or a bar chart, start here before reaching for D3.

Example questions: linear regression fit (drag sliders to find best slope/intercept), histograms for statistics, election results analysis, experimental-data visualization.

Plotly.js — Scientific plots, including 3D surfaces and contour maps

Heavier-weight, more scientific than Chart.js. Especially strong at 3D surface plots, contour plots, and interactive scientific visualization.

Example questions: gradient descent on a 3D landscape (click to drop a ball and watch it roll downhill), level-curve explorer, 3D function grapher, real-time oscilloscope, molecular dynamics timeline.

MathJax — Render LaTeX math beautifully

Turns plain text like $x^2 + 3x$ into proper typeset math with real superscripts, fractions, integrals. This is the gold standard for displaying math on the web.

Example questions: anywhere you need a nicely-rendered formula in your question prompt or feedback. Often paired with math.js (which can output LaTeX from parsed expressions).

MathQuill — Let students type math WYSIWYG

A math input field. Students type x^2 and see a proper as they type; type / for a fraction, sqrt for a radical. Same editor used in TinyMCE's math button elsewhere in the site.

Example questions: any question where the student has to input a mathematical expression — derivative matcher, algebraic simplification, equation solver, integration-by-parts practice.

3Dmol.js — Interactive 3D molecule viewer (chemistry)

Built specifically for chemistry — displays molecules from standard formats (PDB, XYZ, SDF), color-codes atoms by element, and supports multiple rendering modes (stick, sphere, cartoon). Students can rotate, zoom, and click individual atoms.

Example questions: identify atoms of a specific element in a molecule, identify chiral centers, match a 3D structure to a name, explore protein-substrate binding, identify functional groups.

Cytoscape.js — Networks and graphs (biology pathways, social networks)

For anything shaped like a graph — nodes connected by edges. Supports force-directed layouts (natural-looking arrangements), click events, custom styling, and animations.

Example questions: trace a signaling pathway (EGF → EGFR → RAS → MAPK → JUN), identify hub proteins in a regulatory network, food-web analysis, phylogenetic tree navigation, sociogram exploration.

D3.js — Custom data visualizations + geographic maps

The most flexible visualization library. Use it when no prefab chart fits: Sankey flows (energy cascades, dollar flows, nitrogen cycle), hierarchies, chord diagrams, custom timelines, geographic maps (world-atlas TopoJSON is bundled for country-level world maps).

Example questions: ecosystem energy flow Sankey (find the dominant pathway), click-the-country geography quiz, supply-chain flow analysis, historical-timeline identification, phylogenetic tree click questions.

SortableJS — Drag-to-order / ranking questions

Turns any list into a drag-to-reorder list, with smooth animations and touch support built in. Tiny library with a huge range of question applications across every subject.

Example questions: order historical events chronologically, order mitosis stages, rank countries by GDP, sort algorithm steps, reconstruct a scrambled sentence, order steps of a chemical synthesis.

Compromise — English grammar parsing

A lightweight natural-language parser for English. Tags every word with its part of speech (noun/verb/adjective/adverb), identifies named entities (people/places/dates), converts verb tenses. Unique capability — nothing else here understands English grammar.

Example questions: click all the verbs/nouns/adjectives in a passage, identify named entities in a news article, convert a paragraph from present to past tense, sentence-diagramming exercises.

Use the Custom CDN URLs textarea below the picker to add any library not in the list. Those URLs hit the public internet, so anything you add there inherits the risk of being blocked by aggressive network filters — the self-hosted set above is blocker-proof.

Mobile-friendly questions

Every Interactive2 question should work on a phone. A large share of students submit work from a 375px-wide phone screen. The sandbox does most of the responsive work for you automatically; your UI code just needs to avoid fixed-px layouts and wire up a one-line helper for any canvas or library-managed renderer.

What the sandbox does automatically

  • A <meta viewport> tag is already set inside the iframe, so CSS media queries (@media (max-width: 480px), etc.) inside your UI code actually fire on iOS Safari.
  • Global CSS defaults prevent overflow: img/video/svg/canvas all have max-width: 100%, long words break gracefully, <pre>/<code> get a horizontal scroll instead of pushing layout, and tables are capped at the iframe width. Opt out of any rule with data-i2-no-responsive="1" on the element.
  • A thin toolbar above your iframe shows the title (set with $interactivetitle) and an expand button. Students on phones can tap expand to work at full viewport width — the Fullscreen API is used where available (desktop + Android + iPad), with a CSS overlay fallback on iPhone Safari.

Sizing variables (set in the Variables section)

VariablePurpose
$interactivetitle Short title shown in the toolbar above the iframe (e.g. "Pendulum Lab"). Always set this.
$interactiveheight Optional minimum height in pixels. The iframe autosizes to the active section's content height — gallery/tabs only measures the visible section, default layout measures the whole stack — so most questions can omit this entirely. Set it only when you want a floor (e.g. reserve a particular initial paint size, or guarantee a single-section sim has some breathing room). Final height is max(measured_content, $interactiveheight). Do not size to your largest section; autosize handles that for free.
$interactivemaxwidth Optional max-width in pixels (or CSS length like "90%"). Default is 100% — the container fills its column. Only set this when your question needs more horizontal room on wide screens but should still shrink on mobile.
$interactiveallowexpand Boolean, default true. Set to false only for trivial text-only widgets where a toolbar would feel like overkill.

Responsive helpers (one-line per library)

The sandbox exposes window.I2 with a set of helpers that wire up a ResizeObserver and call the library's resize method. Call one of these once, right after you create the library instance — the student can now resize, rotate their phone, or tap the expand button and your interactive will re-lay out correctly.

// Plain 2D canvas — handles devicePixelRatio for crisp rendering on HiDPI phones
container.innerHTML = '<canvas id="cv" style="width:100%;height:260px;"></canvas>';
I2.responsiveCanvas(container.querySelector('#cv'), function(w, h, ctx) {
  ctx.clearRect(0, 0, w, h);
  // draw using w, h as the current CSS (logical) dimensions
});

// three.js
I2.responsiveThree(renderer, camera);
// Orthographic camera: I2.responsiveThree(renderer, cam, {orthoFrustumHeight: 10});

// Plotly
Plotly.newPlot('plot-id', data, layout, {responsive: true});
I2.responsivePlotly('plot-id');

// Cytoscape
I2.responsiveCytoscape(cy);          // default 30px padding for cy.fit()
I2.responsiveCytoscape(cy, 50);

// matter.js — resizes render canvas; physics coordinates stay fixed
I2.responsiveMatter(render);

// p5.js (instance mode)
I2.responsiveP5(p, mountEl);

// Chart.js — works best when chart was created with responsive:true, maintainAspectRatio:false
I2.responsiveChart(chart);

// Low-level fallback for anything else
I2.onResize(element, function(w, h) { /* ... */ });

Layout patterns

  • Stack on narrow screens. Use CSS grid or flexbox with a media query, not fixed px widths. A two-column desktop layout that stacks to one column on mobile:
    .wrap { display: grid; grid-template-columns: 1fr 220px; gap: 12px; }
    @media (max-width: 560px) { .wrap { grid-template-columns: 1fr; } }
  • Wrap controls. Button and input rows should use display: flex; flex-wrap: wrap; gap: 8px; so they stack comfortably on narrow viewports.
  • Tap targets. Buttons need min-height: 36–40px. Number inputs should have inputmode="decimal" or inputmode="numeric" so phones show the right keyboard.
  • Font size. Keep body text at 13–14px minimum. Anything smaller is hard to read on phones.
  • Canvas sizing. Style the canvas element with width: 100% and an explicit height. Let I2.responsiveCanvas handle the drawing buffer + devicePixelRatio — don't set width/height attributes yourself.

Physics sims and pixel-locked coords

When NOT to force responsive layout: Some simulations (matter.js pendulums, p5 games with pixel-level positioning, fixed coordinate grids) have physics logic tightly coupled to their drawing coordinates. Rescaling breaks the coordinate relationships. In those cases: keep the scene at its natural size, use I2.responsiveMatter(render) to resize the view canvas without rescaling physics, and rely on the expand-to-fullscreen button as the mobile experience. Students tap expand, get a larger usable canvas, collapse to submit. This is often a better UX than a cramped, miniaturised physics sim.

Starter templates

Click Browse Templates… in the Interactive2 Settings panel to open the template gallery. The gallery is searchable (type to filter by name, description, or library), filterable by subject category (Mechanics, E&M, Chemistry, Biology, Data Visualization, Social Studies, English, and more), and remembers your recently-used templates.

Picking a card loads the template's code into all three editors, checks the right library boxes, and sets the appropriate scoring method. Everything is customizable — you can edit the code afterward, add your own variables, tweak the visuals, swap data sources. The templates are the fastest way to learn how Interactive2 questions are structured.

If you don't find a template that fits, the Copy AI Prompt button next to Browse Templates gives you a complete prompt you can paste into Claude or ChatGPT with your own question idea — the AI writes working code in the exact format you paste into the three editors.

Saving & scoring method

Settings are applied to the Common Control automatically when you save the question — there is no separate Apply step.

The Score Method dropdown has three values:

  • auto — the Cloud Function runs your scoring code and sets the score. This is the default.
  • manual — the instructor grades by hand (used when scoring is too complex for code).
  • takeanything — any non-empty response earns full credit (useful for reflections/exploration).
Note: Auto scoring requires the cloud_scoring block in config.php to point at a deployed scoreInteractive2 Cloud Function. If it's unreachable or the function errors, the submission falls through to manual grading with a message to the student.

Copy the AI prompt

Click the button below to copy a ready-made AI system prompt to your clipboard. Paste it into Claude or ChatGPT, append your specific question idea, and the AI returns code in the exact format you can paste into the Variables, UI Code, and Scoring Code editors. The same button is available directly in the Interactive2 Settings panel on any question editor page.

Show full prompt text

Code Samples in Question Text

Code Samples are syntax-highlighted code blocks that can be embedded in the question text of any question type — not just Code questions. They are inserted using the { } button in the TinyMCE toolbar when editing question text.

Tip: Code Samples and Code questions complement each other perfectly. Use a Code Sample in the question text to show an example or reference code, then use the Code answer type for students to write their own code. Students can even ask the AI to explain the sample code.

How to Insert a Code Sample

  1. In the Question Text editor (TinyMCE), click the { } toolbar button.
  2. Paste your code into the editor area in the dialog.
  3. Configure the settings below.
  4. Click Insert (or Update when editing).
  5. To edit later: double-click the code block in the editor.

Code Sample Settings

SettingOptionsDescription
Language JavaScript, Python, HTML, CSS, SQL, PHP, C, C++, Java Determines syntax highlighting. Does not affect execution.
Allow students to edit Checkbox (default: off) When enabled, students can modify the code and experiment. Changes are not graded. A “Reset” button lets students restore the original.
Wrap long lines Checkbox (default: off) Wraps long lines instead of horizontal scrolling.
Visible lines Auto, 5, 10, 15, 20, 25, 30 Sets a fixed height. “Auto” expands to fit all code. Fixed heights show a scrollbar for additional lines.
Enable AI Chat Checkbox (default: off) Adds an “Ask AI about this code” panel. Students can ask questions about the code (up to 5 messages per code block). They can highlight specific lines to ask about.
Instructor Context Text area (visible when AI Chat is enabled) Optional guidance for the AI about the code’s purpose and what to emphasize. Example: “This code demonstrates recursion. Focus on explaining the base case.”
Note: Code Samples are purely display/learning tools within the question text. They are not submitted or graded. For graded code input, use the Code question type.

Multipart

This type of question can contain multiple parts, where each part is one of the previous question types.

Required Variables

$anstypes = an array or list of answer types
Defines the answer type for each part. Example: $anstypes = array("number","number","choices")
Refer to this list for the short names of each question type:
  • Number: "number"
  • Calculated: "calculated"
  • Multiple Choice: "choices"
  • Multiple Answer: "multans"
  • Matching: "matching"
  • Function/expression: "numfunc"
  • Drawing: "draw"
  • N-tuple: "ntuple"
  • Calculated N-tuple: "calcntuple"
  • Matrix: "matrix"
  • Calculated Matrix: "calcmatrix"
  • Complex: "complex"
  • Calculated Complex: "calccomplex"
  • Interval: "interval"
  • Calculated Interval: "calcinterval"
  • Chemical Equation: "chemeqn"
  • Chemical Molecule Drawing: "molecule"
  • Essay: "essay"
  • File Upload: "file"
  • Code: "code"
  • String: "string"
Note: The Writing and Code question types work best as standalone questions due to their complex editor interfaces. While “code” is technically available as a multipart sub-type, the full-featured code editor is most effective as a dedicated question. Use “essay” for basic text input parts.
Question part variables
For each question part, you will need to define the variables (like $answer, $questions, etc.) you would normally need to define. However, you will need to suffix the variable with a part designator. For example, based on $anstypes above, the first answer is a number. Instead of $answer = 5, enter $answer[0] = 5. This designates that this answer belongs to the first element of $anstypes. Likewise, to set the variables for the "numfunc" type, you'd set $variables[5] = "x".
$answerbox[partnum] (In Question Text)
The array $answerbox will contain the entry boxes for each answer type. In the question text, you will need to position these boxes within the question. For example: "Enter a number: $answerbox[0]. Now a function: $answerbox[1]". Alternatively, you can use [AB#]: "Enter a number: [AB0]. Now a function: [AB1]"

Optional Variables

$answeights = an array or list of weights for each question
By default the points for a problem are divided evenly over the parts. Use this option if you wish to weight parts differently. Example: $answeights = array(.2,.3,.5). Best practice is to use percents, but if other values are used, they will be converted to percents.
$scoremethod = "singlescore" or "allornothing"
Instead of recording individual scores for each question part, these will cause a single score to be recorded for the question. "singlescore" totals the individual part scores, while "allornothing" will only give full credit or no credit. If you need to specify per-part indexed scoremethod values as well, you can define this as the array value $scoremethod['whole'] instead.
Question part options
You can define any optional variable for each question part. Like above, suffix the variable with the part designator.
$showanswer
You can either define $showanswer for individual question parts (ie, $showanswer[1]="`x^2`"), or you can set one $showanswer, which will be the only answer shown for the problem (ie, $showanswer = "x=$answer[0], y=$answer[1]")
$showanswerloc (In Question Text)
Optionally, you can use $showanswerloc to place a single $showanswer "Show Answer" button, or $showanswerloc[part] to place "Show Answer" buttons for each part. You can also use short tags of the form [SAB] or [SABn] (like [SAB2]). Note that if you use this to place one Show Answer button, you must place all of them, or else the remainder will not show. Use $showanswerstyle = 'inline' to allow Show Answer to be placed inline with text rather than on its own line.

Scaffolding

Scaffolded questions, also know as Sequential Multipart questions, allow you to break a question up into chunks, where the second chunk only shows after the first chunk is correctly answered or the student runs out of tries. This allows you to use the answer to the first chunk in the second without "giving away" the answer, and allows a student who gets stuck on the first chunk to move on to the rest of the question.

Note: Scaffolding is only available in the new assessment interface. If you are using the old interface, the question will behave like a regular multipart question.

Scaffolded questions are an extension of Multipart questions. To turn a multipart question into a scaffolded question, just add an isolated line with three or more slashes in the Question Text where you want the chunks broken apart.

An example: (in the Question Text)

To simplify $a(x+$b) + $c, first we need to distribute:

$a(x+$b) = $answerbox[0]

///

Next, combine like terms:

$a x + $ab + $c = $answerbox[1]

Conditional

A variation on multipart questions, a conditional question can include multiple answer boxes, but assigns a single score. The score is based on applying some comparison or conditional test to the student answers, referenced through the $stuanswers array. This allows the question writer to essentially create their own question type.

Required Variables

$anstypes = an array or list of answer types
Defines the answer type for each part. Example: $anstypes = "number,number". See the Multipart help above for the list of short names
$answer = any of these:
  • A boolean (true/false) expression: Something that evaluates to true or false.
    Example: $answer = ($a>3)
    Example: $answer = comparefunctions($f,'x^2') && ($a!=0)
  • A single numerical value in the interval [0,1]: will award that percentage of the total possible points.
  • array('function',$a,$b): Will compare the functions $a and $b and mark the question correct if they are equivalent. Can set $variables, $reltolerance, $abstolerance, and $domain as needed, like with Function type questions
  • array('number',$a,$b): Will compare the numbers or numerical expressions $a and $b and mark the question correct if they are equivalent. Can set $reltolerance or $abstolerance as needed, like with Number/Calculated type questions
  • Multiple comparisons: You can mix the two types above by creating an array of comparisons. All must be true for the question to be marked correct.
    Example: $answer = array($a>3, array('function',$b,c), array('number',evalfunc($b,$a),5))
Question part variables
For each question part, you will need to define the variables (like $questions, etc.) you would normally need to define, except you should not define an $answer. However, you will need to suffix the variable with a part designator. For example, based on $anstypes above, the first answer is a number. Instead of $displayformat = "select", enter $displayformat[0] = "select". This designates that this setting belongs to the first element of $anstypes.
$answerbox[partnum] (In Question Text)
The array $answerbox will contain the entry boxes for each answer type. In the question text, you will need to position these boxes within the question. For example: "Enter a number: $answerbox[0]. Now a function: $answerbox[5]"

Optional Variables

Question part options
You can define any optional variable for each question part. Like above, suffix the variable with the part designator. Note that $variables, $domain, $reltolerance, and $abstolerance may be used for the comparison, and should not be set for individual parts.
$showanswer
By default the $showanswer for conditional types is "Answers may vary". Set $showanswer to override this.

Scaffolding

While not as simple as scaffolding multipart questions, you can add scaffolding to a Conditional question. As with multipart, put an isolated line with three slashes in the question text to indicate where the breaks occur. Then you will need to set $seqPartDone[pn] to true for each part index once that part should be considered completed. The scaffolding will move onto the next chunk when all parts in the previous chunk have $seqPartDone set to true.

Table of Contents