WeBWorK Problems

Limited Numeric Context and Custom Answer Checkers

Limited Numeric Context and Custom Answer Checkers

by Steven Fiedler -
Number of replies: 5

I noticed an issue while hardening my code for a problem.  Despite using the LimitedNumeric context, a student entering a character instead of an expected number for an answer, would view a "PG warning message" of "The evaluated answer is not an answer hash."

This issue could be traced to the use of the "withPostFilter" flag in the custom answer checker.  Below is a MWE that exemplifies the issue.  The call of ANS on line 11 triggers the "answer hash" alert, however the call of ANS on line 12 (sans "withPostFilter") behaves as expected. 

Unfortunately, I need to use the wtihPostFilter flag in my sig fig code to properly display input in the "Entered" and "Answer Preview" columns. In principle, I could encapsulate triggering statements such as line 16 in the MWE with a regular expression in a conditional or attempt to use perl's Scalar::Util::looks_like_number() , but such approaches appear redundant and against the spirit of the LimitedNumeric context. 

I would appreciate any suggestions.

DOCUMENT();
loadMacros("PGstandard.pl", "PGML.pl");

Context("LimitedNumeric");
$corr=Real(1);

BEGIN_PGML
Enter the number 1: [___]
END_PGML
 
ANS($corr->cmp->withPostFilter(
#ANS($corr->cmp(
   sub {
      $ansHash=shift;
      $sval = $ansHash->{student_value};         
     Real($sval);  #To trip the answer hash warning
     return $ansHash;        

    }#end sub
   ) #end cmp
); #end ANS()



ENDDOCUMENT();

Attachment Screenshot_2023-10-15_16-22-01ee.png
In reply to Steven Fiedler

Re: Limited Numeric Context and Custom Answer Checkers

by Glenn Rice -

I don't know exactly what you are trying to do, so I am not entirely certain how to answer your question.

In a post filter, unlike in a checker, there are no guarantees as to what the student_value will be.

In a post filter you can use the Value::classMatch method to see if it matches the class of what you are looking for.  So do "if (Value::classMatch($ansHash->{student_value}, 'Real') { .... }".  Of course your code that works with the student value should go where the ellipsis is.

There are other checks you could use depending on what you are doing, but you need something.  If the student's answer doesn't even parse into a MathObject, then the $ansHash->{student_value} will be undefined.  A string answer will not parse into a MathObject in your MWE, so that might be enough for you.

In reply to Glenn Rice

Re: Limited Numeric Context and Custom Answer Checkers

by Steven Fiedler -

Thank you Glenn. Both of your suggestions resolved the issue with the MWE. 

As Glenn suspected, the MWE was too simplified.  The problem code needs to use $ansHash->{original_student_ans} in lieu of $ansHash->{student_value};  Unfortunately, neither the if(defined... nor the if(Value... approaches handle the original_student_ans in the same manner as student_value.  Below is another MWE and screenshot that demonstrates this behavior.  The Result score should be 0.25% correct, which is achievable if line 16 is used in place of line 17.

I would appreciate any thoughts and apologize about having to revisit this.

DOCUMENT();
loadMacros("PGstandard.pl", "PGML.pl");

Context("LimitedNumeric");
$corr=Real(1);

BEGIN_PGML
Enter the number 1: [___]
END_PGML
 
ANS($corr->cmp->withPostFilter(
   sub {
     $ansHash=shift;
     
#     $sval=$ansHash->{student_value};
    $sval=$ansHash->{original_student_ans};
     if(Value::classMatch($sval,'Real')){
        Real($sval);
        $ansHash->{score} = .25;
     };

     return $ansHash;        

    }#end sub
   ) #end cmp
); #end ANS()

ENDDOCUMENT();



Attachment Screenshot_2023-10-15_19-39-29ff.png
In reply to Steven Fiedler

Re: Limited Numeric Context and Custom Answer Checkers

by Steven Fiedler -
After a bit of thought, sensitive code in the post filter can be insulated in the following manner.

DOCUMENT();
loadMacros("PGstandard.pl", "PGML.pl");

Context("LimitedNumeric");
$corr=Real(1);

BEGIN_PGML
Enter the number 1: [___]
END_PGML

ANS($corr->cmp->withPostFilter(
sub {
$ansHash=shift;
$key=$ansHash->{student_value};
$sval=$ansHash->{original_student_ans};
if(defined($key)){
Real($sval);
};

return $ansHash;

}#end sub
) #end cmp
); #end ANS()

ENDDOCUMENT();
In reply to Steven Fiedler

Re: Limited Numeric Context and Custom Answer Checkers

by Andrew Parker -

`original_student_ans` is always a string.

`student_value` is a MathObject, provided that `original_student_ans` is able to be parsed as such.

As a result, original_student_ans will never Value::classMatch against any MathObject class.

On the other hand, student_value at least has a chance to classMatch, depending on what the user submits. 

In your MWE, use student_value instead of original_student_ans, and then submit 'x' as a response. This will not classMatch with 'Real' (it is a 'Formula'). Then submit 'a' as a response. This will not classMatch with anything, because student_value will not be defined ('a' is not defined in this Context, thus a Formula cannot be created from the string 'a').

You can verify the above by using this modified form of your MWE:

ANS($corr->cmp->withPostFilter(
   sub {
     $ansHash=shift;
     
     $sval=$ansHash->{student_value};

     if (Value::classMatch($sval,'Real')) {
        $ansHash->{score} = .25;
     } elsif (Value::classMatch($sval,'Formula')) {
        $ansHash->{score} = .15;
     } elsif (defined $sval) {
        $ansHash->{score} = .1;
     } elsif ($ansHash->{original_student_ans} eq 'a') {
        $ansHash->{score} = .05;
     }


     return $ansHash;        

    }#end sub
   ) #end cmp
); #end ANS()


In reply to Andrew Parker

Re: Limited Numeric Context and Custom Answer Checkers

by Steven Fiedler -
Thank you Andrew - I appreciate the clarification. My sig fig code is operational again.