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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6016 - (download) (as text) (annotate)
Sun Mar 1 22:56:23 2009 UTC (10 years, 9 months ago) by dpvc
File size: 7910 byte(s)
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/&/\&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 #
  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