-
-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Convenience Method for MultiAnswer #926
Convenience Method for MultiAnswer #926
Conversation
There is another alternative, which would be to allow you to pass a MathObjects answer checker directly to The lines that need changing are pg/macros/parsers/parserMultiAnswer.pl Lines 189 to 192 in e131356
and making them something like foreach my $x (@data) {
if (ref($x) eq 'AnswerEvaluator') {
Value::Error('Only MathObject answer checkers can be passed to MultiAnswer()')
unless defined($x->{correct_value});
push(@cmp, $x);
$x = $x->{correct_value};
} else {
$x = Value::makeValue($x, context => $context) unless Value::isValue($x);
push(@cmp, $x->cmp(@ans_defaults));
}
} should do the trick (though I haven't tested this). Then you can use the individual answer checkers to set their options. E.g., $ma = MultiAnswer(
Fraction(1,2)->cmp(studentsMustReduceFractions => 1),
Real(3)->cmp(showTypeWarnings => 0)
)->with(
checker => sub {
...
}
); |
I actually attempted to do this before, supporting AnswerEvaluators passed into the MultiAnswer constructor, but I couldn't get around the retrieval of the correct answer from the evaluator. In your code suggestion, It would be nice to supplement to the convenience method by supporting this approach as well, but do you know of a better way for us to recover the original MathObject from the AnswerEvaluator? |
Sorry, you are right, it is on the AnswerEvaluator's answer hash, not the AnswerEvaluator itself (as I mentioned, I hadn't tested the code; I was writing from memory).
True, but you don't want You don't want to re-parse the |
a8c1ca8
to
c5efb93
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this generally looks good. A couple of suggestions though.
I think it would be good to add the new capability of passing an AnswerEvaluator
directly to the MultiAnswer
constructor to the POD documentation.
Also, you removed the section in the POD that describes how the checker works, and that states that a checker is required. I think that should be added back. The examples don't show everything that was previously in the explanation, and are not clear on the return values of the checker.
I think a comment about the width of answer rules should still be in the POD as well. That should be updated for how to do that with PGML answers.
macros/parsers/parserMultiAnswer.pl
Outdated
$success = MultiAnswer($fraction_obj)->setCmpFlags(1, studentsMustReduceFractions => 1); | ||
$failure = MultiAnswer($fraction_obj)->setCmpFlags(2, studentsMustReduceFractions => 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a little confusing. If you add code like this to the POD, authors may think that this might work. I think you mean that the first example will throw an error message, and the second will not. But that is not entirely clear. Also, it seems to insinuate that the $success
or $failure
variables are something other than what they are. The value of the $success
variable would actually be the answer hash for the $fraction_obj
answer. Of course $failure
would not be set because the die
would occur. In any case, the result of the MultiAnswer
constructor call is never stored in a variable, and so the call would not be particularly useful.
macros/parsers/parserMultiAnswer.pl
Outdated
If the specified C<$which_rule> does not correspond to an existing answer rule, this method | ||
will throw an error with the message "Answer $which_rule is not defined." | ||
|
||
$failure = MultiAnswer($math_obj)->setMessage(2, "It's like a jungle sometimes..."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has the same problem as the example code in the setCmpFlags
section.
my ($self, $cmp_number, %flags) = @_; | ||
die "Answer $cmp_number is not defined." unless defined($self->{cmp}[ $cmp_number - 1 ]); | ||
$self->{cmp}[ $cmp_number - 1 ]->ans_hash(%flags); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In light of the comments by @drgrice1, perhaps this method should return $self
so that you can chain the calls together. E.g.,
$ma = MultiAnswser("1/2", "sqrt(x-10)")->
setCmpFlags(1, studentsMustReduceFractions => 1)->
setCmpFlags(2, limits => [10, 15]);
and still have $ma
be the MultiAnswer object.
dae025b
to
0243a6f
Compare
Following the above suggestions,
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks good now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
0243a6f
to
aee8ca5
Compare
I will merge this since it has two approvals. |
MultiAnswer and AnswerEvaluator Attributes
After some discussion about #925, I think the clearer solution is to offer a convenience method for passing settings for individual answer rules.
Thanks to @dpvc for feedback regarding maintaining existing functionality.
setCmpFlags
setCmpFlags
is the answer rule to be targeted (starting with 1).Use Cases
Type Checking:
The original problem I faced involved customizing the error messages when type matching failed. I wrote a post-filter to replace the default error messages, but I also wanted to provide partial credit. However, the presence of the type-match warning prevented my checker from doing so (see #925 for details). Now, with this method I can avoid the default type-match warning and provide my own instead with partial credit in my checker:
Custom Context Flags:
Thanks to @drgrice1 for this example:
When working with
Context("Fraction")
, thestudentsMustReduceFractions => 0
setting will automatically reduce student responses before they reach ourMultiAnswer->{checker}
subroutine. If one wishes to provide partial credit for un-reduced fraction answers, it is necessary to ensure that this flag is true. Before the introduction of this convenience method, code contortions were necessary to configure this setting in a MultiAnswer object.