WeBWorK Problems

postFilter issues in develop

postFilter issues in develop

by Alex Jordan -
Number of replies: 2
Since pulling to the develop branches, some problems of ours are broken, and it appears to me that the reason is consistently when
  • there is a postFilter applied to the answer checker
  • which uses some kind of MathObject creator command (like Compute or Formula)
  • and within the postFilter, it's not respecting the ambient Context from the problem. I assume it's using the default Numeric instead.

Unfortunately the examples are complicated by their nature. Below is code for one such problem that is breaking. The intent is to give two points, and get the student to write a line equation in point-slope form. parserImplicitPlane is used for this, and the special answer checking makes sure that it is in the real point-slope form. I should note that the underlying issue is in other problems of ours too that do not use parserImplicitPlane, since I know that has been a troublesome macro in the past. I don't think it has anything to do with the issue.

In the problem below, with seed 1234, when answers are submitted, the error message is:
  • Error in Translator.pm::process_answers: Answer AnSwEr0001: |y-10=2/3(x-1)|
  • Variable 'y' is not defined in this context; see position 1 of formula at line 94 of (eval 2110)
    Died within main::Formula called at line 94 of (eval 2110)
  • Error in Translator.pm::process_answers: Answer AnSwEr0001:
  • Answer evaluators must return a hash or an AnswerHash type, not type || at /opt/webwork/pg/lib/WeBWorK/PG/Translator.pm line 1241
  • Error in Translator.pm::process_answers: Answer AnSwEr0002: |y-13=2/3(x-2)|
You can see in the postFilter code below, that it uses Formula several times. And this error message is objecting to the 'y' in that Formula call. But 'y' is definitely a variable in the ambient ImplicitPlane context.

I'm posting this here, because I'm starting to think that something may have changed in a bad way with postFilters. Normally I assume it's my shoddy hack-y code that wasn't written well enough to survive improvements at deeper levels. But this may be a bug with develop/2.11.

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGML.pl",
"parserImplicitPlane.pl",
"PGcourse.pl",
);

##############################################

Context("Numeric");
Context()->variables->add(y=>'Real');
Context()->noreduce('(-x)-y','(-x)+y');
Context()->flags->set(showExtraParens=>0);

$m=random(2,5,1);
$b=random(1,10,1);

$x1=random(1,5,1);
$y1=$m*$x1+$b;
$x2=random(1,5,1);
while ($x2==$x1) {$x2=random(1,5,1);}
$y2=$m*$x2+$b;

Context()->texStrings;
$ansPSstringTeX1 = "y-$y1=$m(x-$x1)";
Context()->normalStrings;
$ansPSstring1 = "y-$y1=$m(x-$x1)";

Context()->texStrings;
$ansPSstringTeX2 = "y-$y2=$m(x-$x2)";
Context()->normalStrings;
$ansPSstring2 = "y-$y2=$m(x-$x2)";


Context("ImplicitPlane");
Context()->variables->are(x=>'Real',y=>'Real');
Context()->flags->set(showExtraParens=>0);
Context()->flags->set(showExtraParens=>0);
$ansPS1 = ImplicitPlane("$ansPSstring1");
$ansPS2 = ImplicitPlane("$ansPSstring2");

##############################################

TEXT(beginproblem());

BEGIN_PGML

A line passes through the points [`([$x1],[$y1])`] and [`([$x2],[$y2])`]. Find this line's equation in point-slope form.

Using the point [`([$x1],[$y1])`], this line's point-slope form equation is [___________________].

Using the point [`([$x2],[$y2])`], this line's point-slope form equation is [___________________].

END_PGML

##############################################


Context()->flags->set(reduceConstants=>0);
Context()->flags->set(reduceConstantFormulas=>0);

ANS($ansPS1->cmp(correct_ans_latex_string => $ansPSstringTeX1
) -> withPostFilter(sub {
my $ansHash = shift;
my $student = $ansHash->{original_student_ans};
my @sides = split('=',"$student");

#if it's an implicit plane object, reset how student's answer is displayed:
if ($ansHash->{student_formula}->cmp_class eq "an Implicit line") {
$ansHash->{preview_text_string} = "$sides[0]=$sides[1]";
my $leftTex = Formula("$sides[0]")->TeX;
my $rightTex = Formula("$sides[1]")->TeX;
$ansHash->{preview_latex_string} = "$leftTex=$rightTex";
$ansHash->{student_ans} = $ansHash->{original_student_ans};
}

#if they have the line correct, then check each side to see if the sides are correct
if ($ansHash->{score}) {
if (Formula("y-$y1") != Formula("$sides[0]") and Formula("y-$y1") != Formula("$sides[1]")) {
$ansHash->{score} = 0;
$ansHash->{ans_message} = "This is an equation for the line, but it is not the point-slope equation that uses the given point";
}
}
return $ansHash;
}));



ANS($ansPS2->cmp(correct_ans_latex_string => $ansPSstringTeX2
) -> withPostFilter(sub {
my $ansHash = shift;
my $student = $ansHash->{original_student_ans};
my @sides = split('=',"$student");

#if it's an implicit plane object, reset how student's answer is displayed:
if ($ansHash->{student_formula}->cmp_class eq "an Implicit line") {
$ansHash->{preview_text_string} = "$sides[0]=$sides[1]";
my $leftTex = Formula("$sides[0]")->TeX;
my $rightTex = Formula("$sides[1]")->TeX;
$ansHash->{preview_latex_string} = "$leftTex=$rightTex";
$ansHash->{student_ans} = $ansHash->{original_student_ans};
}

#if they have the line correct, then check each side to see if the sides are correct
if ($ansHash->{score}) {
if (Formula("y-$y2") != Formula("$sides[0]") and Formula("y-$y2") != Formula("$sides[1]")) {
$ansHash->{score} = 0;
$ansHash->{ans_message} = "This is an equation for the line, but it is not the point-slope equation that uses the given point";
}
}
return $ansHash;
}));


$s1=$y2-$y1;
$s2=$x2-$x1;
$s3=$m*$x1;
$s4=-$s3;

$outputy1 = $y1<0 ? "($y1)" : $y1;
$outputx1 = $x1<0 ? "($x1)" : $x1;

BEGIN_PGML_SOLUTION

A line's equation in point-slope form looks like [` y-y_{1}=m(x-x_{1}) `] where [`m`] is the slope of the line and [`(x_{1},y_{1})`] is a point that the line passes through. We first need to find the line's slope.

To find a line's slope, we can use the slope formula:

[`` \text{slope}=\frac{y_{2}-y_{1}}{x_{2}-x_{1}} ``]

We mark which number corresponds to which variable in the formula:

[`` ([$x1],[$y1]) \longrightarrow (x_{1},y_{1}) ``]

[`` ([$x2],[$y2]) \longrightarrow (x_{2},y_{2}) ``]

Now we substitute these values into the corresponding variables in the slope formula:

[`` \begin{aligned}\text{slope}&=\frac{y_{2}-y_{1}}{x_{2}-x_{1}}\\&=\frac{[$y2]-[$outputy1]}{[$x2]-[$outputx1]}\\&=\frac{[$s1]}{[$s2]}\\&=[$m]\end{aligned} ``]

Now we have [` y-y_{1}=[$m](x-x_{1}) `]. The next step is to use a point that we know the line passes through.

If we choose to use the point [`([$x1],[$y1])`], we have:

[`
\begin{aligned}
y-y_{1} &= m(x-x_{1}) \\
y-[$y1] &= [$m](x-[$x1])
\end{aligned}
`]

If we choose to use the point [`([$x2],[$y2])`], we have:

[`
\begin{aligned}
y-y_{1} &= m(x-x_{1}) \\
y-[$y2] &= [$m](x-[$x2])
\end{aligned}
`]

Note that these two equations are equivalent. You will see why once you change both equations to slope-intercept form. This is left as an exercise.

END_PGML_SOLUTION

ENDDOCUMENT();

In reply to Alex Jordan

Re: postFilter issues in develop

by Davide Cervone -
This turns out to be a bug in the MathObjects Formula object that causes the current context to be incorrectly set after the main answer evaluator runs but before the post-filters run. This means that the post-filters don't have the ImplicitPlane context set, and are using the default Numeric context instead. That is the origin of the error message about the missing "y", since that context doesn't have a variable "y".

I have submitted a pull request to patch the problem.
In reply to Alex Jordan

Re: postFilter issues in develop

by Davide Cervone -
In the meantime, you can add a Context() call to your post-filter, and that will get the context set to the correct thing again.