--- loncom/homework/optionresponse.pm	2011/03/07 19:42:21	1.175
+++ loncom/homework/optionresponse.pm	2011/11/29 13:24:38	1.183
@@ -1,7 +1,7 @@
 # LearningOnline Network with CAPA
 # option list style responses
 #
-# $Id: optionresponse.pm,v 1.175 2011/03/07 19:42:21 www Exp $
+# $Id: optionresponse.pm,v 1.183 2011/11/29 13:24:38 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -32,6 +32,7 @@
 
 package Apache::optionresponse;
 use strict;
+use Apache::inputtags();
 use Apache::response();
 use Apache::lonlocal;
 use Apache::lonnet;
@@ -155,13 +156,9 @@ ENDTABLE
       splice(@options,$delopt-1,1);
       $optchanged=1;
     }
-    if ($env{"form.$Apache::lonxml::curdepth.options"}) {
+    if ($env{"form.$Apache::lonxml::curdepth.options"} ne '') {
       my $newopt = $env{"form.$Apache::lonxml::curdepth.options"};
-      if ($options[0]) {
-	push(@options,$newopt);
-      } else {
-	$options[0]=$newopt;
-      }
+      push(@options,$newopt);
       $optchanged=1;
     }
     my $rebuildtag = &Apache::edit::get_new_args($token,$parstack,$safeeval,
@@ -213,7 +210,7 @@ sub end_foilgroup {
     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,@opt);
+      $result.=&displayfoils($target,$max,$randomize,$TeXlayout,$checkboxvalue,$checkboxchoices,$tex_option_switch,@opt);
       $Apache::lonxml::post_evaluate=0;
     } elsif ( $target eq 'answer') {
       $result.=&displayanswers($max,$randomize,@opt);
@@ -226,23 +223,6 @@ sub end_foilgroup {
 	push (@{ $Apache::lonhomework::analyze{"$part_id.options"} },@opt);
     } elsif ( $target eq 'grade') {
 
-      my $nonlenient=0;
-      my $part=$Apache::inputtags::part;
-      my $lenientparm=&Apache::lonnet::EXT("resource.$part.lenient");
-
-      if ($Apache::lonhomework::scantronmode) {
-         $nonlenient=0;
-# Grading an exam: we are grading lenient unless told not to
-         if ($lenientparm=~/^0|off|no$/i) {
-            $nonlenient=1;
-         }
-      } else {
-# Web mode: we are non-lenient unless told to
-         $nonlenient=1;
-         if ($lenientparm=~/^1|on|yes$/i) {
-            $nonlenient=0;
-         }
-      }
       if ( &Apache::response::submitted()) {
 
 	my @whichopt = &whichfoils($max,$randomize);
@@ -252,11 +232,43 @@ sub end_foilgroup {
 	my $right=0;
 	my $wrong=0;
 	my $ignored=0;
+        my ($numrows,$bubbles_per_row);
+        if ($Apache::lonhomework::scantronmode) {
+            my $numitems = scalar(@opt);
+            ($numrows,$bubbles_per_row) =
+                &Apache::optionresponse::getnumrows($numitems);
+        }
+        if ($numrows < 1) {
+            $numrows = 1;
+        }
 	foreach $name (@whichopt) {
-	  my $response=&Apache::response::getresponse($temp);
-	  if ($env{'form.submitted'} eq 'scantron' && $response=~/\S/) {
-	      $response = $opt[$response];
-	  }
+	  my $response;
+          if ($env{'form.submitted'} eq 'scantron') {
+              if ($numrows > 1) {
+                  my $num = $temp;
+                  my $totalnum;
+                  for (my $i=0; $i<$numrows; $i++) {
+                      my $item = &Apache::response::getresponse($num);
+                      if ($item =~ /^\d+$/) {
+                          $totalnum = $i*$bubbles_per_row + $item;
+                      }
+                      $num ++;
+                  }
+                  if ($totalnum =~ /^\d+$/) {
+                      $response = $opt[$totalnum];
+                  }
+                  $temp += $numrows;
+              } else {
+                  $response=&Apache::response::getresponse($temp);
+                  if ($response=~/\S/) {
+                      $response = $opt[$response];
+                  }
+                  $temp ++;
+              }
+	  } else {
+              $response=&Apache::response::getresponse($temp);
+              $temp ++;
+          }
 	  if ( $response =~ /[^\s]/) {
 	    $responsehash{$name}=$response;
 	    my $value=$Apache::response::foilgroup{$name.'.value'};
@@ -269,9 +281,9 @@ sub end_foilgroup {
 	  } else {
 	    $ignored++;
 	  }
-	  $temp++;
 	}
 	my $part=$Apache::inputtags::part;
+        my $nonlenient=&Apache::inputtags::grading_is_nonlenient($part);
 	my $id = $Apache::inputtags::response['-1'];
 	my $responsestr=&Apache::lonnet::hash2str(%responsehash);
 	my $gradestr   =&Apache::lonnet::hash2str(%grade);
@@ -347,8 +359,16 @@ sub end_foilgroup {
     }
     my $part_id     = $Apache::inputtags::part;
     my $response_id = $Apache::inputtags::response[-1];
-    &Apache::lonxml::increment_counter(&getfoilcounts($max),
-				       "$part_id.$response_id");
+    my ($numrows,$bubbles_per_row);
+    if (($target eq 'tex') && ($Apache::lonhomework::type eq 'exam')) {
+        ($numrows,$bubbles_per_row) =
+            &Apache::optionresponse::getnumrows(scalar(@opt));
+    }
+    if ($numrows < 1) {
+        $numrows = 1;
+    }
+    my $increment = &getfoilcounts($max) * $numrows;
+    &Apache::lonxml::increment_counter($increment,"$part_id.$response_id");
     if ($target eq 'analyze') {
 	&Apache::lonhomework::set_bubble_lines();
     }
@@ -446,7 +466,8 @@ sub check_for_invalid {
 }
 
 sub displayfoils {
-  my ($target,$max,$randomize,$TeXlayout,$checkboxvalue,$checkboxchoices,@opt)=@_;
+  my ($target,$max,$randomize,$TeXlayout,$checkboxvalue,$checkboxchoices,
+      $tex_option_switch,@opt)=@_;
   if (!defined(@{ $Apache::response::foilgroup{'names'} })) {return;}
   my @names = @{ $Apache::response::foilgroup{'names'} };
   my @truelist;
@@ -456,7 +477,9 @@ sub displayfoils {
   my $displayoptionintex=1;
   my @alphabet = ('A'..'Z');
   my @whichopt = &whichfoils($max,$randomize);
-  &check_for_invalid(\@whichopt,\@opt);
+  unless (($target eq 'tex') && ($tex_option_switch eq 'nochoice')) {
+      &check_for_invalid(\@whichopt,\@opt);
+  }
   my $part=$Apache::inputtags::part;
   my $id=$Apache::inputtags::response[-1];
   my $break;
@@ -631,9 +654,24 @@ sub displayfoils {
 	  }
 	  if ($Apache::lonhomework::type eq 'exam') {
 	      $result.='\vskip -1 mm\noindent';
-              $result.= '\textbf{'. $internal_counter.'}. \vskip -3mm'.&bubbles(\@alphabet,\@opt).
-		                 ' \strut ';
-	      $internal_counter++;
+              my ($numrows,$bubbles_per_row) = &getnumrows(scalar(@opt)); 
+              if ($numrows == 1) {  
+                  $result .= '\textbf{'.$internal_counter.'}. \vskip -3mm';
+              } else {
+                  my $linetext;
+                  for (my $i=0; $i<$numrows; $i++) {
+                      $linetext .= $internal_counter+$i.', ';
+                  }
+                  $linetext =~ s/,\s$//;
+                  $result .= '\small {\textbf{'.$linetext.'}} '.
+                             '\hskip 2 mm {\footnotesize '.
+                             &mt('(Bubble once in [_1] lines)',$numrows).
+                             '} \vskip 1 mm';
+              }
+              $result.= &bubbles(\@alphabet,\@opt,undef,undef,$numrows,
+                                 $bubbles_per_row,$internal_counter).
+                        ' \strut ';
+	      $internal_counter += $numrows;
 	  }
           if ($target eq 'tex' && $env{'form.pdfFormFields'} eq 'yes'
               && $Apache::inputtags::status[-1] eq 'CAN_ANSWER'
@@ -714,7 +752,8 @@ sub webbubbles {
 
 
 sub bubbles {
-    my ($ralphabet,$ropt,$response, $max_width) = @_;
+    my ($ralphabet,$ropt,$response,$max_width,$numrows,$bubbles_per_row,
+        $internal_counter) = @_;
     my @alphabet = @$ralphabet;
     my @opt = @$ropt;
     my ($result,$head,$line) =('','','');
@@ -735,28 +774,37 @@ sub bubbles {
     }
     &Apache::lonxml::debug("Final maxwidth: $textwidth");
     for (my $ind=0;$ind<=$number_of_bubbles;$ind++) {
+        my $item;
+        if ($numrows > 1) {
+            my $num = $internal_counter+int($ind/$bubbles_per_row);
+            my $idx = int($ind % $bubbles_per_row);
+            $item = $num.$alphabet[$idx];
+        } else {
+            $item = $alphabet[$ind];
+        }
 	my $leftmargin;
 	$opt[$ind]=&Apache::lonxml::latex_special_symbols($opt[$ind]);
 	if ($response eq 'rankresponse') {$opt[$ind]='Rank '.$opt[$ind];}
 	if ($ind==0) {$leftmargin=6;} else {$leftmargin=10;}
 
-	$current_length += (length($opt[$ind])+length($alphabet[$ind])+4)*2;
+	$current_length += (length($opt[$ind])+length($item)+4)*2;
+        
 	if ($current_length<($textwidth-$leftmargin) and $ind!=$number_of_bubbles) {
-	    $line.='\hskip 4 mm {\small \textbf{'.$alphabet[$ind].'}}$\bigcirc$\hskip -1 mm & \hskip -3 mm {\small '.$opt[$ind].'} & ';
+            
+	    $line.='\hskip 4 mm {\small \textbf{'.$item.'}}$\bigcirc$\hskip -1 mm & \hskip -3 mm {\small '.$opt[$ind].'} & ';
 	    $head.='lr';
 	} else {
 	    $line=~s/\&\s*$//;
 	    $result.='\vskip -1 mm\noindent\setlength{\tabcolsep}{2 mm}\renewcommand{\arraystretch}{1.25}\begin{tabular}{'.$head.'}'.$line.'\\\\\end{tabular}\vskip 0 mm';
-	    $line = '\hskip 4 mm {\small \textbf{'.$alphabet[$ind].'}}$\bigcirc$\hskip -1 mm & \hskip -3 mm {\small '.$opt[$ind].'} & ';;
+	    $line = '\hskip 4 mm {\small \textbf{'.$item.'}}$\bigcirc$\hskip -1 mm & \hskip -3 mm {\small '.$opt[$ind].'} & ';
 	    $head ='lr';
-	    $current_length = (length($opt[$ind])+length($alphabet[$ind]))*2;
+	    $current_length = (length($opt[$ind])+length($item))*2;
 	}
 
     }
     return $result;
 }
 
-
 sub start_conceptgroup {
   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   $Apache::optionresponse::conceptgroup=1;
@@ -901,6 +949,24 @@ sub insert_foil {
 sub insert_drawoptionlist {
     return '<drawoptionlist />';
 }
+
+sub getnumrows {
+    my ($numitems) = @_;
+    my $bubbles_per_row;
+    my $default_numbubbles = 10;
+    if (($env{'form.bubbles_per_row'} =~ /^\d+$/) &&
+        ($env{'form.bubbles_per_row'} > 0)) {
+        $bubbles_per_row = $env{'form.bubbles_per_row'};
+    } else {
+        $bubbles_per_row = $default_numbubbles;
+    }
+    my $numrows = int ($numitems/$bubbles_per_row);
+    if (($numitems % $bubbles_per_row) != 0) {
+        $numrows ++;
+    }
+    return ($numrows,$bubbles_per_row);
+}
+
 1;
 __END__