Skip to content

Writing Exercises: Answer Types

Alex Lopatin edited this page Jul 30, 2013 · 29 revisions

Answer Types

There are a few answer types available. You can specify what type of answer is expected by using the data-type attribute on the .solution element.

  • text

    It compares the answer strings literally; no numerical interpretation is done at all (e.g., 1.0 would be marked incorrect if the answer was 1, even though they're numerically equal). The only text transformation is to strip leading and trailing whitespace before comparison.

    <p class="solution" data-type="text"><var>ANSWER</var></p>
  • radio (default if ul.choices present)

    If you want the user to pick an answer from a list, you can provide the possible choices that you want the user to select from, using an un-ordered list. You'll need to add an UL with a class of choices inside of your main problem container.

    <p class="solution"><code><var>A</var>x <var>BP + B</var></code></p>
    <ul class="choices">
        <li><code><var>-1 * A</var>x <var>BP + B</var></code></li>
        <li><code><var>A</var>x <var>BN + (-1 * B)</var></code></li>
        <li><code><var>B</var>x <var>AP + A</var></code></li>
        <li><code><var>-1 * B</var>x <var>AN + (-1 * A)</var></code></li>
    </ul>

    The above markup will generate a problem that has 5 possible choices to choose from, one of which is the valid solution. Note that when you use multiple choice formatting you can let the user pick from more-complicated answers (such as formulas). Do not put the correct answer among the choices, unless you are using category.

    Example: Limits 2

    The framework also gives you the ability to provide more possible choices than what may actually be displayed. For example you could provide a total of 5 choices (1 solution + 4 other choices) but only show 3 of them (1 of which will always be the valid answer).

    <ul class="choices" data-show="3"> ... </ul>

    Example: Plugging in Values

    Additionally the framework provides a mechanism for supplying a "None of the above" choice as a viable option. All you would need to do is supply a data-none="true" attribute on your choices UL to enable it, like so:

    <ul class="choices" data-show="5" data-none="true"> ... </ul>

    In this example, 5 possible choices will be displayed - one of which will be the "None of the above" choice. It's possible that the valid solution will be hidden and that "None of the above" will be the correct answer.

    Example: Multiplying Polynomials

  • list If your exercise involves asking the user something like an inequality, where you want the answer or part of the answer to be one of a list of options, you can have the answer come from a drop down menu.

    Here is an example of how this works:

        <p class="solution" data-type="multiple">
            <code>x</code>
            <span class="sol" data-type="list" data-choices="['', '&lt;', '&gt;', '&le;', '&ge;']">
            </span>
            <span class="sol" data-type="rational"><var>( D - B ) / ( A - C )</var></span></p>

    This produces drop down menu in the answer area with <, >, <= and >= options and then a free answer box with type rational. Thus, the list answer type takes in an array and outputs a drop down menu.

    Example: Range of a Function

  • category (a type of radio)

    If your exercise involves asking the user to choose from the same set of choices displayed in the same order every time, supply a data-category="true" attribute. Note that you should supply the solution in the unordered list as well (Normal radio answers only have wrong answers in the unordered list.).

    <div class="solution">Acute</div>
    <ul class="choices" data-category="true">
        <li>Acute</li>
        <li>Right</li>
        <li>Obtuse</li>
    </ul>

    Example: Scaling Vectors

  • decimal(decimal)

    Just like text except it compares numerical equality. With decimal, 1.0 is the same as 1, but no other evaluation is done so fractions and the like don't work.

    <p class="solution" data-type="decimal">1.0</p>

    Example: Units

    If an error margin needs to be allowed in the answer, as is the case in many statistics problems, you can specify the amount of error that is to be allowed.

    <p class="solution" data-inexact data-max-error="0.1" data-type="decimal">1.0</p>

    Example: Standard Deviation

  • rational

    Compares two fractions for equality. Under the hood, it converts both to decimals so the contents of p.solution should actually be a decimal version of the correct answer. You can accomplish this using var:

    <p class="solution" data-type="rational"><var>2/3</var></p>

    Example: Subtracting Fractions

    By default, answers must be reduced to be considered correct. (4/6 would not be a correct answer.) If you want to specifically allow unsimplified answers, add data-simplify="optional" to the element containing the solution.

    Example: Adding fractions with common denominators

  • radical

    Use this type if your answer involves a radical, like in the Simplifying Radicals exercise. Specify the coefficient and the part under the radical in separate span tags.

    <div class="solution" data-type="radical">
        <span><var>COEFFICIENT</var></span><span><var>RADICAL</var></span>
    </div>

    Example: Pythagorean Theorem 1

  • line

    Use this if the answer is a function, like 2(3x + 7)/5. Currently being developed.

  • regex

    Just what it sounds like. Omit the delimiting slashes but include ^ and $ if appropriate. To match the four smilies :), ;), :P, ;P:

    <p class="solution" data-type="regex">^[:;][\)P]$</p>
  • multiple

    This special type allows you to have a composite of other answer forms as an answer. The "Slope Intercept Form" exercise uses this to ask the user for the slope m and y-intercept b of a line:

    Example: Slope Intercept Form

    <div class="solution" data-type="multiple">
        <p><code>m</code> = <span class="sol" data-type="rational"><var>M</var></span></p>
        <p><code>b</code> = <span class="sol" data-type="rational"><var>B</var></span></p>
    </div>

    The code inside the solution will be copied into the solution area and each .sol element will be interpreted as if it was its own answer. In this case, you'll get a form that asks for m and b and gives two separate text entry boxes. Since data-type="rational" was specified on each .sol element, each text box acts like a single rational answer.

    Answers are marked correct only if all of the parts are correct. Having a radio input as a part of an answer has not been tested. (You probably don't need more than one radio input, anyway.)

    Since multiple-type answers can vary wildly in what they expect from the user, the framework won't show the predefined "acceptable answers," unlike with most of the default answer types. Instead, you should define your own examples inside the solution block to help the user answer properly:

    <div class="solution" data-type="multiple">
        <p><code>m</code> = <span class="sol" data-type="rational"><var>M</var></span></p>
        <p><code>b</code> = <span class="sol" data-type="rational"><var>B</var></span></p>
        <p class="example"><code>m</code> = a <em>simplified proper</em> fraction, like <code>3/5</code></p>
        <p class="example"><code>b</code> = a <em>simplified proper</em> fraction, like <code>2/5</code></p>
    </div>
  • set

    This special type permits one or more correct answers to be entered in any order. You provide a list of correct answers and indicate how many of them you want. If you provide more answers than inputs, the student can enter any subset. If you provide more inputs than answers, the student must leave some boxes blank.

    This example allows the user to provide two answers that can be entered in either order. In this case, the solutions to a quadratic equation:

        <div class="solution" data-type="set">
            <div class="set-sol"><var>A</var></div>
            <div class="set-sol"><var>B</var></div>
            <div class="input-format">
                <p><code>x = </code><span class="entry"></span> or</p>
                <p><code>x = </code><span class="entry"></span></p>
            </div>
            <p class="example">two integers like <code>6</code> or <code>9</code></p>
        </div>

    The code consists of three sections: the set-sol elements, the input-format element, and the example elements. The set-sol elements list the correct answers to the question. In the example above, it's the values of the variables A and B. The input-format section defines what the solution area looks like to the student. Within the input-format element, you also provide one or more entry elements to create blanks where the student will enter his or her answer. In the example above, there are two entry elements, so the student would be expected to provide two answers (A and B, but in either order). The example elements function in the same way as described in multiple above.

    The next example provides two right answers, and the user may enter either one of them:

        <div class="solution" data-type="set">
            <div class="set-sol"><var>X1</var></div>
            <div class="set-sol"><var>X2</var></div>
            <div class="input-format">
                <p><code>x = \quad</code><span class="entry"></span><code></p>
            </div>
            <p class="example">an integer, like <code>6</code>
        </div>

    Because there is only one entry element in the input-format, there will only be a single text box to enter an answer. Because there are fewer entry elements (one) than correct answers (two set-sol elements), the user is allowed to enter either answer. You can extend this by providing any number of inputs and/or correct answers.

    The next example is like the previous in that there are two correct answers and the user may enter either one of them, but in this case the answers are themselves multiple answers. In other words this requires the student to provide (X1 and Y1 and SLOPE) or (X and Y and SLOPE):

        <div class="solution" data-type="set">
            <div class="set-sol" data-type="multiple">
                <span class="sol"><var>X1</var></span>
                <span class="sol"><var>Y1</var></span>
                <span class="sol"><var>SLOPE</var></span>
            </div>
            <div class="set-sol" data-type="multiple">
                <span class="sol"><var>X</var></span>
                <span class="sol"><var>Y</var></span>
                <span class="sol"><var>SLOPE</var></span>
            </div>
    
            <div class="input-format">
                <p class="entry" data-type="multiple">
                    <code>\text{x1 = }</code><span class="sol"></span><br />
                    <code>\text{y1 = }</code><span class="sol"></span><br />
                    <code>\text{m = }</code><span class="sol"></span>
                </p>
            </div>
        </div>

    In this example, the user is asked to provide two numbers that multiply to 15. The solution type is going to be "multiple", since the answer could be "3 and 5" or "1 and 15", but not "5 and 15" as the second factor depends on the first. Let's say you have defined a variable that is an array of the factors of 15:

            <div class="vars">
                <var id="FACTORS">[1, 3, 5, 15]</var>
            </div>

    The solution can be implemented by utilizing the "set" and "multiple" solution types as in the example above, iterating through the array of factors and defining the second acceptable answer as 15 divided by the current element. Notice the use of data-each when setting the solutions.

        <div class="solution" data-type="set">
            <div class="set-sol" data-type="multiple" data-each="FACTORS as factor">
                <span class="sol"><var>factor</var></span>
                <span class="sol"><var>15 / factor</var></span>
            </div>
    			
            <div class="input-format">
                <div class="entry" data-type="multiple">
                    <p><code>x = \enspace</code><span class="sol"></span></p>
                    <p><code>y = \enspace</code><span class="sol"></span></p>
                </div>
            </div>
        </div>
  • expression

    The expression answer type parses a given expression or equation and semantically compares it to the solution. In addition, instant feedback is provided by rendering the last answer that fully parsed.

    <p class="solution" data-type="expression"><var>A</var>x + <var>B</var></p>

    By default, single-letter symbols are interpreted as variables. This can be overwritten by specifying, via the data-functions attribute, a space or comma separated list of variables that should be interpreted as functions. Variables are case sensitive; e and i are reserved. If no functions are specified, f(x+y) == fx + fy. However if f is a function, f(x+y) cannot be expanded.

    <p class="solution" data-type="expression" data-functions="f g">f(<var>x</var>) + g(<var>y</var>)</p>

    Sometimes you don't want to accept just any answer. For example, if the problem is "Factor x^2 + x - 2" you don't want the student to get credit for just repeating the question back. You can impose a stricter equality requirement by specifying the data-same-form attribute. If present, the answer must match the solution's structure in addition to evaluating the same. Commutativity and excess negation are ignored, but all other changes will trigger a rejection.

    <p class="solution" data-type="expression" data-same-form>(x-1)(x+2)</p>

    The above snippet will accept (x-1)(x+2), (x+2)(x-1), ---(-x-2)(-1+x), and similar answers. It will reject x^2+x-2, x*x+x-2, x(x+1)-2, (x-1)(x+2)^1, etc. with the message "Your answer is not in the correct form."

    Example: Factoring Polynomials 1

    Other times you don't care about a particular form, but you do want the student's answer to be simplified. For example, if the question is "Simplify ((n*x^5)^5) / (n^(-2)*x^2)^-3". That's easy - just use the data-simplify attribute. If present, the answer must be fully expanded and simplified. Use this carefully - simplification is hard and there may be bugs, or you might not agree on the definition of "simplified" used. You will get an error when using this if the provided solution is not itself fully expanded and simplified.

    <p class="solution" data-type="expression" data-simplify>x^31 / n</p>

    The above snippet will accept x^31 / n, x^31 / n^1, n^(-1) * x^31. It will reject (x^25 * n^5) / (x^(-6) * n^6), etc. with the message "Your answer is not fully expanded and simplified."

    Finally, you can tweak the way that the student's answer get rendered. By default, explicit multiplication (such as between numbers) will be rendered with a center dot (TeX: \cdot). There may be cases where you want to use the cross/x symbol instead (TeX: \times). To do so, just specify the data-times attribute like below.

    <p class="solution" data-type="expression" data-times>2 * 3^x</p>
  • custom

    This type allows you to create a unique type of answer for your exercise. This is particularly useful for interactive exercises, but could also be used in any exercise where you need to do more complex validation of the answer. But before using it, be sure you can't do what you're trying to do using the existing answer types. For example, a combination of set and multiple can often be used to validate an answer that at first seems to require using a custom answer type.

    This example from the interactive exercise Graphing linear equations, checks to see that the student has correctly positioned two points to graph a line:

    <div class="solution" data-type="custom">
        <div class="instruction">
            Drag the two points to move the line into the correct position.
        </div>
        <div class="guess"> [ graph.pointA.coord, graph.pointB.coord ] </div>
        <div class="validator-function">
            var slope = ( guess[1][1] - guess[0][1] ) / ( guess[1][0] - guess[0][0] );
            var yint = slope * ( 0 - guess[0][0] ) + guess[0][1];
            return abs( SLOPE - slope ) &lt; 0.001 &amp;&amp; abs( YINT - yint ) &lt; 0.001;
        </div>
        <div class="show-guess">
            graph.pointA.setCoord( guess[0] );
            graph.pointB.setCoord( guess[1] );
            graph.line1.transform( true );
        </div>
        <div class="example">acceptable answer format goes here</div>
    </div>

    As shown in the example above, the custom answer type uses the following five elements:

    • instruction

      The content within this div is copied to the solution area just above the "Check Answer" button. In this case, it tells the student to graph a line, but you can include anything you like: buttons, input boxes, or other form elements. If you're just using input boxes, you might be better served using the other answer types rather than creating a custom answer.

    • guess

      This is evaluated to determine what the student's answer is. Since it gets sent to the server and stored in the user's history, you should try to limit the amount of information that makes up an answer. In the example above, the guess consists of the coordinates of the two points the student can drag around to make the graph.

    • validator-function

      This is where you determine whether the student's answer is correct or not. Within this block, the framework will provide the variable guess which will be of the format you created in the previous guess element. It's important that you only use information contained in the guess variable to determine if the answer is correct or not! The validator-function is called in different contexts (such as when a coach is reviewing a student's answers) and the only context you can count on having is whatever you put into the guess variable.

      In the example above, you can see the validator-function uses the two points stored in the guess variable to calculate the slope and y-intercept of the line the student graphed. It compares the graphed slope and y-intercept to the correct answer and returns true or false if the answer is correct or incorrect. Note the use of &lt; and &amp; rather than < or &. Since this is an HTML document, you should escape certain characters to ensure all browsers parse it correctly.

      In addition to true and false, your validator-function can return a string. If you return a string, the answer will be marked wrong, but the string will be displayed to the user to give a clue about why it was marked wrong. This is similar to the feedback provided by the built-in answer types that require an answer to be simplified. If you enter a correct answer that hasn't been simplified, a message is displayed saying the answer is almost correct, but must be simplified.

      As a special case, if you return an empty string "" from the validator-function, the answer won't be graded at all. You should try to do this any time the user hasn't provided an answer yet. This will prevent frustration if the user accidentally clicks the "Check answer" button too quickly.

    • show-guess

      A great feature of the Khan Academy framework is the ability for a student or coach to look back at previous problems done and see exactly what answers were given and what hints were taken, showing the student or coach a replay of what the student did. To make this work, the existing answer types know how to "display themselves" to recreate a view of the problem the student did. When creating a custom answer type, you'll have to do this yourself.

      Like the validator element, the show-guess element is provided with a guess variable containing the student's guess. But in show-guess you must use the guess variable to recreate the answer the student gave. For example: copying the values from the guess into text boxes, moving points around an interactive exercise, etc. In the example code above, the two points are moved into the positions provided by the guess and the line between the points is redrawn. This allows a coach to see exactly where the student placed the points after the fact.

      As you're developing, you can append ?debug to the URL and you'll see an "Answer timeline" link on the right. If you provide a few answers to a problem, then click this link, you'll see the same timeline view that a coach reviewing a student's work would see. Use this timeline view to make sure your show-guess function properly displays the student's work.

    • example

      This optional element works the same way as it does for multiple or set answers. Use it to include additional information in the "Acceptable answer formats" section.

Back to Writing Exercises: Home

  • percent

    See utils/answer-types.js.