(1,2,3)
be considered the same as 1,2,3
? That is, should the delimiters matter? Both are lists consisting of the numbers 1, 2, and 3, so they should be the same, right?
The problem comes when you consider lists of lists; how should you represent a list of one list?. Is (1,2,3) a list of one item (a list), or is it a list of three items (the three numbers)?
For example, if the correct answer is the list (1,2,3),(4,5,6), and the student enters (1,2,3), we would want this to be interpreted as a list consisting of a single item, the list of three numbers, rather than a list consisting of three numbers. If we considered (1,2,3) to be a list of three numbers (rather than a list consisting of a single item, a list of three numbers), then there would be no way to enter a list consisting of a single list, and the treatment of (1,2,3) and (1,2,3),(4,5,6) would create (1,2,3) very differently in those to cases for the same answer blank.
Because of this case (the singleton list of lists), by default MathObjects considers an explicitly delimited list (when entered for a list answer) as a singleton list consisting of a single list. If you look carefully at the error message, it is suggesting that there is a list where a number was expected. That is, you asked for a list of numbers, but you got a list of lists (consisting of a single list). It is a subtle difference, and a hard one to make very clear.
This behavior is controlled by the implicitList
flag for the List answer checker. If you did
ANS(List("1,2,3")->cmp(implicitList=>0));then entering
(1,2,3)
would cause the student's answer to be treated as the list of three numbers rather than a list of one list, and the answer would be marked incorrect silently, since the delimiters don't match the ones you entered (since your list had no delimiters).
If you want to have (1,2,3)
to be marked correct, then you need to use
ANS(List("1,2,3")->cmp(implicitList=>0,parensMustMatch=>0));so that the parentheses won't have to match the ones from your list.
If neither of those is what you were after, then you will need to be more explicit about the behavior that you are looking for before I can tell you how to get it.
Hope that clarifies things.
Unfortunately, there are some messages that don't go through the
{error}{msg}
translation process (but should -- there certainly are still improvements to be made to MathObjects). It turns out that the type-check message is one of them. For that, you would have to use your original idea of supplying a PostFilter to change the message. Sorry!
Note that the setOrientation
set is such a homework set (it instructs the student about the student interface and how to enter answers into WeBWorK of various types). You might want to look at that as a starting point. We have found that it really helped reduce the questions and frustration level at Union.
In terms of the error message, you have done very well to get this far, and also to be concerned about what the errors will be. It looks like the String context needs to be fixed to use a better message when only one string is defined (though to be fair, this is a pretty unusual situation, since the only thing you can enter in the context is one of the strings, and since there is only one, that means there is only one possible answer that can be entered, not something that a normal problem would include).
The reason your code didn't work is a subtle one: the actual string used in the original message has two space between "one of" and "or Go", and you have only used one space in your test for it, so that turns out not to be true, and the messages is not changed. The reason there are two spaces is that (had there been more strings in the context), you would have had the list of them at that location in the string (with a space before and after the list). The list was empty, leaving just the two spaces next to each other.
If you take that into account, the problem will work as expected.
ANS($bearcats->cmp->withPostFilter(sub { my $ans = shift; $ans->{ans_message} = 'Your answer should be "Go Bearcats!"' if $ans->{ans_message} eq "Your answer should be one of or Go Bearcats!"; return $ans; }));There is another way to go about it, though. There is a mechanism in the Context object that allows the error messages to be customized. You could use that to replace the message automatically:
Context("String"); Context()->strings->add("Go Bearcats!"=>{}); Context()->{error}{msg}{"Your answer should be one of or Go Bearcats!"} = 'Your answer should be "Go Bearcats!";Again, note the two spaces in the original message.
Hope that clears it up for you.