WeBWorK Problems

Passing flags when using MultiAnswer

Passing flags when using MultiAnswer

by Danny Glin -
Number of replies: 1
How do I pass flags when using a custom grader as part of a MultiAnswer?

My code is as follows:

Context("Vector");

$a=non_zero_random(-5,5,1);
$b=non_zero_random(-5,5,1);
$c=non_zero_random(-5,5,1);

$v=Vector(($a,$b,$c));

$mp = MultiAnswer($v)->with(
singleResult => 1,
checker => sub {
my ($correct,$student,$self) = @_; # get the parameters
my ($student_answer) = @{$student}; # extract the student answers
Context()->flags->set(parallel=>1);
return $student_answer == $v;
},
);

Context()->texStrings;

TEXT(beginproblem());

BEGIN_TEXT
Find a vector parallel to \($v\).$BR

\{mbox "\(\vec{v}=\)", $mp->ans_array(10)\}

END_TEXT

Context()->normalStrings;

ANS($mp->cmp);

I've also tried ANS($mp->cmp(parallel=>1));
Regardless of what I do, it doesn't seem to accept the parallel flag.
Any thoughts?

In reply to Danny Glin

Re: Passing flags when using MultiAnswer

by Davide Cervone -
When you use the MultiAnswer object, you do the answer checking by hand, so the answer checkers for the individual objects that are part of the MultiAnswer object are not use, and so there is nothing to pass the flags to. Instead, you are using the equality operator (the "==" in your code) to do the check, and that is where the problem is. That does equality checking, not parallel checking. Instead, you need to use the isParallel() method of the vector object. For example
    return $v->isParallel($student_answer);
should do the trick.

On the other hand, it looks to me like you are using the MultiAnswer object when you don't need to, since you are using it with only one MathObject. That suggests that you don't need really need a MultiAnswer, since that is for when you need to know about two or more student answers in order to tell if they are right. It looks like you are using the MultiAnswer for its ans_array() method, but you don't need to since the vector object also has its own ans_array() method. So you can use $v->ans_array directly, and then ANS($v->cmp(parallel=>1)) as usual.

You may also find that some of the macros in pg/macros/parserVectorUtils.pl are useful to you. For example, non_zero_vector3D() for creating a non-zero 3-vector (some coordinates can be zero, but not all of them).

So my suggestion for your code would be:


    loadMacros("parserVectorUtils.pl");

    TEXT(beginproblem);

    Context("Vector");

    $v = non_zero_vector3D(-5,5,1);
    $V = '\vec{v}';

    Context()->texStrings;
    BEGIN_TEXT
    Find a vector \($V\) that is parallel to \($v\).$BR
    \($V\) = \{$v->ans_array(10)\}
    END_TEXT
    Context()->normalStrings;

    ANS($v->cmp(parallel=>1));

Of course, you may not want to allow the student to enter the vector $v itself, in which case you may want to provide a custom checker that rules that out and that gives a helpful message indicating what the problem is. The pg/macros/answerHints.pl file might come in handy. For example:

    loadMacros("answerHints.pl");
    ANS($v->cmp(parallel=>1)->with(AnswerHints(
        $v => ["You need to provide a vector other than the one originally given",
                   checkCorrect=>1, score=>0]
    )));

(I didn't test this, but something like that should work). Note, however, that since you are using $v for the answer checker, that is what will be given as the "correct" answer when the student requests correct answers (after the due date), so it may be a bit confusing to show that as the correct answer when it is not allowed. In that case, you might do something like:

    ANS((2*$v)->cmp(parallel=>1)->with(AnswerHints(
        $v => ["You need to provide a vector other than the one originally given",
                   checkCorrect=>1, score=>0]
    )));
so that the correct answer will be shown as something other than $v itself.

Hope that helps.

Davide