--- loncom/homework/default_homework.lcpm 2006/07/28 15:22:28 1.115 +++ loncom/homework/default_homework.lcpm 2006/09/29 20:55:33 1.116 @@ -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.115 2006/07/28 15:22:28 www Exp $ +# $Id: default_homework.lcpm,v 1.116 2006/09/29 20:55:33 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -33,6 +33,72 @@ $pi=atan2(1,1)*4; $rad2deg=180.0/$pi; $deg2rad=$pi/180.0; $"=' '; +use strict; +{ + my $n = 0; + my $total = 0; + my $num_left = 0; + my @order; + my $type; + + sub init_permutation { + my ($size,$requested_type) = @_; + @order = (0..$size-1); + $n = $size; + $type = $requested_type; + if ($type eq 'ordered') { + $total = $num_left = 1; + } elsif ($type eq 'unordered') { + $total = $num_left = &factorial($size); + } else { + die("Unkown type: $type"); + } + } + + sub get_next_permutation { + if ($num_left == $total) { + $num_left--; + return @order; + } + + # Find largest index j with a[j] < a[j+1] + + my $j = scalar(@order) - 2; + while ($order[$j] > $order[$j+1]) { + $j--; + } + + # Find index k such that a[k] is smallest integer + # greater than a[j] to the right of a[j] + + my $k = scalar(@order) - 1; + while ($order[$j] > $order[$k]) { + $k--; + } + + # Interchange a[j] and a[k] + + @order[($k,$j)] = @order[($j,$k)]; + + # Put tail end of permutation after jth position in increasing order + + my $r = scalar(@order) - 1; + my $s = $j + 1; + + while ($r > $s) { + @order[($s,$r)]=@order[($r,$s)]; + $r--; + $s++; + } + + $num_left--; + return(@order); + } + + sub get_permutations_left { + return $num_left; + } +} sub check_commas { my ($response)=@_; @@ -78,17 +144,16 @@ sub caparesponse_check { #type's definitons come from capaParser.h - my $message=''; + #remove leading and trailing whitespace if (!defined($response)) { $response=''; } if ($response=~ /^\s|\s$/) { $response=~ s:^\s+|\s+$::g; - $message .="Removed ws now :$response:\n"; - } else { - $message .="no ws in :$response:\n"; + &LONCAPA_INTENAL_DEBUG("Removed ws now :$response:"); } + &LONCAPA_INTERNAL_DEBUG(" type is $type "); if ($type eq 'cs' || $type eq 'ci') { #for string answers make surec all places spaces occur, there is @@ -113,7 +178,7 @@ sub caparesponse_check { if (length($response) > 500) { return "TOO_LONG: Answer too long"; } if ($type eq '' ) { - $message .= "Didn't find a type :$type: defaulting\n"; + &LONCAPA_INTERNAL_DEBUG("Didn't find a type :$type: defaulting"); if ( $answer eq ($answer *1.0)) { $type = 2; } else { $type = 3; } } else { @@ -133,7 +198,7 @@ sub caparesponse_check { #formula type setup the sample points if ($type eq '8') { ($id_list,$points)=split(/@/,$samples); - $message.="Found :$id_list:$points: points in $samples\n"; + &LONCAPA_INTERNAL_DEBUG("Found :$id_list:$points: points in $samples"); } if ($tol eq '') { $tol=0.0; @@ -185,7 +250,8 @@ sub caparesponse_check { elsif ($result =='15') { $result='UNIT_IRRECONCIBLE'; } else {$result = "ERROR: Unknown Result:$result:$@:";} - return ("$result:\nRetError $reterror:\nAnswer $answer:\nResponse $response:\n type-$type|$tol|$tol_type|$sig:$sig_lbound:$sig_ubound|$unit|\n$message",$reterror); + &LONCAPA_INTERNAL_DEBUG("RetError $reterror: Answer $answer: Response $response: type-$type|$tol|$tol_type|$sig:$sig_lbound:$sig_ubound|$unit|",$reterror); + return ($result,$reterror) } sub maxima_cas_formula_fix { @@ -229,19 +295,21 @@ sub caparesponse_check_list { &LONCAPA_INTERNAL_DEBUG("args ".join(':',%LONCAPA::CAPAresponse_args)); my @responselist; my $type = $LONCAPA::CAPAresponse_args{'type'}; - $result.="Got type :$type:\n"; - if ($type ne '' && $#LONCAPA::CAPAresponse_answer > 0) { + &LONCAPA_INTERNAL_DEBUG("Got type :$type:\n"); + my $num_answers = scalar(@{$LONCAPA::CAPAresponse_answer->{'answers'}}); + if ($type ne '' + && $num_answers > 1) { (@responselist)=split(/,/,$response); - if (@responselist < @LONCAPA::CAPAresponse_answer) { + if (@responselist < $num_answers) { return 'MISSING_ANSWER'; } - if (@responselist > @LONCAPA::CAPAresponse_answer) { + if (@responselist > $num_answers) { return 'EXTRA_ANSWER'; } } else { (@responselist)=($response); } - $result.="Initial final response :$responselist['-1']:\n"; + &LONCAPA_INTERNAL_DEBUG("Initial final response :$responselist['-1']:"); my $unit; if ($type eq '' || $type eq 'float') { #for numerical problems split off the unit @@ -250,34 +318,47 @@ sub caparesponse_check_list { $unit=$2; } } - $result.="Final final response :$responselist['-1']:$unit:\n"; + &LONCAPA_INTERNAL_DEBUG("Final final response :$responselist['-1']:$unit:"); $unit=~s/\s//; - my ($awards, @msgs, $i); - foreach my $thisanswer (@LONCAPA::CAPAresponse_answer) { - my ($msg,$aresult); - $result.="trying answer :$thisanswer:\n"; - if (defined($thisanswer)) { - if ($unit eq '') { - ($aresult,$msg)=&caparesponse_check($thisanswer, - $responselist[$i]); + #&reset_caparesponse_memoization(); + my ($final_award,$final_msg); + &init_permutation(scalar(@responselist), + $LONCAPA::CAPAresponse_answer->{'type'}); + while( &get_permutations_left() ) { + my @responses_ordered = @responselist[&get_next_permutation()]; + my (@awards, @msgs, $i); + foreach my $thisanswer (@{ $LONCAPA::CAPAresponse_answer->{'answers'} }) { + my ($msg,$aresult); + if (defined($thisanswer)) { + my $response = $responses_ordered[$i]; + if ($unit eq '') { + $response .= " $unit"; + } + ($aresult,$msg)=&caparesponse_check($thisanswer,$response); } else { - ($aresult,$msg)=&caparesponse_check($thisanswer, - $responselist[$i]." $unit"); + $aresult='ERROR'; + $msg='answer was undefined'; } + #&LONCAPA_INTERNAL_DEBUG("after if $aresult -- $msg"); + my ($temp)=split(/:/, $aresult); + push(@awards,$temp); + push(@msgs,$msg); + $i++; + } + my ($possible_award,$possible_msg) = + &LONCAPA_INTERNAL_FINALIZEAWARDS(\@awards,\@msgs); + if ($final_award) { + ($final_award,$final_msg) = + &LONCAPA_INTERNAL_FINALIZEAWARDS([$final_award,$possible_award], + [$final_msg,$possible_msg], + undef,1); } else { - $aresult='ERROR'; - $msg='answer was undefined'; + ($final_award,$final_msg) = ($possible_award,$possible_msg); } - &LONCAPA_INTERNAL_DEBUG("after if $aresult -- $msg"); - my ($temp)=split(/:/, $aresult); - $awards.="$temp,"; - $result.=$aresult; - push(@msgs,$msg); - $i++; } - chop($awards); - return ("$awards:\n$result",@msgs); + #&reset_caparesponse_memoization(); + return ($final_award,$final_msg); } sub tex {