--- loncom/homework/hint.pm 2003/04/18 07:53:15 1.41 +++ loncom/homework/hint.pm 2006/12/19 00:40:38 1.65 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # implements the tags that control the hints # -# $Id: hint.pm,v 1.41 2003/04/18 07:53:15 albertel Exp $ +# $Id: hint.pm,v 1.65 2006/12/19 00:40:38 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -29,11 +29,16 @@ package Apache::hinttags; use strict; -use Apache::lonnet; +use Apache::lonnet(); use capa; +use Apache::caparesponse(); +use Apache::lonmaxima(); +use Apache::response(); +use Apache::lonlocal; +use Storable qw(dclone); BEGIN { - &Apache::lonxml::register('Apache::hinttags',('hintgroup','hintpart','numericalhint','stringhint','formulahint','optionhint','radiobuttonhint')); + &Apache::lonxml::register('Apache::hinttags',('hintgroup','hintpart','numericalhint','stringhint','formulahint','optionhint','radiobuttonhint','mathhint','customhint')); } @@ -47,15 +52,30 @@ sub start_hintgroup { my $id=$Apache::inputtags::part; my $numtries=$Apache::lonhomework::history{"resource.$id.tries"}; if ( $numtries eq '') { $numtries = 0; } - my $hinttries=&Apache::lonnet::EXT("resource.$id.hinttries"); - if ( $hinttries eq '') { $hinttries = 1; } + my $hinttries=&Apache::response::get_response_param($id,"hinttries",1); &Apache::lonxml::debug("found :$id:$numtries:$hinttries:"); - if ( $numtries < $hinttries ) { - &Apache::lonxml::get_all_text("/hintgroup",$parser); + my $gradestatus= + $Apache::lonhomework::history{"resource.$id.solved"}; + my $showoncorrect=lc(&Apache::lonxml::get_param('showoncorrect',$parstack,$safeeval)); + &Apache::lonxml::debug("onc orrect $showoncorrect, $gradestatus"); + if ( ($showoncorrect ne 'yes' && &Apache::response::show_answer()) || + ( $numtries < $hinttries) ) { + &Apache::lonxml::debug("Grabbin all"); + &Apache::lonxml::get_all_text("/hintgroup",$parser,$style); } &Apache::lonxml::startredirection; } elsif ($target eq 'tex') { $result .= '\keephidden{'; + } elsif ($target eq 'edit') { + $result.=&Apache::edit::tag_start($target,$token); + $result.=&Apache::edit::select_arg('Show hint even if problem Correct:','showoncorrect',[['no',&mt('No')],['yes',&mt('Yes')]],$token); + $result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row(); + } elsif ($target eq 'modified') { + my $constructtag=&Apache::edit::get_new_args($token,$parstack,$safeeval,'showoncorrect'); + if ($constructtag) { + $result =&Apache::edit::rebuild_tag($token); + $result.=&Apache::edit::handle_insert(); + } } @Apache::hint::which=(); return $result; @@ -69,8 +89,7 @@ sub end_hintgroup { my $id=$Apache::inputtags::part; my $numtries=$Apache::lonhomework::history{"resource.$id.tries"}; if ( $numtries eq '') { $numtries = 0; } - my $hinttries=&Apache::lonnet::EXT("resource.$id.hinttries"); - if ( $hinttries eq '') { $hinttries = 1; } + my $hinttries=&Apache::response::get_response_param($id,"hinttries",1); &Apache::lonxml::debug("found :$id:$numtries:$hinttries:"); my $hinttext=&Apache::lonxml::endredirection; if ($Apache::lonhomework::type ne 'exam' && @@ -79,7 +98,7 @@ sub end_hintgroup { $hinttext.''; } } elsif ($target eq 'edit') { - $result.=&Apache::edit::end_table(); + $result.=&Apache::edit::end_row().&Apache::edit::end_table(); } elsif ($target eq 'tex') { $result .= '}'; } @@ -101,10 +120,10 @@ sub start_numericalhint { &Apache::loncommon::help_open_topic('Physical_Units'); $result.=&Apache::edit::text_arg('Format:','format',$token,4). &Apache::loncommon::help_open_topic('Numerical_Response_Format'); - } elsif ($token->[1] eq 'stringhint') { - $result.=&Apache::edit::select_arg('Type:','type',['cs','ci','mc'],$token); } elsif ($token->[1] eq 'formulahint') { - $result.=&Apache::edit::text_arg('Sample Points:','samples',$token,40); + $result.=&Apache::edit::text_arg('Sample Points:','samples', + $token,40). + &Apache::loncommon::help_open_topic('Formula_Response_Sampling'); } $result.=&Apache::edit::end_row(); $result.=&Apache::edit::start_spanning_row(); @@ -114,10 +133,6 @@ sub start_numericalhint { $constructtag=&Apache::edit::get_new_args($token,$parstack, $safeeval,'name', 'answer','unit','format'); - } elsif ($token->[1] eq 'stringhint') { - $constructtag=&Apache::edit::get_new_args($token,$parstack, - $safeeval,'name','answer', - 'type'); } elsif ($token->[1] eq 'formulahint') { $constructtag=&Apache::edit::get_new_args($token,$parstack, $safeeval,'name','answer', @@ -141,53 +156,304 @@ sub end_numericalhint { &Apache::lonxml::default_homework_load($safeeval); } $safeeval->share_from('capa',['&caparesponse_capa_check_answer']); - my $name= &Apache::lonxml::get_param('name',$parstack,$safeeval); - &Apache::response::setup_params('numericalhint'); + my $hint_name= &Apache::lonxml::get_param('name',$parstack,$safeeval); + &Apache::response::setup_params('numericalhint',$safeeval); + my $partid=$Apache::inputtags::part; - my $id=$Apache::inputtags::response['-1']; + my $id=$Apache::inputtags::hint[-1]; #id submissions occured under - my $submitid=$Apache::inputtags::response['-2']; + my $submitid=$Apache::inputtags::response[-1]; + my $response = $Apache::lonhomework::history{ "resource.$partid.$submitid.submission"}; &Apache::lonxml::debug("hintgroup is using $response
\n"); - #build safe space expression - my $expression="&caparesponse_check_list('".$response."','". - $$parstack[$#$parstack]; - #need to get all possible parms - foreach my $key (keys(%Apache::inputtags::params)) { - $expression.= ';my $'. #' - $key.'="'.$Apache::inputtags::params{$key}.'"'; - } - $expression.="');"; - $result = &Apache::run::run($expression,$safeeval); - &Apache::lonxml::debug("$expression:result:$result:$Apache::lonxml::curdepth"); - my ($awards) = split /:/ , $result; - my ($ad) = &Apache::inputtags::finalizeawards(split /,/ , $awards); - if ($ad eq 'EXACT_ANS' || $ad eq 'APPROX_ANS') { push (@Apache::hint::which,$name); } + + my @args = ('type','tol','sig','ans_fmt','unit','calc','samples'); + my $args_ref = + &Apache::caparesponse::setup_capa_args($safeeval,$parstack, + \@args,$response); + + my $hideunit=&Apache::response::get_response_param($partid.'_'.$submitid,'turnoffunit'); + if (lc($hideunit) eq "yes") { delete($$args_ref{'unit'}); } + + if ($$tagstack[-1] eq 'formulahint') { + $$args_ref{'type'}='fml'; + } elsif ($$tagstack[-1] eq 'numericalhint') { + $$args_ref{'type'}='float'; + } + &Apache::caparesponse::add_in_tag_answer($parstack,$safeeval); + my %answer = &Apache::caparesponse::get_answer(); + my (@final_awards,@final_msgs,@ans_names); + foreach my $ans_name (keys(%answer)) { + &Apache::lonxml::debug(" doing $ans_name with ".join(':',@{ $answer{$ans_name}{'answers'} })); + + ${$safeeval->varglob('LONCAPA::CAPAresponse_answer')}= + dclone($answer{$ans_name}); + &Apache::caparesponse::setup_capa_response($args_ref,$response); + my ($result,@msgs) = + &Apache::run::run("&caparesponse_check_list()",$safeeval); + &Apache::lonxml::debug("checking $ans_name $result with $response"); + &Apache::lonxml::debug('msgs are '.join(':',@msgs)); + my ($awards)=split(/:/,$result); + my @awards= split(/,/,$awards); + my ($ad, $msg) = + &Apache::inputtags::finalizeawards(\@awards,\@msgs); + push(@final_awards,$ad); + push(@final_msgs,$msg); + push(@ans_names,$ans_name); + } + my ($ad, $msg, $ans_name) = + &Apache::inputtags::finalizeawards(\@final_awards, + \@final_msgs, + \@ans_names,1); + if ($ad eq 'EXACT_ANS' || $ad eq 'APPROX_ANS') { + push(@Apache::hint::which,$hint_name); + } $result=''; } elsif ($target eq 'meta') { $result=&Apache::response::meta_package_write($token->[1]); } elsif ($target eq 'edit') { - $result.=''.&Apache::edit::end_table; + $result.=&Apache::edit::end_row().&Apache::edit::end_table(); } &Apache::response::end_hintresponse(); return $result; } -sub start_stringhint { +sub start_formulahint { return &start_numericalhint(@_); } -sub end_stringhint { +sub end_formulahint { return &end_numericalhint(@_); } -sub start_formulahint { - return &start_numericalhint(@_); +sub start_mathhint { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + #do everything in end, so intervening and work + &Apache::response::start_hintresponse($parstack,$safeeval); + &Apache::lonxml::register('Apache::response',('answer')); + my $result; + if ($target eq 'edit') { + $result.=&Apache::edit::tag_start($target,$token); + $result.=&Apache::edit::text_arg('Name:','name',$token); + $result.=&Apache::edit::select_arg('Algebra System:', + 'cas', + ['maxima'], + $token); + $result.=&Apache::edit::text_arg('Argument Array:', + 'args',$token); + $result.=&Apache::edit::end_row(); + $result.=&Apache::edit::start_spanning_row(); + } elsif ($target eq 'modified') { + my $constructtag; + $constructtag=&Apache::edit::get_new_args($token,$parstack, + $safeeval,'name','cas', + 'args'); + $result = &Apache::edit::rebuild_tag($token); + $result .= &Apache::edit::handle_insert(); + } elsif ($target eq 'web') { + &Apache::response::reset_params(); + } + return $result; } -sub end_formulahint { - return end_numericalhint(@_); +sub end_mathhint { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + my $result; + if ($target eq 'web') { + if (!$Apache::lonxml::default_homework_loaded) { + &Apache::lonxml::default_homework_load($safeeval); + } + my $name= &Apache::lonxml::get_param('name',$parstack,$safeeval); + &Apache::response::setup_params('mathhint',$safeeval); + my $partid=$Apache::inputtags::part; + my $submitid=$Apache::inputtags::response[-1]; + my $response = $Apache::lonhomework::history{ + "resource.$partid.$submitid.submission"}; + + my $cas = &Apache::lonxml::get_param('cas',$parstack,$safeeval); + my $award; + if ($cas eq 'maxima') { + my $args = [&Apache::lonxml::get_param_var('args',$parstack,$safeeval)]; + $award=&Apache::lonmaxima::maxima_run($Apache::response::custom_answer[-1],$response,$args); + } + if ($award eq 'EXACT_ANS' || $award eq 'APPROX_ANS') { + push (@Apache::hint::which,$name); + } + $result=''; + } elsif ($target eq 'meta') { + $result=&Apache::response::meta_package_write($token->[1]); + } elsif ($target eq 'edit') { + $result.=&Apache::edit::end_row().&Apache::edit::end_table(); + } + pop(@Apache::response::custom_answer); + pop(@Apache::response::custom_answer_type); + &Apache::response::end_hintresponse(); + return $result; +} + +sub start_customhint { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + #do everything in end, so intervening and work + &Apache::response::start_hintresponse($parstack,$safeeval); + &Apache::lonxml::register('Apache::response',('answer')); + my $result; + if ($target eq 'edit') { + $result.=&Apache::edit::tag_start($target,$token); + $result.=&Apache::edit::text_arg('Name:','name',$token); + $result.=&Apache::edit::end_row(); + $result.=&Apache::edit::start_spanning_row(); + } elsif ($target eq 'modified') { + my $constructtag; + $constructtag=&Apache::edit::get_new_args($token,$parstack, + $safeeval,'name'); + $result = &Apache::edit::rebuild_tag($token); + $result .= &Apache::edit::handle_insert(); + } elsif ($target eq 'web') { + &Apache::response::reset_params(); + } + return $result; +} + +sub end_customhint { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + my $result; + if ($target eq 'web') { + if (!$Apache::lonxml::default_homework_loaded) { + &Apache::lonxml::default_homework_load($safeeval); + } + my $name= &Apache::lonxml::get_param('name',$parstack,$safeeval); + &Apache::response::setup_params('customhint',$safeeval); + my $partid=$Apache::inputtags::part; + my $submitid=$Apache::inputtags::response[-1]; + my $response = $Apache::lonhomework::history{ + "resource.$partid.$submitid.submission"}; + my $award; + if ( $response =~ /[^\s]/ && + $Apache::response::custom_answer_type[-1] eq 'loncapa/perl') { + if (!$Apache::lonxml::default_homework_loaded) { + &Apache::lonxml::default_homework_load($safeeval); + } + ${$safeeval->varglob('LONCAPA::customresponse_submission')}= + $response; + + $award = &Apache::run::run('{ my $submission=$LONCAPA::customresponse_submission;'.$Apache::response::custom_answer[-1].'}',$safeeval); + } + if ($award eq 'EXACT_ANS' || $award eq 'APPROX_ANS') { + push (@Apache::hint::which,$name); + } + $result=''; + } elsif ($target eq 'meta') { + $result=&Apache::response::meta_package_write($token->[1]); + } elsif ($target eq 'edit') { + $result.=&Apache::edit::end_row().&Apache::edit::end_table(); + } + pop(@Apache::response::custom_answer); + pop(@Apache::response::custom_answer_type); + &Apache::response::end_hintresponse(); + return $result; +} + +sub start_stringhint { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + #do everything in end, so intervening work + &Apache::response::start_hintresponse($parstack,$safeeval); + my $result; + if ($target eq 'edit') { + $result.=&Apache::edit::tag_start($target,$token); + $result.=&Apache::edit::text_arg('Name:','name',$token); + $result.=&Apache::edit::text_arg('Answer:','answer',$token); + $result.=&Apache::edit::select_arg('Type:','type', + [['cs','Case Sensitive'],['ci','Case Insensitive'], + ['mc','Case Insensitive, Any Order'], + ['re','Regular Expression']],$token); + $result.=&Apache::edit::end_row(); + $result.=&Apache::edit::start_spanning_row(); + } elsif ($target eq 'modified') { + my $constructtag; + $constructtag=&Apache::edit::get_new_args($token,$parstack, + $safeeval,'name','answer', + 'type'); + $result = &Apache::edit::rebuild_tag($token); + $result .= &Apache::edit::handle_insert(); + } elsif ($target eq 'web') { + &Apache::response::reset_params(); + } + return $result; +} + +sub end_stringhint { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + my $result; + if ($target eq 'web') { + if (!$Apache::lonxml::default_homework_loaded) { + &Apache::lonxml::default_homework_load($safeeval); + } + $safeeval->share_from('capa',['&caparesponse_capa_check_answer']); + my $hint_name= &Apache::lonxml::get_param('name',$parstack,$safeeval); + &Apache::response::setup_params('stringhint',$safeeval); + my $partid=$Apache::inputtags::part; + my $id=$Apache::inputtags::hint[-1]; + #id submissions occured under + my $submitid=$Apache::inputtags::response[-1]; + my $response = $Apache::lonhomework::history{ + "resource.$partid.$submitid.submission"}; + &Apache::lonxml::debug("hintgroup is using $response
\n"); + my $type = &Apache::lonxml::get_param('type',$parstack,$safeeval); + my ($ad,$msg); + if ($type eq 're' ) { + my $answer=&Apache::lonxml::get_param('answer',$parstack, + $safeeval); + ${$safeeval->varglob('LONCAPA::response')}=$response; + my $compare='='; + if ($answer=~/^\s*NOT\s*/) { + $answer=~s/^\s*NOT\s*//; + $compare='!'; + } + my $test='$LONCAPA::response'.$compare.'~m'.$answer; + &Apache::lonxml::debug("test $test"); + $result = &Apache::run::run("return $test",$safeeval); + &Apache::lonxml::debug("current $response"); + &Apache::lonxml::debug("current $answer"); + $ad = ($result) ? 'APPROX_ANS' : 'INCORRECT'; + } else { + my @args = ('type'); + my $args_ref = + &Apache::caparesponse::setup_capa_args($safeeval,$parstack, + \@args,$response); + &Apache::caparesponse::add_in_tag_answer($parstack,$safeeval); + my (@final_awards,@final_msgs,@ans_names); + my %answer = &Apache::caparesponse::get_answer(); + foreach my $ans_name (keys(%answer)) { + &Apache::lonxml::debug(" doing $ans_name with ".join(':',@{ $answer{$ans_name}{'answers'} })); + ${$safeeval->varglob('LONCAPA::CAPAresponse_answer')}=dclone($answer{$ans_name}); + 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); + ($ad,$msg) = + &Apache::inputtags::finalizeawards(\@awards,\@msgs); + push(@final_awards,$ad); + push(@final_msgs,$msg); + push(@ans_names,$ans_name); + &Apache::lonxml::debug("\n
result:$result:$Apache::lonxml::curdepth
\n"); + } + my ($ad, $msg, $ans_name) = + &Apache::inputtags::finalizeawards(\@final_awards, + \@final_msgs, + \@ans_names,1); + } + if ($ad eq 'EXACT_ANS' || $ad eq 'APPROX_ANS') { + push(@Apache::hint::which,$hint_name); + } + $result=''; + } elsif ($target eq 'meta') { + $result=&Apache::response::meta_package_write($token->[1]); + } elsif ($target eq 'edit') { + $result.=&Apache::edit::end_row().&Apache::edit::end_table(); + } + &Apache::response::end_hintresponse(); + return $result; } # a part shows if it is on, if no specific parts are on, then default shows @@ -206,10 +472,10 @@ sub start_hintpart { foreach $which (@Apache::hint::which) { if ($which eq $on) { $show = 1; last } } } if (!$show) { - &Apache::lonxml::get_all_text("/hintpart",$parser); + &Apache::lonxml::get_all_text("/hintpart",$parser,$style); } } elsif ($target eq 'grade') { - &Apache::lonxml::get_all_text("/hintpart",$parser); + &Apache::lonxml::get_all_text("/hintpart",$parser,$style); } elsif ($target eq 'edit') { $result.= &Apache::edit::tag_start($target,$token); $result.= &Apache::edit::text_arg('On:','on',$token); @@ -229,7 +495,9 @@ sub start_hintpart { sub end_hintpart { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result; - if ($target eq 'edit') { $result.=&Apache::edit::end_table; } + if ($target eq 'edit') { + $result.=&Apache::edit::end_row().&Apache::edit::end_table(); + } return $result; } @@ -264,12 +532,13 @@ sub end_optionhint { my $name= &Apache::lonxml::get_param('name',$parstack,$safeeval); my $partid=$Apache::inputtags::part; #id submissions occured under - my $submitid=$Apache::inputtags::response['-2']; + my $submitid=$Apache::inputtags::response[-1]; my $part_id="$partid.$submitid"; my %answer; my $answer=&Apache::lonxml::get_param('answer',$parstack,$safeeval); if ($answer) { eval('%answer ='.$answer); + &Apache::lonxml::debug("answwer hash"); &Apache::lonhomework::showhash(%answer); my $response = $Apache::lonhomework::history{ "resource.$part_id.submission"}; @@ -305,8 +574,9 @@ sub end_optionhint { ($foilmatch eq '-1' || $foilmatch eq '1') ) { push(@Apache::hint::which,$name); } - } elsif ($target eq 'edit') { $result.=&Apache::edit::end_table; } - if ($target eq 'edit') { $result.=&Apache::edit::end_table; } + } elsif ($target eq 'edit') { + $result.=&Apache::edit::end_row().&Apache::edit::end_table(); + } &Apache::response::end_hintresponse(); return $result; } @@ -343,22 +613,36 @@ sub end_radiobuttonhint { eval('@answer ='.$answer); my $partid=$Apache::inputtags::part; #id submissions occured under - my $submitid=$Apache::inputtags::response['-2']; + my $submitid=$Apache::inputtags::response[-1]; my $part_id="$partid.$submitid"; my $response = $Apache::lonhomework::history{ "resource.$part_id.submission"}; ($response)=&Apache::lonnet::str2hash($response); - if ($answer[0] eq 'foil' && $response eq $answer[1]) { - push (@Apache::hint::which,$name); + &Apache::lonxml::debug("response is $response"); + + if ($answer[0] eq 'foil') { + shift(@answer); + foreach my $answer (@answer) { + if ($response eq $answer) { + push (@Apache::hint::which,$name); + last; + } + } } elsif ($answer[0] eq 'concept') { - if (ref($Apache::hint::radiobutton{"$part_id.concept.".$answer[1]})) { - my @names=@{ $Apache::hint::radiobutton{"$part_id.concept.".$answer[1]} }; - if (grep(/^\Q$response\E$/,@names)) { - push(@Apache::hint::which,$name); + shift(@answer); + foreach my $answer (@answer) { + if (ref($Apache::hint::radiobutton{"$part_id.concept.".$answer})) { + my @names=@{ $Apache::hint::radiobutton{"$part_id.concept.".$answer} }; + if (grep(/^\Q$response\E$/,@names)) { + push(@Apache::hint::which,$name); + last; + } } } } - } elsif ($target eq 'edit') { $result.=&Apache::edit::end_table; } + } elsif ($target eq 'edit') { + $result.=&Apache::edit::end_row().&Apache::edit::end_table(); + } &Apache::response::end_hintresponse(); return $result; } 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.