@@ -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#
9193sub 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
475496C<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
481502The C<checker > routine receives four parameters: a reference to the array of correct answers,
482503a 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
495526Indicates whether to show only one entry in the results table (C<< singleResult => 1 >>)
@@ -501,6 +532,12 @@ =head2 namedRules
501532if you need to intersperse other rules with the ones for the C<MultiAnswer > . In this case, you must
502533use 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
506543Specifies whether the types of the student and professor's answers must match exactly
0 commit comments