NAME

parserMultiAnswer.pl - Tie several blanks to a single answer checker.

DESCRIPTION

MultiAnswer objects let you tie several answer blanks to a single answer checker, so you can have the answer in one blank influence the answer in another. The MultiAnswer can produce either a single result in the answer results area, or a separate result for each blank.

To create a MultiAnswer pass a list of answers to MultiAnswer() in the order they will appear in the problem. For example:

$mp = MultiAnswer("x^2",-1,1);

or

$mp = MultiAnswer(Vector(1,1,1),Vector(2,2,2))->with(singleResult=>1);

Then, use $mp->ans_rule to create answer blanks for the various parts just as you would ans_rule. You can pass the width of the blank, which defaults to 20 otherwise. For example:

BEGIN_TEXT
\(f(x)\) = \{$mp->ans_rule(20)\} produces the same value
at \(x\) = \{$mp->ans_rule(10)\} as it does at \(x\) = \{$mp->ans_rule(10)\}.
END_TEXT

Finally, call $mp->cmp to produce the answer checker(s) used in the MultiAnswer. You need to provide a checker routine that will be called to determine if the answers are correct or not. The checker will only be called if the student answers have no syntax errors and their types match the types of the professor's answers, so you don't have to worry about handling bad data from the student (at least as far as typechecking goes).

The checker routine should accept four parameters: a reference to the array of correct answers, a reference to the array of student answers, a reference to the MultiAnswer itself, and a reference to the answer hash. It should do whatever checking it needs to do and then return a score for the MultiAnswer as a whole (every answer blank will be given the same score), or a reference to an array of scores, one for each blank. The routine can set error messages via the MultiAnswer's setMessage() method (e.g.,

$mp->setMessage(1,"The function can't be the identity");

would set the message for the first answer blank of the MultiAnswer), or can call Value::Error() to generate an error and die.

The checker routine can be supplied either when the MultiAnswer is created, or when the cmp() method is called. For example:

$mp = MultiAnswer("x^2",1,-1)->with(
    singleResult => 1,
    checker => sub {
        my ($correct,$student,$self) = @_;  # get the parameters
        my ($f,$x1,$x2) = @{$student};      # extract the student answers
        Value::Error("Function can't be the identity") if ($f == 'x');
        Value::Error("Function can't be constant") if ($f->isConstant);
        return $f->eval(x=>$x1) == $f->eval(x=>$x2);
    },
);
ANS($mp->cmp);

or

$mp = MultiAnswer("x^2",1,-1)->with(singleResult=>1);
sub check {
    my ($correct,$student,$self) = @_;  # get the parameters
    my ($f,$x1,$x2) = @{$student};      # extract the student answers
    Value::Error("Function can't be the identity") if ($f == 'x');
    Value::Error("Function can't be constant") if ($f->isConstant);
    return $f->eval(x=>$x1) == $f->eval(x=>$x2);
};
ANS($mp->cmp(checker=>~~&check));

CONSTRUCTOR

MultiAnswer($answer1, $answer2, ...);
MultiAnswer($answer1, $answer2, ...)->with(...);

Create a new MultiAnswer item from a list of items. The items are converted if Value items, if they aren't already. You can set the following fields of the resulting item:

checker => code            a subroutine to be called to check the
                           student answers.  The routine is passed
                           four parameters: a reference to the array
                           or correct answers, a reference to the
                           array of student answers, a reference to the
                           MultiAnswer object itself, and a reference to
                           the checker's answer hash.  The routine
                           should return either a score or a reference
                           to an array of scores (one for each answer).

singleResult => 0 or 1     whether to show only one entry in the
                           results area at the top of the page,
                           or one for each answer rule.
                           (Default: 0)

namedRules => 0 or 1       whether to use named rules or default
                           rule names.  Use named rules if you need
                           to intersperse other rules with the
                           ones for the MultiAnswer, in which case
                           you must use NAMED_ANS not ANS.
                           (Default: 0)

checkTypes => 0 or 1       whether the types of the student and
                           professor's answers must match exactly
                           or just pass the usual type-match error
                           checking (in which case, you should check
                           the types before you use the data).
                           (Default: 1)

allowBlankAnswers=>0 or 1  whether to remove the blank-check prefilter
                           from the answer checkers used for type
                           checking the student's answers.
                           (Default: 0)

separator => string        the string to use between entries in the
                           results area when singleResult is set.
                           (Default: semicolon)

tex_separator => string    same, but for the preview area.
                           (Default: semicolon followed by thinspace)

format => string           an sprintf-style string used to format the
                           students answers for the results area
                           when singleResults is true.  If undefined,
                           the separator parameter (above) is used to
                           form the string.
                           (Default: undef)

tex_format => string       an sprintf-style string used to format the
                           students answer previews when singleResults
                           mode is in effect.  If undefined, the
                           tex_separator (above) is used to form the
                           string.
                           (Default: undef)