| … | |
… | |
| 490 | package Value::List; |
490 | package Value::List; |
| 491 | |
491 | |
| 492 | sub cmp_defaults { |
492 | sub cmp_defaults { |
| 493 | my $self = shift; |
493 | my $self = shift; |
| 494 | my %options = (@_); |
494 | my %options = (@_); |
|
|
495 | my $element = Value::makeValue($self->{data}[0]); |
|
|
496 | $element = Value::Formula->new($element) unless Value::isValue($element); |
| 495 | return ( |
497 | return ( |
| 496 | Value::Real->cmp_defaults(@_), |
498 | Value::Real->cmp_defaults(@_), |
| 497 | showHints => undef, |
499 | showHints => undef, |
| 498 | showLengthHints => undef, |
500 | showLengthHints => undef, |
| 499 | showParenHints => undef, |
501 | showParenHints => undef, |
| 500 | partialCredit => undef, |
502 | partialCredit => undef, |
| 501 | ordered => 0, |
503 | ordered => 0, |
| 502 | showEqualErrors => $options{ordered}, |
504 | showEqualErrors => $options{ordered}, |
| 503 | entry_type => undef, |
505 | entry_type => undef, |
| 504 | list_type => undef, |
506 | list_type => undef, |
| 505 | typeMatch => Value::makeValue($self->{data}[0]), |
507 | typeMatch => $element, |
|
|
508 | extra => $element, |
| 506 | requireParenMatch => 1, |
509 | requireParenMatch => 1, |
| 507 | removeParens => 1, |
510 | removeParens => 1, |
| 508 | ); |
511 | ); |
| 509 | } |
512 | } |
| 510 | |
513 | |
| … | |
… | |
| 625 | # Finalize the score |
628 | # Finalize the score |
| 626 | # |
629 | # |
| 627 | $score = 0 if ($score != $maxscore && !$partialCredit); |
630 | $score = 0 if ($score != $maxscore && !$partialCredit); |
| 628 | $ans->score($score/$maxscore); |
631 | $ans->score($score/$maxscore); |
| 629 | push(@errors,"Score = $ans->{score}") if $ans->{debug}; |
632 | push(@errors,"Score = $ans->{score}") if $ans->{debug}; |
|
|
633 | my $error = join("\n",@errors); $error =~ s!</DIV>\n!</DIV>!g; |
| 630 | $ans->{error_message} = $ans->{ans_message} = join("\n",@errors); |
634 | $ans->{error_message} = $ans->{ans_message} = $error; |
| 631 | } |
635 | } |
| 632 | |
636 | |
| 633 | # |
637 | # |
| 634 | # Compare the contents of the list to see of they are equal |
638 | # Compare the contents of the list to see of they are equal |
| 635 | # |
639 | # |
| … | |
… | |
| 638 | my $correct = shift; my $student = shift; my $ans = shift; my $value = shift; |
642 | my $correct = shift; my $student = shift; my $ans = shift; my $value = shift; |
| 639 | my @correct = @{$correct}; my @student = @{$student}; my $m = scalar(@student); |
643 | my @correct = @{$correct}; my @student = @{$student}; my $m = scalar(@student); |
| 640 | my $ordered = $ans->{ordered}; |
644 | my $ordered = $ans->{ordered}; |
| 641 | my $showTypeWarnings = $ans->{showTypeWarnings} && !$ans->{isPreview}; |
645 | my $showTypeWarnings = $ans->{showTypeWarnings} && !$ans->{isPreview}; |
| 642 | my $typeMatch = $ans->{typeMatch}; |
646 | my $typeMatch = $ans->{typeMatch}; |
|
|
647 | my $extra = $ans->{extra}; |
| 643 | my $showHints = getOption($ans,'showHints') && !$ans->{isPreview}; |
648 | my $showHints = getOption($ans,'showHints') && !$ans->{isPreview}; |
| 644 | my $error = $$Value::context->{error}; |
649 | my $error = $$Value::context->{error}; |
| 645 | my $score = 0; my @errors; my $i = 0; |
650 | my $score = 0; my @errors; my $i = 0; |
| 646 | |
651 | |
| 647 | # |
652 | # |
| … | |
… | |
| 655 | ENTRY: foreach my $entry (@student) { |
660 | ENTRY: foreach my $entry (@student) { |
| 656 | $i++; $$Value::context->clearError; |
661 | $i++; $$Value::context->clearError; |
| 657 | $entry = Value::makeValue($entry); |
662 | $entry = Value::makeValue($entry); |
| 658 | $entry = Value::Formula->new($entry) if !Value::isValue($entry); |
663 | $entry = Value::Formula->new($entry) if !Value::isValue($entry); |
| 659 | if ($ordered) { |
664 | if ($ordered) { |
|
|
665 | if (scalar(@correct)) { |
| 660 | if (shift(@correct)->cmp_compare($entry,$ans)) {$score++; next ENTRY} |
666 | if (shift(@correct)->cmp_compare($entry,$ans)) {$score++; next ENTRY} |
|
|
667 | } else { |
|
|
668 | $extra->cmp_compare($entry,$ans); # do syntax check |
|
|
669 | } |
| 661 | if ($error->{flag} == $CMP_ERROR) {$self->cmp_error($ans); return} |
670 | if ($error->{flag} == $CMP_ERROR) {$self->cmp_error($ans); return} |
| 662 | } else { |
671 | } else { |
| 663 | foreach my $k (0..$#correct) { |
672 | foreach my $k (0..$#correct) { |
| 664 | if ($correct[$k]->cmp_compare($entry,$ans)) { |
673 | if ($correct[$k]->cmp_compare($entry,$ans)) { |
| 665 | splice(@correct,$k,1); |
674 | splice(@correct,$k,1); |
| … | |
… | |
| 677 | $nth = ' '.$self->NameForNumber($i); |
686 | $nth = ' '.$self->NameForNumber($i); |
| 678 | $class = $ans->{cmp_class}; |
687 | $class = $ans->{cmp_class}; |
| 679 | $answer = 'value'; |
688 | $answer = 'value'; |
| 680 | } |
689 | } |
| 681 | if ($error->{flag} && $ans->{showEqualErrors}) { |
690 | if ($error->{flag} && $ans->{showEqualErrors}) { |
| 682 | push(@errors,"<I>An error occured while processing your$nth $answer:</I>", |
691 | my $message = $error->{message}; $message =~ s/\s+$//; |
|
|
692 | push(@errors,"<SMALL>There is a problem with your$nth $value:</SMALL>", |
| 683 | '<DIV STYLE="margin-left:1em">'.$error->{message}.'</DIV>'); |
693 | '<DIV STYLE="margin-left:1em">'.$message.'</DIV>'); |
| 684 | } elsif ($showTypeWarnings && !$typeMatch->typeMatch($entry,$ans) && |
694 | } elsif ($showTypeWarnings && !$typeMatch->typeMatch($entry,$ans) && |
| 685 | !($ans->{ignoreStrings} && $entry->class eq 'String')) { |
695 | !($ans->{ignoreStrings} && $entry->class eq 'String')) { |
| 686 | push(@errors,"Your$nth $answer isn't ".lc($class). |
696 | push(@errors,"Your$nth $answer isn't ".lc($class). |
| 687 | " (it looks like ".lc($entry->showClass).")"); |
697 | " (it looks like ".lc($entry->showClass).")"); |
| 688 | } elsif ($showHints && $m > 1) { |
698 | } elsif ($showHints && $m > 1) { |