--- loncom/homework/optionresponse.pm	2015/04/09 09:48:02	1.197
+++ loncom/homework/optionresponse.pm	2025/02/21 20:55:17	1.204
@@ -1,7 +1,7 @@
 # LearningOnline Network with CAPA
 # option list style responses
 #
-# $Id: optionresponse.pm,v 1.197 2015/04/09 09:48:02 droeschl Exp $
+# $Id: optionresponse.pm,v 1.204 2025/02/21 20:55:17 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -106,7 +106,7 @@ sub start_foilgroup {
   $Apache::optionresponse::conceptgroup=0;
   &Apache::response::pushrandomnumber(undef,$target);
   if ($target eq 'edit') {
-    my $optionlist="<option></option>\n";
+    my $optionlist="<option value=\"\"></option>\n";
     my $option;
     my @opt;
     my @raw_options = &Apache::lonxml::get_param('options', $parstack, $safeeval, 0,  0, 1);
@@ -300,6 +300,10 @@ sub end_foilgroup {
 	my $wrong=0;
 	my $ignored=0;
         my $checked=0;
+        my $corrchkd=0;
+        my $corrunchkd=0;
+        my $incorrchkd=0;
+        my $incorrunchkd=0;
         my ($numrows,$bubbles_per_row);
         if ($Apache::lonhomework::scantronmode) {
             my $numitems = scalar(@opt);
@@ -329,6 +333,10 @@ sub end_foilgroup {
                 }
             }
         }
+        my $part=$Apache::inputtags::part;
+        my $id = $Apache::inputtags::response['-1'];
+        my @relweights;
+        my $nonlenient=&grading_is_nonlenient($part,$id,\@relweights);
 	foreach $name (@whichopt) {
 	  my $response;
           if ($env{'form.submitted'} eq 'scantron') {
@@ -369,15 +377,23 @@ sub end_foilgroup {
             if ($checkboxopt) {
                 if ($response eq $checkboxopt) {
                     $checked++;
+                    if ($grade{$name}) {
+                        $corrchkd ++;
+                    } else {
+                        $incorrchkd ++;
+                    }
+                } else {
+                    if ($grade{$name}) {
+                        $corrunchkd ++;
+                    } else {
+                        $incorrunchkd ++;
+                    }
                 }
-            } 
+            }
 	  } else {
 	    $ignored++;
 	  }
 	}
-	my $part=$Apache::inputtags::part;
-        my $nonlenient=&grading_is_nonlenient($part);
-	my $id = $Apache::inputtags::response['-1'];
 	my $responsestr=&Apache::lonnet::hash2str(%responsehash);
 	my $gradestr   =&Apache::lonnet::hash2str(%grade);
 	my %previous=&Apache::response::check_for_previous($responsestr,
@@ -453,8 +469,22 @@ sub end_foilgroup {
 		    $ad='ASSIGNED_SCORE';
 	        }
 	        $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=$ad;
+                my $awarded;
+                my $totalfoils = $#{ $Apache::response::foilgroup{'names'} }+1;
+                if (($checkboxopt) && ($max >= $totalfoils) && (@relweights > 0)) {
+                    if ($right == scalar(@whichopt)) {
+                        $awarded = 1;
+                    } else {
+                        $awarded = ($corrchkd*$relweights[0] + $corrunchkd*$relweights[1] +
+                                    $incorrchkd*$relweights[2] + $incorrunchkd*$relweights[3])/(scalar(@whichopt));
+                        $awarded = 1 if ($awarded > 1);
+                        $awarded = 0 if ($awarded < 0);
+                    }
+                } else {
+                    $awarded = $right/(scalar(@whichopt));
+                }
 	        $Apache::lonhomework::results{"resource.$part.$id.awarded"}=
-		    $right/(scalar(@whichopt));
+		    $awarded;
 	        $Apache::lonhomework::results{"resource.$part.$id.numfoils"}=
 		    scalar(@whichopt);
 	     }
@@ -492,22 +522,38 @@ sub end_foilgroup {
 }
 
 sub grading_is_nonlenient {
-    my ($part) = @_;
+    my ($part,$id,$relweights) = @_;
 # Web mode: we are non-lenient unless told otherwise
     my $defaultparm = 'off';
-    my $nonlenient = 0;
+    my $nonlenient = 1;
 # Grading a bubblesheet exam: we are grading lenient unless told otherwise
     if ($Apache::lonhomework::scantronmode) {
         $defaultparm = 'on';
-        $nonlenient = 1;
+        $nonlenient = 0;
     }
     my $lenientparm =
         &Apache::response::get_response_param($part,'lenient',$defaultparm);
-    if ($lenientparm=~/^0|off|no$/i) {
+    if ($lenientparm eq 'default') {
+        $lenientparm = $defaultparm;
+    }
+    $lenientparm =
+        &Apache::response::get_response_param($part.'_'.$id,'lenient',$lenientparm);
+    if ($lenientparm eq 'default') {
+        $lenientparm = $defaultparm;
+    }
+    if ($lenientparm=~/^(?:0|off|no)$/i) {
         $nonlenient = 1;
-    } elsif ($lenientparm=~/^1|on|yes$/i) {
+    } elsif ($lenientparm=~/^(?:1|on|yes)$/i) {
+        $nonlenient = 0;
+    } elsif ($lenientparm =~ /^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$/) {
+        if (ref($relweights) eq 'ARRAY') {
+            @{$relweights} = split(/,/,$lenientparm);
+        }
         $nonlenient = 0;
     }
+    if (!$nonlenient) {
+        $Apache::inputtags::leniency=1;
+    }
     return $nonlenient;
 }
 
@@ -690,16 +736,17 @@ sub displayfoils {
                  &mt('Select all that are [_1].','<b>'.$checkboxopt.'</b>');
     }
     foreach $name (@whichopt) {
+      if ($target eq 'web') {
+          $result.= '<div class="LC_optionfoil">';
+      }
       my $text=$Apache::response::foilgroup{$name.'.text'};
       if ($text!~/^\s*$/) {
 	  if ($target eq 'tex') {
 	      $break='\vskip 0 mm ';
-	  } elsif ($target eq 'web') {
-	      $break='<br />';
 	  }
       }
       my $lastopt=$lastresponse{$name};
-      my $optionlist="<option></option>\n";
+      my $optionlist="<option value=\"\"></option>\n";
 
       if($target eq 'tex' and $env{'form.pdfFormFields'} eq 'yes'
          && $Apache::inputtags::status[-1] eq 'CAN_ANSWER') {
@@ -747,12 +794,12 @@ sub displayfoils {
 # lastopt is what the user submitted before
 # defopt is what the field is going to start out with: either previous choice or altopt
 # fieldname is this input field's name after HWVAL_
-                  $optionlist='<input type="hidden" name="HWVAL_'.$fieldname.'" value="'.$escdefopt.'" />'.
+                  $optionlist='<input type="hidden" name="HWVAL_'.$fieldname.'" value="'.$escdefopt.'" /><label>'.
                   '<input type="checkbox" name="HWCHK_'.$fieldname.'" onclick="javascript:if (this.form.elements[\'HWCHK_'.
-                  $fieldname.'\'].checked) { this.form.elements[\'HWVAL_'.$fieldname.'\'].value=\''.$esccheckboxopt.'\'; } else { this.form.elements[\'HWVAL_'.$fieldname.'\'].value=\''.$escaltopt.'\'; };setSubmittedPart(\''.$part.'\');"'.($defopt eq $checkboxopt?' checked="checked"':'')." />\n";
+                  $fieldname.'\'].checked) { this.form.elements[\'HWVAL_'.$fieldname.'\'].value=\''.$esccheckboxopt.'\'; } else { this.form.elements[\'HWVAL_'.$fieldname.'\'].value=\''.$escaltopt.'\'; };javascript:setSubmittedPart(\''.$part.'\');"'.($defopt eq $checkboxopt?' checked="checked"':'')." />\n";
               } else {
 # classic selection list
-	          $optionlist='<select onchange="javascript:setSubmittedPart(\''.
+	          $optionlist='<label><select onchange="javascript:setSubmittedPart(\''.
 		  $part.'\');" name="HWVAL_'.
 		  $Apache::inputtags::response['-1'].':'.$temp.'">'.
 		  $optionlist."</select>\n";
@@ -774,6 +821,8 @@ sub displayfoils {
 	  $result.=$break.$text."\n";
 	  if ($Apache::lonhomework::type eq 'exam') {
 	      $result.=&webbubbles(\@opt,\@alphabet,$temp,$lastopt);
+	  } else {
+	      $result.= '</label>';
 	  }
 	  $temp++;
       } else {
@@ -833,6 +882,9 @@ sub displayfoils {
           }
 	  $displayoptionintex=0;
       }
+      if ($target eq 'web') {
+          $result.= '</div>';
+      }
     }
   }
 
@@ -883,21 +935,23 @@ sub webbubbles {
     my @alphabet=@$ralphabet;
     my $result='';
     my $number_of_bubbles = $#opt + 1;
-    $result.= '<table border="1"><tr>';
+    $result.= '<fieldset class="LC_webbubbles">'.
+              '<legend class="LC_visually_hidden">'.&mt('Choose one').'</legend>'.
+              '<ul class="LC_webbubbles">';
     for (my $ind=0;$ind<$number_of_bubbles;$ind++) {
 	my $checked='';
 	if ($lastopt eq $opt[$ind]) {
 	    $checked=' checked="on" ';
 	}
-	$result.='<td><input type="radio" name="HWVAL_'.
+	$result.='<li><label><input type="radio" name="HWVAL_'.
 	    $Apache::inputtags::response['-1'].':'.$temp.
 	    '" value="'.$opt[$ind].'" '.$checked.' />';
 	if ($alphabet[$ind]) {
 	    $result.=$alphabet[$ind].': ';
 	}
-	$result.=$opt[$ind].'</td>';
+	$result.=$opt[$ind].'</label></li>';
     }
-    $result.='</tr></table>';
+    $result.='</ul></fieldset>';
     return $result;
 }