--- loncom/homework/structuretags.pm 2004/08/10 18:25:53 1.263 +++ loncom/homework/structuretags.pm 2005/11/21 22:16:38 1.325 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # definition of tags that give a structure to a document # -# $Id: structuretags.pm,v 1.263 2004/08/10 18:25:53 sakharuk Exp $ +# $Id: structuretags.pm,v 1.325 2005/11/21 22:16:38 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -36,7 +36,7 @@ use Apache::File(); use Apache::lonmenu; use Apache::lonlocal; use Apache::lonxml; - +use Time::HiRes qw( gettimeofday tv_interval ); BEGIN { &Apache::lonxml::register('Apache::structuretags',('block','languageblock','instructorcomment','while','randomlist','problem','library','web','tex','part','preduedate','postanswerdate','solved','notsolved','problemtype','startouttext','endouttext','simpleeditbutton','definetag')); } @@ -68,6 +68,33 @@ sub end_tex { return ''; } +sub body_tag_start { + my ($target,$background,$bgcolor)=@_; + my $body_tag_start=''; + $form_tag_start='
'; } return ($result,$head_tag_start,$body_tag_start,$form_tag_start); } @@ -135,13 +161,14 @@ sub get_resource_name { if (defined($Apache::lonhomework::name)) { return $Apache::lonhomework::name; } - my $name=&Apache::lonnet::gettitle(); + my ($symb)=&Apache::lonxml::whichuser(); + my $name=&Apache::lonnet::gettitle($symb); if ($name eq '') { $name=&Apache::lonnet::EXT('resource.title'); if ($name eq 'con_lost') { $name = ''; } } if ($name!~/\S+/) { - $name=$ENV{'request.uri'}; + $name=$env{'request.uri'}; $name=~s-.*/([^/]+)$-$1-; } $Apache::lonhomework::name=$name; @@ -152,26 +179,28 @@ sub setup_rndseed { my ($safeeval)=@_; my $rndseed; my ($symb)=&Apache::lonxml::whichuser(); - if ($ENV{'request.state'} eq "construct" || $symb eq '' || + if ($env{'request.state'} eq "construct" || $symb eq '' || $Apache::lonhomework::history{'resource.CODE'}) { - $rndseed=$ENV{'form.rndseed'}; + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['rndseed']); + $rndseed=$env{'form.rndseed'}; if (!$rndseed) { $rndseed=$Apache::lonhomework::history{'rndseed'}; if (!$rndseed) { $rndseed=time; } - $ENV{'form.rndseed'}=$rndseed; + $env{'form.rndseed'}=$rndseed; } - if ($ENV{'form.resetdata'} eq &mt('New Problem Variation') || - $ENV{'form.newrandomization'} eq &mt('New Randomization')) { + if ($env{'form.resetdata'} eq &mt('New Problem Variation') || + $env{'form.newrandomization'} eq &mt('New Randomization')) { srand(time); $rndseed=int(rand(2100000000)); - $ENV{'form.rndseed'}=$rndseed; - delete($ENV{'form.resetdata'}); - delete($ENV{'form.newrandomization'}); + $env{'form.rndseed'}=$rndseed; + delete($env{'form.resetdata'}); + delete($env{'form.newrandomization'}); } if (defined($rndseed) && $rndseed ne int($rndseed)) { - $rndseed=join(',',&Math::Random::random_seed_from_phrase($rndseed)); + $rndseed=join(':',&Apache::lonnet::digest($rndseed)); } if ($Apache::lonhomework::history{'resource.CODE'}) { $rndseed=&Apache::lonnet::rndseed(); @@ -184,8 +213,16 @@ sub setup_rndseed { return $rndseed; } +sub remember_problem_state { + return ' + + + '; +} + sub problem_edit_header { - return ' + return ''. + &Apache::structuretags::remember_problem_state().' @@ -194,20 +231,20 @@ sub problem_edit_header {
'. &Apache::loncommon::help_open_menu('','Problem Editing Help','Problem_Editor_XML_Index','',5,'Authoring',undef,undef,undef,'Problem Editing Help') .'
'. - '
'; + '
'; } sub problem_edit_footer { return '

'. &Apache::lonhtmlcommon::htmlareaselectactive(@Apache::lonxml::htmlareafields). - "\n\n\n"; + "\n\n".&Apache::loncommon::endbodytag()."\n"; } sub option { my ($value,$name) = @_; my $result =" ".&option('problem','problemtype').&mt("Homework problem")." ".&option('survey' ,'problemtype').&mt("Survey Question")." @@ -261,15 +306,16 @@ Feedback Mode:
"; - my $numtoanalyze=$ENV{'form.numtoanalyze'}; - if (!$numtoanalyze) { $numtoanalyze=20; } - $result.= ' for + my $numtoanalyze=$env{'form.numtoanalyze'}; + if (!$numtoanalyze) { $numtoanalyze=20; } + $result.= ' for '.&mt('versions of this problem'). '.'.&Apache::loncommon::help_open_topic("Analyze_Problem", '',undef,undef,300). '
'; + } return $result; } @@ -277,9 +323,9 @@ sub initialize_storage { %Apache::lonhomework::results=(); %Apache::lonhomework::history=(); my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser(); - if ($ENV{'request.state'} eq 'construct' || $symb eq '') { + if ($env{'request.state'} eq 'construct' || $symb eq '') { %Apache::lonhomework::history= - &Apache::lonnet::tmprestore($ENV{'request.uri'},'',$domain,$name); + &Apache::lonnet::tmprestore($env{'request.uri'},'',$domain,$name); my ($temp)=keys %Apache::lonhomework::history ; &Apache::lonxml::debug("Return message of $temp"); } else { @@ -295,24 +341,73 @@ sub initialize_storage { # Stores away the result has to a student's environment # checks form.grade_ for specific values, other wises stores # to the running users environment +# Will increment totals for attempts, students, and corrects +# if running user has student role. sub finalize_storage { my $result; - my ($temp) = keys %Apache::lonhomework::results; - if ( $temp ne '' ) { + if (%Apache::lonhomework::results) { + my @remove = grep(/^INTERNAL_/,keys(%Apache::lonhomework::results)); + delete(@Apache::lonhomework::results{@remove}); my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser(); - if ($ENV{'request.state'} eq 'construct' || $symb eq '') { - $Apache::lonhomework::results{'rndseed'}=$ENV{'form.rndseed'}; + if ($env{'request.state'} eq 'construct' || $symb eq '') { + $Apache::lonhomework::results{'rndseed'}=$env{'form.rndseed'}; $result=&Apache::lonnet::tmpstore(\%Apache::lonhomework::results, - $ENV{'request.uri'},'',$domain,$name); + $env{'request.uri'},'',$domain,$name); &Apache::lonxml::debug('Construct Store return message:'.$result); } else { $result=&Apache::lonnet::cstore(\%Apache::lonhomework::results, $symb,$courseid,$domain,$name); &Apache::lonxml::debug('Store return message:'.$result); + if ($env{'request.role'} =~/^st/) { + &store_aggregates($symb,$courseid); + } } + } else { + &Apache::lonxml::debug('Nothing to store'); } return $result; } +use Data::Dumper; + +# -------------------------------------------------------------store_aggregates +# Sends hash of values to be incremented in nohist_resourcetracker.db +# for the course. Increments total number of attempts, unique students +# and corrects for each part for an instance of a problem, as appropriate. +sub store_aggregates { + my ($symb,$courseid) = @_; + my %aggregate; + my @parts; + my $cdomain = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cname = $env{'course.'.$env{'request.course.id'}.'.num'}; + foreach my $key (keys(%Apache::lonhomework::results)) { + if ($key =~ /resource\.([^\.]+)\.tries/) { + push(@parts, $1); + } + } + foreach my $part (@parts) { + if ($Apache::lonhomework::results{'resource.'.$part.'.award'} + eq 'APPROX_ANS' || + $Apache::lonhomework::results{'resource.'.$part.'.award'} + eq 'EXACT_ANS') { + $aggregate{$symb."\0".$part."\0correct"} = 1; + } + if ($Apache::lonhomework::results{'resource.'.$part.'.tries'} == 1) { + $aggregate{$symb."\0".$part."\0users"} = 1; + } else { + my (undef,$last_reset) = &Apache::grades::get_last_resets($symb,$env{'request.course.id'},[$part]); + if ($last_reset) { + if (&Apache::grades::get_num_tries(\%Apache::lonhomework::history,$last_reset,$part) == 0) { + $aggregate{$symb."\0".$part."\0users"} = 1; + } + } + } + $aggregate{$symb."\0".$part."\0attempts"} = 1; + } + if (keys (%aggregate) > 0) { + &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, + $cdomain,$cname); + } +} sub checkout_msg { my %lt=&Apache::lonlocal::texthash( @@ -327,7 +422,7 @@ sub checkout_msg {

$lt{'warning'}

-
+
@@ -341,7 +436,7 @@ sub firstaccess_msg { &Apache::lonxml::debug("map is $map title is $foldertitle"); return (<The resources in "$foldertitle" are open for a limited time. Once you click the 'Show Resource' button below you have $time to complete all resources "$foldertitle". -
+
@@ -351,15 +446,26 @@ ENDCHECKOUT sub init_problem_globals { my ($type)=@_; #initialize globals + # For problems, we start out in part 0 (outside a tag). + # and part 0 is used to describe the main body of the + # if ($type eq 'problem') { $Apache::inputtags::part='0'; @Apache::inputtags::partlist=('0'); + $Apache::lonhomework::problemstatus=&get_problem_status('0'); + $Apache::lonhomework::ignore_response_errors=0; - $Apache::lonhomework::problemstatus=&get_problem_status('0') - } else { + } elsif ($type eq 'library') { $Apache::inputtags::part=''; @Apache::inputtags::partlist=(); $Apache::lonhomework::problemstatus=''; + $Apache::lonhomework::ignore_response_errors=1; + + } elsif ($type eq 'Task') { + $Apache::inputtags::part='0'; + @Apache::inputtags::partlist=('0'); + $Apache::lonhomework::problemstatus=''; + $Apache::lonhomework::ignore_response_errors=1; } @Apache::inputtags::responselist = (); @Apache::inputtags::importlist = (); @@ -387,7 +493,7 @@ sub reset_problem_globals { sub set_problem_state { my ($part)=@_; - if ($ENV{'form.problemstate'} eq 'CANNOT_ANSWER_correct') { + if ($env{'form.problemstate'} eq 'CANNOT_ANSWER_correct') { $Apache::lonhomework::history{"resource.$part.solved"}= 'correct_by_student'; } @@ -395,12 +501,14 @@ sub set_problem_state { sub get_problem_status { my ($part)=@_; - my $problem_status=&Apache::lonnet::EXT("resource.$part.problemstatus"); - &Apache::lonxml::debug("problem status for $part is $problem_status"); - &Apache::lonxml::debug("env probstat is ".$ENV{'form.problemstatus'}); - if ($ENV{'request.state'} eq 'construct' && - defined($ENV{'form.problemstatus'})) { - $problem_status=$ENV{'form.problemstatus'}; + my $problem_status; + if ($env{'request.state'} eq 'construct' && + defined($env{'form.problemstatus'})) { + $problem_status=$env{'form.problemstatus'}; + } else { + $problem_status=&Apache::lonnet::EXT("resource.$part.problemstatus"); + &Apache::lonxml::debug("problem status for $part is $problem_status"); + &Apache::lonxml::debug("env probstat is ".$env{'form.problemstatus'}); } return $problem_status; } @@ -408,6 +516,14 @@ sub get_problem_status { sub start_problem { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + # We'll use the redirection to fix up printing of duedates. + if (!$Apache::lonxml::metamode) { + &Apache::lonxml::startredirection(); + } + + # Problems don't nest and we don't allow more than one in + # a .problem file. + # if ( $Apache::inputtags::part ne '' || $Apache::lonhomework::parsing_a_problem) { &Apache::lonxml::error('Only one <problem> allowed in a .problem file'); @@ -418,7 +534,7 @@ sub start_problem { $Apache::lonhomework::parsing_a_problem=1; &init_problem_globals('problem'); - if (defined($ENV{'scantron.maxquest'})) { + if (defined($env{'scantron.maxquest'})) { $Apache::lonhomework::scantronmode=1; } @@ -427,16 +543,16 @@ sub start_problem { if ($target eq 'web') { &Apache::lonhomework::showhash(%Apache::lonhomework::history); } - if ($ENV{'request.state'} eq 'construct') { &set_problem_state('0'); } + if ($env{'request.state'} eq 'construct') { &set_problem_state('0'); } $Apache::lonhomework::type=&Apache::lonnet::EXT('resource.0.type'); - if (($ENV{'request.state'} eq 'construct') && - defined($ENV{'form.problemtype'})) { - $Apache::lonhomework::type=$ENV{'form.problemtype'}; + if (($env{'request.state'} eq 'construct') && + defined($env{'form.problemtype'})) { + $Apache::lonhomework::type=$env{'form.problemtype'}; } &Apache::lonxml::debug("Found this to be of type :$Apache::ltonhomework::type:"); } if ($Apache::lonhomework::type eq '' ) { - my $uri=$ENV{'request.uri'}; + my $uri=$env{'request.uri'}; if ($uri=~/\.(\w+)$/) { $Apache::lonhomework::type=$1; &Apache::lonxml::debug("Using type of $1"); @@ -445,6 +561,7 @@ sub start_problem { &Apache::lonxml::debug("Using default type, problem, :$uri:"); } } + $Apache::lonhomework::default_type = $Apache::lonhomework::type; #added vars to the scripting enviroment my $expression='$external::part=\''.$Apache::inputtags::part.'\';'; @@ -456,7 +573,7 @@ sub start_problem { #should get back a or the neccesary stuff to start XML/MathML my ($result,$head_tag_start,$body_tag_start,$form_tag_start)= &page_start($target,$token,$tagstack,$parstack,$parser,$safeeval); - if ($target eq 'tex' and $ENV{'request.symb'} =~ m/\.page_/) {$result='';} + if ($target eq 'tex' and $env{'request.symb'} =~ m/\.page_/) {$result='';} if ($target eq 'analyze') { my $rndseed=&setup_rndseed($safeeval); } if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || @@ -465,38 +582,53 @@ sub start_problem { if ($Apache::lonhomework::type eq 'exam') { my $token= $Apache::lonhomework::history{"resource.0.outtoken"}; - if (($ENV{'form.doescheckout'}) && (!$token)) { + if (($env{'form.doescheckout'}) && (!$token)) { $token=&Apache::lonxml::maketoken(); $Apache::lonhomework::history{"resource.0.outtoken"}= $token; } $body_tag_start.=&Apache::lonxml::printtokenheader($target,$token); } - if ($ENV{'form.markaccess'}) { + if ($env{'form.markaccess'}) { &Apache::lonnet::set_first_access('map'); } #handle rand seed in construction space my $rndseed=&setup_rndseed($safeeval); my ($symb)=&Apache::lonxml::whichuser(); - if ($ENV{'request.state'} ne "construct" && $symb eq '') { + if ($env{'request.state'} ne "construct" && $symb eq '') { $form_tag_start.=''. ''. '
'; + value="'.$env{'form.username'}.'" />'; + if ($env{'user.adv'}) { + $form_tag_start.= + '