--- loncom/homework/default_homework.lcpm 2004/10/11 16:31:34 1.90
+++ loncom/homework/default_homework.lcpm 2006/06/30 21:24:27 1.108
@@ -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.90 2004/10/11 16:31:34 albertel Exp $
+# $Id: default_homework.lcpm,v 1.108 2006/06/30 21:24:27 www Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -34,6 +34,32 @@ $rad2deg=180.0/$pi;
$deg2rad=$pi/180.0;
$"=' ';
+sub check_commas {
+ my ($response)=@_;
+ #print("$response ");
+ my @numbers=split(',',$response);
+ #print(" numbers ".join('-',@numbers)." ");
+ if (scalar(@numbers) > 1) {
+ #print(" numbers[0] ".$numbers[0]." ");
+ if (length($numbers[0]) > 3 || length($numbers[0]) == 0) { return -1; }
+ shift(@numbers);
+ #print(" numbers ".scalar(@numbers)." ");
+ while (scalar(@numbers) > 1) {
+ #print(" numbers ".join('-',@numbers)." ");
+ if (length($numbers[0]) != 3) { return -2; }
+ shift(@numbers);
+ }
+ my ($number)=split('\.',$numbers[0]);
+ #print(" number ".$number." ");
+ #print(" numbers[0] ".$numbers[0]." ");
+ if (length($number) != 3) { return -3; }
+ } else {
+ my ($number)=split('\.',$numbers[0]);
+ if (length($number) > 3) { return -4; }
+ }
+ return 1;
+}
+
sub caparesponse_check {
my ($answer,$response)=@_;
#not properly used yet: calc
@@ -63,18 +89,26 @@ sub caparesponse_check {
} else {
$message .="no ws in :$response:\n";
}
- if ($type eq 'cs' || $type eq 'ci' || $type eq 'mc') {
+ &LONCAPA_INTERNAL_DEBUG(" type is $type ");
+ if ($type eq 'cs' || $type eq 'ci') {
#for string answers make surec all places spaces occur, there is
#really only 1 space, in both the answer and the response
$answer=~s/ +/ /g;
$response=~s/ +/ /g;
+ } elsif ($type eq 'mc') {
+ $answer=~s/[\s,]//g;
+ $response=~s/[\s,]//g;
}
- if ($type eq 'float') { $response=~s/,//g; }
- if ($type eq 'float' && $ans_fmt=~/\$/) {
+ if ($type eq 'float' && $unit=~/\$/) {
if ($response!~/^\$/) { return "NO_UNIT: Missing \$ "; }
$response=~s/\$//g;
}
+ if ($type eq 'float' && $unit=~/\,/ && (&check_commas($response)<0)) {
+ return "COMMA_FAIL:";
+ }
$ans_fmt=~s/\W//g;
+ $unit=~s/[\$,]//g;
+ if ($type eq 'float') { $response=~s/,//g; }
if (length($response) > 500) { return "TOO_LONG: Answer too long"; }
@@ -83,10 +117,11 @@ sub caparesponse_check {
if ( $answer eq ($answer *1.0)) { $type = 2;
} else { $type = 3; }
} else {
- if ($type eq 'cs') { $type = 4; }
+ if ($type eq 'cs') { $type = 4; }
elsif ($type eq 'ci') { $type = 3 }
elsif ($type eq 'mc') { $type = 5; }
elsif ($type eq 'fml') { $type = 8; }
+ elsif ($type eq 'math') { $type = 9; }
elsif ($type eq 'subj') { $type = 7; }
elsif ($type eq 'float') { $type = 2; }
elsif ($type eq 'int') { $type = 1; }
@@ -115,13 +150,17 @@ sub caparesponse_check {
($sig_ubound,$sig_lbound)=&LONCAPA_INTERNAL_get_sigrange($sig);
my $reterror="";
- my $result = &caparesponse_capa_check_answer($response,$answer,$type,
+ my $result;
+ if ($type eq '9') {
+ $result = &maxima_check(&maxima_cas_formula_fix($response),&maxima_cas_formula_fix($answer),\$reterror);
+ } else {
+ $result = &caparesponse_capa_check_answer(&capa_formula_fix($response),&capa_formula_fix($answer),$type,
$tol_type,$tol,
$sig_lbound,$sig_ubound,
$ans_fmt,$unit,$calc,$id_list,
$points,$external::randomseed,
\$reterror);
-
+ }
if ($result == '1') { $result='EXACT_ANS'; }
elsif ($result == '2') { $result='APPROX_ANS'; }
elsif ($result == '3') { $result='SIG_FAIL'; }
@@ -133,6 +172,8 @@ sub caparesponse_check {
elsif ($result == '9') { $result='ANS_CNT_NOT_MATCH'; }
elsif ($result =='10') { $result='SUB_RECORDED'; }
elsif ($result =='11') { $result='BAD_FORMULA'; }
+ elsif ($result =='12' && !$response) { $result='MISSING_ANSWER'; }
+ elsif ($result =='12') { $result='WANTED_NUMERIC'; }
elsif ($result =='13') { $result='UNIT_INVALID_INSTRUCTOR'; }
elsif ($result =='141') { $result='UNIT_INVALID_STUDENT'; }
elsif ($result =='142') { $result='UNIT_INVALID_STUDENT'; }
@@ -143,26 +184,44 @@ sub caparesponse_check {
return ("$result:\nRetError $reterror:\nAnswer $answer:\nResponse $response:\n type-$type|$tol|$tol_type|$sig:$sig_lbound:$sig_ubound|$unit|\n$message",$reterror);
}
+sub maxima_cas_formula_fix {
+ my ($expression)=@_;
+ return &implicit_multiplication($expression);
+}
+
+sub capa_formula_fix {
+ my ($expression)=@_;
+ return &implicit_multiplication($expression);
+}
+
+sub implicit_multiplication {
+ my ($expression)=@_;
+ $expression=~s/\s+/\*/g;
+ $expression=~s/(\d)([a-zA-Z\(])/$1\*$2/g;
+ $expression=~s/\)(\w)/\)\*$1/g;
+ return $expression;
+}
sub caparesponse_check_list {
my $response=$LONCAPA::CAPAresponse_args{'response'};
- my ($result,@list);
- @list=@LONCAPA::CAPAresponse_answer;
- my $aresult='';
- my $current_answer;
- my $answers=join(':',@list);
- $result.="Got response :$answers:\n";
- &LONCAPA_INTERNAL_DEBUG(" got ".join(':',%LONCAPA::CAPAresponse_args));
+ my $result="Got response :".join(':',@LONCAPA::CAPAresponse_answer).":\n";
+ &LONCAPA_INTERNAL_DEBUG("args ".join(':',%LONCAPA::CAPAresponse_args));
my @responselist;
my $type = $LONCAPA::CAPAresponse_args{'type'};
$result.="Got type :$type:\n";
- if ($type ne '' && $#list > 0) {
- (@responselist)=split /,/,$response;
+ if ($type ne '' && $#LONCAPA::CAPAresponse_answer > 0) {
+ (@responselist)=split(/,/,$response);
+ if (@responselist < @LONCAPA::CAPAresponse_answer) {
+ return 'MISSING_ANSWER';
+ }
+ if (@responselist > @LONCAPA::CAPAresponse_answer) {
+ return 'EXTRA_ANSWER';
+ }
} else {
(@responselist)=($response);
}
- my $unit='';
$result.="Initial final response :$responselist['-1']:\n";
+ my $unit;
if ($type eq '' || $type eq 'float') {
#for numerical problems split off the unit
if ( $responselist['-1']=~ /(.*[^\s])\s+([^\s]+)/ ) {
@@ -171,28 +230,32 @@ sub caparesponse_check_list {
}
}
$result.="Final final response :$responselist['-1']:$unit:\n";
- $result.=":$#list: answers\n";
$unit=~s/\s//;
- my $i=0;
- my $awards='';
- my @msgs;
- for ($i=0; $i<@list;$i++) {
- my $msg;
- $result.="trying answer :$list[$i]:\n";
- my $thisanswer=$list[$i];
+
+ my ($awards, @msgs, $i);
+ foreach my $thisanswer (@LONCAPA::CAPAresponse_answer) {
+ my ($msg,$aresult);
$result.="trying answer :$thisanswer:\n";
- if ($unit eq '') {
- ($aresult,$msg)=&caparesponse_check($thisanswer,$responselist[$i]);
+ if (defined($thisanswer)) {
+ if ($unit eq '') {
+ ($aresult,$msg)=&caparesponse_check($thisanswer,
+ $responselist[$i]);
+ } else {
+ ($aresult,$msg)=&caparesponse_check($thisanswer,
+ $responselist[$i]." $unit");
+ }
} else {
- ($aresult,$msg)=&caparesponse_check($thisanswer,
- $responselist[$i]." $unit");
+ $aresult='ERROR';
+ $msg='answer was undefined';
}
- my ($temp)=split /:/, $aresult;
+ &LONCAPA_INTERNAL_DEBUG("after if $aresult -- $msg");
+ my ($temp)=split(/:/, $aresult);
$awards.="$temp,";
$result.=$aresult;
push(@msgs,$msg);
+ $i++;
}
- chop $awards;
+ chop($awards);
return ("$awards:\n$result",@msgs);
}
@@ -415,14 +478,14 @@ sub random_negative_binomial {
return @retArray;
}
-sub abs { abs(shift) }
-sub sin { sin(shift) }
-sub cos { cos(shift) }
-sub exp { exp(shift) }
-sub int { int(shift) }
-sub log { log(shift) }
-sub atan2 { atan2($_[0],$_[1]) }
-sub sqrt { sqrt(shift) }
+sub abs { CORE::abs(shift) }
+sub sin { CORE::sin(shift) }
+sub cos { CORE::cos(shift) }
+sub exp { CORE::exp(shift) }
+sub int { CORE::int(shift) }
+sub log { CORE::log(shift) }
+sub atan2 { CORE::atan2($_[0],$_[1]) }
+sub sqrt { CORE::sqrt(shift) }
sub tan { CORE::sin($_[0]) / CORE::cos($_[0]) }
#sub atan { atan2($_[0], 1); }
@@ -486,10 +549,15 @@ sub format {
#if ($options =~ /\$/) { $dollamode=1; }
#if ($options =~ /,/) { $commamode=1; }
if ($options =~ /\./) { $alwaysperiod=1; }
- $fmt=~s/e/E/g;
- my $result=sprintf('%.'.$fmt,$value);
- if ($alwaysperiod && $fmt eq '0f') { $result .='.'; }
- $result=~s/(E[+-]*)0/$1/;
+ my $result;
+ if ($fmt=~/s$/i) {
+ $result=&format_significant_figures($value,$fmt);
+ } else {
+ $fmt=~s/e/E/g;
+ $result=sprintf('%.'.$fmt,$value);
+ if ($alwaysperiod && $fmt eq '0f') { $result .='.'; }
+ $result=~s/(E[+-]*)0/$1/;
+ }
#if ($dollarmode) {$result=&dollarformat($result);}
#if ($commamode) {$result=&commaformat($result);}
return $result;
@@ -497,24 +565,33 @@ sub format {
sub chemparse {
my ($reaction) = @_;
- my @tokens = split(/(\s\+|\->|<=>)/,$reaction);
+ my @tokens = split(/(\s\+|\->|<=>|<\-|\.)/,$reaction);
my $formula = '';
foreach my $token (@tokens) {
if ($token eq '->' ) {
$formula .= '
The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.
More information about this error may be available in the server error log.