# The LearningOnline Network with CAPA # definition of tags that give a structure to a document # # $Id: structuretags.pm,v 1.220 2003/11/01 16:37:21 www Exp $ # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). # # LON-CAPA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # LON-CAPA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with LON-CAPA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ # # 2/19 Guy # 6/26/2001 fixed extra web display at end of tags # 8/17,8/18,8/20 Gerd Kortemeyer package Apache::structuretags; use strict; use Apache::lonnet; use Apache::File(); use Apache::lonmenu; use Apache::lonlocal; BEGIN { &Apache::lonxml::register('Apache::structuretags',('block','languageblock','instructorcomment','while','randomlist','problem','library','web','tex','part','preduedate','postanswerdate','solved','notsolved','startouttext','endouttext', 'simpleeditbutton','definetag')); } sub start_web { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $bodytext=&Apache::lonxml::get_all_text("/web",$parser); if ($target eq 'web') { return $bodytext; } return ''; } sub end_web { return ''; } sub start_tex { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result=''; my $bodytext=&Apache::lonxml::get_all_text("/tex",$parser); if ($target eq 'tex') { return $bodytext.' '; } return $result;; } sub end_tex { return ''; } sub page_start { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my %found; foreach my $taginside (@$tagstack) { foreach my $taglookedfor ('html','body','form') { if ($taginside =~ /^$taglookedfor$/i) {$found{$taglookedfor} = 1;} } } my $result; my $head_tag_start; if (!defined($found{'html'})) { $result=&Apache::londefdef::start_html($target,$token,$tagstack, $parstack,$parser,$safeeval); $head_tag_start=''.&Apache::lonmenu::registerurl(undef,$target); } my $body_tag_start; if (!defined($found{'body'})) { $body_tag_start='"; $body_tag_start.=$help; } } } my $form_tag_start; if (!defined($found{'form'})) { $form_tag_start='
'; } return ($result,$head_tag_start,$body_tag_start,$form_tag_start); } #use Time::HiRes(); sub get_resource_name { my ($parstack,$safeeval)=@_; if (defined($Apache::lonhomework::name)) { return $Apache::lonhomework::name; } my $name=&Apache::lonnet::gettitle(); if ($name eq '') { $name=&Apache::lonnet::EXT('resource.title'); if ($name eq 'con_lost') { $name = ''; } } if ($name!~/\S+/) { $name=$ENV{'request.uri'}; $name=~s-.*/([^/]+)$-$1-; } $Apache::lonhomework::name=$name; return $name; } sub setup_rndseed { my ($safeeval)=@_; my $rndseed; my ($symb)=&Apache::lonxml::whichuser(); if ($ENV{'request.state'} eq "construct" || $symb eq '') { $rndseed=$ENV{'form.rndseed'}; if (!$rndseed) { $rndseed=$Apache::lonhomework::history{'rndseed'}; if (!$rndseed) { $rndseed=time; $ENV{'form.rndseed'}=$rndseed; } } 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'}); } if (defined($rndseed) && $rndseed ne int($rndseed)) { $rndseed=join(',',&Math::Random::random_seed_from_phrase($rndseed)); } &Apache::lonxml::debug("Setting rndseed to $rndseed"); &Apache::run::run('$external::randomseed='.$rndseed.';',$safeeval); } return $rndseed; } sub problem_edit_header { return '

 

'; } sub problem_edit_footer { return '

'; } sub problem_web_to_edit_header { my ($rndseed)=@_; my $result.=' '; 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; } 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 '') { %Apache::lonhomework::history= &Apache::lonnet::tmprestore($ENV{'request.uri'},'',$domain,$name); my ($temp)=keys %Apache::lonhomework::history ; &Apache::lonxml::debug("Return message of $temp"); } else { %Apache::lonhomework::history= &Apache::lonnet::restore($symb,$courseid,$domain,$name); } #ignore error conditions my ($temp)=keys %Apache::lonhomework::history ; if ($temp =~ m/^error:.*/) { %Apache::lonhomework::history=(); } } # -------------------------------------------------------------finalize_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 sub finalize_storage { my $result; my ($temp) = keys %Apache::lonhomework::results; if ( $temp ne '' ) { my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser(); 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); &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); } } return $result; } sub checkout_msg { my %lt=&Apache::lonlocal::texthash( 'resource'=>'The resource needs to be checked out', 'id_expln'=>'As a resource gets checked out, a unique timestamped ID is given to it, and a permanent record is left in the system.', 'warning'=>'Checking out resources is subject to course policies, and may exclude future credit even if done erroneously.', 'checkout'=>'Check out Exam for Viewing', 'checkout?'=>'Check out Exam?'); return (<$lt{'resource'}

$lt{'id_expln'}

$lt{'warning'}

ENDCHECKOUT } sub init_problem_globals { my ($type)=@_; #initialize globals if ($type eq 'problem') { $Apache::inputtags::part='0'; @Apache::inputtags::partlist=('0'); $Apache::lonhomework::problemstatus= &Apache::lonnet::EXT('resource.0.problemstatus'); } else { $Apache::inputtags::part=''; @Apache::inputtags::partlist=(); $Apache::lonhomework::problemstatus=''; } @Apache::inputtags::responselist = (); @Apache::inputtags::importlist = (); @Apache::inputtags::previous=(); @Apache::inputtags::previous_version=(); $Apache::structuretags::printanswer='No'; @Apache::structuretags::whileconds=(); @Apache::structuretags::whilebody=(); @Apache::structuretags::whileline=(); $Apache::lonhomework::scantronmode=0; undef($Apache::lonhomework::name); } sub reset_problem_globals { my ($type)=@_; undef(%Apache::lonhomework::history); undef(%Apache::lonhomework::results); undef($Apache::inputtags::part); #don't undef this, lonhomework.pm takes care of this, we use this to #detect if we try to do 2 problems in one file # undef($Apache::lonhomework::parsing_a_problem); undef($Apache::lonhomework::name); } sub start_problem { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; if ( $Apache::inputtags::part ne '' || $Apache::lonhomework::parsing_a_problem) { &Apache::lonxml::error('Only one <problem> allowed in a .problem file'); #my $bodytext=&Apache::lonxml::get_all_text("/problem",$parser); return ''; } $Apache::lonhomework::parsing_a_problem=1; &init_problem_globals('problem'); if (defined($ENV{'scantron.maxquest'})) { $Apache::lonhomework::scantronmode=1; } if ($target ne 'analyze') { &initialize_storage(); if ($target eq 'web') { &Apache::lonhomework::showhash(%Apache::lonhomework::history); } $Apache::lonhomework::type=&Apache::lonnet::EXT('resource.0.type'); &Apache::lonxml::debug("Found this to be of type :$Apache::lonhomework::type:"); } if ($Apache::lonhomework::type eq '' ) { my $uri=$ENV{'request.uri'}; if ($uri=~/\.(\w+)$/) { $Apache::lonhomework::type=$1; &Apache::lonxml::debug("Using type of $1"); } else { $Apache::lonhomework::type='problem'; &Apache::lonxml::debug("Using default type, problem, :$uri:"); } } #added vars to the scripting enviroment my $expression='$external::part=\''.$Apache::inputtags::part.'\';'; &Apache::run::run($expression,$safeeval); my $status; my $accessmsg; #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 'analyze') { my $rndseed=&setup_rndseed($safeeval); } if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || $target eq 'tex') { #handle exam checkout if ($Apache::lonhomework::type eq 'exam') { my $token= $Apache::lonhomework::history{"resource.0.outtoken"}; if (($ENV{'form.doescheckout'}) && (!$token)) { $token=&Apache::lonxml::maketoken(); $Apache::lonhomework::history{"resource.0.outtoken"}= $token; } $body_tag_start.=&Apache::lonxml::printtokenheader($target,$token); } #handle rand seed in construction space my $rndseed=&setup_rndseed($safeeval); my ($symb)=&Apache::lonxml::whichuser(); if ($ENV{'request.state'} ne "construct" && $symb eq '') { $form_tag_start.=''. ''. '
'; } ($status,$accessmsg) = &Apache::lonhomework::check_access('0'); push (@Apache::inputtags::status,$status); my $expression='$external::datestatus="'.$status.'";'; $expression.='$external::gradestatus="'.$Apache::lonhomework::history{"resource.0.solved"}.'";'; &Apache::run::run($expression,$safeeval); &Apache::lonxml::debug("Got $status"); if (( $status eq 'CLOSED' ) || ( $status eq 'UNCHECKEDOUT') || ( $status eq 'BANNED') || ( $status eq 'UNAVAILABLE') || ( $status eq 'INVALID_ACCESS')) { my $bodytext=&Apache::lonxml::get_all_text("/problem",$parser); if ( $target eq "web" ) { $result.= $head_tag_start.''; my $msg=$body_tag_start; if ($status eq 'UNAVAILABLE') { $result.='

'.&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'

'; } else { $result.='

'.&mt('Not open to be viewed').'

'; } if ($status eq 'CLOSED' || $status eq 'INVALID_ACCESS') { $msg.='The problem '.$accessmsg; } elsif ($status eq 'UNCHECKEDOUT') { $msg.=&checkout_msg; } $result.=$msg.'
'; } elsif ($target eq 'tex') { $result.='\begin{document}\noindent \vskip 1 mm \begin{minipage}{\textwidth}\vskip 0 mm'; if ($status eq 'UNAVAILABLE') { $result.=&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'\vskip 0 mm '; } else { $result.=&mt('Problem is not open to be viewed. It')." $accessmsg \\vskip 0 mm "; } } } elsif ($target eq 'web') { my $name= &get_resource_name($parstack,$safeeval); if ($status eq 'CAN_ANSWER') { # create a page header and exit $result.="$head_tag_start$name $body_tag_start \n $form_tag_start". ''; if ($ENV{'request.state'} eq "construct") { $result.= &problem_web_to_edit_header($ENV{'form.rndseed'}); } # if we are viewing someone else preserve that info if (defined $ENV{'form.grade_symb'}) { foreach my $field ('symb','courseid','domain','username') { $result .= ''."\n"; } } } elsif ($status eq 'SHOW_ANSWER' || $status eq 'CANNOT_ANSWER' || $status eq 'CLOSED' || $status eq 'UNAVALAILABLE' || $status eq 'INVALID_ACCESS') { $result.=$head_tag_start. "$name\n$body_tag_start\n"; } } elsif ($target eq 'tex') { my $startminipage = ''; if (not $ENV{'form.problem_split'}=~/yes/) { $startminipage = '\begin{minipage}{\textwidth}'; } my $id = $Apache::inputtags::part; my $weight = &Apache::lonnet::EXT("resource.$id.weight"); my $allkeys=&Apache::lonnet::metadata($ENV{'request.uri'},'keys'); my @allkeys = split /,/,$allkeys; my $allow_print_points = 0; foreach my $partial_key (@allkeys) { if ($partial_key=~m/weight/) { $allow_print_points++; } } my $duedate = &Apache::lonnet::EXT("resource.$id.duedate"); $duedate = POSIX::strftime("%c",localtime($duedate)); my $temp_file; my $filename = "/home/httpd/prtspool/$ENV{'user.name'}_$ENV{'user.domain'}_printout.due"; if (-e $filename) { $temp_file = Apache::File->new($filename); } else { $temp_file = Apache::File->new('>>'.$filename); } my @due_file_content = <$temp_file>; my $due_file_content = $due_file_content[$#due_file_content]; chomp $due_file_content; my $name_of_resourse= &get_resource_name($parstack,$safeeval); if ($due_file_content ne $duedate) { $temp_file = Apache::File->new('>'.$filename); print $temp_file "$duedate\n"; if (not $ENV{'request.symb'} =~ m/\.page_/) { if(not $duedate=~m/1969/ and $Apache::lonhomework::type ne 'exam') { $result .= '\begin{document} \typeout{STAMPOFPASSEDRESOURCESTART Resource

"'.$name_of_resourse.'"

located in
'.$ENV{'request.uri'}.'
STAMPOFPASSEDRESOURCEEND} \noindent\textit{Due date: '.$duedate.'} \vskip 1 mm\noindent '.$startminipage.'\addcontentsline{toc}{subsection}{'.$name_of_resourse.'}'; } else { $result .= '\begin{document} \typeout{STAMPOFPASSEDRESOURCESTART Resource

"'.$name_of_resourse.'"

located in
'.$ENV{'request.uri'}.'
STAMPOFPASSEDRESOURCEEND} \noindent \vskip 1 mm \noindent'.$startminipage.'\addcontentsline{toc}{subsection}{'.$name_of_resourse.'}'; if ($Apache::lonhomework::type eq 'exam' and $allow_print_points==1) { $result .= '\fbox{\textit{'.$weight.' pt}}';} } } else { $result .= '\vskip 1mm\textit{Due date: '.$duedate.'} \\\\\\\\'; } } else { if (not $ENV{'request.symb'} =~ m/\.page_/) { $result .= '\begin{document} \typeout{STAMPOFPASSEDRESOURCESTART Resource

"'.$name_of_resourse.'"

located in
'.$ENV{'request.uri'}.'
STAMPOFPASSEDRESOURCEEND} \noindent \vskip 1 mm\noindent'.$startminipage.'\addcontentsline{toc}{subsection}{'.$name_of_resourse.'}'; if (($Apache::lonhomework::type eq 'exam') and ($allow_print_points==1)) { $result .= '\fbox{\textit{'.$weight.' pt}}';} } else { $result .= '\vskip 1mm \\\\\\\\'; } } } } elsif ($target eq 'edit') { $result.=$head_tag_start."".$body_tag_start.$form_tag_start. &problem_edit_header(); my $temp=&Apache::edit::insertlist($target,$token); $result.=$temp; } elsif ($target eq 'modified') { $result=$token->[4]; $result.=&Apache::edit::handle_insert(); } else { # page_start returned a starting result, delete it if we don't need it $result = ''; } return $result; } sub end_problem { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result=''; my $status=$Apache::inputtags::status['-1']; if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' || $target eq 'tex') { if ( $target eq 'grade' && $Apache::inputtags::part eq '0' && $status eq 'CAN_ANSWER' ) { # if part is zero, no s existed, so we need to the grading &Apache::inputtags::grade; } elsif ( ($target eq 'web' || $target eq 'tex') && $Apache::inputtags::part eq '0' && $status ne 'UNCHECKEDOUT') { # if part is zero, no s existed, so we need show the current # grading status my $gradestatus = &Apache::inputtags::gradestatus($Apache::inputtags::part,$target); $result.= $gradestatus; } if ( (($target eq 'web') && ($ENV{'request.state'} ne 'construct')) || ($target eq 'answer') || ($target eq 'tex') ) { if ($status eq 'CAN_ANSWER') { if ($target ne 'tex' && $ENV{'form.answer_output_mode'} ne 'tex') { $result.="\n"; } } elsif ($status eq 'SHOW_ANSWER' || $status eq 'CANNOT_ANSWER' || $status eq 'UNCHECKEDOUT' || $status eq 'INVALID_ACCESS') { if ($target ne 'tex' && $ENV{'form.answer_output_mode'} ne 'tex') { $result.="\n"; } } if ($target eq 'web') { $result.=&Apache::lonxml::xmlend(); } elsif ($target eq 'tex') { my $endminipage = ''; if (not $ENV{'form.problem_split'}=~/yes/) { $endminipage = '\end{minipage}'; } $result .= '\keephidden{ENDOFPROBLEM}\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}'; if (not $ENV{'request.symb'} =~ m/\.page_/) { $result .= $endminipage.'\end{document} '; } else { $result .= ''; } } } if ($target eq 'grade') { &Apache::lonhomework::showhash(%Apache::lonhomework::results); &finalize_storage(); } if ($target eq 'answer' && ($ENV{'request.state'} eq 'construct') && $ENV{'form.answer_output_mode'} ne 'tex') { $result.=''; # normally we get it from xmlend, but in CSTR # we always show answer mode too. } } elsif ($target eq 'meta') { if ($Apache::inputtags::part eq '0') { @Apache::inputtags::response=(); $result=&Apache::response::mandatory_part_meta; } $result.=&Apache::response::meta_part_order(); } elsif ($target eq 'edit') { &Apache::lonxml::debug("in end_problem with $target, edit"); $result = &problem_edit_footer(); } if ($ENV{'request.state'} eq 'construct' && $target eq 'web') { &Apache::inputtags::check_for_duplicate_ids(); } &reset_problem_globals('problem'); return $result; } sub start_library { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my ($result,$head_tag_start,$body_tag_start,$form_tag_start); if ($$tagstack[0] eq 'library') { &init_problem_globals('library') }; if ($target eq 'edit') { ($result,$head_tag_start,$body_tag_start,$form_tag_start)= &page_start($target,$token,$tagstack,$parstack,$parser,$safeeval); $result.=$head_tag_start."".$body_tag_start.$form_tag_start. &problem_edit_header(); my $temp=&Apache::edit::insertlist($target,$token); $result.=$temp; } elsif ($target eq 'modified') { $result=$token->[4]; $result.=&Apache::edit::handle_insert(); } elsif ($target eq 'web' && $$tagstack[0] ne 'problem' && $ENV{'request.state'} eq "construct" ) { ($result,$head_tag_start,$body_tag_start,$form_tag_start)= &page_start($target,$token,$tagstack,$parstack,$parser,$safeeval); my $name=&get_resource_name($parstack,$safeeval); my $rndseed=&setup_rndseed($safeeval); $result.="$head_tag_start$name $body_tag_start \n $form_tag_start". ''; $result.=&problem_web_to_edit_header($rndseed); } return $result; } sub end_library { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result=''; if ($target eq 'edit') { $result=&problem_edit_footer(); } elsif ($target eq 'web' && $$tagstack[0] ne 'problem' && $ENV{'request.state'} eq "construct") { $result.=''.&Apache::lonxml::xmlend(); } if ($$tagstack[0] eq 'library') { &reset_problem_globals('library') }; return $result; } sub start_definetag { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result; my $name = $token->[2]->{'name'}; my $skip=&Apache::lonxml::get_all_text("/definetag",$parser); if ($name=~/^\//) { $result= '
'; } else { $result= '
END '.$name.'
'; } $skip=~s/\/\>\;/gs; $result.='
BEGIN '.$name.'
'.$skip.'
'; return $result; } sub end_definetag { return ''; } sub start_block { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result; if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || $target eq 'tex' || $target eq 'analyze') { my $code = $token->[2]->{'condition'}; if (defined($code)) { if (!$Apache::lonxml::default_homework_loaded) { &Apache::lonxml::default_homework_load($safeeval); } $result = &Apache::run::run($code,$safeeval); &Apache::lonxml::debug("block :$code: returned :$result:"); } else { $result='1'; } if ( ! $result ) { my $skip=&Apache::lonxml::get_all_text("/block",$parser,$style); &Apache::lonxml::debug("skipping ahead :$skip: $$parser[-1]"); } $result=''; } elsif ($target eq 'edit') { $result .=&Apache::edit::tag_start($target,$token); $result .=&Apache::edit::text_arg('Test Condition:','condition', $token,40); $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row(); } elsif ($target eq 'modified') { my $constructtag=&Apache::edit::get_new_args($token,$parstack, $safeeval,'condition'); if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); } } return $result; } sub end_block { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result; if ($target eq "edit") { $result.= &Apache::edit::tag_end($target,$token,''); } return $result; } sub start_languageblock { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result; if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || $target eq 'tex' || $target eq 'analyze') { my $include = $token->[2]->{'include'}; my $exclude = $token->[2]->{'exclude'}; my %languages=&Apache::loncommon::display_languages(); $result='1'; if ($include) { $result=''; foreach (split(/\,/,$include)) { if ($languages{$_}) { $result='1'; } } } if ($exclude) { foreach (split(/\,/,$exclude)) { if ($languages{$_}) { $result='0'; } } } if ( ! $result ) { my $skip=&Apache::lonxml::get_all_text("/languageblock",$parser, $style); &Apache::lonxml::debug("skipping ahead :$skip: $$parser[-1]"); } $result=''; } elsif ($target eq 'edit') { $result .=&Apache::edit::tag_start($target,$token); $result .=&Apache::edit::text_arg(&mt('Include Language:'),'include', $token,40); $result .=&Apache::edit::text_arg(&mt('Exclude Language:'),'exclude', $token,40); $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row(); } elsif ($target eq 'modified') { my $constructtag=&Apache::edit::get_new_args($token,$parstack, $safeeval,'include', 'exclude'); if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); } } return $result; } sub end_languageblock { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result; if ($target eq "edit") { $result.= &Apache::edit::tag_end($target,$token,''); } return $result; } sub start_instructorcomment { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result; if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || $target eq 'tex' || $target eq 'analyze') { $result=($ENV{'request.role'}=~/^(in|cc|au|ca|li)/); if ( ! $result ) { my $skip=&Apache::lonxml::get_all_text("/instructorcomment", $parser,$style); &Apache::lonxml::debug("skipping ahead :$skip: $$parser[-1]"); } $result=''; } elsif ($target eq 'edit') { $result .=&Apache::edit::tag_start($target,$token); $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row(); } return $result; } sub end_instructorcomment { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result; if ($target eq "edit") { $result.= &Apache::edit::tag_end($target,$token,''); } return $result; } sub start_while { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result; if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || $target eq 'tex' || $target eq 'analyze') { my $code = $token->[2]->{'condition'}; push( @Apache::structuretags::whileconds, $code); if (!$Apache::lonxml::default_homework_loaded) { &Apache::lonxml::default_homework_load($safeeval); } my $result = &Apache::run::run($code,$safeeval); my $bodytext=&Apache::lonxml::get_all_text("/while",$parser); push( @Apache::structuretags::whilebody, $bodytext); push( @Apache::structuretags::whileline, $token->[5]); &Apache::lonxml::debug("s code $code got -$result-"); if ( $result ) { &Apache::lonxml::newparser($parser,\$bodytext); } } elsif ($target eq 'edit') { $result .=&Apache::edit::tag_start($target,$token); $result .=&Apache::edit::text_arg(&mt('Test Condition:'),'condition', $token,40); $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row(); } elsif ($target eq 'modified') { my $constructtag=&Apache::edit::get_new_args($token,$parstack, $safeeval,'condition'); if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); } } return $result; } sub end_while { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result; if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || $target eq 'tex' || $target eq 'analyze') { my $code = pop(@Apache::structuretags::whileconds); my $bodytext = pop(@Apache::structuretags::whilebody); my $line = pop(@Apache::structuretags::whileline); my $return = &Apache::run::run($code,$safeeval); my $starttime=time; my $error=0; while ($return) { if (time-$starttime > $Apache::lonnet::perlvar{'lonScriptTimeout'}) { $return = 0; $error=1; next; } $result.=&Apache::scripttag::xmlparse($bodytext); $return = &Apache::run::run($code,$safeeval); } if ($error) { &Apache::lonxml::error('
'.&mt('Code ran too long. It ran for more than').' '.$Apache::lonnet::perlvar{'lonScriptTimeout'}.' '.&mt('seconds occured while running <while$gt; on line').' '.$line.'
'); } } elsif ($target eq "edit") { $result.= &Apache::edit::tag_end($target,$token,''); } return $result; } # # .. # .. # .. # ... # sub start_randomlist { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result; if ($target eq 'answer' || $target eq 'grade' || $target eq 'web' || $target eq 'tex' || $target eq 'analyze') { my $body= &Apache::lonxml::get_all_text("/randomlist",$parser); my $b_parser= HTML::TokeParser->new(\$body); my $b_tok; my @randomlist; my $list_item; while($b_tok = $b_parser->get_token() ) { if($b_tok->[0] eq 'S') { # start tag # get content of the tag until matching end tag # get all text upto the matching tag # and push the content into @randomlist $list_item = &Apache::lonxml::get_all_text('/'.$b_tok->[1], $b_parser); $list_item = "$b_tok->[4]"."$list_item"."[1]>"; push(@randomlist,$list_item); # print "
START-TAG $b_tok->[1], $b_tok->[4], # $list_item"; } if($b_tok->[0] eq 'T') { # text # what to do with text in between tags? # print "TEXT $b_tok->[1]
"; } # if($b_tok->[0] eq 'E') { # end tag, should not happen # print "END-TAG $b_tok->[1]
"; # } } my @idx_arr = (0 .. $#randomlist); &Apache::structuretags::shuffle(\@idx_arr); my $bodytext = ''; my $show=$#randomlist; my $showarg=&Apache::lonxml::get_param('show',$parstack,$safeeval); $showarg--; if ( ($showarg >= 0) && ($showarg < $show) ) { $show = $showarg; } for(0 .. $show) { $bodytext .= "$randomlist[ $idx_arr[$_] ]"; } &Apache::lonxml::newparser($parser,\$bodytext); } elsif ($target eq 'edit' ) { $result .=&Apache::edit::tag_start($target,$token); $result .=&Apache::edit::text_arg('Maximum Tags to Show:','show', $token,5); $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row(); } elsif ($target eq 'modified' ) { my $constructtag=&Apache::edit::get_new_args($token,$parstack, $safeeval,'show'); if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); } } return $result; } sub shuffle { my $a=shift; my $i; if (defined(@$a)) { &Apache::response::setrandomnumber(); for($i=@$a;--$i;) { my $j=int(&Math::Random::random_uniform() * ($i+1)); next if $i == $j; @$a[$i,$j] = @$a[$j,$i]; } } } sub end_randomlist { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result; if ($target eq 'edit' ) { $result=&Apache::edit::tag_end($target,$token, 'End Randomly Parsed Block'); } return $result; } sub start_part { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result=''; my $id= &Apache::lonxml::get_param('id',$parstack,$safeeval); if ($id eq '') { $id = $Apache::lonxml::curdepth; } $Apache::inputtags::part=$id; push(@Apache::inputtags::partlist,$id); @Apache::inputtags::response=(); @Apache::inputtags::previous=(); @Apache::inputtags::previous_version=(); $Apache::lonhomework::problemstatus= &Apache::lonnet::EXT("resource.$id.problemstatus"); my $hidden=&Apache::loncommon::check_if_partid_hidden($Apache::inputtags::part); my $expression='$external::part=\''.$Apache::inputtags::part.'\';'; &Apache::run::run($expression,$safeeval); if ($target eq 'meta') { return &Apache::response::mandatory_part_meta; } elsif ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || $target eq 'tex') { if ($hidden) { my $bodytext=&Apache::lonxml::get_all_text("/part",$parser); } else { my ($status,$accessmsg) = &Apache::lonhomework::check_access($id); push (@Apache::inputtags::status,$status); my $expression='$external::datestatus="'.$status.'";'; $expression.='$external::gradestatus="'.$Apache::lonhomework::history{"resource.$id.solved"}.'";'; &Apache::run::run($expression,$safeeval); if (( $status eq 'CLOSED' ) || ( $status eq 'UNCHECKEDOUT') || ( $status eq 'BANNED') || ( $status eq 'UNAVAILABLE') || ( $status eq 'INVALID_ACCESS')) { my $bodytext=&Apache::lonxml::get_all_text("/part",$parser); if ( $target eq "web" ) { $result="
".&mt('Part is not open to be viewed. It')." $accessmsg
"; } elsif ( $target eq 'tex' ) { if (not $ENV{'form.problem_split'}=~/yes/) { $result="\\end{minipage}\\vskip 0 mm ".&mt('Part is not open to be viewed. It')." $accessmsg \\\\\\begin{minipage}{\\textwidth}"; } else { $result="\\vskip 0 mm ".&mt('Part is not open to be viewed. It')." $accessmsg \\\\"; } } } else { if ($target eq 'tex') { if (not $ENV{'form.problem_split'}=~/yes/) { $result.='\noindent \end{minipage}\vskip 0 mm \noindent \begin{minipage}{\textwidth}\noindent'; } my $weight = &Apache::lonnet::EXT("resource.$id.weight"); if ($Apache::lonhomework::type eq 'exam') { $result .= '\fbox{\textit{'.$weight.' pt}}';} } } } } elsif ($target eq 'edit') { $result.=&Apache::edit::tag_start($target,$token); $result.=&Apache::edit::text_arg('Part ID:','id',$token). &Apache::loncommon::help_open_topic("Part_Tag_Edit_Help"). &Apache::edit::end_row().&Apache::edit::start_spanning_row(); } elsif ($target eq 'modified') { my $constructtag=&Apache::edit::get_new_args($token,$parstack, $safeeval,'id'); if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); $result.=&Apache::edit::handle_insert(); } } return $result; } sub end_part { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; &Apache::lonxml::debug("in end_part $target "); my $status=$Apache::inputtags::status['-1']; my $hidden=&Apache::loncommon::check_if_partid_hidden($Apache::inputtags::part); my $result=''; if ( $target eq 'meta' ) { $result=''; } elsif ( $target eq 'grade' && $status eq 'CAN_ANSWER' && !$hidden) { $result=&Apache::inputtags::grade; } elsif (($target eq 'web' || $target eq 'tex') && !$hidden ) { my $gradestatus=&Apache::inputtags::gradestatus($Apache::inputtags::part, $target); if ($Apache::lonhomework::type eq 'exam' && $target eq 'tex') { $gradestatus=''; } $result=$gradestatus; } elsif ($target eq 'edit') { $result=&Apache::edit::end_table(); } pop @Apache::inputtags::status; $Apache::inputtags::part=''; return $result; } sub start_preduedate { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || $target eq 'tex') { if ($Apache::inputtags::status['-1'] ne 'CAN_ANSWER' && $Apache::inputtags::status['-1'] ne 'CANNOT_ANSWER' && $Apache::inputtags::status['-1'] ne 'SHOW_ANSWER') { &Apache::lonxml::get_all_text("/preduedate",$parser); } } return ''; } sub end_preduedate { return ''; } sub start_postanswerdate { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; if ($target eq 'web' || $target eq 'grade' || $target eq 'tex') { if ($Apache::inputtags::status['-1'] ne 'SHOW_ANSWER') { &Apache::lonxml::get_all_text("/postanswerdate",$parser); } } elsif ($target eq 'tex') { return '\vskip 0 mm \noindent'; } return ''; } sub end_postanswerdate { return ''; } sub start_notsolved { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || $target eq 'tex') { my $gradestatus=$Apache::lonhomework::history{"resource.$Apache::inputtags::part.solved"}; &Apache::lonxml::debug("not solved has :$gradestatus:"); if ($gradestatus =~ /^correct/) { &Apache::lonxml::debug("skipping"); &Apache::lonxml::get_all_text("/notsolved",$parser); } } return ''; } sub end_notsolved { return ''; } sub start_solved { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || $target eq 'tex') { my $gradestatus=$Apache::lonhomework::history{"resource.$Apache::inputtags::part.solved"}; if ($gradestatus !~ /^correct/) { &Apache::lonxml::get_all_text("/solved",$parser); } } return ''; } sub end_solved { return ''; } sub start_startouttext { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my @result=(''.''); if ($target eq 'edit' || $target eq 'modified' ) { @result=('','no'); } return (@result); } sub end_startouttext { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result=''; my $text=''; if ($target eq 'edit') { $text=&Apache::lonxml::get_all_text("endouttext",$parser); $result.=&Apache::edit::start_table($token)."".&mt('Text Block')." ".&mt('Delete:'). &Apache::edit::deletelist($target,$token) ." ". &Apache::edit::insertlist($target,$token). &Apache::edit::end_row(). &Apache::edit::start_spanning_row()."\n" . &Apache::loncommon::helpLatexCheatsheet () . &Apache::edit::editfield($token->[1],$text,"",80,4); } if ($target eq 'modified') { $result=''.&Apache::edit::modifiedfield("endouttext",$parser); } if ($target eq 'tex') { $result .= '\noindent '; } return $result; } sub start_endouttext { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result=''; if ($target eq "edit" ) { $result="".&Apache::edit::end_table()."\n"; } if ($target eq "modified") { $result=''. &Apache::edit::handle_insertafter('startouttext'); } return $result; } sub end_endouttext { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my @result=('',''); if ($target eq "edit" || $target eq 'modified') { @result=('','no'); } return (@result); } sub delete_startouttext { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; # my $text=&Apache::lonxml::get_all_text("endouttext",$parser); my $text=$$parser['-1']->get_text("/endouttext"); my $ntoken=$$parser['-1']->get_token(); &Apache::lonxml::debug("Deleting :$text: and :$ntoken->[0]:$ntoken->[1]:$ntoken->[2]: for startouttext"); &Apache::lonxml::end_tag($tagstack,$parstack,$ntoken); # Deleting 2 parallel tag pairs, but we need the numbers later to look like # they did the last time round &Apache::lonxml::increasedepth($ntoken); &Apache::lonxml::decreasedepth($ntoken); return 1; } sub start_simpleeditbutton { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result=''; if (($target eq 'web') && (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'}))) { my $url=$ENV{'request.noversionuri'}; $url=~s/\?.*$//; $result='
'. ''.&mt('Simple Problem Editor').' - '.&mt('Note: it can take up to 10 minutes for changes to take effect for all users.'). &Apache::loncommon::help_open_topic('Caching').'

'; } return $result; } sub end_simpleeditbutton { return ''; } 1; __END__