--- loncom/homework/optionresponse.pm	2015/04/09 09:48:02	1.197
+++ loncom/homework/optionresponse.pm	2025/01/27 14:18:38	1.203
@@ -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.203 2025/01/27 14:18:38 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;
 }
 
@@ -699,7 +745,7 @@ sub displayfoils {
 	  }
       }
       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 +793,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 +820,8 @@ sub displayfoils {
 	  $result.=$break.$text."\n";
 	  if ($Apache::lonhomework::type eq 'exam') {
 	      $result.=&webbubbles(\@opt,\@alphabet,$temp,$lastopt);
+	  } else {
+	      $result.= '</label>';
 	  }
 	  $temp++;
       } else {