Mike:
I had suggested a mechanism for adding filters to answer checkers
sometime last year. It may have been before the developer's mailing
list, as I don't see it archived there. My recommendation at that time
was to add new methods called withPreFilter , withPostFilter and so on that would take the filter code, add it to the answer checker, and return the checker as their result, so you could do things like: ANS(fun_cmp("sin(x)")->withPreFilter(must_have("tan",'no',"You can't use tan() here")));
The key difference between withPreFilter and the current install_prefilter is that the latter does not return the answer checker, it returns the list of filters. With withPreFilter ,
you get back the answer checker, so can add filters without having to
make separate variables, and can continue to add more filters by
stringing on more withPreFilter or withPostFilter calls.
The reason I like this better than fun_cmp("sin(x)",filters=>...) is that that syntax requires each answer checker to implement the filters option itself, whereas using a withPreFilter
method, every answer checker would allow this automatically. That would
include the Parser answer checkers, by the way, so you could do ANS(Vector(1,2,3)->cmp->withPostFilter(sub { my $ans = shift; return unless $ans->{score} == 1; my $V = $ans->{student_value}; # where Parser stores the parsed object if (norm($V) == 0) { $ans->score(0); $ans->{ans_message} = "The zero vector is not allowed" unless $ans->{isPreview}; # parser sets this } });
which adds a post filter that rejects the zero vector, but only if the
score was counted as correct, and the student is not previewing the
answer. This might be easier using the Parser's checker
field, but you see why this could be useful. This is especially true if
the filters are predefined somewhere, so you could just do ANS(Vector(1,2,3)->cmp->withPostFilter(no_zero_vector);
I was going to add these methods to the answer checker used by the
Parser, but it turns out that you can't subclass the AnswerEvaluator
object (the PG translator checks that the answer checker is actually an
AnswerEvaluator object (or one of the legacy possibilities), and so a
subclass of the AnswerEvaluator won't be accepted. I think you changed
this recently, so I could add it to the Parser, but it seems to me that
it is useful enough to be added to the actual AnswerEvaluator.
Anyway, that's my two cent's worth.
Davide
<| Post or View Comments |>
|