--- loncom/homework/default_homework.lcpm 2004/03/16 15:31:52 1.73 +++ loncom/homework/default_homework.lcpm 2004/10/05 20:18:29 1.88 @@ -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.73 2004/03/16 15:31:52 albertel Exp $ +# $Id: default_homework.lcpm,v 1.88 2004/10/05 20:18:29 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -26,12 +26,7 @@ # http://www.lon-capa.org/ # # -# Guy Albertelli -# -# 05/25/2001 H. K. Ng -# 05/31/2001 H. K. Ng -# 12/21/2001 Matthew -# + #init some globals $hidden::RANDOMINIT=0; $pi=atan2(1,1)*4; @@ -40,16 +35,20 @@ $deg2rad=$pi/180.0; $"=' '; sub caparesponse_check { + my ($answer,$response)=@_; #not properly used yet: calc #not to be used: $ans_fmt - my ($type,$tol,$sig,$ans_fmt,$unit,$calc,$samples) = - eval $_[2]. - ';return ($__LC__type,$__LC__tol,$__LC__sig,$__LC__ans_fmt,$__LC__unit,$__LC__calc,$__LC__samples);'; + my $type=$LONCAPA::CAPAresponse_args{'type'}; + my $tol=$LONCAPA::CAPAresponse_args{'tol'}; + my $sig=$LONCAPA::CAPAresponse_args{'sig'}; + my $ans_fmt=$LONCAPA::CAPAresponse_args{'format'}; + my $unit=$LONCAPA::CAPAresponse_args{'unit'}; + my $calc=$LONCAPA::CAPAresponse_args{'calc'}; + my $samples=$LONCAPA::CAPAresponse_args{'samples'}; my $tol_type=''; # gets it's value from whether tol has a % or not done my $sig_lbound=''; #done my $sig_ubound=''; #done - my ($answer,$response,$expr)=@_; #type's definitons come from capaParser.h @@ -64,11 +63,24 @@ sub caparesponse_check { } else { $message .="no ws in :$response:\n"; } + if ($type eq 'cs' || $type eq 'ci' || $type eq 'mc') { + #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; + } + if ($type eq 'float') { $response=~s/,//g; } + &LONCAPA_INTERNAL_DEBUG("fmt $ans_fmt, res is $response"); + if ($type eq 'float' && $ans_fmt=~/\$/) { + if ($response!~/^\$/) { return "NO_UNIT: Missing \$ "; } + $response=~s/\$//g; + } + $ans_fmt=~s/\W//g; if (length($response) > 500) { return "TOO_LONG: Answer too long"; } if ($type eq '' ) { - $message .= "Didn't find a type :$type:$expr: defaulting\n"; + $message .= "Didn't find a type :$type: defaulting\n"; if ( $answer eq ($answer *1.0)) { $type = 2; } else { $type = 3; } } else { @@ -101,17 +113,8 @@ sub caparesponse_check { } } - if ($sig eq '') { - $sig_lbound = 0; #SIG_LB_DEFAULT - $sig_ubound =15; #SIG_UB_DEFAULT - } else { - ($sig_lbound,$sig_ubound) = split /,/,$sig; - if (!defined($sig_lbound)) { - $sig_lbound = 0; #SIG_LB_DEFAULT - $sig_ubound =15; #SIG_UB_DEFAULT - } - if (!defined($sig_ubound)) { $sig_ubound=$sig_lbound; } - } + ($sig_ubound,$sig_lbound)=&LONCAPA_INTERNAL_get_sigrange($sig); + my $reterror=""; my $result = &caparesponse_capa_check_answer($response,$answer,$type, $tol_type,$tol, @@ -131,23 +134,28 @@ 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') { $result='WANTED_NUMERIC'; } + elsif ($result =='13') { $result='UNIT_INVALID_INSTRUCTOR'; } + elsif ($result =='141') { $result='UNIT_INVALID_STUDENT'; } + elsif ($result =='142') { $result='UNIT_INVALID_STUDENT'; } + elsif ($result =='143') { $result='UNIT_INVALID_STUDENT'; } + elsif ($result =='15') { $result='UNIT_IRRECONCIBLE'; } else {$result = "ERROR: Unknown Result:$result:$@:";} - return ("$result:\nRetError $reterror:\nError $error:\nAnswer $answer:\nResponse $response:\n type-$type|$tol|$tol_type|$sig:$sig_lbound:$sig_ubound|$unit|\n$message$expr",$reterror); + return ("$result:\nRetError $reterror:\nAnswer $answer:\nResponse $response:\n type-$type|$tol|$tol_type|$sig:$sig_lbound:$sig_ubound|$unit|\n$message",$reterror); } sub caparesponse_check_list { - my ($response,$expr)=@_; + my $response=$LONCAPA::CAPAresponse_args{'response'}; my ($result,@list); - @list=@CAPARESPONSE_CHECK_LIST_answer; + @list=@LONCAPA::CAPAresponse_answer; my $aresult=''; my $current_answer; my $answers=join(':',@list); $result.="Got response :$answers:\n"; + &LONCAPA_INTERNAL_DEBUG("Yo! got ".join(':',%LONCAPA::CAPAresponse_args)); my @responselist; - my $type =eval $expr.';return $__LC__type;'; + my $type = $LONCAPA::CAPAresponse_args{'type'}; $result.="Got type :$type:\n"; if ($type ne '' && $#list > 0) { (@responselist)=split /,/,$response; @@ -163,7 +171,7 @@ sub caparesponse_check_list { $unit=$2; } } - $result.="Final final response :$responselist['-1']:\n"; + $result.="Final final response :$responselist['-1']:$unit:\n"; $result.=":$#list: answers\n"; $unit=~s/\s//; my $i=0; @@ -175,12 +183,10 @@ sub caparesponse_check_list { my $thisanswer=$list[$i]; $result.="trying answer :$thisanswer:\n"; if ($unit eq '') { - ($aresult,$msg)=&caparesponse_check($thisanswer,$responselist[$i], - $expr); + ($aresult,$msg)=&caparesponse_check($thisanswer,$responselist[$i]); } else { ($aresult,$msg)=&caparesponse_check($thisanswer, - $responselist[$i]." $unit", - $expr); + $responselist[$i]." $unit"); } my ($temp)=split /:/, $aresult; $awards.="$temp,"; @@ -234,7 +240,10 @@ sub random { if ( ! $hidden::RANDOMINIT ) { if ($external::randomseed == 0) { $external::randomseed=1; } if ($external::randomseed =~/,/) { - my ($num1,$num2)=split(/,/,$seed); + my ($num1,$num2)=split(/,/,$external::randomseed); + &random_set_seed(1,abs($num1)); + } elsif ($external::randomseed =~/:/) { + my ($num1,$num2)=split(/:/,$external::randomseed); &random_set_seed(abs($num1),abs($num2)); } else { &random_set_seed(1,int(abs($external::randomseed))); @@ -342,7 +351,7 @@ sub random_multivariate_normal { my ($item_cnt,$seed,$mean,$covar) = @_; my @oldseed=&random_get_seed(); &random_set_seed_from_phrase($seed); - @retArray=&math_random_multivariate_normal($item_cnt,@$mean,@$covar); + my @retArray=&math_random_multivariate_normal($item_cnt,@$mean,@$covar); &random_set_seed(@oldseed); return @retArray; } @@ -352,7 +361,7 @@ sub random_multinomial { my @oldseed=&random_get_seed(); my @retArray; &random_set_seed_from_phrase($seed); - @retArray=&math_random_multinomial($item_cnt,@p); + my @retArray=&math_random_multinomial($item_cnt,@p); &random_set_seed(@oldseed); return @retArray; } @@ -473,25 +482,82 @@ sub floor {return (($_[0]-CORE::int($_[ sub format { my ($value,$fmt)=@_; - my $dollarmode; - if ($fmt =~ /^\$(.*)/) { $fmt=$1; $dollarmode=1; } + my ($dollarmode,$commamode,$alwaysperiod,$options); + if ($fmt =~ /^([^\d]*)(.*)/) { $options=$1; $fmt=$2; } + #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/; - if ($dollarmode) {$result=&dollarmode($result);} + #if ($dollarmode) {$result=&dollarformat($result);} + #if ($commamode) {$result=&commaformat($result);} return $result; } +sub chemparse { + my ($reaction) = @_; + my @tokens = split(/(\s\+|\->|<=>)/,$reaction); + my $formula = ''; + foreach my $token (@tokens) { + if ($token eq '->' ) { + $formula .= '\ensuremath{\rightarrow} '; + next; + } + if ($token eq '<=>') { + if ($external::target eq 'web' && + &EXT('request.browser.unicode')) { + $formula .= '⇌ '; + } else { + $formula .= &web('<=> ','\ensuremath{\rightleftharpoons} ', + '<=$gt; '); + } + next; + } + $token =~ /^\s*(\d*)(.*)/; + $formula .= $1 if ($1 > 1); # stoichiometric coefficient + + my $molecule = $2; + # subscripts + $molecule =~ s|(?<=[a-zA-Z\)\]\s])(\d+)|$1|g; + # superscripts + $molecule =~ s|\^(\d*[+\-]*)|$1|g; + # strip whitespace + $molecule =~ s/\s*//g; + # forced space + $molecule =~ s/_/ /g; + $formula .= $molecule.' '; + } + # get rid of trailing space + $formula =~ s/(\ \;| )$//; + + return &xmlparse($formula); +} + sub prettyprint { my ($value,$fmt,$target)=@_; + &LONCAPA_INTERNAL_DEBUG("format -$fmt-"); my $result; - my $dollarmode; if (!$target) { $target = $external::target; } - if ($fmt =~ /^\$(.*)/) { $fmt=$1; $dollarmode=1; } + if ($fmt =~ /chem/i) { return(&chemparse($value)); } + my ($dollarmode,$commamode,$alwaysperiod,$options); + if ($fmt =~ /^([^\d]*)(.*)/) { $options=$1; $fmt=$2; } + if ($options =~ /\$/) { $dollarmode=1; } + if ($options =~ /,/) { $commamode=1; } + if ($options =~ /\./) { $alwaysperiod=1; } if ($fmt) { $value=sprintf('%.'.$fmt,$value); } + if ($alwaysperiod && $fmt eq '0f') { + if ($target eq 'tex') { + $value .='\\ensuremath{.}'; + } else { + $value .='.'; + } + } if ($value =~ /([0-9\.\-\+]+)E([0-9\-\+]+)/i ) { my $frac=$1; if ($dollarmode) { $frac=&dollarformat($frac); } + if ($commamode) { $frac=&commaformat($frac); } my $exponent=$2; $exponent=~s/^\+0*//; $exponent=~s/^-0*/-/; @@ -510,14 +576,14 @@ sub prettyprint { } } else { $result=$value; - if ($dollarmode) { $result=&dollarformat($result,$target); } + if ($dollarmode) { $result=&dollarformat($result,$target); } + elsif ($commamode) { $result=&commaformat($result,$target); } } return $result; } -sub dollarformat { +sub commaformat { my ($number,$target) = @_; - if (!$target) { $target = $external::target; } if ($number =~ /\./) { while ($number =~ /([^\.,]+)([^\.,][^\.,][^\.,])([,0-9]*\.[0-9]*)$/) { $number = $1.','.$2.$3; @@ -527,6 +593,13 @@ sub dollarformat { $number = $1.','.$2.$3; } } + return $number; +} + +sub dollarformat { + my ($number,$target) = @_; + if (!$target) { $target = $external::target; } + $number=&commaformat($number,$target); if ($target eq 'tex') { $number='\$'.$number; #' stupid emacs } else {