[system] / trunk / pg / macros / PGasu.pl Repository:
ViewVC logotype

Diff of /trunk/pg/macros/PGasu.pl

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1941 Revision 1943
14 14
15# Answer evaluator which always marks things correct 15# Answer evaluator which always marks things correct
16 16
17=head3 auto_right() 17=head3 auto_right()
18 18
19=pod
20
21 Usage: ANS(auto_right());
22 or
23 ANS(auto_right("this answer can be left blank"));
24
25This answer checker marks any answer correct. It is useful when you want
26to leave multiple answer blanks, only some of which will be used. If you
27turn off showing partial correct answers and partial credit, the effect is
28not visible to the students. The comment in the second case is what will
29be displayed as the correct answer. This helps avoid confusion.
19 30
20=cut 31=cut
21 32
22sub auto_right { 33sub auto_right {
23 my $ae = std_str_cmp("");
24
25 my $ans_eval = sub {
26 my $tried = shift;
27 my $ans_hash = &$ae($tried);
28 $ans_hash->{score} = 1;
29 return $ans_hash;
30 };
31 return $ans_eval;
32}
33
34# Evaluate in tth mode
35
36=head3 tthev()
37
38
39
40=cut
41
42sub tthev {
43 my $cmt = shift; 34 my $cmt = shift;
35 my %params = @_;
36 $cmt = '' unless defined($cmt);
37
38 my $answerEvaluator = new AnswerEvaluator;
39 $answerEvaluator->ans_hash(
40 type => "auto_right",
41 correct_ans => "$cmt"
42 );
43 $answerEvaluator->install_pre_filter('reset');
44 $answerEvaluator->install_evaluator(\&auto_right_checker,%params);
44 45
45 $mdm = $main::displayMode; 46 return $answerEvaluator;
46 $main::displayMode = 'HTML_tth';
47 $cmt = EV3($cmt);
48 $cmt =~ s/\\par/<P>/g;
49 $cmt =~ s/\\noindent//g;
50 $main::displayMode =$mdm;
51 $cmt
52} 47}
48
49# used in auto_right above
50
51sub auto_right_checker {
52 my $ans = shift;
53 $ans->score(1);
54 return($ans);
55}
56
53 57
54=head3 no_decs() 58=head3 no_decs()
55 59
60=pod
56 61
62Can be wrapped around an numerical evaluation. It marks the answer wrong
63if it contains a decimal point. Usage:
64
65 ANS(no_decs(num_cmp("sqrt(3)")));
66
67This will accept "sqrt(3)" or "3^(1/2)" as answers, but not 1.7320508
57 68
58=cut 69=cut
59 70
60 71
61sub no_decs { 72sub no_decs {
68 return $old_evaluator; 79 return $old_evaluator;
69 } 80 }
70 81
71=head3 must_include() 82=head3 must_include()
72 83
73 84=pod
85
86Wrapper for other answer evaluators. It insists that a string is part of
87the answer to be marked right.
74 88
75=cut 89=cut
76 90
77sub must_include { 91sub must_include {
78 my ($old_evaluator) = shift; 92 my ($old_evaluator) = shift;
80 94
81 $old_evaluator->install_pre_filter(must_have_filter($muststr)); 95 $old_evaluator->install_pre_filter(must_have_filter($muststr));
82 $old_evaluator->install_post_filter(\&raw_student_answer_filter); 96 $old_evaluator->install_post_filter(\&raw_student_answer_filter);
83 return $old_evaluator; 97 return $old_evaluator;
84 } 98 }
99
85=head3 no_trig_fun() 100=head3 no_trig_fun()
86 101
102Wrapper for other answer evaluators. It marks the answer wrong if
103it contains one of the six basic trig functions.
87 104
105This is useful if you want students to report the value of sin(pi/4),
106but you don't want to allow "sin(pi/4)" as the answer.
88 107
89=cut 108=cut
90 109
91sub no_trig_fun { 110sub no_trig_fun {
92 my ($ans) = shift; 111 my ($ans) = shift;
100 $new_eval->install_pre_filter(must_have_filter("cot", 'no', $msg)); 119 $new_eval->install_pre_filter(must_have_filter("cot", 'no', $msg));
101 120
102 return $new_eval; 121 return $new_eval;
103} 122}
104 123
105=head3 no_trig()
106
107
108
109=cut
110=head3 no_trig() 124=head3 no_trig()
111 125
112 126
113 127
114=cut 128=cut
149} 163}
150 164
151 165
152=head3 must_have_filter() 166=head3 must_have_filter()
153 167
168=pod
154 169
170Filter for checking that an answer has (or doesn't have) a certain
171string in it. This can be used to screen answers where you want them
172in a particular form (e.g., if you allow most functions, but not trig
173functions in the answer, or if the answer must include some string).
155 174
156 # First argument is the string to have, or not have 175First argument is the string to have, or not have
157 # Second argument is optional, and tells us whether yes or no 176Second argument is optional, and tells us whether yes or no
158 # Third argument is the error message to produce (if any). 177Third argument is the error message to produce (if any).
159 178
160=cut 179=cut
161 180
162 181
163# First argument is the string to have, or not have 182# First argument is the string to have, or not have
296 return $ans_hash; 315 return $ans_hash;
297 }; 316 };
298 return $answer_evaluator; 317 return $answer_evaluator;
299} 318}
300 319
301=head3 log_switcheroo()
302
303
304
305=cut
306
307
308sub log_switcheroo {
309 my $foo = shift;
310
311 $foo =~ s/log(?!ten)/logten/gi;
312 return $foo;
313}
314
315# only used below, so assumes it is being applied to num_cmp
316sub log_switcheroo_filter {
317 my ($rh_ans) = shift;
318 $rh_ans->{student_ans} = log_switcheroo($rh_ans->{student_ans});
319
320 return $rh_ans;
321 }
322
323=head3 log10_cmp()
324
325
326
327=cut
328
329
330
331sub log10_cmp {
332 my(@stuff) = @_;
333 $stuff[0] = log_switcheroo($stuff[0]);
334 my ($ae) = num_cmp(@stuff);
335 $ae->install_pre_filter(\&log_switcheroo_filter);
336 return $ae;
337}
338
339
340=head3 with_comments() 320=head3 with_comments()
341 321
342 322
343 # Wrapper for an answer evaluator which can also supply comments 323 # Wrapper for an answer evaluator which can also supply comments
344 324
393# [answer_evaluator, partial credit factor, comment] 373# [answer_evaluator, partial credit factor, comment]
394# it applies evaluators from the list until it hits one with positive credit, 374# it applies evaluators from the list until it hits one with positive credit,
395# weights it by the partial credit factor, and throws in its comment 375# weights it by the partial credit factor, and throws in its comment
396 376
397sub pc_evaluator { 377sub pc_evaluator {
398 my ($evaluator_list) = @_; 378 my @ev_list;
399 379 if(ref($_[0]) ne 'ARRAY') {
380 warn "Improper input to pc_evaluator";
381 }
382 if(ref($_[0]->[0]) ne 'ARRAY') {
383 @ev_list = @_;
384 } else {
385 @ev_list = @{$_[0]};
386 }
387
400 my $ans_evaluator = sub { 388 my $ans_evaluator = sub {
401 my $tried = shift; 389 my $tried = shift;
402 my $ans_hash; 390 my $ans_hash;
403 for($j=0;$j<scalar(@{$evaluator_list}); $j++) { 391 for($j=0;$j<scalar(@ev_list); $j++) {
404 my $old_evaluator = $evaluator_list->[$j][0]; 392 my $old_evaluator = $ev_list[$j][0];
405 my $cmt = $evaluator_list->[$j][2]; 393 my $cmt = $ev_list[$j][2];
406 my $weight = $evaluator_list->[$j][1]; 394 my $weight = $ev_list[$j][1];
395 $weight = 1 unless defined($weight);
407 396
408 if ( ref($old_evaluator) eq 'AnswerEvaluator' ) { # new style 397 if ( ref($old_evaluator) eq 'AnswerEvaluator' ) { # new style
409 $ans_hash = $old_evaluator->evaluate($tried); 398 $ans_hash = $old_evaluator->evaluate($tried);
410 } elsif (ref($old_evaluator) eq 'CODE' ) { #old style 399 } elsif (ref($old_evaluator) eq 'CODE' ) { #old style
411 $ans_hash = &$old_evaluator($tried); 400 $ans_hash = &$old_evaluator($tried);
412 } else { 401 } else {
413 warn "There is a problem using the answer evaluator"; 402 warn "There is a problem using the answer evaluator";
414 } 403 }
415 404
416 if($ans_hash->{score}>0) { 405 if($ans_hash->{score}>0) {
417 $ans_hash -> setKeys( 'ans_message' => $cmt); 406 $ans_hash -> setKeys( 'ans_message' => $cmt) if defined($cmt);
418 $ans_hash->{score} *= $weight; 407 $ans_hash->{score} *= $weight;
419 return $ans_hash; 408 return $ans_hash;
420 }; 409 };
421 }; 410 };
422 return $ans_hash; 411 return $ans_hash;
423 }; 412 };
424 413
425 $ans_evaluator; 414 $ans_evaluator;
426} 415}
427 416
417
428=head3 nicestring 418=head3 nicestring
429 419
420=pod
421
422A formatting function for dealing with 1, -1, and 0 coefficients in
423linear combinations.
424
425Usage:
426
427 $a = nicestring([0,1,-1,2], ['x', 'y', 'z', 'w']);
428
429produces "y-z+ 2w" in $a.
430
431As a shorthand for polynomials,
432
433 $b = nicestring([1,2, -1, 0, 3]);
434
435produces 'x^4 + 2 x^3 - x^2 + 3' in $b.
430 436
431 437
432=cut 438=cut
433 439
434 440
469 } 475 }
470 return($ans); 476 return($ans);
471} 477}
472 478
473 479
474=head3 displaymat 480=head3 weighted_partial_grader
475 481
482=pod
476 483
484This is a grader which weights the different parts of the problem
485differently. The weights passed to it through the environment. In
486the problem:
477 487
478=cut 488 $ENV{'partial_weights'} = [.2,.2,.2,.3];
479 489
490This will soon be superceded by a better grader.
480 491
481sub displaymat {
482 my $tmpp = shift;
483 my %opts = @_;
484 my @myrows = @{$tmpp};
485 my $numrows = scalar(@myrows);
486 my @arow = $myrows->[0];
487 my ($number)= scalar(@arow); #number of columns in table
488 my $out;
489 my $j;
490 my $align1=''; # alignment as a string
491 my @align; # alignment as a list
492 if(defined($opts{'align'})) {
493 $align1= $opts{'align'};
494 @align = split //, $opts{'align'};
495 } else {
496 for($j=0; $j<$number; $j++) {
497 $align[$j] = "c";
498 $align1 .= "c";
499 }
500 }
501
502 $out .= beginmatrix($align1);
503 $out .= matleft($numrows);
504 for $j (@myrows) {
505 $out .= matrow($j, @align);
506 }
507 $out .= matright($numrows);
508 $out .= endmatrix();
509 $out;
510}
511
512=head3 beginmatrix
513
514
515
516=cut 492=cut
517 493
518 494sub weighted_partial_grader {
519sub beginmatrix { 495 my $rh_evaluated_answers = shift;
520 my ($aligns)=shift; #alignments of columns in table 496 my $rh_problem_state = shift;
521# my %options = @_; 497 my %form_options = @_;
522 my $out = ""; 498 my %evaluated_answers = %{$rh_evaluated_answers};
523 if ($displayMode eq 'TeX') { 499 # The hash $rh_evaluated_answers typically contains:
524 $out .= "\n\\(\\displaystyle\\left(\\begin{array}{$aligns} \n"; 500 # 'answer1' => 34, 'answer2'=> 'Mozart', etc.
525 } 501
526 elsif ($displayMode eq 'Latex2HTML') { 502 # By default the old problem state is simply passed back out again.
527 $out .= "\n\\begin{rawhtml} <TABLE BORDER=0>\n\\end{rawhtml}"; 503 my %problem_state = %$rh_problem_state;
528 } 504
529 elsif ($displayMode eq 'HTML' || $displayMode eq 'HTML_tth' || $displayMode eq 'HTML_dpng') { 505
530 $out .= "<TABLE BORDER=0>\n" 506 # %form_options might include
531 } 507 # The user login name
532 else { 508 # The permission level of the user
533 $out = "Error: beginmatrix: Unknown displayMode: $displayMode.\n"; 509 # The studentLogin name for this psvn.
534 } 510 # Whether the form is asking for a refresh or
535 $out; 511 # is submitting a new answer.
536} 512
513 # initial setup of the answer
514 my $total=0;
515 my %problem_result = ( score => 0,
516 errors => '',
517 type => 'custom_problem_grader',
518 msg => $ENV{'grader_message'}
519 );
537 520
538 521
539=head3 matleft 522 # Return unless answers have been submitted
523 unless ($form_options{answers_submitted} == 1) {
524 return(\%problem_result,\%problem_state);
525 }
526 # Answers have been submitted -- process them.
527
528 ########################################################
529 # Here's where we compute the score. The variable #
530 # $numright is the number of correct answers. #
531 ########################################################
540 532
541 533
534 my $numright=0;
535 my $i;
536 my $ans_ref;
542 537
543=cut 538 warn "Partial value weights not defined" if not defined($ENV{'partial_weights'});
539 my @partial_weights = @{$ENV{'partial_weights'}};
540 my $total_weight=0;
544 541
542 # Renormalize weights so they add to 1
543 for $i (@partial_weights) { $total_weight += $i; }
544 warn("Weights do not add to a positive number") unless ($total_weight >0);
545 for $i (0..$#partial_weights) { $partial_weights[$i] /= $total_weight; }
545 546
547 $i = 1;
548 while (defined($ans_ref = $evaluated_answers{'AnSwEr'."$i"})) {
549 $total += $ans_ref->{score}*$partial_weights[$i-1];
550 $i++;
551 }
552
553 $problem_result{score} = $total;
554 # increase recorded score if the current score is greater.
555 $problem_state{recorded_score} = $problem_result{score} if $problem_result{score} > $problem_state{recorded_score};
546 556
547sub matleft { 557 $problem_state{num_of_correct_ans}++ if $total == 1;
548 my $numrows = shift; 558 $problem_state{num_of_incorrect_ans}++ if $total < 1 ;
549 if ($displayMode eq 'TeX') { 559
550 return ""; 560 (\%problem_result, \%problem_state);
551 }
552 my $out='';
553 my $j;
554
555 if(($displayMode eq 'HTML_dpng') || ($displayMode eq 'Latex2HTML')) {
556# if($numrows>12) { $numrows = 12; }
557 if($displayMode eq 'Latex2HTML') { $out .= '\begin{rawhtml}'; }
558 $out .= "<tr><td nowrap=\"nowrap\" align=\"left\">";
559 if($displayMode eq 'Latex2HTML') { $out .= '\end{rawhtml}'; }
560# $out .= "<img alt=\"(\" src = \"".
561# $main::imagesURL."/left$numrows.png\" >";
562# return $out;
563 $out .= '\(\left.\begin{array}{c}';
564 for($j=0;$j<$numrows;$j++) { $out .= ' \\\\'; }
565 $out .= '\end{array}\right(\)';
566
567 if($displayMode eq 'Latex2HTML') { $out .= '\begin{rawhtml}'; }
568 $out .= "<td><table border=0 cellspacing=5>\n";
569 if($displayMode eq 'Latex2HTML') { $out .= '\end{rawhtml}'; }
570 return $out;
571 }
572 $out = "<tr><td nowrap=\"nowrap\" align=\"left\"><font face=\"symbol\"><br />";
573 for($j=0;$j<$numrows;$j++) {
574 $out .= "<br />";
575 }
576 $out .= "</font></td>\n";
577 $out .= "<td><table border=0 cellspacing=5>\n";
578 return $out;
579} 561}
580 562
581 5631;
582=head3 matright
583
584
585
586=cut
587
588
589sub matright {
590 my $numrows = shift;
591 my $out='';
592 my $j;
593
594 if ($displayMode eq 'TeX') {
595 return "";
596 }
597
598 if(($displayMode eq 'HTML_dpng') || ($displayMode eq 'Latex2HTML')) {
599 if($displayMode eq 'Latex2HTML') { $out .= '\begin{rawhtml}'; }
600 $out .= "</table><td nowrap=\"nowrap\" align=\"right\">";
601 if($displayMode eq 'Latex2HTML') { $out .= '\end{rawhtml}'; }
602
603# $out .= "<img alt=\"(\" src = \"".
604# "/webwork_system_html/images"."/right$numrows.png\" >";
605 $out .= '\(\left)\begin{array}{c}';
606 for($j=0;$j<$numrows;$j++) { $out .= ' \\\\'; }
607 $out .= '\end{array}\right.\)';
608 return $out;
609 }
610
611 $out .= "</table>";
612 $out .= "<td nowrap=\"nowrap\" align=\"left\"><font face=\"symbol\"><br />";
613 for($j=0;$j<$numrows;$j++) {
614 $out .= "<br />";
615 }
616 $out .= "</font></td>\n";
617 return $out;
618}
619
620=head3 endmatrix
621
622
623
624=cut
625
626
627sub endmatrix {
628 my $out = "";
629 if ($displayMode eq 'TeX') {
630 $out .= "\n\\end{array}\\right)\\)\n";
631 }
632 elsif ($displayMode eq 'Latex2HTML') {
633 $out .= "\n\\begin{rawhtml} </TABLE >\n\\end{rawhtml}";
634 }
635 elsif ($displayMode eq 'HTML' || $displayMode eq 'HTML_tth' || $displayMode eq 'HTML_dpng') {
636 $out .= "</TABLE>\n";
637 }
638 else {
639 $out = "Error: PGchoicemacros: endtable: Unknown displayMode: $displayMode.\n";
640 }
641 $out;
642}
643
644
645=head3 matrow
646
647
648
649=cut
650
651
652
653sub matrow {
654 my $elements = shift;
655 my @align = @_;
656 my @elements = @{$elements};
657 my $out = "";
658 if ($displayMode eq 'TeX') {
659 while (@elements) {
660 $out .= shift(@elements) . " &";
661 }
662 chop($out); # remove last &
663 $out .= "\\\\ \n";
664 # carriage returns must be added manually for tex
665 }
666 elsif ($displayMode eq 'Latex2HTML') {
667 $out .= "\n\\begin{rawhtml}\n<TR>\n\\end{rawhtml}\n";
668 while (@elements) {
669 $out .= " \n\\begin{rawhtml}\n<TD> \n\\end{rawhtml}\n" . shift(@elements) . " \n\\begin{rawhtml}\n</TD> \n\\end{rawhtml}\n";
670 }
671 $out .= " \n\\begin{rawhtml}\n</TR> \n\\end{rawhtml}\n";
672 }
673 elsif ($main::displayMode eq 'HTML' || $main::displayMode eq 'HTML_tth' || $displayMode eq 'HTML_dpng') {
674 $out .= "<TR><td nowrap=\"nowrap\">\n";
675 while (@elements) {
676 my $myalign;
677 #do {$myalign = shift @align;} until($myalign ne "|");
678 $myalign = shift @align;
679 if($myalign eq "|") {
680 $out .= '<td> | </td>';
681 } else {
682 if($myalign eq "c") { $myalign = "center";}
683 if($myalign eq "l") { $myalign = "left";}
684 if($myalign eq "r") { $myalign = "right";}
685 $out .= "<TD nowrap=\"nowrap\" align=\"$myalign\">" . shift(@elements) . "</TD>";
686 }
687 }
688 $out .= "<td>\n</TR>\n";
689 }
690 else {
691 $out = "Error: matrow: Unknown displayMode: $main::displayMode.\n";
692 }
693 $out;
694}
695
696 564
697## Local Variables: 565## Local Variables:
698## mode: CPerl 566## mode: CPerl
699## font-lock-mode: t 567## font-lock-mode: t
700## End: 568## End:

Legend:
Removed from v.1941  
changed lines
  Added in v.1943

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9