WeBWorK Problems

Custom Answer Checker for strings

Custom Answer Checker for strings

by roo biki -
Number of replies: 4

Is it possible to write a custom answer checker (or even multi answer checkers) if the answer to a problem is supposed to be a string of text?  Here's an example of a problem I'm trying to create.  The code below will work, but only if   

DOCUMENT();

loadMacros(
  "PGstandard.pl",
  "MathObjects.pl"
);

TEXT(beginproblem());

Context()->texStrings;

BEGIN_TEXT

A \{ans_rule(10)\}, or \{ans_rule(10)\} from \( A \) to \( B \) is a rule that assigns, to each \( x\in A \), a unique element \( y \in B \).

END_TEXT

Context()->normalStrings;

ANS(str_cmp("function"));
ANS(str_cmp("mapping"));
ENDDOCUMENT();

The problem with this though, is that if the student enters the words "mapping" and "function" in reverse order, they are both graded wrong.


In reply to roo biki

Re: Custom Answer Checker for strings

by Danny Glin -

It's worth mentioning that the str_cmp method is deprecated, so you should avoid using that in the future.

MathObjects has a String class, which will allow you to compare strings.  You can combine this with a MultiAnswer construction, and it should do what you want.

Of course this doesn't solve the challenges that are inherent to comparing strings (e.g. spaces, spelling, other synonyms).

In reply to Danny Glin

Re: Custom Answer Checker for strings

by roo biki -

Thanks so much for your answer, and for the comment about str_cmp()!

If I was going to write a custom answer checker for a problem where the answer is a string, I'd write something like this.  It doesn't give any errors, but it doesn't work as intended either.  According to my understanding, this should accept any answer.  It accepts function as correct, but rejects functionf.

DOCUMENT();

loadMacros(
  "PGstandard.pl",
  "MathObjects.pl"
);

TEXT(beginproblem());

Context()->strings->add(
  function=>{}
);

Context()->texStrings;

BEGIN_TEXT

A \{ans_rule(10)\} from \( A \) to \( B \) is a rule that assigns, to each \( x\in A \), a unique element \( y \in B \).

END_TEXT

Context()->normalStrings;

ANS(String("function")->cmp(
  checker => sub {
    return 1;
  }
));

ENDDOCUMENT();

Am I forgetting something, or more likely misunderstanding something?

In reply to roo biki

Re: Custom Answer Checker for strings

by Danny Glin -

What version of WeBWorK are you running?  When I run your code on 2.17 I do get feedback messages when I enter incorrect answers.  For example if I type "functionf" I get the message "Variable 'f' is not defined in this context".

This is the expected behaviour.  If you do not explicitly set a context then it defaults to the "Numeric" context, which is for handling real-valued functions and numerical responses.  In your code you have added the string "function" to the context, so it recognizes that string along with the strings that are already present in the context (e.g. "DNE", "infinity").  In the Numeric context WeBWorK defaults to expecting a number as the correct answer.  If you enter anything that doesn't fit into that context it gets marked wrong before it even gets to the answer checker, and gives a related message.

What this means is that for your code answers such as "function", "3", and "DNE" will be marked correct, because they are allowed answers in the context.  Answers such as "functionf" should get the message I quoted above, because the 'f' is not allowed.  Answers such as "3x" should get the message "Your answer isn't a number (it looks like a formula that returns a number)".

If you want students to be able to type arbitrary strings you should use the ArbitraryString context, which allows students to enter any text without WeBWorK trying to interpret it as math.

Here's sample problem code that should do what you intended.  I've also added the flag to turn off MathQuill (the assistive math formula editor) for this answer, which will prevent the answer box from interpreting the input as a mathematical formula.  My code uses PGML syntax, which is the current recommended approach rather than the old BEGIN_TEXT/END_TEXT syntax.

DOCUMENT();

loadMacros(

  "PGstandard.pl",

  "MathObjects.pl",

  "contextArbitraryString.pl",

  "PGML.pl",

  "PGcourse.pl"

);


TEXT(beginproblem());


Context("ArbitraryString");


$ans = String("function")->cmp(mathQuillOpts => "disabled",

    checker => sub {

        return 1;

        }

);


BEGIN_PGML

A [_]{$ans}{10} from [` A `] to [` B `] is a rule that assigns, to each [` x\in A `], a unique element [` y \in B `].

END_PGML


ENDDOCUMENT();

In reply to Danny Glin

Re: Custom Answer Checker for strings

by roo biki -
Thanks so much for your reply. You resolved my issue, while also answering several other questions I didn't even know I had!