[LON-CAPA-cvs] cvs: doc /loncapafiles loncapafiles.lpml loncom/homework edit.pm inputtags.pm optionresponse.pm structuretags.pm loncom/html/adm/help/tex Wrong_Num_Boxes_Checked.tex

raeburn raeburn at source.lon-capa.org
Fri Nov 28 13:23:14 EST 2014


raeburn		Fri Nov 28 18:23:14 2014 EDT

  Added files:                 
    /loncom/html/adm/help/tex	Wrong_Num_Boxes_Checked.tex 

  Modified files:              
    /loncom/homework	edit.pm inputtags.pm optionresponse.pm 
                    	structuretags.pm 
    /doc/loncapafiles	loncapafiles.lpml 
  Log:
  - Optionresponse in "checkbox" mode:
    - Additional (optional) attributes: maxcheck and mincheck available to enforce
      requirement on number of checkboxes which may be checked.
    - Intended use case is polling with optionresponse used in survey mode, 
      and maximum number of selections voter may make is to be limited.
  
  
-------------- next part --------------
Index: loncom/homework/edit.pm
diff -u loncom/homework/edit.pm:1.151 loncom/homework/edit.pm:1.152
--- loncom/homework/edit.pm:1.151	Tue Dec  3 17:47:30 2013
+++ loncom/homework/edit.pm	Fri Nov 28 18:23:03 2014
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA 
 # edit mode helpers
 #
-# $Id: edit.pm,v 1.151 2013/12/03 17:47:30 bisitz Exp $
+# $Id: edit.pm,v 1.152 2014/11/28 18:23:03 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -796,6 +796,49 @@
     return ' onclick="is_submit=true;'.$extra_action.'" ';
 }
 
+sub js_update_linknum {
+    return (<<SCRIPT);
+<script type="text/javascript">
+// <![CDATA[
+function updateNumber(name,index,caller,textprompt) {
+    var pickitem = document.getElementById(name+'_'+index);
+    var picknumtext = document.getElementById(name+'_numtext_'+index);
+    if (pickitem.checked) {
+        var showval = '';
+        if (pickitem.value != 'nochoice') {
+            showval = pickitem.value;
+        } 
+        var picknum=prompt(textprompt,showval);
+        if (picknum == '' || picknum == null) {
+            if (caller == 'check') {
+                pickitem.checked=false;
+                pickitem.value='nochoice';
+            }
+        } else {
+            picknum.toString();
+            var regexdigit=/^\\d+\$/;
+            if (regexdigit.test(picknum)) {
+                pickitem.value = picknum;
+                picknumtext.innerHTML = ' <a href="javascript:updateNumber(\\''+name+'\\',\\''+index+'\\',\\'link\\',\\''+textprompt+'\\');">'+picknum+'</a>';
+            } else {
+                if (caller == 'check') {
+                    pickitem.checked=false;
+                    pickitem.value='nochoice';
+                }
+                return;
+            }
+        }
+    } else {
+        pickitem.value = '';
+        picknumtext.innerHTML = '';
+    }
+}
+
+// ]]>
+</script>
+SCRIPT
+
+}
 
 sub textarea_sizes {
     my ($data)=@_;
@@ -941,7 +984,7 @@
 }
 
 sub checked_arg {
-    my ($description,$name,$list,$token) = @_;
+    my ($description,$name,$list,$token,$onclick,$useid) = @_;
     my $result;
     my $optionlist="";
     my $allselected=$token->[2]{$name};
@@ -964,7 +1007,10 @@
 		last;
 	    }
 	}
-	$result.=&element_change_detection().' />'.$text.'</label></span>'."\n";
+        if ($useid) {
+            $result .= ' id="'.&html_element_name($name).'" ';
+        }
+	$result.=&element_change_detection().$onclick.' />'.$text.'</label></span>'."\n";
     }
     return $result;
 }
Index: loncom/homework/inputtags.pm
diff -u loncom/homework/inputtags.pm:1.327 loncom/homework/inputtags.pm:1.328
--- loncom/homework/inputtags.pm:1.327	Fri Nov  7 22:00:17 2014
+++ loncom/homework/inputtags.pm	Fri Nov 28 18:23:04 2014
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # input  definitons
 #
-# $Id: inputtags.pm,v 1.327 2014/11/07 22:00:17 raeburn Exp $
+# $Id: inputtags.pm,v 1.328 2014/11/28 18:23:04 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -878,7 +878,7 @@
 sub valid_award {
     my ($award) =@_;
     foreach my $possibleaward ('EXTRA_ANSWER','MISSING_ANSWER', 'ERROR',
-			       'NO_RESPONSE',
+			       'NO_RESPONSE','WRONG_NUMBOXESCHECKED',
 			       'TOO_LONG', 'UNIT_INVALID_INSTRUCTOR',
 			       'UNIT_INVALID_STUDENT', 'UNIT_IRRECONCIBLE',
 			       'UNIT_FAIL', 'NO_UNIT',
@@ -898,7 +898,7 @@
 
 {
     my @awards = ('EXTRA_ANSWER', 'MISSING_ANSWER', 'ERROR', 'NO_RESPONSE',
-		  'TOO_LONG',
+		  'WRONG_NUMCHECKEDBOXES','TOO_LONG',
 		  'UNIT_INVALID_INSTRUCTOR', 'UNIT_INVALID_STUDENT',
 		  'UNIT_IRRECONCIBLE', 'UNIT_FAIL', 'NO_UNIT',
 		  'UNIT_NOTNEEDED', 'WANTED_NUMERIC', 'BAD_FORMULA',  'NOT_FUNCTION', 
@@ -1125,6 +1125,13 @@
         }
 	$css_class=$possible_class{'not_charged_try'};
 	$button = 1;
+    } elsif ($award eq 'WRONG_NUMBOXESCHECKED') {
+        $message = &mt('Number of boxes checked outside permissible range (either too few or too many).');
+        if ($target ne 'tex') {
+           $message .= &Apache::loncommon::help_open_topic('Wrong_Num_Boxes_Checked');
+        }
+        $css_class=$possible_class{'not_charged_try'};
+        $button = 1;
     } elsif ($award eq 'ERROR') {
 	$message = &mt('An error occurred while grading your answer.');
 	$css_class=$possible_class{'not_charged_try'};
Index: loncom/homework/optionresponse.pm
diff -u loncom/homework/optionresponse.pm:1.194 loncom/homework/optionresponse.pm:1.195
--- loncom/homework/optionresponse.pm:1.194	Thu Nov 27 17:37:09 2014
+++ loncom/homework/optionresponse.pm	Fri Nov 28 18:23:04 2014
@@ -1,7 +1,7 @@
 # LearningOnline Network with CAPA
 # option list style responses
 #
-# $Id: optionresponse.pm,v 1.194 2014/11/27 17:37:09 raeburn Exp $
+# $Id: optionresponse.pm,v 1.195 2014/11/28 18:23:04 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -124,6 +124,8 @@
         sel => 'Select Options',
         add => 'Add new Option:',
         del => 'Delete an Option:',
+        maxcheck => 'Enter maximum number students may check (e.g., 3)',
+        mincheck => 'Enter minimum number students need to check (e.g., 1)',
     );
     $result.= (<<ENDTABLE);
       <tr><td>$lt{'sel'}</td>
@@ -147,12 +149,37 @@
        $result.='>'.$option.'</option>';
     }
     $result.='</select></label> ';
+    my %checknumtxt = (
+                        maxcheck => 'Max. boxes permitted to check',
+                        mincheck => 'Min. boxes required to check',
+    );
+    my (%onclicknum,%checknum);
+    foreach my $item ('maxcheck','mincheck') {
+        $onclicknum{$item} = 'onclick="'."updateNumber('$item','$Apache::lonxml::curdepth','check','$lt{$item}');".'"';
+        $checknum{$item} = &Apache::lonxml::get_param($item,$parstack,$safeeval);
+    }
     $result.=&Apache::edit::checked_arg('Checkbox options:','checkboxoptions',
                                          [ ['nochoice',"Don't show option list"] ]
                                          ,$token).' '.
              &Apache::edit::checked_arg('','noprompt',
                                          [ ['nochoice','Omit "Select all that are ... "' ] ]
-                                         ,$token).'</td>';
+                                         ,$token);
+    foreach my $item ('maxcheck','mincheck') {
+        my $currnum = $checknum{$item};
+        unless ($currnum =~ /^\d+$/) {
+            $currnum = 'nochoice';
+        } 
+        $result.= ' <span class="LC_nobreak">'.
+                  &Apache::edit::checked_arg('',$item,[ [$currnum,$checknumtxt{$item}] ],
+                                        $token,$onclicknum{$item},1).' '.
+                  '<span id="'.$item.'_numtext_'.$Apache::lonxml::curdepth.'">';
+        if ($checknum{$item} ne '') {
+            $result .= ': <a href="javascript:updateNumber('."'$item','$Apache::lonxml::curdepth','link','$lt{$item}'".')">'.
+                       $checknum{$item}.'</a>';
+        }
+        $result .= '</span></span>';
+    } 
+    $result.= '</td>';
     $result.= &Apache::edit::end_row();
     $result.= &Apache::edit::start_spanning_row();
     $result.= $insertlist.'<br />';
@@ -177,7 +204,22 @@
     }
     my $rebuildtag = &Apache::edit::get_new_args($token,$parstack,$safeeval,
 						 'texoptions','checkboxvalue','checkboxoptions',
-                                                 'noprompt');
+                                                 'noprompt','maxcheck','mincheck');
+    if ($rebuildtag) {
+        my $maxcheck = $token->[2]->{'maxcheck'};
+        my $mincheck = $token->[2]->{'mincheck'};
+        if ($mincheck =~ /D/) {
+            $token->[2]->{'mincheck'}='';
+        }
+        if ($maxcheck =~ /D/) {
+            $token->[2]->{'maxcheck'}='';
+        }
+        if (($mincheck ne '') && ($maxcheck ne '')) {
+            if ($mincheck > $maxcheck) {
+                $token->[2]->{'mincheck'}=$maxcheck; 
+            }
+        }
+    }
     if ($optchanged || $rebuildtag ) {
       $result = "<foilgroup options=\"(";
       foreach my $option (@options) {
@@ -190,7 +232,9 @@
       $result .= 'texoptions="'.$token->[2]{'texoptions'}.'" ';
       $result .= 'checkboxoptions="'.$token->[2]{'checkboxoptions'}.'" ';
       $result .= 'checkboxvalue="'.$token->[2]{'checkboxvalue'}.'" ';
-      $result .= 'noprompt="'.$token->[2]{'noprompt'}.'"';
+      $result .= 'noprompt="'.$token->[2]{'noprompt'}.'" ';
+      $result .= 'maxcheck="'.$token->[2]{'maxcheck'}.'" ';
+      $result .= 'mincheck="'.$token->[2]{'mincheck'}.'"';
       $result .= '>';
     } # else nothing changed so just use the default mechanism
   }
@@ -220,6 +264,10 @@
 					     -2,0);
     my $checkboxvalue=&Apache::lonxml::get_param('checkboxvalue',$parstack,$safeeval);
     my $checkboxchoices=(&Apache::lonxml::get_param('checkboxoptions',$parstack,$safeeval) ne 'nochoice');
+    my $maxcheck=&Apache::lonxml::get_param('maxcheck', $parstack, $safeeval);
+    $maxcheck =~ s/\D+//g;
+    my $mincheck=&Apache::lonxml::get_param('mincheck', $parstack, $safeeval);
+    $mincheck =~ s/\D+//g;
     my $noprompt=&Apache::lonxml::get_param('noprompt', $parstack, $safeeval);
 
     if ($target eq 'tex' && $tex_option_switch eq 'nochoice') {@opt=();}
@@ -228,7 +276,7 @@
     my $randomize = &Apache::lonxml::get_param('randomize',$parstack,
 					       $safeeval,'-2');
     if ($target eq 'web' || $target eq 'tex') {
-      $result.=&displayfoils($target,$max,$randomize,$TeXlayout,$checkboxvalue,$checkboxchoices,$tex_option_switch, $noprompt, @opt);
+      $result.=&displayfoils($target,$max,$randomize,$TeXlayout,$checkboxvalue,$checkboxchoices,$tex_option_switch, $noprompt,$maxcheck,$mincheck, @opt);
       $Apache::lonxml::post_evaluate=0;
     } elsif ( $target eq 'answer') {
       $result.=&displayanswers($max,$randomize, at opt);
@@ -250,6 +298,7 @@
 	my $right=0;
 	my $wrong=0;
 	my $ignored=0;
+        my $checked=0;
         my ($numrows,$bubbles_per_row);
         if ($Apache::lonhomework::scantronmode) {
             my $numitems = scalar(@opt);
@@ -259,6 +308,26 @@
         if ($numrows < 1) {
             $numrows = 1;
         }
+        my $checkboxopt;
+        if ($checkboxvalue) {
+            $checkboxopt = &check_box_opt($target,$checkboxvalue, at opt);
+            if (($checkboxopt) && ($Apache::lonhomework::type !~ /survey/)) {
+                my $corrnumcheck = 0;
+                if (($maxcheck ne '') || ($mincheck ne '')) {
+                    foreach $name (@whichopt) {
+                        if ($Apache::response::foilgroup{$name.'.value'} eq $checkboxopt) {
+                            $corrnumcheck ++; 
+                        }
+                    }
+                    if (($maxcheck ne '') && ($corrnumcheck > $maxcheck)) {
+                        $maxcheck = $corrnumcheck;
+                    }
+                    if (($mincheck ne '') && ($corrnumcheck < $mincheck)) {
+                        $mincheck = $corrnumcheck;
+                    }
+                }
+            }
+        }
 	foreach $name (@whichopt) {
 	  my $response;
           if ($env{'form.submitted'} eq 'scantron') {
@@ -296,6 +365,11 @@
 	    } else {
 		$grade{$name}='0'; $wrong++;
 	    }
+            if ($checkboxopt) {
+                if ($response eq $checkboxopt) {
+                    $checked++;
+                }
+            } 
 	  } else {
 	    $ignored++;
 	  }
@@ -314,65 +388,76 @@
         if ($Apache::lonhomework::type eq 'randomizetry') {
             $Apache::lonhomework::results{"resource.$part.$id.foilorder"} = &Apache::lonnet::array2str(@whichopt);
         }
-	if (($Apache::lonhomework::type eq 'survey') ||
-            ($Apache::lonhomework::type eq 'surveycred') ||
-            ($Apache::lonhomework::type eq 'anonsurvey') ||
-            ($Apache::lonhomework::type eq 'anonsurveycred')) {
-	    if ($ignored == 0) {
-                my $ad;
-                if ($Apache::lonhomework::type eq 'anonsurveycred') {
-                    $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='ANONYMOUS_CREDIT';
-                } elsif ($Apache::lonhomework::type eq 'anonsurvey') {
-                    $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='ANONYMOUS';
-                } elsif ($Apache::lonhomework::type eq 'surveycred') {
-                    $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='SUBMITTED_CREDIT';
-                } else {
-		    $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='SUBMITTED';
-                }
-		&Apache::response::handle_previous(\%previous,$ad);
-	    } elsif ($wrong==0 && $right==0) {
-	    } else {
-		my $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='MISSING_ANSWER';
-		&Apache::response::handle_previous(\%previous,$ad);
-	    }
-	} elsif ($nonlenient) {
+        my $skipaward;
+        if ($checkboxvalue) {
+            if ((($maxcheck ne '') && ($checked > $maxcheck)) ||
+                (($mincheck ne '') && ($checked < $mincheck))) {
+                my $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='WRONG_NUMBOXESCHECKED';
+                &Apache::response::handle_previous(\%previous,$ad);
+                $skipaward = 1;
+            }
+        }
+        unless ($skipaward) {
+	    if (($Apache::lonhomework::type eq 'survey') ||
+                ($Apache::lonhomework::type eq 'surveycred') ||
+                ($Apache::lonhomework::type eq 'anonsurvey') ||
+                ($Apache::lonhomework::type eq 'anonsurveycred')) {
+	        if ($ignored == 0) {
+                    my $ad;
+                    if ($Apache::lonhomework::type eq 'anonsurveycred') {
+                        $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='ANONYMOUS_CREDIT';
+                    } elsif ($Apache::lonhomework::type eq 'anonsurvey') {
+                        $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='ANONYMOUS';
+                    } elsif ($Apache::lonhomework::type eq 'surveycred') {
+                        $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='SUBMITTED_CREDIT';
+                    } else {
+		        $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='SUBMITTED';
+                    }
+		    &Apache::response::handle_previous(\%previous,$ad);
+	        } elsif ($wrong==0 && $right==0) {
+	        } else {
+		    my $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='MISSING_ANSWER';
+		    &Apache::response::handle_previous(\%previous,$ad);
+	        }
+	    } elsif ($nonlenient) {
 #
 # Non-lenient mode. All right or all wrong
 #
-	    my $ad;
-	    if ($wrong==0 && $ignored==0) {
-		$ad='EXACT_ANS';
-	    } elsif ($wrong==0 && $right==0) {
-		#nothing submitted
-	    } else {
-		if ($ignored==0) {
-		    $ad='INCORRECT';
-		} else {
-		    $ad='MISSING_ANSWER';
-		}
-	    }
-	    $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=$ad;
-	    &Apache::response::handle_previous(\%previous,$ad);
-	} else {
+	        my $ad;
+	        if ($wrong==0 && $ignored==0) {
+		    $ad='EXACT_ANS';
+	        } elsif ($wrong==0 && $right==0) {
+		    #nothing submitted
+	        } else {
+		    if ($ignored==0) {
+		        $ad='INCORRECT';
+		    } else {
+		        $ad='MISSING_ANSWER';
+		    }
+	        }
+	        $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=$ad;
+	        &Apache::response::handle_previous(\%previous,$ad);
+	     } else {
 #
 # This is lenient mode
 #
-	    my $ad;
-	    if ($wrong==0 && $right==0) {
-		#nothing submitted only assign a score if we 
-		#need to override a previous grade
-		if (defined($Apache::lonhomework::history{"resource.$part.$id.awarddetail"})) {
+	        my $ad;
+	        if ($wrong==0 && $right==0) {
+		    #nothing submitted only assign a score if we 
+		    #need to override a previous grade
+		    if (defined($Apache::lonhomework::history{"resource.$part.$id.awarddetail"})) {
+		        $ad='ASSIGNED_SCORE';
+		    }
+	        } else {
 		    $ad='ASSIGNED_SCORE';
-		}
-	    } else {
-		$ad='ASSIGNED_SCORE';
-	    }
-	    $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=$ad;
-	    $Apache::lonhomework::results{"resource.$part.$id.awarded"}=
-		$right/(scalar(@whichopt));
-	    $Apache::lonhomework::results{"resource.$part.$id.numfoils"}=
-		scalar(@whichopt);
-	}
+	        }
+	        $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=$ad;
+	        $Apache::lonhomework::results{"resource.$part.$id.awarded"}=
+		    $right/(scalar(@whichopt));
+	        $Apache::lonhomework::results{"resource.$part.$id.numfoils"}=
+		    scalar(@whichopt);
+	     }
+       }
       }
     }
     my $part_id     = $Apache::inputtags::part;
@@ -481,7 +566,7 @@
 # Check if we are in checkbox mode: checkboxvalue specified, on web, only two options.
 # If so, return "checked" value
     if ($#opt!=1) { return ''; }
-    if ($target ne 'web') { return ''; }
+    unless (($target eq 'web') || ($target eq 'grade')) { return ''; }
     return $checkboxvalue;
 }
 
@@ -508,7 +593,7 @@
 
 sub displayfoils {
   my ($target,$max,$randomize,$TeXlayout,$checkboxvalue,$checkboxchoices,
-      $tex_option_switch, $no_tfprompt, @opt)=@_;
+      $tex_option_switch, $no_tfprompt, $maxcheck, $mincheck, @opt)=@_;
   my @names; 
   if (ref($Apache::response::foilgroup{'names'}) eq 'ARRAY') {
       @names = @{ $Apache::response::foilgroup{'names'} };
@@ -594,7 +679,10 @@
         }
     }
     my $internal_counter=$Apache::lonxml::counter;
-    my $checkboxopt=&check_box_opt($target,$checkboxvalue, at opt);
+    my $checkboxopt;
+    if ($target eq 'web') {
+        $checkboxopt=&check_box_opt($target,$checkboxvalue, at opt);
+    }
     if ($checkboxopt && (!$no_tfprompt)) {
        $result.='<br />'.
                 ($checkboxchoices?&mt('Choices: ').'<b>'.$opt[0].','.$opt[1].'</b>. ':'').
Index: loncom/homework/structuretags.pm
diff -u loncom/homework/structuretags.pm:1.524 loncom/homework/structuretags.pm:1.525
--- loncom/homework/structuretags.pm:1.524	Mon Nov 24 02:36:26 2014
+++ loncom/homework/structuretags.pm	Fri Nov 28 18:23:04 2014
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA 
 # definition of tags that give a structure to a document
 #
-# $Id: structuretags.pm,v 1.524 2014/11/24 02:36:26 raeburn Exp $
+# $Id: structuretags.pm,v 1.525 2014/11/28 18:23:04 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -419,6 +419,9 @@
 		"if (typeof swmenu != 'undefined') {swmenu.currentURL=null;}\n".
 		&Apache::loncommon::browser_and_searcher_javascript().
                 "\n</script>\n";
+            if ($target eq 'edit') {
+                $extra_head .= &Apache::edit::js_update_linknum();
+            }
 	}
     }
 
Index: doc/loncapafiles/loncapafiles.lpml
diff -u doc/loncapafiles/loncapafiles.lpml:1.900 doc/loncapafiles/loncapafiles.lpml:1.901
--- doc/loncapafiles/loncapafiles.lpml:1.900	Mon Oct 13 14:50:29 2014
+++ doc/loncapafiles/loncapafiles.lpml	Fri Nov 28 18:23:14 2014
@@ -2,7 +2,7 @@
  "http://lpml.sourceforge.net/DTD/lpml.dtd">
 <!-- loncapafiles.lpml -->
 
-<!-- $Id: loncapafiles.lpml,v 1.900 2014/10/13 14:50:29 goltermann Exp $ -->
+<!-- $Id: loncapafiles.lpml,v 1.901 2014/11/28 18:23:14 raeburn Exp $ -->
 
 <!--
 
@@ -3704,6 +3704,7 @@
 What_Is_LON-CAPA.tex;
 Why_LON-CAPA.tex;
 Wishlist.tex;
+Wrong_Num_Boxes_Checked.tex;
 </filenames>
 </fileglob>
 <fileglob>

Index: loncom/html/adm/help/tex/Wrong_Num_Boxes_Checked.tex
+++ loncom/html/adm/help/tex/Wrong_Num_Boxes_Checked.tex
\label{Wrong_Num_Boxes_Checked}
In a case where you were asked to select all that apply, the number of boxes you checked was outside the range which the creator of the question expected.

You should review the question again, to see if the instructions include any information about the number of boxes you may check, and then, depending on what you find, submit your answer again, this time checking a different number of boxes. Note: this could either be fewer than you checked on your previous submission, or could be more. 


More information about the LON-CAPA-cvs mailing list