Skip to content

Commit a49b458

Browse files
authored
Merge pull request #1140 from somiaj/multi-answer-convenice
Add MultiAnswer convenience methods (default checker and passing cmp options).
2 parents 6a409c6 + 29f85de commit a49b458

File tree

1 file changed

+42
-5
lines changed

1 file changed

+42
-5
lines changed

macros/parsers/parserMultiAnswer.pl

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ sub new {
6262
part => 0,
6363
singleResult => 0,
6464
namedRules => 0,
65+
cmpOpts => undef,
6566
checkTypes => 1,
6667
allowBlankAnswers => 0,
6768
tex_separator => $separator . '\,',
@@ -70,6 +71,7 @@ sub new {
7071
format => undef,
7172
context => $context,
7273
single_ans_messages => [],
74+
partialCredit => $main::showPartialCorrectAnswers,
7375
}, $class;
7476
}
7577

@@ -89,15 +91,34 @@ sub setCmpFlags {
8991
# the individual answer checkers.
9092
#
9193
sub cmp {
92-
my $self = shift;
93-
my %options = @_;
94+
my ($self, %options) = @_;
95+
96+
%options = (%options, %{ $self->{cmpOpts} }) if ref($self->{cmpOpts}) eq 'HASH';
97+
9498
foreach my $id ('checker', 'separator') {
9599
if (defined($options{$id})) {
96100
$self->{$id} = $options{$id};
97101
delete $options{$id};
98102
}
99103
}
100-
die "You must supply a checker subroutine" unless ref($self->{checker}) eq 'CODE';
104+
105+
unless (ref($self->{checker}) eq 'CODE') {
106+
die "Your checker must be a subroutine." if defined($self->{checker});
107+
$self->{checker} = sub {
108+
my ($correct, $student, $self, $ans) = @_;
109+
my @scores;
110+
111+
for (0 .. $self->length - 1) {
112+
push(@scores, $correct->[$_] == $student->[$_] ? 1 : 0);
113+
}
114+
return \@scores if $self->{partialCredit};
115+
for (@scores) {
116+
return 0 unless $_;
117+
}
118+
return 1;
119+
}
120+
}
121+
101122
if ($self->{allowBlankAnswers}) {
102123
foreach my $cmp (@{ $self->{cmp} }) {
103124
$cmp->install_pre_filter('erase');
@@ -474,9 +495,9 @@ =head1 ATTRIBUTES
474495
475496
C<MultiAnswer> objects have the following attributes:
476497
477-
=head2 checker (required)
498+
=head2 checker
478499
479-
A coderef to be called to check student answers. This is the only required attribute.
500+
A coderef to be called to check student answers.
480501
481502
The C<checker> routine receives four parameters: a reference to the array of correct answers,
482503
a reference to the array of student answers, a reference to the C<MultiAnswer> object itself,
@@ -490,6 +511,16 @@ =head2 checker (required)
490511
}
491512
$multianswer_obj = $multianswer_obj->with(checker=>~~&always_right);
492513
514+
If a C<checker> is not provided, a default checker is used. The default checker checks if each
515+
answer is equal to its correct answer (using the overloaded C<==> operator). If C<< partialCredit => 1 >>,
516+
the checker returns an array of 0s and 1s listing which answers are correct giving partial credit.
517+
If C<< partialCredit => 0 >>, the checker only returns 1 if all answers are correct, otherwise returns 0.
518+
519+
=head2 partialCredit
520+
521+
This is used with the default checker to determine if the default checker should reward partial
522+
credit, based on the number of correct answers, or not. Default: C<$showPartialCorrectAnswers>.
523+
493524
=head2 singleResult
494525
495526
Indicates whether to show only one entry in the results table (C<< singleResult => 1 >>)
@@ -501,6 +532,12 @@ =head2 namedRules
501532
if you need to intersperse other rules with the ones for the C<MultiAnswer>. In this case, you must
502533
use C<NAMED_ANS> instead of C<ANS>. Default: 0.
503534
535+
=head2 cmpOpts
536+
537+
This is a hash of options that will be passed to the cmp method. For example,
538+
C<< cmpOpts => { weight => 0.5 } >>. This option is provided to make it more convenient to pass
539+
options to cmp when utilizing PGML. Default: undef (no options are sent).
540+
504541
=head2 checkTypes
505542
506543
Specifies whether the types of the student and professor's answers must match exactly

0 commit comments

Comments
 (0)