When my list of solutions has two solutions in it, my checkers seem to work perfectly, but when there is only one solution in the lists, they do not seem to be working as I would expect.
Similarly, it seems that they do not work as I would expect when the student has only entered a single item in the list when the correct answer has two (or more?) items. The checker does not give any helpful feedback, just returning incorrect, and it also seems to be simplifying the student answer in that case in the preview.
I am still learning about these, and much of this code is my attempt to edit example code from PCC problems or directly from Alex Jordan.
Here is an example of a checker that I used that only seems to work with more than one assignment. When there is just one, it does not seem to see the individual items as assignments, and it was not seeming to work properly. It was not exactly a list but a solution stated in the form: n = 2 or n = 5. In this case the correct answer only had one assignment and was in the form: n = 4.
Here is my code for the solution set:
Defining the correct answer:
Context()->flags->set(showMixedNumbers => 0);
Context()->variables->are(n=>'Real');
Context()->strings->add("No solution"=>{NONE});
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 "});
Context()->flags->set(
reduceConstants=>0, # no decimals
reduceConstantFunctions=>0, # combine 4+5*2?
formatStudentAnswer=>'parsed', # no decimals
);
$possols = Compute("n = $an1");
Correcting the answer:
\{ SECTION_ANS($possols->cmp( entry_type => "a possible solution",
checker => sub {
my ($correct,$student,$ans,$nth,$value) = @_;
if ($correct->type eq "Assignment") {
my ($svar,$sfrac) = $student->value; # get the variable and fraction
if(Value::classMatch($sfrac,'Fraction'))
{
return 0 unless $sfrac->isReduced;
}
}
return $correct == $student;
},
extra => sub {
my ($student,$ansHash,$nth,$value) = @_;
if($student eq "No solution")
{
$student->context->setError("This equation does have some solutions- look back at your work","",undef,undef,$Value::CMP_WARNING)
unless $ans->{isPreview};
return;
}
if ($student->type ne "Assignment" && $ansHash->{student_formula}->type ne "Assignment") {
$student->context->setError("Your $nth solution should be written n = $US$US$US","",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);
}
)), $possols->ans_rule(30) \}
Then when I used a list_checker instead, I was very surprised that I needed to return a score of 2.0 from the list checker to award 100% even though there was only one element in the list. I had thought that I needed to return a score equal to the number of items in the list in order to award 100%.
Do I need to use a different checker for problems in which there is only one solution than I use when there are two or more solutions? If so, this seems more complicated than it should be.
Here is that code:
Defining answer:
Context("LimitedFraction")->flags->set(reduceFractions => 0);
Context()->flags->set(showMixedNumbers => 0);
Context()->variables->are(n=>'Real');
Context()->strings->add("No solution"=>{NONE});
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 "});
Context()->operators->set(
'/' => {class => 'bizarro::BOP::divide', isCommand => 1},
'//' => {class => 'bizarro::BOP::divide', isCommand => 1},
' /' => {class => 'bizarro::BOP::divide', isCommand => 1},
'/ ' => {class => 'bizarro::BOP::divide', isCommand => 1},
);
Context()->flags->set(
reduceConstants=>0, # no decimals
reduceConstantFunctions=>0, # combine 4+5*2?
formatStudentAnswer=>'parsed', # no decimals
);
$possols = Compute("n = $an1");
Correcting answer:
\{ SECTION_ANS($possols->cmp( entry_type => "a possible solution",
list_checker => sub {
my ($correct,$student,$ansHash,$value) = @_;
return 0 if $ansHash->{isPreview};
$student = $ansHash->{student_formula};
$correct = $ansHash->{correct_ans};
$student = Formula("$student"); $correct = Formula("$correct");
return 0 unless ($correct == $student);
Context()->flags->set(bizarroDiv=>1);
delete $correct->{test_values}, $student->{test_values};
my $OK = (($correct == $student) or ($student == $correct)) ;
Context()->flags->set(bizarroDiv=>0);
Value::Error("Your answer is correct, but please simplify it further.") unless $OK;
return $OK*2;
}
)), $possols->ans_rule(30) \}
Thanks!
Paul