Parent Directory
|
Revision Log
Added grader information
1 ################################################################################ 2 # WeBWorK Online Homework Delivery System 3 # Copyright © 2009 The WeBWorK Project, http://openwebwork.sf.net/ 4 # $CVSHeader: pg/macros/problemPanic.pl,v 1.1 2009/03/01 15:15:35 dpvc Exp $ 5 # 6 # This program is free software; you can redistribute it and/or modify it under 7 # the terms of either: (a) the GNU General Public License as published by the 8 # Free Software Foundation; either version 2, or (at your option) any later 9 # version, or (b) the "Artistic License" which comes with this package. 10 # 11 # This program is distributed in the hope that it will be useful, but WITHOUT 12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 # FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the 14 # Artistic License for more details. 15 ################################################################################ 16 17 =head1 NAME 18 19 problemPanic.pl - Allow for a PANIC button that gives additional 20 hints, possibly costing some points. 21 22 =head1 DESCRIPTION 23 24 This file implements a mechanism for you to provide one or more "panic 25 button" that your students can use to get additional hints, at the 26 cost of a portion of their score. 27 28 To include the button, use the command Panic::Button command within a 29 BEGIN_TEXT/END_TEXT block. E.g., 30 31 BEGIN_TEXT 32 \{Panic::Button(label => "Request a Hint", penalty => .25)\} 33 (you will lose 25% of your points if you do) 34 END_TEXT 35 36 When the student presses the hint button, the button will not longer 37 be available, and the "panic level" will be increased. This sets the 38 variable $panic, which you can use to determine whether to include the 39 hints or not. For example 40 41 if ($panic) { 42 BEGIN_TEXT 43 Hint: You should factor the numerator and cancel 44 one of the factors with the denominator. 45 END_TEXT 46 } 47 48 Note that you can create a "cascade" of hints by including a second 49 panic button in the hint received from the first button. This will 50 set $panic to 2 (panic level 2) and you can use that to include the 51 second hint. 52 53 if ($panic) { 54 BEGIN_TEXT 55 Hint: You should factor the numerator and cancel 56 one of the factors with the denominator. 57 $PAR 58 \{Panic::Button(label => "Another Hint", penalty => .25)\} 59 (costing an additional 25%) 60 END_TEXT 61 62 if ($panic > 1) { 63 BEGIN_TEXT 64 Additional Hint: one of the factors is \(x+$a)\). 65 END_TEXT 66 } 67 } 68 69 You can add more buttons in a similar way. You can not have separate 70 buttons for separate hints that are NOT cascaded, however. (That may 71 be possible in future versions.) 72 73 The Panic::Button command takes two optional parameters: 74 75 =over 76 77 =item S<C<< label => "text" >>> 78 79 Sets the text to use for the button. The default is "Request a Hint". 80 81 =item S<C<< penalty => percent >>> 82 83 Specifies the number points to lose (as a number from 0 to 1) if this 84 hint is displayed. When more than one panic button is used, the 85 penalties are cumulative. That is, two penalties of .25 would produce 86 a total penalty of .5, so the student would lose half his points if 87 both hints were given. 88 89 =back 90 91 Once a hint is displayed, the panic button for that hint will no 92 longer be shown, and the hint will continue to be displayed as the 93 student submits new answers. 94 95 A professor will be given a "Reset problem hints" checkbox at the 96 bottom of the problem, and can use that to request that the panic 97 level be reset back to 0. This also sets the score and the number of 98 attempts back to 0 as well, so this effectively resets the problem to 99 its original state. This is intended for use primarily during problem 100 development, but can be used to allow a student to get full credit for 101 a problem even after he or she has asked for a hint. 102 103 To allow the grading penalties to work, you must include the command 104 105 Panic::GradeWithPenalty; 106 107 in order to install the panic-button grader. You should do this afer 108 setting the grader that you want to use for the problem itself, as the 109 panic grader will use the one that is installed at the time the 110 Panic::GradWithPenalty command is issued. 111 112 =cut 113 114 sub _problemPanic_init {Panic::Init()} 115 116 117 # 118 # The packge to contain the routines and data for the Panic buttons 119 # 120 package Panic; 121 122 my $isTeX = 0; # true in hardcopy mode 123 my $allowReset = 0; # true if a professor is viewing the problem 124 my $buttonCount = 0; # number of panic buttons displayed so far 125 my @penalty = (0); # accummulated penalty values 126 my $grader; # problem's original grader 127 128 # 129 # Allow resets if permission level is high enough. 130 # Look up the panic level and reset it if needed. 131 # Save the panic level for the next time through. 132 # 133 sub Init { 134 $allowReset = $main::permissionLevel > $main::PRINT_FILE_NAMES_PERMISSION_LEVEL; 135 $isTeX = ($main::displayMode eq 'TeX'); 136 unless ($isTeX) { 137 $main::panicked = $main::inputs_ref->{_panicked} || 0; 138 $main::panicked = 0 if $main::inputs_ref->{_panic_reset} && $allowReset; 139 main::TEXT(qq!<input type="hidden" name="_panicked" id="_panicked" value="$main::panicked" />!); 140 main::RECORD_FORM_LABEL("_panicked"); 141 } 142 } 143 144 # 145 # Place a panic button on the page, if it's not hardcopy mode and its not at the wrong level. 146 # You can set the label, the penalty for taking this hint, and the panic level for this button. 147 # Use submitAnswers if it is before the due date, and checkAnswers otherwise. 148 # 149 sub Button { 150 $buttonCount++; 151 my %options = ( 152 label => "Request a Hint", 153 level => $buttonCount, 154 penalty => 0, 155 @_ 156 ); 157 my $label = $options{label}; 158 my $level = $options{level}; 159 $penalty[$buttonCount] = $penalty[$buttonCount] + $options{penalty}; 160 $penalty[$buttonCount] = 1 if $penalty[$buttonCount] > 1; 161 return if $isTeX || $main::panicked >= $level; 162 my $time = time(); 163 my $name = ($main::openDate <= $time && $time <= $main::dueDate ? "submitAnswers" : "checkAnswers"); 164 $value = quoteHTML($value); 165 return qq!<input type="submit" name="$name" value="$label" onclick="document.getElementById('_panicked').value++">!; 166 } 167 168 # 169 # The reset button 170 # 171 sub ResetButton { 172 main::RECORD_FORM_LABEL("_panic_reset"); 173 return qq!<input type="checkbox" name="_panic_reset"> Reset problem hints!; 174 } 175 176 # 177 # Handle HTML in the value 178 # 179 sub quoteHTML { 180 my $string = shift; 181 $string =~ s/&/\&/g; $string =~ s/"/\"/g; 182 $string =~ s/>/\>/g; $string =~ s/</\</g; 183 return $string; 184 } 185 186 # 187 # Install the panic grader, saving the original one 188 # 189 sub GradeWithPenalty { 190 $grader = $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} || \&main::avg_problem_grader; 191 main::install_problem_grader(\&Panic::grader); 192 } 193 194 # 195 # The grader for the panic levels. 196 # 197 sub grader { 198 # 199 # Save the old score and call the original grader. 200 # Compute the penalized score, and save it, if it is better than the old score. 201 # Reset the values if we are resetting scores. 202 # 203 my $oldScore = $_[1]->{recorded_score} || 0; 204 my ($result,$state) = &{$grader}(@_); 205 $result->{score} *= 1-$penalty[$main::panicked]; 206 $state->{recorded_score} = ($result->{score} > $oldScore ? $result->{score} : $oldScore); 207 $state->{recorded_score} = $state->{num_of_incorrect_ans} = $state->{num_of_correct_ans} = 0 208 if $main::inputs_ref->{_panic_reset} && $allowReset; 209 210 # 211 # Add the problemPanic message and data 212 # 213 $result->{type} = "problemPanic ($result->{type})"; 214 if ($main::panicked) { 215 $result->{msg} .= '</i><p><b>Note:</b> <i>' if $result->{msg}; 216 $result->{msg} .= 'Your score was reduced by '.(int($penalty[$main::panicked]*100)).'%' 217 . ' because you accepted '.($main::panicked == 1 ? 'a hint.' : $main::panicked.' hints.'); 218 # 219 # Add the reset checkbox, if needed 220 # 221 $result->{msg} .= '<p>'.ResetButton() if $allowReset; 222 } 223 224 return ($result,$state); 225 }
aubreyja at gmail dot com | ViewVC Help |
Powered by ViewVC 1.0.9 |