There are a couple of issues behind this. First, your
$ans
is
Compute("-$a, $a")
, so you are looking for a list of numbers but have entered a list of assignments. That is the reason for the warning message. (Also, it should really be
entry_type => "a solution"
in order to get this error message to read correctly; that was my fault).
I see that you have commented out the
$ans = Compute("$var = -$a, $var = $a");
that is the correct answer. Fixing that gets you past that message, but gets you pick screens due to an error in your checker.
The problem here is that the checker functions gets a MathObject that represents the assignment, not a parse tree for the formula that created the assignment. You are trying to take the left and right operands of the equality, but that is trying to use the object as a parse tree. The actual MathObject result of an equality is a List that contains the variable name as the first element and the value as the second element in the list (you do not normally have to deal with it at this level, so aren't aware of that). So to get the variable and fraction, use
my ($var,$frac) = $student->value;
(If you go back to the discussion you cite, you will see that this is how it works there.)
Fixing that does allow the answer to be marked as correct, but it also produces a bunch of warnings about undefined values. That has to do with the fact that the assignment is really a list, and it appears that the lists are being broken up into the separate pieces during the checking; I haven't tracked that down completely, but know how to prevent it (see below). The parserAssignment object seems to be a bit buggy in a couple of places, and it might be worth reworking it.
For now, however, you can add
return 0 unless $correct->type eq "Assignment";
to the checker function just after obtaining the value for
$correct
. This will avoid the warning messages for the case where the checker is being called at the wrong time (and should not hurt anything when I fix the bugs in the assignment object).
There are still a couple of other issues, however. First, in your extra
routine, you use $cfrac and $check2, which are undefined. I'm not sure exactly what you are after, but if you remove them, that avoids the warning messages.
Another problem is that where you have the error message about reduced fractions isn't correct. The checker
routine may be called multiple times on each student answer (as it is checked against the various correct answers to see if it matches one). So the error messages it produces are ignored (in case an error is produced when checking against a correct answer that it doesn't match). After all the correct answers are found the incorrect ones are passed to the extra
routine for final error messages (for things like syntax messages). So you need the checker
function to mark an unreduced fraction as incorrect (but no message given), and the extra
function to produce the error message about not being reduced.
I've fixed those issues in the code the follows:
loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"parserAssignment.pl",
"answerHints.pl",
"PGML.pl",
"contextFraction.pl",
);
##############################################
Context("LimitedFraction")->flags->set(reduceFractions => 0);
parser::Assignment->Allow;
Context()->operators->redefine(',',using=>',',from=>'Numeric');
Context()->operators->redefine('or',using=>',',from=>'Numeric');
Context()->operators->set(
','=>{string=>' or ',TeX=>'\hbox{ or }'},
'or'=>{string=>' or ',TeX=>'\hbox{ or }'}
);
Context()->lists->set(List => {separator => " or "});
$var = "x";
$a = Fraction(1,random(2,10,1));
$ans = Compute("$var = -$a, $var = $a");
##############################################
TEXT(beginproblem());
BEGIN_PGML
Solve the quadratic equation
[` [$var]^2 = [$a**2] `]
[______________________]
END_PGML
##############################################
$showPartialCorrectAnswers = 1;
ANS($ans->cmp(
entry_type => "a solution",
checker => sub {
my ($correct,$student,$ans,$nth,$value) = @_;
if ($correct->type eq "Assignment") {
my ($svar,$sfrac) = $student->value; # get the variable and fraction
return 0 unless Value::classMatch($sfrac,'Fraction') && $sfrac->isReduced;
}
return $correct == $student;
},
extra => sub {
my ($student,$ansHash,$nth,$value) = @_;
if ($student->type ne "Assignment" && $ansHash->{student_formula}->type ne "Assignment") {
$student->context->setError("$nth $value: $student should be written $var = ___","",undef,undef,$Value::CMP_WARNING)
unless $ans->{isPreview};
return;
}
my ($svar,$sfrac) = $student->value; # get the variable and fraction
if (Value::classMatch($sfrac,'Fraction') && !$sfrac->isReduced) {
$student->context->setError("Your $nth $value is not reduced","",undef,undef,$Value::CMP_WARNING)
unless $ans->{isPreview};
return;
}
return Value::Real->typeMatch($student);
}
)->withPostFilter(AnswerHints(
["$var=$a","$var=-$a"] => "Are you sure you have all the solutions?",
[$a,-$a] => ["Your solution is a correct one, but you should write $var = ___<br>Are you sure you have all the solutions?",replaceMessage=>1],
["$a,-$a","-$a,$a"] => ["Your solutions are correct, but you should write $var = ___",replaceMessage=>1],
)));
I see that you have tried to make the comma display as an " or ", but this isn't working. The reason is that the result of parsing
x = -1/7, x = 1/7
is actually a constant List (basically the list
(("x",-1/7),("x",1/7))
), and so the item whose string and TeX form is being used is that constant List, so it is the List
string
and
TeX
function that is called. These don't use the context's comma operator to do their formatting. You can set the List object's
separator
value (as I do above) to get it to stringify using " or ", but unfortunately the TeX output is hardcoded with a comma (that need to be fixed).
Finally, something seems to be not working with the AnswerHints, as they are not being applied when they should be. I have to look into that further, but wanted to get this much out before doing that.
Hope that helps.
Davide