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

Annotation of /trunk/pg/macros/problemPanic.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6226 - (view) (download) (as text)

1 : dpvc 6015 ################################################################################
2 :     # WeBWorK Online Homework Delivery System
3 :     # Copyright 2009 The WeBWorK Project, http://openwebwork.sf.net/
4 : dpvc 6226 # $CVSHeader: pg/macros/problemPanic.pl,v 1.6 2010/04/27 02:00:37 dpvc Exp $
5 : dpvc 6015 #
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 : dpvc 6017 variable $panicked, which you can use to determine whether to include the
39 : dpvc 6015 hints or not. For example
40 :    
41 : dpvc 6017 if ($panicked) {
42 : dpvc 6015 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 : dpvc 6017 if ($panicked) {
54 : dpvc 6015 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 : dpvc 6017 if ($panicked > 1) {
63 : dpvc 6015 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 : dpvc 6016 To allow the grading penalties to work, you must include the command
104 :    
105 : dpvc 6225 Panic::GradeWithPenalty();
106 : dpvc 6016
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 : dpvc 6015 =cut
113 :    
114 :     sub _problemPanic_init {Panic::Init()}
115 :    
116 :     #
117 :     # The packge to contain the routines and data for the Panic buttons
118 :     #
119 :     package Panic;
120 :    
121 :     my $isTeX = 0; # true in hardcopy mode
122 :     my $allowReset = 0; # true if a professor is viewing the problem
123 :     my $buttonCount = 0; # number of panic buttons displayed so far
124 :     my @penalty = (0); # accummulated penalty values
125 :     my $grader; # problem's original grader
126 :    
127 :     #
128 :     # Allow resets if permission level is high enough.
129 :     # Look up the panic level and reset it if needed.
130 :     # Save the panic level for the next time through.
131 :     #
132 :     sub Init {
133 : dpvc 6018 $main::permissionLevel = 0 unless defined $main::permissionLevel;
134 : dpvc 6015 $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 : dpvc 6226 $penalty[$buttonCount] = $penalty[$buttonCount-1] + $options{penalty};
160 : dpvc 6015 $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/&/\&amp;/g; $string =~ s/"/\&quot;/g;
182 :     $string =~ s/>/\&gt;/g; $string =~ s/</\&lt;/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 : dpvc 6225 #
197 : dpvc 6015 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