[LON-CAPA-cvs] cvs: loncom /homework default_homework.lcpm inputtags.pm /homework/caparesponse caparesponse.pm /xml lonxml.pm

albertel lon-capa-cvs@mail.lon-capa.org
Wed, 01 Nov 2006 23:24:55 -0000


This is a MIME encoded message

--albertel1162423495
Content-Type: text/plain

albertel		Wed Nov  1 18:24:55 2006 EDT

  Modified files:              
    /loncom/xml	lonxml.pm 
    /loncom/homework	default_homework.lcpm inputtags.pm 
    /loncom/homework/caparesponse	caparesponse.pm 
  Log:
  - adding support for <vector> answers
      <answer><value>1</value><value>2</value></answer>
      requires 2 <textline>s
      <answer><vector>1,2</vector></answer>
      requires 1 textline
  
      Still borken:
      <answer type="unordered"><vector>1,2</vector><value>3</value></answer>
  
  
  
--albertel1162423495
Content-Type: text/plain
Content-Disposition: attachment; filename="albertel-20061101182455.txt"

Index: loncom/xml/lonxml.pm
diff -u loncom/xml/lonxml.pm:1.423 loncom/xml/lonxml.pm:1.424
--- loncom/xml/lonxml.pm:1.423	Tue Oct 17 11:11:37 2006
+++ loncom/xml/lonxml.pm	Wed Nov  1 18:24:51 2006
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # XML Parser Module 
 #
-# $Id: lonxml.pm,v 1.423 2006/10/17 15:11:37 albertel Exp $
+# $Id: lonxml.pm,v 1.424 2006/11/01 23:24:51 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -776,7 +776,7 @@
   $safehole->wrap(\&Apache::inputtags::finalizeawards,$safeeval,'&LONCAPA_INTERNAL_FINALIZEAWARDS');
   $safehole->wrap(\&Apache::caparesponse::get_sigrange,$safeeval,'&LONCAPA_INTERNAL_get_sigrange');
   use Data::Dumper;
-  $safehole->wrap(\&Data::Dumper::Dumper,$safeeval,'&Dumper');
+  $safehole->wrap(\&Data::Dumper::Dumper,$safeeval,'&LONCAPA_INTERNAL_Dumper');
 #need to inspect this class of ops
 # $safeeval->deny(":base_orig");
   $safeeval->permit("require");
Index: loncom/homework/default_homework.lcpm
diff -u loncom/homework/default_homework.lcpm:1.118 loncom/homework/default_homework.lcpm:1.119
--- loncom/homework/default_homework.lcpm:1.118	Mon Oct  2 14:23:38 2006
+++ loncom/homework/default_homework.lcpm	Wed Nov  1 18:24:52 2006
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA 
 # used by lonxml::xmlparse() as input variable $safeinit to Apache::run::run()
 #
-# $Id: default_homework.lcpm,v 1.118 2006/10/02 18:23:38 albertel Exp $
+# $Id: default_homework.lcpm,v 1.119 2006/11/01 23:24:52 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -152,7 +152,7 @@
     }
     if ($response=~ /^\s|\s$/) {
 	$response=~ s:^\s+|\s+$::g;
-	#&LONCAPA_INTERNAL_DEBUG("Removed ws now :$response:");
+	&LONCAPA_INTERNAL_DEBUG("Removed ws now :$response:");
     }
 
     #&LONCAPA_INTERNAL_DEBUG(" type is $type ");
@@ -179,7 +179,7 @@
     if (length($response) > 500) { return ('TOO_LONG',undef); }
 
     if ($type eq '' ) {
-	#&LONCAPA_INTERNAL_DEBUG("Didn't find a type :$type: defaulting");
+	&LONCAPA_INTERNAL_DEBUG("Didn't find a type :$type: defaulting");
 	if ( $answer eq ($answer *1.0)) { $type = 2;
 				      } else { $type = 3; }
     } else {
@@ -199,7 +199,7 @@
     #formula type setup the sample points
     if ($type eq '8') {
 	($id_list,$points)=split(/@/,$samples);
-	#&LONCAPA_INTERNAL_DEBUG("Found :$id_list:$points: points in $samples");
+	&LONCAPA_INTERNAL_DEBUG("Found :$id_list:$points: points in $samples");
     }
     if ($tol eq '') {
 	$tol=0.0;
@@ -251,8 +251,8 @@
     elsif ($result =='15') { $result='UNIT_IRRECONCIBLE'; }
     else  {$result = "ERROR: Unknown Result:$result:$@:";}
 
-    #&LONCAPA_INTERNAL_DEBUG("RetError $reterror: Answer $answer: Response $response:  type-$type|$tol|$tol_type|$sig:$sig_lbound:$sig_ubound|$unit|");
-    #&LONCAPA_INTERNAL_DEBUG(" $answer $response $result ");
+    &LONCAPA_INTERNAL_DEBUG("RetError $reterror: Answer $answer: Response $response:  type-$type|$tol|$tol_type|$sig:$sig_lbound:$sig_ubound|$unit|");
+    &LONCAPA_INTERNAL_DEBUG(" $answer $response $result ");
     return ($result,$reterror)
 }
 
@@ -292,68 +292,129 @@
 }
 
 sub caparesponse_check_list {
-    my $response=$LONCAPA::CAPAresponse_args{'response'};
-    my $result="Got response :".join(':',@LONCAPA::CAPAresponse_answer).":\n";
+    my $responses=$LONCAPA::CAPAresponse_args{'response'};
+    &LONCAPA_INTERNAL_DEBUG(" answer is ".
+			    &LONCAPA_INTERNAL_Dumper($LONCAPA::CAPAresponse_answer).":\n");
+    &LONCAPA_INTERNAL_DEBUG(" respons is ".
+			    &LONCAPA_INTERNAL_Dumper($responses).":\n");
     &LONCAPA_INTERNAL_DEBUG("args ".join(':',%LONCAPA::CAPAresponse_args));
-    my @responselist;
     my $type = $LONCAPA::CAPAresponse_args{'type'};
     &LONCAPA_INTERNAL_DEBUG("Got type :$type:\n");
-    my $num_answers = scalar(@{$LONCAPA::CAPAresponse_answer->{'answers'}});
+    
+    my $num_input_lines =
+	scalar(@{$LONCAPA::CAPAresponse_answer->{'answers'}});
     if ($type ne '' 
-	&& $num_answers > 1) {
-	(@responselist)=split(/,/,$response);
-	if (@responselist < $num_answers) {
+	&& $num_input_lines > 1) {
+	if (scalar(@$responses) < $num_input_lines) {
 	    return 'MISSING_ANSWER';
 	}
-	if (@responselist > $num_answers) {
+	if (scalar(@$responses) > $num_input_lines) {
 	    return 'EXTRA_ANSWER';
 	}
-    } else {
-	(@responselist)=($response);
+
+    }
+
+    foreach my $which (0..($num_input_lines-1)) {
+	my $answer_size = 
+	    scalar(@{$LONCAPA::CAPAresponse_answer->{'answers'}[$which]});
+	if ($type ne '' 
+	    && $answer_size > 1) {
+	    $responses->[$which]=[split(/,/,$responses->[$which])];
+	} else {
+	    $responses->[$which]=[$responses->[$which]];
+	}
     }
-    &LONCAPA_INTERNAL_DEBUG("Initial final response :$responselist['-1']:");
+    &LONCAPA_INTERNAL_DEBUG(" parsed response is ".
+			    &LONCAPA_INTERNAL_Dumper($responses).":\n");
+    foreach my $which (0..($num_input_lines-1)) {
+	my $answer_size = 
+	    scalar(@{$LONCAPA::CAPAresponse_answer->{'answers'}[$which]});
+	my $response_size = 
+	    scalar(@{$responses->[$which]});
+	if ($answer_size > $response_size) {
+	    return 'MISSING_ANSWER';
+	}
+	if ($answer_size < $response_size) {
+	    return 'EXTRA_ANSWER';
+	}
+    }
+
+    &LONCAPA_INTERNAL_DEBUG("Initial final response :$responses->[0][-1]:");
     my $unit;
     if ($type eq '' || $type eq 'float') {
 	#for numerical problems split off the unit
-	if ( $responselist['-1']=~ /(.*[^\s])\s+([^\s]+)/ ) {
-	    $responselist['-1']=$1;
+	if ( $responses->[0][-1]=~ /(.*[^\s])\s+([^\s]+)/ ) {
+	    $responses->[0][-1]=$1;
 	    $unit=$2;
 	}
     }
-    &LONCAPA_INTERNAL_DEBUG("Final final response :$responselist['-1']:$unit:");
+    &LONCAPA_INTERNAL_DEBUG("Final final response :$responses->[0][-1]:$unit:");
     $unit=~s/\s//;
-
+    if ($unit ne '') {
+	foreach my $response (@$responses) {
+	    foreach my $element (@$response) {	    
+		$element .= " $unit";
+	    }
+	}
+    }
+    
     foreach my $thisanswer (@{ $LONCAPA::CAPAresponse_answer->{'answers'} }) {
 	if (!defined($thisanswer)) {
 	    return ('ERROR','answer was undefined');
 	}
     }
 
-    if ($unit ne '') {
-	foreach my $response (@responselist) {
-	    $response .= " $unit";
-	}
-    }
 
+    &LONCAPA_INTERNAL_DEBUG(&LONCAPA_INTERNAL_Dumper($responses));
     my %memoized;
     if ($LONCAPA::CAPAresponse_answer->{'type'}  eq 'ordered') {
-	for (my $i=0; $i<scalar(@responselist);$i++) {
+	for (my $i=0; $i<scalar(@$responses);$i++) {
 	    my $answer   = $LONCAPA::CAPAresponse_answer->{'answers'}[$i];
-	    my $response = $responselist[$i];
+	    my $response = $responses->[$i];
 	    my $key = "$answer\0$response";
-	    $memoized{$key} = [&caparesponse_check($answer, $response)];
+	    my (@awards,@msgs);
+	    for (my $j=0; $j<scalar(@$response); $j++) { 
+		my ($award,$msg) = &caparesponse_check($answer->[$j],
+						       $response->[$j]);
+		push(@awards,$award);
+		push(@msgs,  $msg);
+	    }
+	    my ($award,$msg) = 
+		&LONCAPA_INTERNAL_FINALIZEAWARDS(\@awards,\@msgs);
+	    $memoized{$key} = [$award,$msg];
 	}
     } else {
-	foreach my $response (@responselist) {
+	#FIXME broken with unorder responses where one is a <value>
+        #      and the other is a <vector> (need to delay parse til
+        #      inside the loop?)
+	foreach my $response (@$responses) {
+	    my $response_size = scalar(@{$response});
 	    foreach my $answer (@{ $LONCAPA::CAPAresponse_answer->{'answers'} }) {
 		my $key = "$answer\0$response";
-		$memoized{$key} = [&caparesponse_check($answer, $response)];
+		my $answer_size =  scalar(@{$answer});
+		my ($award,$msg);
+		if ($answer_size > $response_size) {
+		    $award = 'MISSING_ANSWER';
+		} elsif ($answer_size < $response_size) {
+		    $award = 'EXTRA_ANSWER';
+		} else {
+		    my (@awards,@msgs);
+		    for (my $j=0; $j<scalar(@$response); $j++) {
+			my ($award,$msg) = &caparesponse_check($answer->[$j],
+							       $response->[$j]);
+			push(@awards,$award);
+			push(@msgs,  $msg);
+		    }
+		    ($award,$msg) = 
+			&LONCAPA_INTERNAL_FINALIZEAWARDS(\@awards,\@msgs);
+		}
+		$memoized{$key} = [$award,$msg];
 	    }
 	}
     }
 
     my ($final_award,$final_msg);
-    &init_permutation(scalar(@responselist),
+    &init_permutation(scalar(@$responses),
 		      $LONCAPA::CAPAresponse_answer->{'type'});
 
     # possible FIXMEs
@@ -369,17 +430,22 @@
 	my $order = &get_next_permutation();
 	my (@awards, @msgs, $i);
 	foreach my $thisanswer (@{ $LONCAPA::CAPAresponse_answer->{'answers'} }) {
-	    my $key = "$thisanswer\0".$responselist[$order->[$i]];
+	    my $key = "$thisanswer\0".$responses->[$order->[$i]];
 	    push(@awards,$memoized{$key}[0]);
 	    push(@msgs,$memoized{$key}[1]);
 	    $i++;
+
 	}
+	&LONCAPA_INTERNAL_DEBUG(" all awards ".join(':',@awards));
+
 	my ($possible_award,$possible_msg) = 
 	    &LONCAPA_INTERNAL_FINALIZEAWARDS(\@awards,\@msgs);
+	&LONCAPA_INTERNAL_DEBUG(" pos awards ".$possible_award);
 	push(@final_awards,$possible_award);
 	push(@final_msg,$possible_msg);
     }
 
+    &LONCAPA_INTERNAL_DEBUG(" all final_awards ".join(':',@final_awards));
     my ($final_award,$final_msg) = 
 	&LONCAPA_INTERNAL_FINALIZEAWARDS(\@final_awards,\@final_msg,undef,1);
     return ($final_award,$final_msg);
Index: loncom/homework/inputtags.pm
diff -u loncom/homework/inputtags.pm:1.209 loncom/homework/inputtags.pm:1.210
--- loncom/homework/inputtags.pm:1.209	Tue Oct 17 11:11:11 2006
+++ loncom/homework/inputtags.pm	Wed Nov  1 18:24:52 2006
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # input  definitons
 #
-# $Id: inputtags.pm,v 1.209 2006/10/17 15:11:11 albertel Exp $
+# $Id: inputtags.pm,v 1.210 2006/11/01 23:24:52 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -283,7 +283,7 @@
 sub start_textline {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
     my $result = "";
-    my $id = &start_input($parstack,$safeeval);
+    my $input_id = &start_input($parstack,$safeeval);
     if ($target eq 'web') {
 	$Apache::lonxml::evaluate--;
 	my $partid=$Apache::inputtags::part;
@@ -294,7 +294,14 @@
 	    if ($size eq '') { $size=20; } else {
 		if ($size < 20) { $maxlength=$size; }
 	    }
-	    my $oldresponse = &HTML::Entities::encode($Apache::lonhomework::history{"resource.$partid.$id.submission"},'<>&"');
+	    my $oldresponse = $Apache::lonhomework::history{"resource.$partid.$id.submission"};
+	    &Apache::lonxml::debug("oldresponse $oldresponse is ".ref($oldresponse));
+
+	    if (ref($oldresponse) eq 'ARRAY') {
+		$oldresponse = $oldresponse->[$#Apache::inputtags::inputlist];
+	    }
+	    $oldresponse = &HTML::Entities::encode($oldresponse,'<>&"');
+
 	    if ($Apache::lonhomework::type ne 'exam') {
 		my $addchars=&Apache::lonxml::get_param('addchars',$parstack,$safeeval);
 		$result='';
Index: loncom/homework/caparesponse/caparesponse.pm
diff -u loncom/homework/caparesponse/caparesponse.pm:1.194 loncom/homework/caparesponse/caparesponse.pm:1.195
--- loncom/homework/caparesponse/caparesponse.pm:1.194	Fri Sep 29 16:55:36 2006
+++ loncom/homework/caparesponse/caparesponse.pm	Wed Nov  1 18:24:52 2006
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # caparesponse definition
 #
-# $Id: caparesponse.pm,v 1.194 2006/09/29 20:55:36 albertel Exp $
+# $Id: caparesponse.pm,v 1.195 2006/11/01 23:24:52 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -41,6 +41,8 @@
 
 my %answer;
 my $cur_name;
+my $tag_internal_answer_name = 'INTERNAL';
+
 sub start_answer {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
     my $result;
@@ -93,7 +95,9 @@
 	my $bodytext = &Apache::lonxml::get_all_text("/value",$parser,$style);
 	$bodytext = &Apache::run::evaluate($bodytext,$safeeval,
 					   $$parstack[-1]);
-	push(@{ $answer{$cur_name}{'answers'} },$bodytext);
+	
+	push(@{ $answer{$cur_name}{'answers'} },[$bodytext]);
+	
     }
     return $result;
 }
@@ -104,6 +108,28 @@
     return $result;
 }
 
+sub start_vector {
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
+    my $result;
+    if ( $target eq 'web' || $target eq 'tex' ||
+	 $target eq 'grade' || $target eq 'webgrade' ||
+	 $target eq 'answer' || $target eq 'analyze' ) {
+	my $bodytext = &Apache::lonxml::get_all_text("/vector",$parser,$style);
+	my @values = &Apache::run::run($bodytext,$safeeval,$$parstack[-1]);
+	if (@values == 1) {
+	    @values = split(',',$values[0]);
+	}
+	push(@{ $answer{$cur_name}{'answers'} },\@values);
+    }
+    return $result;
+}
+
+sub end_vector {
+    my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
+    my $result;
+    return $result;
+}
+
 sub start_array {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
     my $result;
@@ -138,7 +164,9 @@
 
 sub start_numericalresponse {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
-    &Apache::lonxml::register('Apache::caparesponse',('answer','answergroup','value','array','unit'));
+    &Apache::lonxml::register('Apache::caparesponse',
+			      ('answer','answergroup','value','array','unit',
+			       'vector'));
     my $id = &Apache::response::start_response($parstack,$safeeval);
     my $result;
     undef(%answer);
@@ -191,8 +219,8 @@
 	    if ($unit =~ /\S/) { $result.=" (in $unit) "; }
 	}
 	if (  &Apache::response::show_answer() ) {
-	    &set_answertext('INTERNAL',$target,$token,$tagstack,$parstack,
-			    $parser,$safeeval,-1);
+	    &set_answertext($tag_internal_answer_name,$target,$token,$tagstack,
+			    $parstack,$parser,$safeeval,-1);
 	}
     }
     return $result;
@@ -201,7 +229,6 @@
 sub set_answertext {
     my ($name,$target,$token,$tagstack,$parstack,$parser,$safeeval,
 	$response_level) = @_;
-    my $answertxt;
     &add_in_tag_answer($parstack,$safeeval,$response_level);
 
     return if ($name eq '' || !ref($answer{$name}));
@@ -212,50 +239,78 @@
 					    $response_level);
 
     &Apache::lonxml::debug("answer looks to be $name");
+    my @answertxt;
     for (my $i=0; $i < scalar(@{$answer{$name}{'answers'}}); $i++) {
+	my $answertxt;
 	my $answer=$answer{$name}{'answers'}[$i];
-	if ( scalar(@$tagstack)
-	     && $tagstack->[$response_level] ne 'numericalresponse') {
-	    $answertxt.=$answer.',';
-	} else {
-	    my $format;
-	    if ($#formats > 0) {
-		$format=$formats[$i];
+	foreach my $element (@$answer) {
+	    if ( scalar(@$tagstack)
+		 && $tagstack->[$response_level] ne 'numericalresponse') {
+		$answertxt.=$element.',';
 	    } else {
-		$format=$formats[0];
+		my $format;
+		if ($#formats > 0) {
+		    $format=$formats[$i];
+		} else {
+		    $format=$formats[0];
+		}
+		if ($unit=~/\$/) { $format="\$".$format; $unit=~s/\$//g; }
+		if ($unit=~/\,/) { $format="\,".$format; $unit=~s/\,//g; }
+		my $formatted=&format_number($element,$format,$target,
+					     $safeeval);
+		$answertxt.=' '.$formatted.',';
 	    }
-	    if ($unit=~/\$/) { $format="\$".$format; $unit=~s/\$//g; }
-	    if ($unit=~/\,/) { $format="\,".$format; $unit=~s/\,//g; }
-	    my $formatted=&format_number($answer,$format,$target,
-					 $safeeval);
-	    $answertxt.=$formatted.',';
+	    
+	}
+	chop($answertxt);
+	if ($target eq 'web') {
+	    $answertxt.=" $unit ";
 	}
+
+	push(@answertxt,$answertxt)
     }
 	
-    chop($answertxt);
-    if ($target eq 'web') {
-	$answertxt.=" $unit ";
-    }
     my $id = $Apache::inputtags::response[-1];
-    $Apache::inputtags::answertxt{$id}=$answertxt;
+    $Apache::inputtags::answertxt{$id}=\@answertxt;
 }
 
-sub check_submission {
-    my ($response,$partid,$id,$tag,$parstack,$safeeval,$ignore_sig)=@_;
+sub setup_capa_args {
+    my ($safeeval,$parstack,$args,$response) = @_;
     my $args_ref= \%{$safeeval->varglob('LONCAPA::CAPAresponse_args')};
-    $$args_ref{'response'}=$response;
-    my $hideunit=&Apache::lonnet::EXT('resource.'.$partid.'_'.$id.'.turnoffunit');
-    
-    foreach my $arg ('type','tol','sig','format','unit','calc',
-		     'samples') {
+    undef(%{ $args_ref });
+ 
+    foreach my $arg (@{$args}) {
 	$$args_ref{$arg}=
 	    &Apache::lonxml::get_param($arg,$parstack,$safeeval);
     }
     foreach my $key (keys(%Apache::inputtags::params)) {
 	$$args_ref{$key}=$Apache::inputtags::params{$key};
     }
+    &setup_capa_response($args_ref,$response);
+    return $args_ref;
+}
+
+sub setup_capa_response {
+    my ($args_ref,$response) = @_;   
+
+    use Data::Dumper;
+    &Apache::lonxml::debug("response dump is ".&Dumper($response));
     
-    #no way to enter units, with radio buttons
+    if (ref($response)) {
+	$$args_ref{'response'}=dclone($response);
+    } else {
+	$$args_ref{'response'}=dclone([$response]);
+    }
+}
+
+sub check_submission {
+    my ($response,$partid,$id,$tag,$parstack,$safeeval,$ignore_sig)=@_;
+    my @args = ('type','tol','sig','format','unit','calc','samples');
+    my $args_ref = &setup_capa_args($safeeval,$parstack,\@args,$response);
+
+    my $hideunit=
+	&Apache::lonnet::EXT('resource.'.$partid.'_'.$id.'.turnoffunit');
+        #no way to enter units, with radio buttons
     if ($Apache::lonhomework::type eq 'exam' ||
 	lc($hideunit) eq "yes") {
 	delete($$args_ref{'unit'});
@@ -280,20 +335,21 @@
     
     &add_in_tag_answer($parstack,$safeeval);
 
-    #FIXME would be nice if we could save name so we know which answer
-    # graded the users submisson correct
-    my (%results,@final_awards,@final_msgs,@names);
+    my (@final_awards,@final_msgs,@names);
     foreach my $name (keys(%answer)) {
 	&Apache::lonxml::debug(" doing $name with ".join(':',@{ $answer{$name}{'answers'} }));
 	
 	${$safeeval->varglob('LONCAPA::CAPAresponse_answer')}=dclone($answer{$name});
+	&setup_capa_response($args_ref,$response);
+	use Time::HiRes;
+	my $t0 = [Time::HiRes::gettimeofday()];
 	my ($result,@msgs) = 
 	    &Apache::run::run("&caparesponse_check_list()",$safeeval);
+	&Apache::lonxml::debug("checking $name $result with $response took ".&Time::HiRes::tv_interval($t0));
 	&Apache::lonxml::debug('msgs are '.join(':',@msgs));
 	my ($awards)=split(/:/,$result);
 	my @awards= split(/,/,$awards);
 	my ($ad, $msg) = &Apache::inputtags::finalizeawards(\@awards,\@msgs);
-	$results{$name}= [$ad,$msg];
 	push(@final_awards,$ad);
 	push(@final_msgs,$msg);
 	push(@names,$name);
@@ -311,8 +367,8 @@
 					      $response_level);
     &Apache::lonxml::debug('answer is'.join(':',@answer));
     if (@answer && defined($answer[0])) {
-	$answer{'INTERNAL'}= {'type' => 'ordered',
-			      'answers' => \@answer };
+	$answer{$tag_internal_answer_name}= {'type' => 'ordered',
+					     'answers' => [\@answer] };
     }
 }
 
@@ -456,7 +512,8 @@
 	my $unit=&Apache::lonxml::get_param_var('unit',$parstack,$safeeval);
 	
 	if ($target eq 'answer') {
-	    $result.=&Apache::response::answer_header($tag);
+	    $result.=&Apache::response::answer_header($tag,undef,
+						      scalar(keys(%answer)));
 	    if ($tag eq 'numericalresponse'
 		&& $Apache::lonhomework::type eq 'exam') {
 		my ($bubble_values,undef,$correct) = &make_numerical_bubbles($partid,
@@ -467,43 +524,61 @@
 	foreach my $name (sort(keys(%answer))) {
 	    my @answers = @{ $answer{$name}{'answers'} };
 	    my ($sigline,$tolline);
+	    if ($name ne $tag_internal_answer_name 
+		|| scalar(keys(%answer)) > 1) {
+		$result.=&Apache::response::answer_part($tag,$name);
+	    }
 	    for(my $i=0;$i<=$#answers;$i++) {
 		my $ans=$answers[$i];
 		my $fmt=$formats[0];
 		if (@formats && $#formats) {$fmt=$formats[$i];}
-		my ($high,$low);
-		if ($Apache::inputtags::params{'tol'}) {
-		    ($high,$low)=&get_tolrange($ans,$Apache::inputtags::params{'tol'});
-		}
 		my ($sighigh,$siglow);
 		if ($Apache::inputtags::params{'sig'}) {
 		    ($sighigh,$siglow)=&get_sigrange($Apache::inputtags::params{'sig'});
 		}
-		if ($fmt && $tag eq 'numericalresponse') {
-		    $fmt=~s/e/E/g;
-		    if ($unit=~/\$/) { $fmt="\$".$fmt; $unit=~s/\$//g; }
-		    if ($unit=~/\,/) { $fmt="\,".$fmt; $unit=~s/\,//g; }
-		    $ans = &format_number($ans,$fmt,$target,$safeeval);
-		    #if ($high) {
-		    #    $high=&format_number($high,$fmt,$target,$safeeval);
-		    #    $low =&format_number($low,$fmt,$target,$safeeval);
-		    #}
+		my @vector;
+		if (ref($ans)) {
+		    @vector = @{ $ans };
+		} else {
+		    @vector = ($ans);
 		}
 		if ($target eq 'answer') {
-		    if ($high && $tag eq 'numericalresponse') {
-			$ans.=' ['.$low.','.$high.']';
-			$tolline .= "[$low, $high]";
-		    }
-		    if (defined($sighigh) && $tag eq 'numericalresponse') {
-			if ($env{'form.answer_output_mode'} eq 'tex') {
-			    $ans.= " Sig $siglow - $sighigh";
-			} else {
-			    $ans.= " Sig <i>$siglow - $sighigh</i>";
-			    $sigline .= "[$siglow, $sighigh]";
+		    my @all_answer_info;
+		    foreach my $element (@vector) {
+			my ($high,$low);
+			if ($Apache::inputtags::params{'tol'}) {
+			    ($high,$low)=&get_tolrange($element,$Apache::inputtags::params{'tol'});
+			}
+			if ($fmt && $tag eq 'numericalresponse') {
+			    $fmt=~s/e/E/g;
+			    if ($unit=~/\$/) { $fmt="\$".$fmt; $unit=~s/\$//g; }
+			    if ($unit=~/\,/) { $fmt="\,".$fmt; $unit=~s/\,//g; }
+			    $element = &format_number($element,$fmt,$target,$safeeval);
+			    #if ($high) {
+			    #    $high=&format_number($high,$fmt,$target,$safeeval);
+			    #    $low =&format_number($low,$fmt,$target,$safeeval);
+			    #}
 			}
+			if ($high && $tag eq 'numericalresponse') {
+			    $element.=' ['.$low.','.$high.']';
+			    $tolline .= "[$low, $high]";
+			}
+			if (defined($sighigh) && $tag eq 'numericalresponse') {
+			    if ($env{'form.answer_output_mode'} eq 'tex') {
+				$element.= " Sig $siglow - $sighigh";
+			    } else {
+				$element.= " Sig <i>$siglow - $sighigh</i>";
+				$sigline .= "[$siglow, $sighigh]";
+			    }
+			}
+			push(@all_answer_info,$element);
 		    }
-		    $result.=&Apache::response::answer_part($tag,$ans);
+		    $result.= &Apache::response::answer_part($tag,join(', ',@all_answer_info));
 		} elsif ($target eq 'analyze') {
+		    my ($high,$low);
+		    if ($Apache::inputtags::params{'tol'}) {
+			($high,$low)=&get_tolrange($ans,$Apache::inputtags::params{'tol'});
+		    }
 		    push (@{ $Apache::lonhomework::analyze{"$part_id.answer"} }, $ans);
 		    if ($high) {
 			push (@{ $Apache::lonhomework::analyze{"$part_id.ans_high"} }, $high);
@@ -520,16 +595,20 @@
 		my $ans=$answers[$i];
 		my $fmt=$formats[0];
 		if (@formats && $#formats) {$fmt=$formats[$i];}
-		if ($fmt && $tag eq 'numericalresponse') {
-		    $fmt=~s/e/E/g;
-		    if ($unit=~/\$/) { $fmt="\$".$fmt; $unit=~s/\$//g; }
-		    if ($unit=~/\,/) { $fmt="\,".$fmt; $unit=~s/\,//g; }
-		    $ans = &format_number($ans,$fmt,$target,$safeeval);
-		    if ($fmt=~/\$/ && $unit!~/\$/) { $ans=~s/\$//; }
+		foreach my $element (@$ans) {		    
+		    if ($fmt && $tag eq 'numericalresponse') {
+			$fmt=~s/e/E/g;
+			if ($unit=~/\$/) { $fmt="\$".$fmt; $unit=~s/\$//g; }
+			if ($unit=~/\,/) { $fmt="\,".$fmt; $unit=~s/\,//g; }
+			$element = &format_number($element,$fmt,$target,
+						  $safeeval);
+			if ($fmt=~/\$/ && $unit!~/\$/) { $element=~s/\$//; }
+		    }
 		}
-		push(@fmt_ans,$ans);
+		push(@fmt_ans,join(',',@$ans));
 	    }
-	    my $response=join(', ',@fmt_ans);
+	    my $response=\@fmt_ans;
+
 	    my $hideunit=&Apache::lonnet::EXT('resource.'.$partid.'_'.
 					      $id.'.turnoffunit');
 	    if ($unit ne ''  && 
@@ -537,24 +616,25 @@
 		   lc($hideunit) eq "yes") )  {
 		my $cleanunit=$unit;
 		$cleanunit=~s/\$\,//g;
-		$response.=" $cleanunit";
+		foreach my $ans (@fmt_ans) {
+		    $ans.=" $cleanunit";
+		}
 	    }
-
 	    my ($ad,$msg)=&check_submission($response,$partid,$id,$tag,
 					    $parstack,$safeeval);
 	    if ($ad ne 'EXACT_ANS' && $ad ne 'APPROX_ANS') {
 		my $error;
 		if ($tag eq 'formularesponse') {
-		    $error=&mt('Computer\'s answer is incorrect ("[_1]").[_2]',$response,$name);
+		    $error=&mt('Computer\'s answer is incorrect ("[_1]").',join(', ',@$response));
 		} else {
 		    # answer failed check if it is sig figs that is failing
 		    my ($ad,$msg)=&check_submission($response,$partid,$id,
 						    $tag,$parstack,
 						    $safeeval,1);
 		    if ($sigline ne '') {
-			$error=&mt('Computer\'s answer is incorrect ("[_1]"). It is likely that the tolerance range [_2] or significant figures [_3] need to be adjusted.[_4]',$response,$tolline,$sigline,$name);
+			$error=&mt('Computer\'s answer is incorrect ("[_1]"). It is likely that the tolerance range [_2] or significant figures [_3] need to be adjusted.',join(', ',@$response),$tolline,$sigline);
 		    } else {
-			$error=&mt('Computer\'s answer is incorrect ("[_1]"). It is likely that the tolerance range [_2] needs to be adjusted.[_3]',$response,$tolline,$name);
+			$error=&mt('Computer\'s answer is incorrect ("[_1]"). It is likely that the tolerance range [_2] needs to be adjusted.',join(', ',@$response),$tolline);
 		    }
 		}
 		if ($ad ne 'EXACT_ANS' && $ad ne 'APPROX_ANS') {
@@ -582,6 +662,7 @@
 		my $samples=&Apache::lonxml::get_param('samples',$parstack,$safeeval);
 		$result.=&Apache::response::answer_part($tag,$samples);
 	    }
+	    $result.=&Apache::response::next_answer($tag,$name);
 	}
 	if ($target eq 'answer') {
 	    $result.=&Apache::response::answer_footer($tag);
@@ -746,7 +827,7 @@
 
 sub get_sigrange {
     my ($sig)=@_;
-    &Apache::lonxml::debug("Got a sig of :$sig:");
+    #&Apache::lonxml::debug("Got a sig of :$sig:");
     my $courseid=$env{'request.course.id'};
     if (lc($env{"course.$courseid.disablesigfigs"}) eq 'yes') {
 	return (15,0);
@@ -810,7 +891,7 @@
 		$answer=
 		    &Apache::lonxml::get_param('answer',$parstack,$safeeval);
 	    }
-	    $Apache::inputtags::answertxt{$id}=$answer;
+	    $Apache::inputtags::answertxt{$id}=[$answer];
 	} 
     } elsif ($target eq 'answer' || $target eq 'grade') {
 	&Apache::response::reset_params();
@@ -861,24 +942,30 @@
 		    &Apache::lonxml::debug("current $answer");
 		    $ad = ($result) ? 'APPROX_ANS' : 'INCORRECT';
 		} else {
-		    my $args_ref= 
-			\%{$safeeval->varglob('LONCAPA::CAPAresponse_args')};
-		
-		    $$args_ref{'response'}=$response;
-		    &Apache::lonxml::debug("current $response");
-		    $$args_ref{'type'}=
-			&Apache::lonxml::get_param('type',$parstack,$safeeval);
-		    foreach my $key (keys(%Apache::inputtags::params)) {
-			$$args_ref{$key}=$Apache::inputtags::params{$key};
+		    my @args = ('type');
+		    my $args_ref = &setup_capa_args($safeeval,$parstack,
+						    \@args,$response);
+
+		    &add_in_tag_answer($parstack,$safeeval);
+		    my (@final_awards,@final_msgs,@names);
+		    foreach my $name (keys(%answer)) {
+			&Apache::lonxml::debug(" doing $name with ".join(':',@{ $answer{$name}{'answers'} }));
+			${$safeeval->varglob('LONCAPA::CAPAresponse_answer')}=dclone($answer{$name});
+			my ($result, @msgs)=&Apache::run::run("&caparesponse_check_list()",$safeeval);
+			&Apache::lonxml::debug('msgs are'.join(':',@msgs));
+			my ($awards)=split(/:/,$result);
+			my (@awards) = split(/,/,$awards);
+			($ad,$msg) = 
+			    &Apache::inputtags::finalizeawards(\@awards,\@msgs);
+			push(@final_awards,$ad);
+			push(@final_msgs,$msg);
+			push(@names,$name);
+			&Apache::lonxml::debug("\n<br>result:$result:$Apache::lonxml::curdepth<br>\n");
 		    }
-		    &Apache::lonxml::debug('answer is'.join(':',$answer));
-		    @{$safeeval->varglob('LONCAPA::CAPAresponse_answer')}=($answer);
-		    ($result, my @msgs)=&Apache::run::run("&caparesponse_check_list()",$safeeval);
-		    &Apache::lonxml::debug('msgs are'.join(':',@msgs));
-		    my ($awards)=split(/:/,$result);
-		    my (@awards) = split(/,/,$awards);
-		    ($ad,$msg) = &Apache::inputtags::finalizeawards(\@awards,\@msgs);
-		    &Apache::lonxml::debug("\n<br>result:$result:$Apache::lonxml::curdepth<br>\n");
+		    my ($ad, $msg, $name) = 
+			&Apache::inputtags::finalizeawards(\@final_awards,
+							   \@final_msgs,
+							   \@names,1);
 		}
 		if ($Apache::lonhomework::type eq 'survey' &&
 		    ($ad eq 'INCORRECT' || $ad eq 'APPROX_ANS' ||

--albertel1162423495--