No answer blank provided for answer evaluator AnSwEr0001
namedRules => 0 or 1 whether to use named rules or default rule names. Use named rules if you need to intersperse other rules with the ones for the MultiAnswer, in which case you must use NAMED_ANS not ANS. (Default: 0)
ans_rule()
method, not by calling NAMED_ANS_RULE()
on your own.
It is possible to do what you want, but you would have to make a subclass of the MultiAnswer object and override its internal ANS_NAME()
method that gets the names of the answer rules to use and have it return the pre-defined answer rules that you want to use. Here is an example:
loadMacros("parserMultiAnswer.pl"); # # Make a subclass of MultiAnswer # package myMultiAnswer; our @ISA = ('MultiAnswer'); # # Override the ANS_NAME method to return the names # of the named answer rules that we create separately # sub ANS_NAME { my $self = shift; my $i = shift; return ('one', 'two')[$i]; } package main; # # Create a new instance of our subclass # $ma = myMultiAnswer->new(1,2)->with( namedRules => 1, checker => sub { my ($correct,$student) = @_; my ($ca,$cb) = @$correct; my ($sa,$sb) = @$student; return ($ca == $sa ? 1 : 0, $cb == $sb ? 1 : 0); } ); # # Create the named rules # BEGIN_TEXT \{NAMED_ANS_RULE('one',5)\} and \{NAMED_ANS_RULE('two',5)\} END_TEXT # # Insert the answer checkers (MultiAnswer inserts the names # and answer checkers for both rules automatically) # NAMED_ANS($ma->cmp);Some things to note:
- You can't use
singleResult => 1
with this approach, because that requires one named answer rule and the rest as answer rule extensions. (If you are creating the second and subsequent answer rules yourself, you could potentially usesingleResult
, but if the other named rules are created by other code you don't control, then no.)
The macro for creating named answer rules is in upper case, not lower case (
NAMED_ANS_RULE()
not named_ans_rule()
). I'm not sure why that is, and perhaps there are other ways to do it.
The
$ma->cmp
call actually includes the names and answer checkers needed by NAMED_ANS()
, so you don't enter those yourself. (The result of $ma->cmp
is a list consisting of one => AnswerEvaluator, two => AnswerEvaluator
, which is just what NAMED_ANS()
needs.)
Hope that does what you need.
ggbEntry
here), since it is the named answer rule, and the others will be formed as extension rules by MultiAnswer. To make things a little easier, I override the new()
method as well, in order to set some needed values, as described below the code.
loadMacros("parserMultiAnswer.pl"); package myMultiAnswer; our @ISA = ('MultiAnswer'); sub new { my $self = shift; my $ma = $self->SUPER::new(@_); $ma->{part} = 1; $ma->{answerName} = 'ggbEntry'; $ma->{id} = $MultiAnswer::answerPrefix.$ma->{answerName}; $ma->{singleResult} = 1; $ma->{namedRules} = 1; return $ma; } sub ANS_NAME { my $self = shift; my $i = shift; return ($i == 0 ? $self->{answerName} : $self->{id}.'_'.$i); } package main; $ma = myMultiAnswer->new(1,2)->with( checker => sub { my ($correct,$student) = @_; my ($ca,$cb) = @$correct; my ($sa,$sb) = @$student; return ($ca == $sa ? 1 : 0, $cb == $sb ? 1 : 0); } ); BEGIN_TEXT \{ NAMED_ANS_RULE('ggbEntry',5) \} and \{ $ma->ans_rule(5) \} END_TEXT NAMED_ANS($ma->cmp);The
new()
method sets the part
to 1, since this is counting the answer blanks, and you are making the first one by hand. It also sets answerName
, which is the answer name of the main answer rule (and is used to tie the extensions to the main rule). The id
is used to create names for the extensions. Finally, I also set singleResults
and namedRules
so you don't have to do that by hand later.
The ANS_NAME()
method returns the answerName
for the first name and the constructed extension name for all the others. That should do it.
Since you are using named answer rules, technically the GeoGebra one could be in any position relative to the others. But note that the order in which they are displayed in the answer table when a student submits the answers will be the GeoGebra one first then the others. If the GeoGebra rule is in a different order, you can use the MultiAnswer format
and tex_format
options to display the results in the same order as the rules (or in whatever oder makes sense). For example, the following puts the GeoGebra blank last, and reorders the values in the format
parameters:
loadMacros("parserMultiAnswer.pl"); package myMultiAnswer; our @ISA = ('MultiAnswer'); sub new { my $self = shift; my $ma = $self->SUPER::new(@_); $ma->{part} = 1; $ma->{answerName} = 'ggbEntry'; $ma->{id} = $MultiAnswer::answerPrefix.$ma->{answerName}; $ma->{singleResult} = 1; $ma->{namedRules} = 1; return $ma; } sub ANS_NAME { my $self = shift; my $i = shift; return ($i == 0 ? $self->{answerName} : $self->{id}.'_'.$i); } package main; $ma = myMultiAnswer->new(1,2)->with( format => '%2$s and %1$s', tex_format => '%2$s \hbox{ and } %1$s', checker => sub { my ($correct,$student) = @_; my ($ca,$cb) = @$correct; my ($sa,$sb) = @$student; return ($ca == $sa ? 1 : 0, $cb == $sb ? 1 : 0); } ); BEGIN_TEXT \{ $ma->ans_rule(5) \} and \{ NAMED_ANS_RULE('ggbEntry',5) \} END_TEXT NAMED_ANS($ma->cmp);The
%2$s
in the format means insert the second value here as a string (2$
specifies second value, while %...s
means as a string). Similarly, %1$s
means insert the first value as a string. So the output is printed in the same order as the answer rules, as "2 and 1" even though the MultiAnswer has them in the order 1 then 2 when it is created.
Hope the makes sense.