## WeBWorK Problems

by tim Payer -
Number of replies: 14
We are trying to combine to aspects of answer checkers: PostFilter AnswerHints with a custom answer checker and are having trouble with the syntax.

Can anyone help with this?

The following code block below (suggested by Danny Glin) works fine. In this block an accuracy score, "$cor", is passed from a GeoGebra applet as a string could be read as an integer score and divided by 100 to be converted into a webwork score ($s/100) for the given assignment.

Context("ArbitraryString");
NAMED_ANS( 'answerBox' => String($cor)->cmp( checker=>sub { my($c, $s,$self) =@_;
$c =~ s/> //; ## Stripping "> " of "> 95%", leaving "95%"$c =~ s/%//; ## Stripping "%" of "95%", leaving "95"
$s =~ s/%//; ## Stripping "%" of the student accuracy, leaving an integer return$s/100;
}));

This code block permitted integer percentages instead of rounded scores in 5% blocks for the student. But we would like to include the comments that we had previously had along with this integer score.
What is the syntax that permits a custom answer checker and PostFilter answer hint to work together?

From the original, for example

Context("ArbitraryString");
NAMED_ANS( 'answerBox' => String($cor)->cmp->withPostFilter(AnswerHints( sub { my($c, $s,$self) =@_;
$c =~ s/> //; ## Stripping "> " of "> 95%", leaving "95%"$c =~ s/%//; ## Stripping "%" of "95%", leaving "95"
$s =~ s/%//; ## Stripping "%" of the student accuracy, leaving an integer return (($s >= 0) && ($s <= 50)); } => ["Oh no! You must score more than 50%, for any credit. Try again.", score => 0], sub { my($c, $s,$self) =@_;
$c =~ s/> //;$c =~ s/%//;
$s =~ s/%//; #$sc = Real($s); return (($s > 50) && ($s <= 60)); } => ["You could do better with another attempt, yes?", score => 0.60], sub { my($c, $s,$self) =@_;
$c =~ s/> //;$c =~ s/%//;
$s =~ s/%//; #$sc = Real($s); return (($s > 60) && ($s <= 70)); } => ["Try again. You can manage better than this.", score => 0.70], sub { my($c, $s,$self) =@_;
$c =~ s/> //;$c =~ s/%//;
$s =~ s/%//; #$sc = Real($s); return (($s > 70) && ($s <= 75)); } => ["This is okay, But you could do better, yes?", score => 0.75], sub { my($c, $s,$self) =@_;
$c =~ s/> //;$c =~ s/%//;
$s =~ s/%//; #$sc = Real($s); return (($s > 75) && ($s <= 80)); } => ["You are getting better, Try another?", score => 0.80], sub { my($c, $s,$self) =@_;
$c =~ s/> //;$c =~ s/%//;
$s =~ s/%//; #$sc = Real($s); return (($s > 80) && ($s <= 85)); } => ["Nice Work!", score => 0.85], sub { my($c, $s,$self) =@_;
$c =~ s/> //;$c =~ s/%//;
$s =~ s/%//; #$sc = Real($s); return (($s > 85) && ($s <= 90)); } => ["Very Good!", score => 0.90], sub { my($c, $s,$self) =@_;
$c =~ s/> //;$c =~ s/%//;
$s =~ s/%//; #$sc = Real($s); return (($s > 90) && ($s <= 95)); } => ["Excellent!", score => 0.95], sub { my($c, $s,$self) =@_;
$c =~ s/> //;$c =~ s/%//;
$s =~ s/%//; return$s > $c; } => ["Perfect!", score => 1], ))); Note that replacing "score => 0.95" with "score =>$s/100" is not accepted by Webwork.

How could we keep the scoring option of "$s/100", while still giving the feedback to the student in these rounded 5% blocks based on their results? Thanks for your continuing help! Tim In reply to tim Payer ### Re: Merging custom answer checkers with PostFilter Answer hints by tim Payer - Correction" "Two" aspects not "to".. Note that the phrase in the previous post "not accepted" by Webwork should be more specific: The integer percentage does come across, but Webwork treats all answers less than 95% as "incorrect". We would like all answers above 60% to be "Correct" but then the student can decide if they want to keep trying for a higher score. Here is the file if interested....Thanks, Tim In reply to tim Payer ### Re: Merging custom answer checkers with PostFilter Answer hints by Davide Cervone - I would not use answerHints for this, but instead just use a more sophisticated answer checker. Here is an example: loadMacros("contextArbitraryString.pl"); Context("ArbitraryString"); # # Messages in the form [test_score, message, new_score] # where the message will be used when the student score is less than # test_score, and the score will be set to new_score in that case, when # new_score is given. # @messages = ( [.50, "Oh no! You must score more than 50%, for any credit. Try again.", 0], [.60, "You could do better with another attempt, yes?"], [.70, "Try again. You can manage better than this."], [.75, "This is okay, But you could do better, yes?"], [.80, "You are getting better, Try another?"], [.85, "Nice Work!"], [.90, "Very Good!"], [.95, "Excellent!"], [1.0, "Perfect!"], ); TEXT(ans_rule(10)); ANS(String("100%")->cmp( checker => sub { my ($c, $s,$ans) = @_;
$s =~ s/%//; my$score = $s/100; for my$data (@messages) {
my ($percent,$msg, $nscore) = @$data;
if ($score <=$percent) {
$ans->{ans_message} =$msg;
$score =$nscore if defined $nscore; last; } } return$score;
}
));


This uses a list of cut-off scores and their associated messages (plus an optional new score to use when that message is given), and the answer checker loops through these scores and selected the appropriate message, which is places in the answer hash by hand, modifying the score to the new score, if needed.

Hope that does the trick.

by tim Payer -
Thank you Micheal,

But there There is an error with the use of this custom checker:

The complaint is that there was no evaluator for question labeled 'answerBox', which is what the javascript is using to carry value from ggb to ww.

I should have included the problem to give more context.

I tried inserting " 'answerBox' =>" before "String" but this did not work.

Thank you so much for answering this specific case!

Tim

by Davide Cervone -
You would need to use NAMED_ANS() not ANS(), and add answerBox => before the String() call.

by tim Payer -
Unfortunately, I still don't have the right syntax...

Here is what I had used:

@messages = (
[.50, "Oh no! You must score more than 50%, for any credit. Try again.", 0],
[.60, "You could do better with another attempt, yes?"],
[.70, "Try again. You can manage better than this."],
[.75, "This is okay, But you could do better, yes?"],
[.80, "You are getting better, Try another?"],
[.85, "Nice Work!"],
[.90, "Very Good!"],
[.95, "Excellent!"],
[1.0, "Perfect!"],
);

TEXT(ans_rule(10));

NAMED_ANS('answerBox' =>String($cor)->cmp( checker => sub { my ($c, $s,$ans) = @_;
$s =~ s/%//; my$score = $s/100; for my$data (@messages) {
my ($percent,$msg, $nscore) = @$data;
if ($score <=$percent) {
$ans->{ans_message} =$msg;
$score =$nscore if defined $nscore; last; } } return$score;
}
));

Thanks for the help!

Tim

by Michael Gage -
I don't think you need

TEXT(ans_rule(10));


That puts an extra answer rule in (named AnSwEr0001 since you didn't explicitly name it) and causes the error since you didn't create an answer evaluator for it using ANS(). I'm assuming you didn't want any obvious answer blank in the problem.

The geogebra applet handler creates a hidden answer blank explicitly

Incidentally setting one of the parameters debug=>1 (this can be done in a couple of places in the code) will show all of the hidden answer blanks. This can make the behavior of the geogebra applet less mysterious.

by tim Payer -
Thank you Michael,

That worked!

We had to insert " 'answerBox' => " before the String() command below and that did the trick:

Context("ArbitraryString");
@messages = (
[.50, "Oh no! You must score more than 50%, for any credit. Try again.", 0],
[.60, "You could do better with another attempt, yes?"],
[.70, "Try again. You can manage better than this."],
[.75, "This is okay, But you could do better, yes?"],
[.80, "You are getting better, Try another?"],
[.85, "Nice Work!"],
[.90, "Very Good!"],
[.95, "Excellent!"],
[1.0, "Perfect!"],
);

my ($c,$s, $ans) = @_;$s =~ s/%//;
my $score =$s/100;
for my $data (@messages) { my ($percent, $msg,$nscore) = @$data; if ($score <= $percent) {$ans->{ans_message} = $msg;$score = $nscore if defined$nscore;