--- loncom/homework/caparesponse/caparesponse.pm 2005/01/10 18:42:21 1.160 +++ loncom/homework/caparesponse/caparesponse.pm 2006/03/09 01:13:16 1.189 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # caparesponse definition # -# $Id: caparesponse.pm,v 1.160 2005/01/10 18:42:21 albertel Exp $ +# $Id: caparesponse.pm,v 1.189 2006/03/09 01:13:16 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -30,16 +30,110 @@ package Apache::caparesponse; use strict; use capa; use Apache::lonlocal; +use Apache::lonnet; BEGIN { &Apache::lonxml::register('Apache::caparesponse',('caparesponse','numericalresponse','stringresponse','formularesponse')); } +my %answer; +my $cur_name; +sub start_answer { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + my $result; + $cur_name = &Apache::lonxml::get_param('name',$parstack,$safeeval); + if ($cur_name =~ /^\s*$/) { $cur_name = $Apache::lonxml::curdepth; } + my $type = &Apache::lonxml::get_param('type',$parstack,$safeeval); + if (!defined($type) && $tagstack->[-2] eq 'answergroup') { + $type = &Apache::lonxml::get_param('type',$parstack,$safeeval,-2); + } + if (!defined($type)) { $type = 'ordered' }; + $answer{$cur_name}= { 'type' => $type, + 'answers' => [] }; + return $result; +} + +sub end_answer { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + my $result; + undef($cur_name); + return $result; +} + +sub start_answergroup { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + my $result; + my $id = $Apache::inputtags::response[-1]; + my $dis = &Apache::lonxml::get_param('answerdisplay',$parstack,$safeeval); + if (defined($dis)) { $Apache::inputtags::answertxt{$id}=$dis; } + return $result; +} + +sub end_answergroup { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + my $result; + return $result; +} + +sub start_value { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + my $result; + if ( $target eq 'web' || $target eq 'tex' || + $target eq 'grade' || $target eq 'webgrade' || + $target eq 'answer' || $target eq 'analyze' ) { + my $bodytext = &Apache::lonxml::get_all_text("/value",$parser,$style); + $bodytext = &Apache::run::evaluate($bodytext,$safeeval, + $$parstack[-1]); + push(@{ $answer{$cur_name}{'answers'} },$bodytext); + } + return $result; +} + +sub end_value { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + my $result; + return $result; +} + +sub start_array { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + my $result; + if ( $target eq 'web' || $target eq 'tex' || + $target eq 'grade' || $target eq 'webgrade' || + $target eq 'answer' || $target eq 'analyze' ) { + my $bodytext = &Apache::lonxml::get_all_text("/array",$parser,$style); + my @values = &Apache::run::evaluate($bodytext,$safeeval, + $$parstack[-1]); + push(@{ $answer{$cur_name}{'answers'} },@values); + } + return $result; +} + +sub end_array { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + my $result; + return $result; +} + +sub start_unit { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + my $result; + return $result; +} + +sub end_unit { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + my $result; + return $result; +} + sub start_numericalresponse { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + &Apache::lonxml::register('Apache::caparesponse',('answer','answergroup','value','array','unit')); my $id = &Apache::response::start_response($parstack,$safeeval); my $result; - undef %{$safeeval->varglob('LONCAPA::CAPAresponse_args')}; + undef(%answer); + undef(%{$safeeval->varglob('LONCAPA::CAPAresponse_args')}); if ($target eq 'edit') { $result.=&Apache::edit::tag_start($target,$token); $result.=&Apache::edit::text_arg('Answer:','answer',$token); @@ -97,17 +191,22 @@ sub start_numericalresponse { $safeeval); for (my $i=0; $i <= $#answers; $i++) { my $answer=$answers[$i]; - my $format; - if ($#formats > 0) { - $format=$formats[$i]; + if ( scalar(@$tagstack) + && $tagstack->[-1] ne 'numericalresponse') { + $answertxt.=$answer.','; } else { - $format=$formats[0]; + my $format; + if ($#formats > 0) { + $format=$formats[$i]; + } else { + $format=$formats[0]; + } + if ($unit=~/\$/) { $format="\$".$format; $unit=~s/\$//g; } + if ($unit=~/\,/) { $format="\,".$format; $unit=~s/\,//g; } + my $formatted=&format_number($answer,$format,$target, + $safeeval); + $answertxt.=$formatted.','; } - if ($unit=~/\$/) { $format="\$".$format; $unit=~s/\$//g; } - if ($unit=~/\,/) { $format="\,".$format; $unit=~s/\,//g; } - my $formatted=&format_number($answer,$format,$target, - $safeeval); - $answertxt.=$formatted.','; } chop $answertxt; if ($target eq 'web') { @@ -119,6 +218,68 @@ sub start_numericalresponse { return $result; } +sub check_submission { + my ($response,$partid,$id,$tag,$parstack,$safeeval,$ignore_sig)=@_; + my $args_ref= \%{$safeeval->varglob('LONCAPA::CAPAresponse_args')}; + $$args_ref{'response'}=$response; + my $hideunit=&Apache::lonnet::EXT('resource.'.$partid.'_'.$id.'.turnoffunit'); + + foreach my $arg ('type','tol','sig','format','unit','calc', + 'samples') { + $$args_ref{$arg}= + &Apache::lonxml::get_param($arg,$parstack,$safeeval); + } + foreach my $key (keys(%Apache::inputtags::params)) { + $$args_ref{$key}=$Apache::inputtags::params{$key}; + } + + #no way to enter units, with radio buttons + if ($Apache::lonhomework::type eq 'exam' || + lc($hideunit) eq "yes") { + delete($$args_ref{'unit'}); + } + #sig fig don't make much sense either + if (($Apache::lonhomework::type eq 'exam' || + &Apache::response::submitted('scantron') || + $ignore_sig) && + $tag eq 'numericalresponse') { + delete($$args_ref{'sig'}); + } + + if ($tag eq 'formularesponse') { + $$args_ref{'type'}='fml'; + } elsif ($tag eq 'numericalresponse') { + $$args_ref{'type'}='float'; + } + my @answer=&Apache::lonxml::get_param_var('answer',$parstack,$safeeval); + &Apache::lonxml::debug('answer is'.join(':',@answer)); + if (@answer && defined($answer[0])) { + $answer{'INTERNAL'}= {'type' => 'ordered', + 'answers' => \@answer }; + } + #FIXME would be nice if we could save name so we know who graded him + #correct + my (%results,@final_awards,@final_msgs,@names); + foreach my $name (keys(%answer)) { + &Apache::lonxml::debug(" doing $name with ".join(':',@{ $answer{$name}{'answers'} })); + @{$safeeval->varglob('LONCAPA::CAPAresponse_answer')}=@{ $answer{$name}{'answers'} }; + my ($result,@msgs) = + &Apache::run::run("&caparesponse_check_list()",$safeeval); + &Apache::lonxml::debug('msgs are '.join(':',@msgs)); + my ($awards)=split(/:/,$result); + my @awards= split(/,/,$awards); + my ($ad, $msg) = &Apache::inputtags::finalizeawards(\@awards,\@msgs); + $results{$name}= [$ad,$msg]; + push(@final_awards,$ad); + push(@final_msgs,$msg); + push(@names,$name); + } + my ($ad, $msg, $name) = &Apache::inputtags::finalizeawards(\@final_awards, + \@final_msgs, + \@names,1); + return($ad,$msg); +} + sub end_numericalresponse { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $increment=1; @@ -126,84 +287,32 @@ sub end_numericalresponse { if (!$Apache::lonxml::default_homework_loaded) { &Apache::lonxml::default_homework_load($safeeval); } + my $partid = $Apache::inputtags::part; + my $id = $Apache::inputtags::response[-1]; my $tag; + $safeeval->share_from('capa',['&caparesponse_capa_check_answer']); if (scalar(@$tagstack)) { $tag=$$tagstack[-1]; } - if ( $target eq 'grade' && defined($ENV{'form.submitted'})) { + if ( $target eq 'grade' && &Apache::response::submitted() ) { &Apache::response::setup_params($tag,$safeeval); - $safeeval->share_from('capa',['&caparesponse_capa_check_answer']); - my $partid = $Apache::inputtags::part; - my $id = $Apache::inputtags::response['-1']; if ($Apache::lonhomework::type eq 'exam' && $tag eq 'formularesponse') { $increment=&Apache::response::scored_response($partid,$id); - } elsif ($Apache::lonhomework::type eq 'survey') { - if ( !defined($ENV{'form.submitted'})) { return ''; } - my $response = &Apache::response::getresponse(); - if ( $response =~ /[^\s]/) { - my %previous=&Apache::response::check_for_previous($response, - $partid,$id); - $Apache::lonhomework::results{"resource.$partid.$id.submission"}=$response; - my $ad=$Apache::lonhomework::results{"resource.$partid.$id.awarddetail"}='SUBMITTED'; - &Apache::response::handle_previous(\%previous,$ad); - } } else { my $response = &Apache::response::getresponse(); if ( $response =~ /[^\s]/) { - my $ad; my %previous = &Apache::response::check_for_previous($response,$partid,$id); &Apache::lonxml::debug("submitted a $response
\n"); &Apache::lonxml::debug($$parstack[-1] . "\n
"); - if ($ENV{'form.submitted'} eq 'scantron') { - my $number_of_bubbles = &Apache::lonnet::EXT('resource.'.$partid.'_'.$id.'.numbubbles'); - if (!$number_of_bubbles) { $number_of_bubbles=8; } - my (@formats)=&Apache::lonxml::get_param_var('format',$parstack,$safeeval); - my (@answers)=&Apache::lonxml::get_param_var('answer',$parstack,$safeeval); - my (@incorrect)=&Apache::lonxml::get_param_var('incorrect',$parstack,$safeeval); - my ($values,$display)=&make_numerical_bubbles($number_of_bubbles,$target,$answers[0],$formats[0],\@incorrect,$safeeval); + if ( &Apache::response::submitted('scantron')) { + my ($values,$display)=&make_numerical_bubbles($partid,$id, + $target,$parstack,$safeeval); $response=$values->[$response]; } $Apache::lonhomework::results{"resource.$partid.$id.submission"}=$response; - my $args_ref= \%{$safeeval->varglob('LONCAPA::CAPAresponse_args')}; - $$args_ref{'response'}=$response; - my $hideunit=&Apache::lonnet::EXT('resource.'.$partid.'_'.$id.'.turnoffunit'); - - foreach my $arg ('type','tol','sig','format','unit','calc', - 'samples') { - $$args_ref{$arg}= - &Apache::lonxml::get_param($arg,$parstack,$safeeval); - } - foreach my $key (keys(%Apache::inputtags::params)) { - $$args_ref{$key}=$Apache::inputtags::params{$key}; - } - - #no way to enter units, with radio buttons - if ($Apache::lonhomework::type eq 'exam' || - lc($hideunit) eq "yes") { - delete($$args_ref{'unit'}); - } - #sig fig don't make much sense either - if (($Apache::lonhomework::type eq 'exam' || - $ENV{'form.submitted'} eq 'scantron') && - $tag eq 'numericalresponse') { - delete($$args_ref{'sig'}); - } - - if ($tag eq 'formularesponse') { - $$args_ref{'type'}='fml'; - } elsif ($tag eq 'numericalresponse') { - $$args_ref{'type'}='float'; - } - my @answer=&Apache::lonxml::get_param_var('answer',$parstack,$safeeval); - &Apache::lonxml::debug('answer is'.join(':',@answer)); - @{$safeeval->varglob('LONCAPA::CAPAresponse_answer')}=@answer; - - ($result,my @msgs) = - &Apache::run::run("&caparesponse_check_list()",$safeeval); - &Apache::lonxml::debug('msgs are'.join(':',@msgs)); - my ($awards)=split(/:/,$result); - my (@awards) = split(/,/,$awards); - ($ad,my $msg) = &Apache::inputtags::finalizeawards(\@awards,\@msgs); + my ($ad,$msg)=&check_submission($response,$partid,$id, + $tag,$parstack,$safeeval); + &Apache::lonxml::debug('ad is'.$ad); if ($ad eq 'SIG_FAIL') { my ($sig_u,$sig_l)= @@ -213,6 +322,11 @@ sub end_numericalresponse { $Apache::inputtags::params{'sig'}); } &Apache::lonxml::debug("\n
result:$result:$Apache::lonxml::curdepth
\n"); + if ($Apache::lonhomework::type eq 'survey' && + ($ad eq 'INCORRECT' || $ad eq 'APPROX_ANS' || + $ad eq 'EXACT_ANS')) { + $ad='SUBMITTED'; + } &Apache::response::handle_previous(\%previous,$ad); $Apache::lonhomework::results{"resource.$partid.$id.awarddetail"}=$ad; $Apache::lonhomework::results{"resource.$partid.$id.awardmsg"}=$msg; @@ -225,23 +339,12 @@ sub end_numericalresponse { my $award = $Apache::lonhomework::history{"resource.$Apache::inputtags::part.solved"}; my $status = $Apache::inputtags::status['-1']; if ($Apache::lonhomework::type eq 'exam') { - my $partid=$Apache::inputtags::part; - my $id=$Apache::inputtags::response[-1]; - my $number_of_bubbles = &Apache::lonnet::EXT('resource.'.$partid.'_'.$id.'.numbubbles'); - if ($Apache::inputtags::params{'numbubbles'}) { - $number_of_bubbles = $Apache::inputtags::params{'numbubbles'}; - } - if (!$number_of_bubbles) { $number_of_bubbles=8; } - - my (@formats)=&Apache::lonxml::get_param_var('format',$parstack, - $safeeval); + my ($bubble_values,$bubble_display)= + &make_numerical_bubbles($partid,$id,$target,$parstack, + $safeeval); + my $number_of_bubbles = scalar(@{ $bubble_values }); my $unit=&Apache::lonxml::get_param_var('unit',$parstack, $safeeval); - my (@incorrect)=&Apache::lonxml::get_param_var('incorrect',$parstack,$safeeval); - my ($bubble_values,$bubble_display)= - &make_numerical_bubbles($number_of_bubbles, - $target,$answers[0], - $formats[0],\@incorrect,$safeeval); my @alphabet=('A'..'Z'); if ($target eq 'web') { if ($tag eq 'numericalresponse') { @@ -259,10 +362,6 @@ sub end_numericalresponse { $bubble_display->[$ind].''; } $result.=''; - } elsif ($tag eq 'formularesponse') { - $result.= '

-

'; } } elsif ($target eq 'tex') { if ((defined $unit) and ($unit=~/\S/) and ($Apache::lonhomework::type eq 'exam')) { @@ -290,26 +389,19 @@ sub end_numericalresponse { } $result.='\end{enumerate}'; } else { - $result.='\fbox{\fbox{\parbox{\textwidth-5mm}{\strut\\\\\strut\\\\\strut\\\\\strut\\\\}}}'; - my $repetition = &Apache::response::repetition(); - $result.='\begin{enumerate}'; - for (my $i=0;$i<$repetition;$i++) { - $result.='\item[\textbf{'.($Apache::lonxml::counter+$i).'}.]\textit{Leave blank on scoring form}\vskip 0 mm'; - } - $increment=$repetition; - $result.= '\end{enumerate}'; + $increment = &Apache::response::repetition(); } } } } elsif ($target eq 'edit') { $result.=''.&Apache::edit::end_table; } elsif ($target eq 'answer' || $target eq 'analyze') { - - my $part_id="$Apache::inputtags::part.$Apache::inputtags::response[-1]"; + my $part_id="$partid.$id"; if ($target eq 'analyze') { push (@{ $Apache::lonhomework::analyze{"parts"} },$part_id); $Apache::lonhomework::analyze{"$part_id.type"} = $tag; my (@incorrect)=&Apache::lonxml::get_param_var('incorrect',$parstack,$safeeval); + if ($#incorrect eq 0) { @incorrect=(split(/,/,$incorrect[0])); } push (@{ $Apache::lonhomework::analyze{"$part_id.incorrect"} }, @incorrect); &Apache::response::check_if_computed($token,$parstack, $safeeval,'answer'); @@ -324,7 +416,14 @@ sub end_numericalresponse { if ($target eq 'answer') { $result.=&Apache::response::answer_header($tag); + if ($tag eq 'numericalresponse' + && $Apache::lonhomework::type eq 'exam') { + my ($bubble_values,undef,$correct) = &make_numerical_bubbles($partid, + $id,$target,$parstack,$safeeval); + $result.=&Apache::response::answer_part($tag,$correct); + } } + my ($sigline,$tolline); for(my $i=0;$i<=$#answers;$i++) { my $ans=$answers[$i]; my $fmt=$formats[0]; @@ -348,12 +447,16 @@ sub end_numericalresponse { #} } if ($target eq 'answer') { - if ($high && $tag eq 'numericalresponse') { $ans.=' ['.$low.','.$high.']'; } + if ($high && $tag eq 'numericalresponse') { + $ans.=' ['.$low.','.$high.']'; + $tolline .= "[$low, $high]"; + } if (defined($sighigh) && $tag eq 'numericalresponse') { - if ($ENV{'form.answer_output_mode'} eq 'tex') { + if ($env{'form.answer_output_mode'} eq 'tex') { $ans.= " Sig $siglow - $sighigh"; } else { $ans.= " Sig $siglow - $sighigh"; + $sigline .= "[$siglow, $sighigh]"; } } $result.=&Apache::response::answer_part($tag,$ans); @@ -363,12 +466,65 @@ sub end_numericalresponse { push (@{ $Apache::lonhomework::analyze{"$part_id.ans_high"} }, $high); push (@{ $Apache::lonhomework::analyze{"$part_id.ans_low"} }, $low); } + if ($fmt) { + push (@{ $Apache::lonhomework::analyze{"$part_id.format"} }, $fmt); + } } } + + my @fmt_ans; + for(my $i=0;$i<=$#answers;$i++) { + my $ans=$answers[$i]; + my $fmt=$formats[0]; + if (@formats && $#formats) {$fmt=$formats[$i];} + if ($fmt && $tag eq 'numericalresponse') { + $fmt=~s/e/E/g; + if ($unit=~/\$/) { $fmt="\$".$fmt; $unit=~s/\$//g; } + if ($unit=~/\,/) { $fmt="\,".$fmt; $unit=~s/\,//g; } + $ans = &format_number($ans,$fmt,$target,$safeeval); + if ($fmt=~/\$/ && $unit!~/\$/) { $ans=~s/\$//; } + } + push(@fmt_ans,$ans); + } + my $response=join(', ',@fmt_ans); + my $hideunit=&Apache::lonnet::EXT('resource.'.$partid.'_'. + $id.'.turnoffunit'); + if ($unit ne '' && + ! ($Apache::lonhomework::type eq 'exam' || + lc($hideunit) eq "yes") ) { + my $cleanunit=$unit; + $cleanunit=~s/\$\,//g; + $response.=" $cleanunit"; + } + + my ($ad,$msg)=&check_submission($response,$partid,$id,$tag, + $parstack,$safeeval); + if ($ad ne 'EXACT_ANS' && $ad ne 'APPROX_ANS') { + my $error; + if ($tag eq 'formularesponse') { + $error=&mt('Computer\'s answer is incorrect ("[_1]").',$response); + } else { + # answer failed check if it is sig figs that is failing + my ($ad,$msg)=&check_submission($response,$partid,$id, + $tag,$parstack, + $safeeval,1); + if ($sigline ne '') { + $error=&mt('Computer\'s answer is incorrect ("[_1]"). It is likely that the tolerance range [_2] or significant figures [_3] need to be adjusted.',$response,$tolline,$sigline); + } else { + $error=&mt('Computer\'s answer is incorrect ("[_1]"). It is likely that the tolerance range [_2] needs to be adjusted.',$response,$tolline); + } + } + if ($ad ne 'EXACT_ANS' && $ad ne 'APPROX_ANS') { + &Apache::lonxml::error($error); + } else { + &Apache::lonxml::warning($error); + } + } + if (defined($unit) and ($unit ne '') and $tag eq 'numericalresponse') { if ($target eq 'answer') { - if ($ENV{'form.answer_output_mode'} eq 'tex') { + if ($env{'form.answer_output_mode'} eq 'tex') { $result.=&Apache::response::answer_part($tag, " Unit: $unit "); } else { @@ -414,11 +570,11 @@ sub get_table_sizes { } $cell_width+=8; my $textwidth; - if ($ENV{'form.textwidth'} ne '') { - $ENV{'form.textwidth'}=~/(\d*)\.?(\d*)/; + if ($env{'form.textwidth'} ne '') { + $env{'form.textwidth'}=~/(\d*)\.?(\d*)/; $textwidth=$1.'.'.$2; } else { - $ENV{'textwidth'}=~/(\d+)\.?(\d*)/; + $env{'form.textwidth'}=~/(\d+)\.?(\d*)/; $textwidth=$1.'.'.$2; } my $bubbles_per_line=int($textwidth/$cell_width); @@ -442,7 +598,7 @@ sub format_number { my $ans; if ($format eq '') { #What is the number? (integer,decimal,floating point) - if ($number=~/^(\d*\.?\d*)(E|e)(\d*)$/) { + if ($number=~/^(\d*\.?\d*)(E|e)[+\-]?(\d*)$/) { $format = '3e'; } elsif ($number=~/^(\d*)\.(\d*)$/) { $format = '4f'; @@ -458,35 +614,56 @@ sub format_number { } sub make_numerical_bubbles { - my ($number_of_bubbles,$target,$answer,$format,$incorrect,$safeeval) =@_; + my ($part,$id,$target,$parstack,$safeeval) =@_; + + my $number_of_bubbles = + &Apache::response::get_response_param($part.'_'.$id,'numbubbles',8); + + my ($format)=&Apache::lonxml::get_param_var('format',$parstack,$safeeval); + my ($answer)=&Apache::lonxml::get_param_var('answer',$parstack,$safeeval); + my (@incorrect)=&Apache::lonxml::get_param_var('incorrect',$parstack, + $safeeval); + if ($#incorrect eq 0) { @incorrect=(split(/,/,$incorrect[0])); } + my @bubble_values=(); - &Apache::lonxml::debug("answer is $answer incorrect is $incorrect"); + my @alphabet=('A'..'Z'); + + &Apache::lonxml::debug("answer is $answer incorrect is @incorrect"); my @oldseed=&Math::Random::random_get_seed(); - if (defined($incorrect) && ref($incorrect)) { - &Apache::lonxml::debug("inside ".(scalar(@$incorrect)+1 gt $number_of_bubbles)); - if (defined($$incorrect[0]) && - scalar(@$incorrect)+1 >= $number_of_bubbles) { - &Apache::lonxml::debug("inside ".(scalar(@$incorrect)+1).":$number_of_bubbles"); + if (@incorrect) { + &Apache::lonxml::debug("inside ".(scalar(@incorrect)+1 gt $number_of_bubbles)); + if (defined($incorrect[0]) && + scalar(@incorrect)+1 >= $number_of_bubbles) { + &Apache::lonxml::debug("inside ".(scalar(@incorrect)+1).":$number_of_bubbles"); &Apache::response::setrandomnumber(); - my @rand_inc=&Math::Random::random_permutation(@$incorrect); + my @rand_inc=&Math::Random::random_permutation(@incorrect); @bubble_values=@rand_inc[0..($number_of_bubbles-2)]; @bubble_values=sort {$a <=> $b} (@bubble_values,$answer); - &Apache::lonxml::debug("Answer was :$answer: returning :".$#bubble_values.": whih are :".join(':',@bubble_values)); + &Apache::lonxml::debug("Answer was :$answer: returning :".$#bubble_values.": which are :".join(':',@bubble_values)); &Math::Random::random_set_seed(@oldseed); + + my $correct; + for(my $i=0; $i<=$#bubble_values;$i++) { + if ($bubble_values[$i] eq $answer) { + $correct = $alphabet[$i]; + last; + } + } + if (defined($format) && $format ne '') { my @bubble_display; foreach my $value (@bubble_values) { push(@bubble_display, &format_number($value,$format,$target,$safeeval)); } - return (\@bubble_values,\@bubble_display); + return (\@bubble_values,\@bubble_display,$correct); } else { - return (\@bubble_values,\@bubble_values); + return (\@bubble_values,\@bubble_values,$correct); } } - if (defined($$incorrect[0]) && - scalar(@$incorrect)+1 < $number_of_bubbles) { - &Apache::lonxml::warning("Not enough incorrect answers were specified in the incorrect array, ignoring the specified incorrect answers and instead generating them."); + if (defined($incorrect[0]) && + scalar(@incorrect)+1 < $number_of_bubbles) { + &Apache::lonxml::warning("Not enough incorrect answers were specified in the incorrect array, ignoring the specified incorrect answers and instead generating them (".join(',',@incorrect).")."); } } my @factors = (1.13,1.17,1.25,1.33,1.45); #default values of factors @@ -503,8 +680,9 @@ sub make_numerical_bubbles { $format,$target,$safeeval); } + my $correct = $alphabet[$number_of_bubbles-$power]; &Math::Random::random_set_seed(@oldseed); - return (\@bubble_values,\@bubble_display); + return (\@bubble_values,\@bubble_display,$correct); } sub get_tolrange { @@ -525,8 +703,8 @@ sub get_tolrange { sub get_sigrange { my ($sig)=@_; &Apache::lonxml::debug("Got a sig of :$sig:"); - my $courseid=$ENV{'request.course.id'}; - if (lc($ENV{"course.$courseid.disablesigfigs"}) eq 'yes') { + my $courseid=$env{'request.course.id'}; + if (lc($env{"course.$courseid.disablesigfigs"}) eq 'yes') { return (15,0); } my $sig_lbound; @@ -546,7 +724,7 @@ sub get_sigrange { ($sig_lbound > 15) || ($sig =~/(\+|-)/ ) ) { my $errormsg=&mt("Invalid Significant figures detected")." ($sig)"; - if ($ENV{'request.state'} eq 'construct') { + if ($env{'request.state'} eq 'construct') { $errormsg.= &Apache::loncommon::help_open_topic('Significant_Figures'); } @@ -598,7 +776,7 @@ sub start_stringresponse { sub end_stringresponse { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; - my $increment=1; + my $result = ''; my $part=$Apache::inputtags::part; my $id=$Apache::inputtags::response[-1]; @@ -609,23 +787,13 @@ sub end_stringresponse { if (!$Apache::lonxml::default_homework_loaded) { &Apache::lonxml::default_homework_load($safeeval); } - if ( $target eq 'grade' && defined($ENV{'form.submitted'})) { + if ( $target eq 'grade' && &Apache::response::submitted() ) { &Apache::response::setup_params('stringresponse',$safeeval); $safeeval->share_from('capa',['&caparesponse_capa_check_answer']); if ($Apache::lonhomework::type eq 'exam' || - $ENV{'form.submitted'} eq 'scantron') { - $increment=&Apache::response::scored_response($part,$id); - } elsif ($Apache::lonhomework::type eq 'survey') { - if ( !defined($ENV{'form.submitted'})) { return ''; } - my $response = &Apache::response::getresponse(); - if ( $response =~ /[^\s]/) { - my %previous=&Apache::response::check_for_previous($response, - $part,$id); - $Apache::lonhomework::results{"resource.$part.$id.submission"}= - $response; - my $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='SUBMITTED'; - &Apache::response::handle_previous(\%previous,$ad); - } + &Apache::response::submitted('scantron')) { + &Apache::response::scored_response($part,$id); + } else { my $response = &Apache::response::getresponse(); if ( $response =~ /[^\s]/) { @@ -644,7 +812,7 @@ sub end_stringresponse { # $answer=$token->[2]->{'answer'}; # } ${$safeeval->varglob('LONCAPA::response')}=$response; - $result = &Apache::run::run('return $LONCAPA::response=~m'.$answer,$safeeval); + $result = &Apache::run::run('if ($LONCAPA::response=~m'.$answer.') { return 1; } else { return 0; }',$safeeval); &Apache::lonxml::debug("current $response"); &Apache::lonxml::debug("current $answer"); $ad = ($result) ? 'APPROX_ANS' : 'INCORRECT'; @@ -668,24 +836,16 @@ sub end_stringresponse { ($ad,$msg) = &Apache::inputtags::finalizeawards(\@awards,\@msgs); &Apache::lonxml::debug("\n
result:$result:$Apache::lonxml::curdepth
\n"); } + if ($Apache::lonhomework::type eq 'survey' && + ($ad eq 'INCORRECT' || $ad eq 'APPROX_ANS' || + $ad eq 'EXACT_ANS')) { + $ad='SUBMITTED'; + } &Apache::response::handle_previous(\%previous,$ad); $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=$ad; $Apache::lonhomework::results{"resource.$part.$id.awardmsg"}=$msg; } } - } elsif ($target eq 'web' || $target eq 'tex') { - my $award = $Apache::lonhomework::history{"resource.$Apache::inputtags::part.solved"}; - my $status = $Apache::inputtags::status['-1']; - if ($Apache::lonhomework::type eq 'exam' && $target eq 'tex') { - $result.='\fbox{\fbox{\parbox{\textwidth-5mm}{\strut\\\\\strut\\\\\strut\\\\\strut\\\\}}}'; - $increment = &Apache::response::repetition(); - $result.='\begin{enumerate}'; - for (my $i=0;$i<$increment;$i++) { - $result.='\item[\textbf{'.($Apache::lonxml::counter+$i). - '}.]\textit{Leave blank on scoring form}\vskip 0 mm'; - } - $result.= '\end{enumerate}'; - } } elsif ($target eq 'answer' || $target eq 'analyze') { if ($target eq 'analyze') { push (@{ $Apache::lonhomework::analyze{"parts"} },"$part.$id"); @@ -700,6 +860,10 @@ sub end_stringresponse { # foreach my $ans (@answers) { if ($target eq 'answer') { $result.=&Apache::response::answer_part('stringresponse',$answer); + if ($type eq 're') { + $result.=&Apache::response::answer_part('stringresponse', + $answerdisplay); + } } elsif ($target eq 'analyze') { push (@{ $Apache::lonhomework::analyze{"$part.$id.answer"} }, $answer); @@ -716,7 +880,7 @@ sub end_stringresponse { $string='Regular Expression'; } if ($target eq 'answer') { - if ($ENV{'form.answer_output_mode'} eq 'tex') { + if ($env{'form.answer_output_mode'} eq 'tex') { $result.=&Apache::response::answer_part('stringresponse', "$string"); } else { @@ -735,7 +899,7 @@ sub end_stringresponse { } if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' || $target eq 'tex' || $target eq 'analyze') { - &Apache::lonxml::increment_counter($increment); + &Apache::lonxml::increment_counter(&Apache::response::repetition()); } &Apache::response::end_response; return $result;