[$j] =~ /[\000-\037]/) {
+ $response->[$j] =~ s/[\000-\037]//g;
+ $control_chars_removed = 1;
+ }
+ }
+ }
+ my ($award,$msg) = &caparesponse_check($answer->[$j],
+ $response->[$j]);
+ if ($type eq 'cs' || $type eq 'ci') {
+ $error = &verify_stringresponse($type,$award,$response->[$j],
+ $answer->[$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(@$responses),
+ $LONCAPA::CAPAresponse_answer->{'type'});
+
+ # possible FIXMEs
+ # - significant time is spent calling non-safe space routine
+ # from safe space
+ # - early outs could be possible with classifying awards is to stratas
+ # and stopping as so as hitting the top strata
+ # - some early outs also might be possible with check ing the
+ # memoized hash of results (is correct even possible? etc.)
+
+ 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".$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,$error,$control_chars_removed,$ansstring);
+}
+
+sub verify_stringresponse {
+ my ($type,$award,$resp,$ans) = @_;
+ return if ($award eq 'EXACT_ANS');
+ my $error;
+ if ($resp =~ /^\s|\s$/) {
+ $resp =~ s{^\s+|\s+$}{}g;
+ }
+ if ($ans =~ /^\s|\s$/) {
+ $ans =~ s{^\s+|\s+$}{}g;
+ }
+ if ($type eq 'ci') {
+ $resp = lc($resp);
+ $ans = lc($ans);
+ }
+ if ($resp eq $ans) {
+ if ($award eq 'INCORRECT') {
+ $error = 'MISGRADED';
+ }
+ }
+ return $error;
+}
+
+sub cas {
+ my ($system,$input,$library)=@_;
+ my $output;
+ my $dump;
+ if ($system eq 'maxima') {
+ $output=&maxima_eval($input,$library);
+ } elsif ($system eq 'R') {
+ ($output,$dump)=&r_eval($input,$library,0);
+ } else {
+ $output='Error: unrecognized CAS';
+ }
+ return $output;
+}
+
+sub cas_hashref {
+ my ($system,$input,$library)=@_;
+ if ($system eq 'maxima') {
+ return 'Error: unsupported CAS';
+ } elsif ($system eq 'R') {
+ return &r_eval($input,$library,1);
+ } else {
+ return 'Error: unrecognized CAS';
+ }
+}
+
+#
+# cas_hashref_entry takes a list of indices and gets the entry in a hash generated by Rreturn.
+# Call: cas_hashref_entry(Rvalue, index1, index2, ...) where Rvalue is a hash returned by Rreturn.
+# Rentry will return the first scalar value it encounters (ignoring excess indices).
+# If an invalid key is given, it returns undef.
+#
+sub cas_hashref_entry {
+ return &Rentry(@_);
+}
+
+#
+# cas_hashref_array takes a list of indices and gets a column array from a hash generated by Rreturn.
+# Call: cas_hashref_array(Rvalue, index1, index2, ...) where Rvalue is a hash returned by Rreturn.
+# If an invalid key is given, it returns undef.
+#
+sub cas_hashref_array {
+ return &Rarray(@_);
}
sub tex {
- if ( $external::target eq "tex" ) {
- return @_[0];
- } else {
- return @_[1];
- }
+ if ( $external::target eq "tex" ) {
+ return $_[0];
+ } else {
+ return $_[1];
+ }
}
sub var_in_tex {
- if ( $external::target eq "tex" ) {
- return @_[0];
- } else {
- return "";
- }
+ if ( $external::target eq "tex" ) {
+ return $_[0];
+ } else {
+ return "";
+ }
}
sub web {
- if ( $external::target eq "tex" ) {
- return @_[1];
- } else {
- if ( $external::target eq "web" || $external::target eq "answer") {
- return @_[2];
+ if ( $external::target eq "tex" ) {
+ return $_[1];
} else {
- return @_[0];
+ if ( $external::target eq "web" || $external::target eq "answer") {
+ return $_[2];
+ } else {
+ return $_[0];
+ }
}
- }
}
sub html {
- if ( $external::target eq "web" ) {
- return shift;
- }
-}
-
-sub problem {
- return '1';
+ if ( $external::target eq "web" ) {
+ return shift;
+ }
}
sub hinton {
- return 0;
+ return 0;
}
sub random {
- my ($start,$end,$step)=@_;
- if ( ! $hidden::RANDOMINIT ) {
- srand($external::randomseed);
- $hidden::RANDOMINIT=1;
- }
- my $num=1+int(($end-$start)/$step);
- my $result=$start + int(rand() * $num)*$step;
- return $result;
+ my ($start,$end,$step)=@_;
+ if ( ! $hidden::RANDOMINIT ) {
+ if ($external::randomseed == 0) { $external::randomseed=1; }
+ if ($external::randomseed =~/,/) {
+ 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)));
+ }
+ &math_random_uniform();
+ $hidden::RANDOMINIT=1;
+ }
+ if (!defined($step)) { $step=1; }
+ my $num=1+int(($end-$start)/$step);
+ my $result=$start + int(&math_random_uniform() * $num)*$step;
+ return $result;
}
sub random_normal {
- my ($item_cnt,$seed,$av,$std_dev) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_normal($item_cnt,$av,$std_dev);
- return @retArray;
+ my ($item_cnt,$seed,$av,$std_dev) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_normal($item_cnt,$av,$std_dev);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_beta {
- my ($item_cnt,$seed,$aa,$bb) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_beta($item_cnt,$aa,$bb);
- return @retArray;
+ my ($item_cnt,$seed,$aa,$bb) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_beta($item_cnt,$aa,$bb);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_gamma {
- my ($item_cnt,$seed,$a,$r) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_gamma($item_cnt,$a,$r);
- return @retArray;
+ my ($item_cnt,$seed,$a,$r) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_gamma($item_cnt,$a,$r);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_exponential {
- my ($item_cnt,$seed,$av) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_exponential($item_cnt,$av);
- return @retArray;
+ my ($item_cnt,$seed,$av) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_exponential($item_cnt,$av);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_poisson {
- my ($item_cnt,$seed,$mu) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_poisson($item_cnt,$mu);
- return @retArray;
+ my ($item_cnt,$seed,$mu) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_poisson($item_cnt,$mu);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_chi {
- my ($item_cnt,$seed,$df) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_chi_square($item_cnt,$df);
- return @retArray;
+ my ($item_cnt,$seed,$df) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_chi_square($item_cnt,$df);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_noncentral_chi {
- my ($item_cnt,$seed,$df,$nonc) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_noncentral_chi_square($item_cnt,$df,$nonc);
- return @retArray;
+ my ($item_cnt,$seed,$df,$nonc) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_noncentral_chi_square($item_cnt,$df,$nonc);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_f {
- my ($item_cnt,$seed,$dfn,$dfd) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_f($item_cnt,$dfn,$dfd);
- return @retArray;
+ my ($item_cnt,$seed,$dfn,$dfd) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_f($item_cnt,$dfn,$dfd);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_noncentral_f {
- my ($item_cnt,$seed,$dfn,$dfd,$nonc) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_noncentral_f($item_cnt,$dfn,$dfd,$nonc);
- return @retArray;
+ my ($item_cnt,$seed,$dfn,$dfd,$nonc) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_noncentral_f($item_cnt,$dfn,$dfd,$nonc);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_multivariate_normal {
- my ($item_cnt,$seed,$mean,$covar) = @_;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_multivariate_normal($item_cnt,@$mean,@$covar);
- return @retArray;
+ my ($item_cnt,$seed,$mean,$covar) = @_;
+ my @oldseed=&random_get_seed();
+ &random_set_seed_from_phrase($seed);
+ my @retArray=&math_random_multivariate_normal($item_cnt,@$mean,@$covar);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_multinomial {
- my ($item_cnt,$seed,@p) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_multinomial($item_cnt,@p);
- return @retArray;
+ my ($item_cnt,$seed,@p) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ my @retArray=&math_random_multinomial($item_cnt,@p);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_permutation {
- my ($seed,@inArray) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_permutation(@inArray);
- return @retArray;
+ my ($seed,@inArray) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_permutation(@inArray);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_uniform {
- my ($item_cnt,$seed,$low,$high) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_uniform($item_cnt,$low,$high);
- return @retArray;
+ my ($item_cnt,$seed,$low,$high) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_uniform($item_cnt,$low,$high);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_uniform_integer {
- my ($item_cnt,$seed,$low,$high) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_uniform_integer($item_cnt,$low,$high);
- return @retArray;
+ my ($item_cnt,$seed,$low,$high) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_uniform_integer($item_cnt,$low,$high);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_binomial {
- my ($item_cnt,$seed,$nt,$p) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_binomial($item_cnt,$nt,$p);
- return @retArray;
+ my ($item_cnt,$seed,$nt,$p) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_binomial($item_cnt,$nt,$p);
+ &random_set_seed(@oldseed);
+ return @retArray;
}
sub random_negative_binomial {
- my ($item_cnt,$seed,$ne,$p) = @_;
- my @retArray;
- &random_set_seed_from_phrase($seed);
- @retArray=&math_random_negative_binomial($item_cnt,$ne,$p);
- 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) }
+ my ($item_cnt,$seed,$ne,$p) = @_;
+ my @oldseed=&random_get_seed();
+ my @retArray;
+ &random_set_seed_from_phrase($seed);
+ @retArray=&math_random_negative_binomial($item_cnt,$ne,$p);
+ &random_set_seed(@oldseed);
+ return @retArray;
+}
+
+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 { sin($_[0]) / cos($_[0]) }
+sub tan { CORE::sin($_[0]) / CORE::cos($_[0]) }
#sub atan { atan2($_[0], 1); }
#sub acos { atan2(sqrt(1 - $_[0] * $_[0]), $_[0] ); }
#sub asin { atan2($_[0], sqrt(1- $_[0] * $_[0]) ); }
-sub log10 { log($_[0])/log(10); }
+sub log10 { CORE::log($_[0])/CORE::log(10); }
sub factorial {
- my $input = int(shift);
+ my $input = CORE::int(shift);
return "Error - unable to take factorial of an negative number ($input)" if $input < 0;
return "Error - factorial result is greater than system limit ($input)" if $input > 170;
return 1 if $input == 0;
@@ -428,17 +852,193 @@ sub sub_string {
}
sub pow {return $_[0] ** $_[1]; }
-sub ceil {return (($_[0]-int($_[0]))== 0.0) ? $_[0] : (($_[0] > 0) ? (int($_[0])+ 1) : int($_[0])); }
-sub floor {return (($_[0]-int($_[0]))== 0.0) ? $_[0] : (($_[0] > 0) ? int($_[0]) : (int($_[0])-1)); }
+sub ceil {return (($_[0]-CORE::int($_[0]))== 0.0) ? $_[0] : (($_[0] > 0) ? (CORE::int($_[0])+ 1) : CORE::int($_[0])); }
+sub floor {return (($_[0]-CORE::int($_[0]))== 0.0) ? $_[0] : (($_[0] > 0) ? CORE::int($_[0]) : (CORE::int($_[0])-1)); }
#sub floor {return int($_[0]); }
sub format {
- my ($value,$fmt)=@_;
- return sprintf('%.'.$fmt,$value);
+ my ($value,$fmt)=@_;
+ my ($dollarmode,$commamode,$alwaysperiod,$options);
+ if ($fmt =~ /^([^\d]*)(.*)/) { $options=$1; $fmt=$2; }
+ #if ($options =~ /\$/) { $dollamode=1; }
+ #if ($options =~ /,/) { $commamode=1; }
+ if ($options =~ /\./) { $alwaysperiod=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;
+}
+
+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 '<-' ) {
+ $formula .= '\ensuremath{\leftarrow} ';
+ next;
+ }
+ if ($token eq '<=>') {
+ if ($external::target eq 'web' &&
+ &EXT('request.browser.unicode')) {
+ $formula .= '⇌ ';
+ } else {
+ $formula .= &web('<=> ','\ensuremath{\rightleftharpoons} ',
+ '<=> ');
+ }
+ next;
+ }
+ if ($token eq '.') {
+ $formula =~ s/(\ \;| )$//;
+ $formula .= '·';
+ next;
+ }
+ $token =~ /^\s*([\d|\/]*(?:&frac\d\d)?)(.*)/;
+ $formula .= $1 if ($1 ne '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;
+ $molecule =~ s/-/−/g;
+ $formula .= $molecule.' ';
+ }
+ # get rid of trailing space
+ $formula =~ s/(\ \;| )$//;
+ return &xmlparse($formula);
+}
+
+sub prettyprint {
+ my ($value,$fmt,$target)=@_;
+ my $result;
+ if (!$target) { $target = $external::target; }
+ 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=~/s$/i) {
+ $value=&format_significant_figures($value,$fmt);
+ } elsif ($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*/-/;
+ $exponent=~s/^-0*/-/;
+ if ($exponent eq '-') { undef($exponent); }
+ if ($exponent) {
+ if ($target eq 'web') {
+ $result=$frac.'×10'.$exponent.'';
+ } elsif ($target eq 'tex') {
+ $result='\ensuremath{'.$frac.'\times 10^{'.$exponent.'}}';
+ } else {
+ $result=$value;
+ }
+ } else {
+ $result=$frac;
+ }
+ } else {
+ $result=$value;
+ if ($dollarmode) { $result=&dollarformat($result,$target); }
+ elsif ($commamode) { $result=&commaformat($result,$target); }
+ }
+ return $result;
+}
+
+sub commaformat {
+ my ($number,$target) = @_;
+ if ($number =~ /\./) {
+ while ($number =~ /([^0-9]*)([0-9]+)([^\.,][^\.,][^\.,])([,0-9]*\.[0-9]*)$/) {
+ $number = $1.$2.','.$3.$4;
+ }
+ } else {
+ while ($number =~ /^([^0-9]*)([0-9]+)([^,][^,][^,])([,0-9]*)$/) {
+ $number = $1.$2.','.$3.$4;
+ }
+ }
+ 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 {
+ $number='$'.$number; #' stupid emacs
+ }
+ return $number;
+}
+
+# format of form ns or nS where n is an integer
+sub format_significant_figures {
+ my ($number,$format) = @_;
+ return '0' if ($number == 0);
+ # extract number of significant figures needed
+ my ($sig) = ($format =~ /(\d+)s/i);
+ # arbitrary choice - suggestions ?? or throw error message?
+ $sig = 3 if ($sig eq '');
+ # save the minus sign
+ my $sign = ($number < 0) ? '-' : '';
+ $number = abs($number);
+ # needed to correct for a number greater than 1 (or
+ my $power = ($number < 1) ? 0 : 1;
+ # could round up. Take the integer part of log10.
+ my $x10 = int(log($number)/log(10));
+ # find number with values left of decimal pt = # of sign figs.
+ my $xsig = $number*10**($sig-$x10-$power);
+ # get just digits left of decimal pt - also rounds off correctly
+ my $xint = sprintf('%.0f',$xsig);
+ # save any trailing zero's
+ my ($zeros) = ($xint =~ /(0+)$/);
+ # return number to original magnitude
+ my $numSig = $xint*10**($x10-$sig+$power);
+ # insert trailing zero's if have decimal point
+ $numSig =~ s/^(\d+)\.(\d+)(\e?(.*)?)$/$1\.$2$zeros$3/;
+ # put a decimal pt for number ending with 0 and length = # of sig fig
+ $numSig.='.' if (length($numSig) == $sig && $numSig =~ /0$/);
+ if (length($numSig) < $sig) {
+ $numSig.='.'.substr($zeros,0,($sig-length($numSig)));
+ }
+ # return number with sign
+ return $sign.$numSig;
+
}
sub map {
my ($phrase,$dest,$source)=@_;
+ my @oldseed=&random_get_seed();
my @seed = &random_seed_from_phrase($phrase);
&random_set_seed(@seed);
my $destct = scalar(@$dest);
@@ -450,6 +1050,7 @@ sub map {
$output[$ctr] = $$dest[$idx[$ctr]];
$ctr++;
}
+ &random_set_seed(@oldseed);
return @output;
} else {
my $num = scalar(@$source);
@@ -469,10 +1070,13 @@ sub map {
}
}
}
+ &random_set_seed(@oldseed);
+ return '';
}
sub rmap {
my ($phrase,$dest,$source)=@_;
+ my @oldseed=&random_get_seed();
my @seed = &random_seed_from_phrase($phrase);
&random_set_seed(@seed);
my $destct = scalar(@$dest);
@@ -490,6 +1094,7 @@ sub rmap {
$output[$ctr] = $$dest[$r_idx[$ctr]];
$ctr++;
}
+ &random_set_seed(@oldseed);
return @output;
} else {
my $num = scalar(@$source);
@@ -515,6 +1120,8 @@ sub rmap {
}
}
}
+ &random_set_seed(@oldseed);
+ return '';
}
sub capa_id { return }
@@ -522,108 +1129,215 @@ sub capa_id { return }
sub problem { return }
sub name{
- my $fullname = &EXT('environment.lastname').', '.&EXT('environment.firstname').' '.&EXT('environment.middlename');
- $fullname = "" if $fullname eq ", ";
- $fullname =~ s/\%2d/-/g;
- return $fullname;
+ my $fullname = &EXT('environment.lastname').', '.&EXT('environment.firstname').' '.&EXT('environment.middlename');
+ $fullname = "" if $fullname eq ", ";
+ $fullname =~ s/\%2d/-/g;
+ return $fullname;
}
sub student_number {
- my $id = &EXT('environment.id');
- $id = '' if $id eq "";
- return $id;
+ my $id = &EXT('environment.id');
+ $id = '' if $id eq "";
+ return $id;
}
sub class {
- my $course = &EXT('course.description');
- $course = '' if $course eq "";
- return $course;
+ my $course = &EXT('course.description');
+ $course = '' if $course eq "";
+ return $course;
+}
+
+sub classid {
+ my $courseid = &EXT('request.course.id');
+ $courseid = '' if $courseid eq "";
+ return $courseid;
+}
+
+sub firstname {
+ my $firstname = &EXT('environment.firstname');
+ $firstname = '' if $firstname eq "";
+ return $firstname;
+}
+
+sub middlename {
+ my $middlename = &EXT('environment.middlename');
+ $middlename = '' if $middlename eq "";
+ return $middlename;
+}
+
+
+sub lastname {
+ my $lastname = &EXT('environment.lastname');
+ $lastname = '' if $lastname eq "";
+ return $lastname;
}
sub sec {
- my $sec = &EXT('request.course.sec');
- $sec = '' if $sec eq "";
- return $sec;
+ my $sec = &EXT('request.course.sec');
+ $sec = '' if $sec eq "";
+ return $sec;
+}
+
+sub submission {
+ my ($partid,$responseid,$subnumber)=@_;
+ my $sub='';
+ if ($subnumber) { $sub=$subnumber.':'; }
+ return &EXT('user.resource.'.$sub.'resource.'.$partid.'.'.$responseid.'.submission');
+}
+
+sub currentpart {
+ return $external::part;
+}
+
+sub eval_time {
+ my ($timestamp)=@_;
+ unless ($timestamp) { return ''; }
+ return &locallocaltime($timestamp);
}
sub open_date {
- my @dc = split(/\s+/,localtime(&EXT('resource.0.opendate')));
- return '' if ($dc[0] eq "Wed" and $dc[2] == 31 and $dc[4] == 1969);
- my @hm = split(/:/,$dc[3]);
- my $ampm = " am";
- if ($hm[0] > 12) {
- $hm[0]-=12;
- $ampm = " pm";
- }
- return $dc[0].', '.$dc[1].' '.$dc[2].', '.$dc[4].' at '.$hm[0].':'.$hm[1].$ampm;
-}
-
-sub due_date {
- my @dc = split(/\s+/,localtime(&EXT('resource.0.duedate')));
- return '' if ($dc[0] eq "Wed" and $dc[2] == 31 and $dc[4] == 1969);
- my @hm = split(/:/,$dc[3]);
- my $ampm = " am";
- if ($hm[0] > 12) {
- $hm[0]-=12;
- $ampm = " pm";
- }
- return $dc[0].', '.$dc[1].' '.$dc[2].', '.$dc[4].' at '.$hm[0].':'.$hm[1].$ampm;
-# return $dc[0].', '.$dc[1].' '.$dc[2].', '.$dc[4].' at '.$dc[3];
+ my ($partid)=@_;
+ unless ($partid) { $partid=0; }
+ return &eval_time(&EXT('resource.'.$partid.'.opendate'));
+}
+
+sub due_date {
+ my ($partid)=@_;
+ unless ($partid) { $partid=0; }
+ return &eval_time(&EXT('resource.'.$partid.'.duedate'));
}
sub answer_date {
- my @dc = split(/\s+/,localtime(&EXT('resource.0.answerdate')));
- return '' if ($dc[0] eq "Wed" and $dc[2] == 31 and $dc[4] == 1969);
- my @hm = split(/:/,$dc[3]);
- my $ampm = " am";
- if ($hm[0] > 12) {
- $hm[0]-=12;
- $ampm = " pm";
- }
- return $dc[0].', '.$dc[1].' '.$dc[2].', '.$dc[4].' at '.$hm[0].':'.$hm[1].$ampm;
-# return $dc[0].', '.$dc[1].' '.$dc[2].', '.$dc[4].' at '.$dc[3];
+ my ($partid)=@_;
+ unless ($partid) { $partid=0; }
+ return &eval_time(&EXT('resource.'.$partid.'.answerdate'));
+}
+
+sub open_date_epoch {
+ my ($partid)=@_;
+ unless ($partid) { $partid=0; }
+ return &EXT('resource.'.$partid.'.opendate');
+}
+
+sub due_date_epoch {
+ my ($partid)=@_;
+ unless ($partid) { $partid=0; }
+ return &EXT('resource.'.$partid.'.duedate');
+}
+
+sub answer_date_epoch {
+ my ($partid)=@_;
+ unless ($partid) { $partid=0; }
+ return &EXT('resource.'.$partid.'.answerdate');
+}
+
+sub parameter_setting {
+ my ($which,$partid)=@_;
+ unless ($partid) { $partid=0; }
+ return &EXT('resource.'.$partid.'.'.$which);
+}
+
+sub stored_data {
+ my ($which,$partid)=@_;
+ unless ($partid) { $partid=0; }
+ return &EXT('user.resource.resource.'.$partid.'.'.$which);
+}
+
+sub wrong_bubbles {
+ my ($correct,$lower,$upper,$step,@given)=@_;
+ my @array=();
+ my %hash=();
+ foreach my $new (@given) {
+ $hash{$new}=1;
+ }
+ my $num=int(¶meter_setting('numbubbles',¤tpart()));
+ unless ($num) { $num=8; }
+ if ($num>1) {
+ for (my $i=0;$i<=500;$i++) {
+ my $new=&random($lower,$upper,$step);
+ if ($hash{$new}) { next; }
+ if (abs($new-$correct)<$step) { next; }
+ $hash{$new}=1;
+ @array=keys(%hash);
+ if ($#array+2>=$num) { last; }
+ }
+ }
+ return @array;
}
sub array_moments {
- my @input=@_;
- my (@output,$N);
- $N=scalar (@input);
- $output[0]=$N;
- if ($N <= 1) {
- $output[1]=$input[0];
- $output[1]="Input array not defined" if ($N == 0);
- $output[2]="variance undefined for N<=1";
- $output[3]="skewness undefined for N<=1";
- $output[4]="kurtosis undefined for N<=1";
+ my @input=@_;
+ my (@output,$N);
+ $N=scalar (@input);
+ $output[0]=$N;
+ if ($N <= 1) {
+ $output[1]=$input[0];
+ $output[1]="Input array not defined" if ($N == 0);
+ $output[2]="variance undefined for N<=1";
+ $output[3]="skewness undefined for N<=1";
+ $output[4]="kurtosis undefined for N<=1";
+ return @output;
+ }
+ my $sum=0;
+ foreach my $line (@input) {
+ $sum+=$line;
+ }
+ $output[1] = $sum/$N;
+ my ($x,$sdev,$var,$skew,$kurt) = 0;
+ foreach my $line (@input) {
+ $x=$line-$output[1];
+ $var+=$x**2;
+ $skew+=$x**3;
+ $kurt+=$x**4;
+ }
+ $output[2]=$var/($N-1);
+ $sdev=CORE::sqrt($output[2]);
+ if ($sdev == 0) {
+ $output[3]="inf-variance=0";
+ $output[4]="inf-variance=0";
+ return @output;
+ }
+ $output[3]=$skew/($sdev**3*$N);
+ $output[4]=$kurt/($sdev**4*$N)-3;
return @output;
- }
- my $sum=0;
- foreach my $line (@input) {
- $sum+=$line;
- }
- $output[1] = $sum/$N;
- my ($x,$sdev,$var,$skew,$kurt) = 0;
- foreach my $line (@input) {
- $x=$line-$output[1];
- $var+=$x**2;
- $skew+=$x**3;
- $kurt+=$x**4;
- }
- $output[2]=$var/($N-1);
- $sdev=sqrt($output[2]);
- if ($sdev == 0) {
- $output[3]="inf-variance=0";
- $output[4]="inf-variance=0";
- return @output;
- }
- $output[3]=$skew/($sdev**3*$N);
- $output[4]=$kurt/($sdev**4*$N)-3;
- return @output;
}
sub choose {
- my $num = $_[0];
- return $_[$num];
+ my $num = $_[0];
+ return $_[$num];
}
+#&sum1(1,$x,sub { &sum1($_[0],2*$_[0], sub { fact($_[0])**2 })});
+#sub sum1 {
+# my ($start,$end,$sub)=@_;
+# my $sum=0;
+# for (my $i=$start;$i<=$end;$i++) {
+# $sum+=&$sub($i);
+# }
+# return $sum
+#}
+
+#&sum2('a',1,$x,'&sum2(\'b\',$a,2*$a, \'&factorial($b)**2\')');
+#sub sum2 {
+# my ($varname,$start,$end,$line)=@_;
+# my $sum=0;
+# for (my $i=$start;$i<=$end;$i++) {
+# my $func=sub {
+# eval("\$".$varname."=$i");
+# eval($line);
+# };
+# $sum+=&$func($i);
+# }
+# return $sum
+#}
+
+# expiremental idea
+sub proper_path {
+ my ($path)=@_;
+ if ( $external::target eq "tex" ) {
+ return '/home/httpd/html'.$path;
+ } else {
+ return $path;
+ }
+}
500 Internal Server Error
Internal Server Error
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.