version 1.112, 2006/07/18 15:26:23
|
version 1.117, 2006/09/29 23:10:22
|
Line 33 $pi=atan2(1,1)*4;
|
Line 33 $pi=atan2(1,1)*4;
|
$rad2deg=180.0/$pi; |
$rad2deg=180.0/$pi; |
$deg2rad=$pi/180.0; |
$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 { |
sub check_commas { |
my ($response)=@_; |
my ($response)=@_; |
Line 60 sub check_commas {
|
Line 126 sub check_commas {
|
return 1; |
return 1; |
} |
} |
|
|
|
|
sub caparesponse_check { |
sub caparesponse_check { |
my ($answer,$response)=@_; |
my ($answer,$response)=@_; |
#not properly used yet: calc |
#not properly used yet: calc |
Line 78 sub caparesponse_check {
|
Line 145 sub caparesponse_check {
|
|
|
|
|
#type's definitons come from capaParser.h |
#type's definitons come from capaParser.h |
my $message=''; |
|
#remove leading and trailing whitespace |
#remove leading and trailing whitespace |
if (!defined($response)) { |
if (!defined($response)) { |
$response=''; |
$response=''; |
} |
} |
if ($response=~ /^\s|\s$/) { |
if ($response=~ /^\s|\s$/) { |
$response=~ s:^\s+|\s+$::g; |
$response=~ s:^\s+|\s+$::g; |
$message .="Removed ws now :$response:\n"; |
#&LONCAPA_INTERNAL_DEBUG("Removed ws now :$response:"); |
} else { |
|
$message .="no ws in :$response:\n"; |
|
} |
} |
&LONCAPA_INTERNAL_DEBUG(" type is $type "); |
|
|
#&LONCAPA_INTERNAL_DEBUG(" type is $type "); |
if ($type eq 'cs' || $type eq 'ci') { |
if ($type eq 'cs' || $type eq 'ci') { |
#for string answers make surec all places spaces occur, there is |
#for string answers make surec all places spaces occur, there is |
#really only 1 space, in both the answer and the response |
#really only 1 space, in both the answer and the response |
Line 100 sub caparesponse_check {
|
Line 166 sub caparesponse_check {
|
$response=~s/[\s,]//g; |
$response=~s/[\s,]//g; |
} |
} |
if ($type eq 'float' && $unit=~/\$/) { |
if ($type eq 'float' && $unit=~/\$/) { |
if ($response!~/^\$/) { return "NO_UNIT: Missing \$ "; } |
if ($response!~/^\$/) { return ('NO_UNIT', undef); } |
$response=~s/\$//g; |
$response=~s/\$//g; |
} |
} |
if ($type eq 'float' && $unit=~/\,/ && (&check_commas($response)<0)) { |
if ($type eq 'float' && $unit=~/\,/ && (&check_commas($response)<0)) { |
Line 110 sub caparesponse_check {
|
Line 176 sub caparesponse_check {
|
$unit=~s/[\$,]//g; |
$unit=~s/[\$,]//g; |
if ($type eq 'float') { $response=~s/,//g; } |
if ($type eq 'float') { $response=~s/,//g; } |
|
|
if (length($response) > 500) { return "TOO_LONG: Answer too long"; } |
if (length($response) > 500) { return ('TOO_LONG',undef); } |
|
|
if ($type eq '' ) { |
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; |
if ( $answer eq ($answer *1.0)) { $type = 2; |
} else { $type = 3; } |
} else { $type = 3; } |
} else { |
} else { |
Line 125 sub caparesponse_check {
|
Line 191 sub caparesponse_check {
|
elsif ($type eq 'subj') { $type = 7; } |
elsif ($type eq 'subj') { $type = 7; } |
elsif ($type eq 'float') { $type = 2; } |
elsif ($type eq 'float') { $type = 2; } |
elsif ($type eq 'int') { $type = 1; } |
elsif ($type eq 'int') { $type = 1; } |
else { return "ERROR: Unknown type of answer: $type" } |
else { return ('ERROR', "Unknown type of answer: $type") } |
} |
} |
|
|
my $points; |
my $points; |
Line 133 sub caparesponse_check {
|
Line 199 sub caparesponse_check {
|
#formula type setup the sample points |
#formula type setup the sample points |
if ($type eq '8') { |
if ($type eq '8') { |
($id_list,$points)=split(/@/,$samples); |
($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 '') { |
if ($tol eq '') { |
$tol=0.0; |
$tol=0.0; |
Line 185 sub caparesponse_check {
|
Line 251 sub caparesponse_check {
|
elsif ($result =='15') { $result='UNIT_IRRECONCIBLE'; } |
elsif ($result =='15') { $result='UNIT_IRRECONCIBLE'; } |
else {$result = "ERROR: Unknown Result:$result:$@:";} |
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|"); |
|
#&LONCAPA_INTERNAL_DEBUG(" $answer $response $result "); |
|
return ($result,$reterror) |
} |
} |
|
|
sub maxima_cas_formula_fix { |
sub maxima_cas_formula_fix { |
Line 206 sub implicit_multiplication {
|
Line 274 sub implicit_multiplication {
|
# 3x10^8 -> 3&8; 3*10^-8 -> 3&-8 |
# 3x10^8 -> 3&8; 3*10^-8 -> 3&-8 |
$expression=~s/(\d+)(?:x|\*)10(?:\^|\*\*)([\+\-]*\d+)/$1\&\($2\)/gsi; |
$expression=~s/(\d+)(?:x|\*)10(?:\^|\*\*)([\+\-]*\d+)/$1\&\($2\)/gsi; |
# Fill in multiplication signs |
# Fill in multiplication signs |
# a b -> a*b |
# a b -> a*b;3 b -> 3*b;3 4 -> 3*4 |
$expression=~s/\s+/\*/gs; |
$expression=~s/(\w)\s+(\w)/$1\*$2/gs; |
# 3a -> 3*a; 3( -> 3*(; 3A -> 3*a |
# )( -> )*(; ) ( -> )*( |
$expression=~s/(\d)([a-zA-Z\(])/$1\*$2/gs; |
$expression=~s/\)\s*\(/\)\*\(/gs; |
# a3 -> a*3; )3 -> )*3 |
# 3a -> 3*a; 3( -> 3*(; 3 ( -> 3*(; 3A -> 3*A |
|
$expression=~s/(\d)\s*([a-zA-Z\(])/$1\*$2/gs; |
|
# a ( -> a*( |
|
$expression=~s/(\w)\s+\(/$1\*\(/gs; |
|
# a3 -> a*3; |
$expression=~s/([a-zA-Z])(\d)/$1\*$2/gs; |
$expression=~s/([a-zA-Z])(\d)/$1\*$2/gs; |
# )a -> )*a |
# )a -> )*a; )3 -> )*3; ) 3 -> )*3 |
$expression=~s/\)(\w)/\)\*$1/gs; |
$expression=~s/\)\s*(\w)/\)\*$1/gs; |
# 3&8 -> 3e8; 3&-4 -> 3e-4 |
# 3&8 -> 3e8; 3&-4 -> 3e-4 |
$expression=~s/(\d+)\&\(([\+\-]*\d+)\)/$1e$2/gs; |
$expression=~s/(\d+)\&\(([\+\-]*\d+)\)/$1e$2/gs; |
return $expression; |
return $expression; |
Line 225 sub caparesponse_check_list {
|
Line 297 sub caparesponse_check_list {
|
&LONCAPA_INTERNAL_DEBUG("args ".join(':',%LONCAPA::CAPAresponse_args)); |
&LONCAPA_INTERNAL_DEBUG("args ".join(':',%LONCAPA::CAPAresponse_args)); |
my @responselist; |
my @responselist; |
my $type = $LONCAPA::CAPAresponse_args{'type'}; |
my $type = $LONCAPA::CAPAresponse_args{'type'}; |
$result.="Got type :$type:\n"; |
&LONCAPA_INTERNAL_DEBUG("Got type :$type:\n"); |
if ($type ne '' && $#LONCAPA::CAPAresponse_answer > 0) { |
my $num_answers = scalar(@{$LONCAPA::CAPAresponse_answer->{'answers'}}); |
|
if ($type ne '' |
|
&& $num_answers > 1) { |
(@responselist)=split(/,/,$response); |
(@responselist)=split(/,/,$response); |
if (@responselist < @LONCAPA::CAPAresponse_answer) { |
if (@responselist < $num_answers) { |
return 'MISSING_ANSWER'; |
return 'MISSING_ANSWER'; |
} |
} |
if (@responselist > @LONCAPA::CAPAresponse_answer) { |
if (@responselist > $num_answers) { |
return 'EXTRA_ANSWER'; |
return 'EXTRA_ANSWER'; |
} |
} |
} else { |
} else { |
(@responselist)=($response); |
(@responselist)=($response); |
} |
} |
$result.="Initial final response :$responselist['-1']:\n"; |
&LONCAPA_INTERNAL_DEBUG("Initial final response :$responselist['-1']:"); |
my $unit; |
my $unit; |
if ($type eq '' || $type eq 'float') { |
if ($type eq '' || $type eq 'float') { |
#for numerical problems split off the unit |
#for numerical problems split off the unit |
Line 246 sub caparesponse_check_list {
|
Line 320 sub caparesponse_check_list {
|
$unit=$2; |
$unit=$2; |
} |
} |
} |
} |
$result.="Final final response :$responselist['-1']:$unit:\n"; |
&LONCAPA_INTERNAL_DEBUG("Final final response :$responselist['-1']:$unit:"); |
$unit=~s/\s//; |
$unit=~s/\s//; |
|
|
my ($awards, @msgs, $i); |
foreach my $thisanswer (@{ $LONCAPA::CAPAresponse_answer->{'answers'} }) { |
foreach my $thisanswer (@LONCAPA::CAPAresponse_answer) { |
if (!defined($thisanswer)) { |
my ($msg,$aresult); |
return ('ERROR','answer was undefined'); |
$result.="trying answer :$thisanswer:\n"; |
} |
if (defined($thisanswer)) { |
} |
if ($unit eq '') { |
|
($aresult,$msg)=&caparesponse_check($thisanswer, |
if ($unit ne '') { |
$responselist[$i]); |
foreach my $response (@responselist) { |
} else { |
$response .= " $unit"; |
($aresult,$msg)=&caparesponse_check($thisanswer, |
} |
$responselist[$i]." $unit"); |
} |
|
|
|
my %memoized; |
|
if ($LONCAPA::CAPAresponse_answer->{'type'} eq 'ordered') { |
|
for (my $i=0; $i<scalar(@responselist);$i++) { |
|
my $answer = $LONCAPA::CAPAresponse_answer->{'answers'}[$i]; |
|
my $response = $responselist[$i]; |
|
my $key = "$answer\0$response"; |
|
$memoized{$key} = [&caparesponse_check($answer, $response)]; |
|
} |
|
} else { |
|
foreach my $response (@responselist) { |
|
foreach my $answer (@{ $LONCAPA::CAPAresponse_answer->{'answers'} }) { |
|
my $key = "$answer\0$response"; |
|
$memoized{$key} = [&caparesponse_check($answer, $response)]; |
} |
} |
} else { |
|
$aresult='ERROR'; |
|
$msg='answer was undefined'; |
|
} |
} |
&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); |
my ($final_award,$final_msg); |
|
&init_permutation(scalar(@responselist), |
|
$LONCAPA::CAPAresponse_answer->{'type'}); |
|
|
|
my (@final_awards,@final_msg); |
|
while( &get_permutations_left() ) { |
|
my $order = &get_next_permutation(); |
|
my (@awards, @msgs, $i); |
|
foreach my $thisanswer (@{ $LONCAPA::CAPAresponse_answer->{'answers'} }) { |
|
my $key = "$thisanswer\0".$responselist[$order->[$i]]; |
|
push(@awards,$memoized{$key}[0]); |
|
push(@msgs,$memoized{$key}[1]); |
|
$i++; |
|
} |
|
my ($possible_award,$possible_msg) = |
|
&LONCAPA_INTERNAL_FINALIZEAWARDS(\@awards,\@msgs); |
|
push(@final_awards,$possible_award); |
|
push(@final_msg,$possible_msg); |
|
} |
|
|
|
my ($final_award,$final_msg) = |
|
&LONCAPA_INTERNAL_FINALIZEAWARDS(\@final_awards,\@final_msg,undef,1); |
|
return ($final_award,$final_msg); |
} |
} |
|
|
sub tex { |
sub tex { |