WeBWorK Problems

parserOneOf - Strings with whitespace trimmed

parserOneOf - Strings with whitespace trimmed

by Chris Pinto -
Number of replies: 2
I have a chemistry problem set I use as my first WebWork problem for new students - basically entering the symbol/name of elements given the other. I used to use str_cmp - which, by default, has 'compress_whitespace' and will remove leading/trailing spaces. One issue I had was with aluminum/aluminium and sulphur/sulfur - so I recently switched to using OneOf. Unfortunately, OneOf doesn't appear to trim spaces from answers. Any recommendations on how I can elegantly get both trimmed strings and multiple possible answers would be greatly appreciated. Problem code below:


DOCUMENT();
loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGchoicemacros.pl",
"parserOneOf.pl",
  "contextArbitraryString.pl",
);
Context("ArbitraryString");
#Setup
@all_elements=();
@all_symbols=();
qa(~~@all_elements, ~~@all_symbols,
OneOf("Hydrogen") => "H", #skip a few
OneOf("Aluminum", "Aluminium") => "Al",
OneOf("Silicon") => "Si",
OneOf("Phosphorus") => "P",
OneOf("Sulfur", "Sulphur") => "S", #skip a few
OneOf("Tungsten") => "W",
OneOf("Manganese") => "Mn"
);
my $num = 30;
my @pick_indexes = NchooseK($#all_elements+1,$num);  
my @elements = @all_elements[ @pick_indexes ];
my @symbols = @all_symbols[ @pick_indexes ];

$table_row="";
for ($i = 0; $i < $num; $i++) {
$table_row  .= row( $symbols[$i], ans_rule(15) );
}
Context()->normalStrings;

# Print problem number and point value (weight) for the problem
TEXT(beginproblem());
# Show which answers are correct and which ones are incorrect
$showPartialCorrectAnswers = 1;
BEGIN_TEXT
Enter the correct name for each element below (please be careful with spaces - there should be no extra spaces before/after the name):$PAR
$BCENTER
\{ begintable(2) \}
\{ row( "Symbol", "Element" ) \}
$table_row
\{ endtable() \}
$ECENTER
END_TEXT
  for ($i = 0; $i < $num; $i++) {
        ANS($elements[$i]->cmp);
}
ENDDOCUMENT();
In reply to Chris Pinto

Re: parserOneOf - Strings with whitespace trimmed

by Davide Cervone -
The ArbitraryString context does no processing of the answer whatsoever, and its intended use is that the problem author will provide a custom checker in the cmp() method. (See the comments at the top of constextArbitraryString.pl for details.) WIthout such a checker, the checking is done as exact strings (spaces included).

Here is an example of a checker that will trim leading and trailing whitespace, and make a case-insensitive check:

    ANS($ans->cmp(
      checker => sub {
        my ($correct,$student,$ans) = @_;
        $correct = lc($correct->string);
        $student = lc($student->string);
        $student =~ s/^ *| *$//g;
        return $correct eq $student;
      }
    ));
Here, we convert the MathObject to a perl string and force it to lower case. Then we remove leading and trailing spaced from the student answer (we assume the correct answers don't have such spaces). Finally, we compare the two and return true when equal and false otherwise.

Hope that helps.

In reply to Davide Cervone

Re: parserOneOf - Strings with whitespace trimmed

by Chris Pinto -
Thanks Davide,
That worked perfectly. I didn't realize the culprit here was the ArbitraryStrings context, good to know for future reference.
Much appreciated.
-Chris