version 1.163, 2013/01/21 06:16:50
|
version 1.177, 2019/11/06 16:20:06
|
Line 29
|
Line 29
|
|
|
#init some globals |
#init some globals |
$hidden::RANDOMINIT=0; |
$hidden::RANDOMINIT=0; |
|
$hidden::RANDOMINITTRYPART=''; |
$pi=atan2(1,1)*4; |
$pi=atan2(1,1)*4; |
$rad2deg=180.0/$pi; |
$rad2deg=180.0/$pi; |
$deg2rad=$pi/180.0; |
$deg2rad=$pi/180.0; |
Line 309 sub caparesponse_check_list {
|
Line 310 sub caparesponse_check_list {
|
#for numerical problems split off the unit |
#for numerical problems split off the unit |
my $part1; |
my $part1; |
my $part2; |
my $part2; |
|
my $match_algebra = qr{^(.*[^\s])\s+([^\s]+)$}; |
|
# FIXME: with the above regexp, algebra with spaces will not be evaluated correctly |
|
my $match_numerical_units = qr{^([\d\.\,\s\$]*(?:(?:[xX\*]10[\^\*]*|[eE]*)[\+\-]*\d*)*(?:^|\S)\d+)([\$\s\w\^\*\/\(\)\+\-]*[^\d\.\s\,][\$\s\w\^\*\/\(\)\+\-]*)$}; |
if ($allowalgebra) { |
if ($allowalgebra) { |
($part1,$part2)=($responses->[0][-1]=~ /^(.*[^\s])\s+([^\s]+)$/); |
($part1,$part2) = ($responses->[0][-1] =~ /$match_algebra/); |
} else { |
} else { |
($part1,$part2)=($responses->[0][-1]=~ /^([\d\.\,\s\$]*(?:(?:[xX\*]10[\^\*]*|[eE]*)[\+\-]*\d*)*(?:^|\S)\d+)([\$\s\w\^\*\/\(\)\+\-]*[^\d\.\s\,][\$\s\w\^\*\/\(\)\+\-]*)$/); |
($part1,$part2) = ($responses->[0][-1] =~ /$match_numerical_units/); |
} |
} |
if (defined($part1) && defined($part2)) { |
if (defined($part1) && defined($part2)) { |
$responses->[0][-1]=$part1; |
$responses->[0][-1]=$part1; |
Line 327 sub caparesponse_check_list {
|
Line 331 sub caparesponse_check_list {
|
} |
} |
} |
} |
} |
} |
|
if (scalar(@$responses) > 0 && defined $answerunit) { |
|
# there are several response values, units should be the same for all |
|
$part2 =~ s/^\s+|\s+$//g; |
|
for (my $i=1; $i<scalar(@$responses); $i++) { |
|
my $element = $responses->[$i][-1]; |
|
my ($part1i, $part2i); |
|
if ($allowalgebra) { |
|
($part1i, $part2i) = ($element =~ /$match_algebra/); |
|
} else { |
|
($part1i, $part2i) = ($element =~ /$match_numerical_units/); |
|
} |
|
$part2i =~ s/^\s+|\s+$//g; |
|
if (!defined $part2i) { |
|
return 'NO_UNIT'; |
|
} elsif ($part2i ne $part2) { |
|
return ('UNIT_FAIL', "$part2 $part2i"); |
|
} else { |
|
$responses->[$i][-1] = $part1i; |
|
} |
|
} |
|
} |
} |
} |
} |
} |
$unit=~s/\s//; |
$unit=~s/\s//; |
Line 631 sub hinton {
|
Line 656 sub hinton {
|
|
|
sub random { |
sub random { |
my ($start,$end,$step)=@_; |
my ($start,$end,$step)=@_; |
if ( ! $hidden::RANDOMINIT ) { |
if (( ! $hidden::RANDOMINIT ) || |
if ($external::randomseed == 0) { $external::randomseed=1; } |
(($external::randomizetrypart ne '') && |
if ($external::randomseed =~/,/) { |
($hidden::RANDOMINITTRYPART ne $external::randomizetrypart))) { |
my ($num1,$num2)=split(/,/,$external::randomseed); |
if ($external::randomseed == 0) { $external::randomseed=1; } |
&random_set_seed(1,abs($num1)); |
if ($external::randomseed =~/,/) { |
} elsif ($external::randomseed =~/:/) { |
my ($num1,$num2) = map { abs($_); } split(/,/,$external::randomseed); |
my ($num1,$num2)=split(/:/,$external::randomseed); |
if ((!$num1) || ($num1 > 2147483398)) { |
&random_set_seed(abs($num1),abs($num2)); |
&random_set_seed_from_phrase($external::randomseed); |
} else { |
} else { |
&random_set_seed(1,int(abs($external::randomseed))); |
&random_set_seed(1,$num1); |
} |
} |
|
} elsif ($external::randomseed =~/:/) { |
|
my ($num1,$num2) = map { abs($_); } split(/:/,$external::randomseed); |
|
if ((!$num1) || (!$num2) || ($num1 > 2147483562) || ($num2 > 2147483398)) { |
|
&random_set_seed_from_phrase($external::randomseed); |
|
} else { |
|
&random_set_seed($num1,$num2); |
|
} |
|
} else { |
|
my $num1 = int(abs($external::randomseed)); |
|
if ((!$num1) || ($num1 > 2147483398)) { |
|
&random_set_seed_from_phrase($external::randomseed); |
|
} else { |
|
&random_set_seed(1,$num1); |
|
} |
|
} |
&math_random_uniform(); |
&math_random_uniform(); |
$hidden::RANDOMINIT=1; |
$hidden::RANDOMINIT=1; |
|
$hidden::RANDOMINITTRYPART=$external::randomizetrypart; |
} |
} |
if (!defined($step)) { $step=1; } |
if (!defined($step)) { $step=1; } |
my $num=1+int(($end-$start)/$step); |
my $num=1+int(($end-$start)/$step); |
Line 902 sub chemparse {
|
Line 943 sub chemparse {
|
my $formula = ''; |
my $formula = ''; |
foreach my $token (@tokens) { |
foreach my $token (@tokens) { |
if ($token eq '->' ) { |
if ($token eq '->' ) { |
$formula .= '<m>\ensuremath{\rightarrow}</m> '; |
if ($external::target eq 'web') { |
|
$formula .= '→ '; |
|
} else { |
|
$formula .= '<m>\ensuremath{\rightarrow}</m> '; |
|
} |
next; |
next; |
} |
} |
if ($token eq '<-' ) { |
if ($token eq '<-' ) { |
$formula .= '<m>\ensuremath{\leftarrow}</m> '; |
if ($external::target eq 'web') { |
|
$formula .= '← '; |
|
} else { |
|
$formula .= '<m>\ensuremath{\leftarrow}</m> '; |
|
} |
next; |
next; |
} |
} |
if ($token eq '<=>') { |
if ($token eq '<=>') { |
Line 944 sub chemparse {
|
Line 993 sub chemparse {
|
return &xmlparse($formula); |
return &xmlparse($formula); |
} |
} |
|
|
|
sub conv_eng_format { |
|
my ($ans,$baseunit)=@_; |
|
my ($value,$answer,$unit); |
|
$baseunit =~ s{[^\w/\-\.]}{}g; |
|
eval { |
|
$value = &number_format_pref($ans); |
|
}; |
|
my ($answer,$prefix) = ($value=~ /^(.+)(\w)$/); |
|
my $unit = $prefix.$baseunit; |
|
return($answer,$unit); |
|
} |
|
|
sub prettyprint { |
sub prettyprint { |
my ($value,$fmt,$target)=@_; |
my ($value,$fmt,$target)=@_; |
my $result; |
my $result; |
Line 1033 sub format_significant_figures {
|
Line 1094 sub format_significant_figures {
|
$number = abs($number); |
$number = abs($number); |
# needed to correct for a number greater than 1 (or |
# needed to correct for a number greater than 1 (or |
my $power = ($number < 1) ? 0 : 1; |
my $power = ($number < 1) ? 0 : 1; |
if ($power && $number =~ /^\d+$/) { |
|
my $nonzeros = $number; |
|
$nonzeros =~ s/0+$//; |
|
if (length($number) - length($nonzeros) > 1) { |
|
# convert to exponential form |
|
my $n = $sig-1; |
|
my $numSig = sprintf('%.' . $n . 'E', $number); |
|
# return number with sign |
|
return $sign.$numSig; |
|
} |
|
} |
|
# could round up. Take the integer part of log10. |
# could round up. Take the integer part of log10. |
my $x10 = int(log($number)/log(10)); |
my $x10 = int(log($number)/log(10)); |
# find number with values left of decimal pt = # of sign figs. |
# find number with values left of decimal pt = # of sign figs. |
Line 1054 sub format_significant_figures {
|
Line 1104 sub format_significant_figures {
|
my ($zeros) = ($xint =~ /(0+)$/); |
my ($zeros) = ($xint =~ /(0+)$/); |
# return number to original magnitude |
# return number to original magnitude |
my $numSig = $xint*10**($x10-$sig+$power); |
my $numSig = $xint*10**($x10-$sig+$power); |
# insert trailing zero's if have decimal point |
if ($numSig =~ /^(\d+)\.(\d+)/) { |
$numSig =~ s/^(\d+)\.(\d+)(\e?(.*)?)$/$1\.$2$zeros$3/; |
# insert trailing zero's if have decimal point |
# put a decimal pt for number ending with 0 and length = # of sig fig |
my @digarray = split('',$1.$2); |
$numSig.='.' if (length($numSig) == $sig && $numSig =~ /0$/); |
my $sigcount; |
if (length($numSig) < $sig) { |
while (@digarray > 0) { |
$numSig.='.'.substr($zeros,0,($sig-length($numSig))); |
my $item = shift(@digarray); |
|
if ($item) { |
|
$sigcount = 1 + @digarray; |
|
last; |
|
} |
|
} |
|
if (($sigcount) && ($sig >= $sigcount)) { |
|
$zeros = substr($zeros,0,($sig - $sigcount)); |
|
} |
|
$numSig =~ s/^(\d+)\.(\d+)(\e?(.*)?)$/$1\.$2$zeros$3/; |
|
} else { |
|
if ($numSig =~ /^(\d+)e([\+\-]\d+)$/i) { |
|
my $pre_exp = $1; |
|
my $exponent = $2; |
|
$numSig = $pre_exp.'.'.$zeros.'E'.$exponent; |
|
} elsif ($numSig =~ /0$/) { |
|
# add decimal pt for number ending with 0 and length == # of sig figs |
|
if (length($numSig) == $sig) { |
|
$numSig.='.'; |
|
} elsif (length($numSig) > $sig) { |
|
# exponential form for number ending with 0 and length > # of sig figs |
|
my $fmtsig = $sig-1; |
|
if ($fmtsig) { |
|
$numSig = sprintf('%.'.$fmtsig.'E',$numSig); |
|
} |
|
} elsif (length($numSig) < $sig) { |
|
$numSig.='.'.substr($zeros,0,($sig-length($numSig))); |
|
} |
|
} else { |
|
if (length($numSig) < $sig) { |
|
$numSig.='.'.substr($zeros,0,($sig-length($numSig))); |
|
} |
|
} |
} |
} |
# return number with sign |
# return number with sign |
return $sign.$numSig; |
return $sign.$numSig; |
|
|
} |
} |
|
|
sub map { |
sub map { |
Line 1208 sub sec {
|
Line 1289 sub sec {
|
} |
} |
|
|
sub submission { |
sub submission { |
my ($partid,$responseid,$subnumber)=@_; |
my ($partid,$responseid,$subnumber,$encode,$cleanupnum,$mapalias)=@_; |
my $sub=''; |
my $sub=''; |
if ($subnumber) { $sub=$subnumber.':'; } |
if ($subnumber) { $sub=$subnumber.':'; } |
return &EXT('user.resource.'.$sub.'resource.'.$partid.'.'.$responseid.'.submission'); |
my $output = |
|
&EXT('user.resource.'.$sub.'resource.'.$partid.'.'.$responseid.'.submission',$mapalias); |
|
if (ref($output) eq 'ARRAY') { |
|
my @items = @{$output}; |
|
if ($encode) { |
|
@items = map { &encode_response($_); } @items; |
|
} |
|
if (ref($cleanupnum) eq 'HASH') { |
|
@items = map { &cleanup_numerical_response($cleanupnum,$_); } @items; |
|
} |
|
return \@items; |
|
} else { |
|
if ($encode) { |
|
$output = &encode_response($output); |
|
} |
|
if (ref($cleanupnum) eq 'HASH') { |
|
$output = &cleanup_numerical_response($cleanupnum,$output); |
|
} |
|
return $output; |
|
} |
|
} |
|
|
|
sub encode_response { |
|
my ($value) = @_; |
|
$value =~ s/&/&/g; |
|
$value =~ s/</</g; |
|
$value =~ s/>/>/g; |
|
$value =~ s/"/"/g; |
|
return $value; |
|
} |
|
|
|
sub cleanup_numerical_response { |
|
my ($cleanupnum,$value) = @_; |
|
if (ref($cleanupnum) eq 'HASH') { |
|
if ($cleanupnum->{exponent}) { |
|
if ($value =~ m{^(.*)[\*xX]\s*10\s*\^\s*(\+|\-)?\s*(\d+)(.*)$}) { |
|
my $pre_exp = $1; |
|
my $sign = $2; |
|
my $exponent = $3; |
|
my $post_exp = $4; |
|
if ($pre_exp !~ /\./) { |
|
$pre_exp .= '.'; |
|
} |
|
if ($sign eq '') { |
|
$sign = '+'; |
|
} |
|
$value = $pre_exp.'E'.$sign.$exponent.$post_exp; |
|
} |
|
} |
|
if ($cleanupnum->{comma}) { |
|
$value =~ s{(\d+),(\d+)}{$1$2}; |
|
} |
|
if ($cleanupnum->{letterforzero}) { |
|
$value =~ s/^\s*o(\.\d+)/0$1/i; |
|
} |
|
if ($cleanupnum->{spaces}) { |
|
$value =~ s{^\s+|\s+$}{}g; |
|
if ($value =~ m{^(.*)\.\s+(\d+)(.*)$}) { |
|
my $pre_pt = $1; |
|
my $decimal = $2; |
|
my $post_dec = $3; |
|
$value = $pre_pt.'.'.$decimal.$post_dec; |
|
} |
|
} |
|
if ($cleanupnum->{format} =~ /^\d+s$/i) { |
|
$value = &format_significant_figures($value,$cleanupnum->{format}); |
|
} |
|
} |
|
return $value; |
} |
} |
|
|
sub currentpart { |
sub currentpart { |
Line 1370 sub proper_path {
|
Line 1519 sub proper_path {
|
} |
} |
} |
} |
|
|
|
sub input_id { |
|
my ($part_id, $response_id, $textline_id) = @_; |
|
return 'HWVAL_'.$part_id.'_'.$response_id.'_'.$textline_id; |
|
} |
|
|