--- loncom/interface/lonprintout.pm 2005/09/01 18:39:47 1.381.2.1 +++ loncom/interface/lonprintout.pm 2006/06/30 21:26:53 1.451 @@ -1,7 +1,7 @@ -# The LearningOnline Network +# The LearningOnline Network # Printout # -# $Id: lonprintout.pm,v 1.381.2.1 2005/09/01 18:39:47 albertel Exp $ +# $Id: lonprintout.pm,v 1.451 2006/06/30 21:26:53 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -41,8 +41,129 @@ use Apache::lonnavmaps; use Apache::lonratedt; use POSIX qw(strftime); use Apache::lonlocal; +use Carp; +use lib '/home/httpd/lib/perl/'; +use LONCAPA; -my $resources_printed = ''; +my %perm; + +# +# Convert a numeric code to letters +# +sub num_to_letters { + my ($num) = @_; + my @nums= split('',$num); + my @num_to_let=('A'..'Z'); + my $word; + foreach my $digit (@nums) { $word.=$num_to_let[$digit]; } + return $word; +} +# Convert a letter code to numeric. +# +sub letters_to_num { + my ($letters) = @_; + my @letters = split('', uc($letters)); + my %substitution; + my $digit = 0; + foreach my $letter ('A'..'J') { + $substitution{$letter} = $digit; + $digit++; + } + # The substitution is done as below to preserve leading + # zeroes which are needed to keep the code size exact + # + my $result =""; + foreach my $letter (@letters) { + $result.=$substitution{$letter}; + } + return $result; +} + +# Determine if a code is a valid numeric code. Valid +# numeric codes must be comprised entirely of digits and +# have a correct number of digits. +# +# Parameters: +# value - proposed code value. +# num_digits - Number of digits required. +# +sub is_valid_numeric_code { + my ($value, $num_digits) = @_; + # Remove leading/trailing whitespace; + $value =~ s/^\s*//g; + $value =~ s/\s*$//g; + + # All digits? + if ($value !~ /^[0-9]+$/) { + return "Numeric code $value has invalid characters - must only be digits"; + } + if (length($value) != $num_digits) { + return "Numeric code $value incorrect number of digits (correct = $num_digits)"; + } + return undef; +} +# Determines if a code is a valid alhpa code. Alpha codes +# are ciphers that map [A-J,a-j] -> 0..9 0..9. +# They also have a correct digit count. +# Parameters: +# value - Proposed code value. +# num_letters - correct number of letters. +# Note: +# leading and trailing whitespace are ignored. +# +sub is_valid_alpha_code { + my ($value, $num_letters) = @_; + + # strip leading and trailing spaces. + + $value =~ s/^\s*//g; + $value =~ s/\s*$//g; + + # All alphas in the right range? + if ($value !~ /^[A-J,a-j]+$/) { + return "Invalid letter code $value must only contain A-J"; + } + if (length($value) != $num_letters) { + return "Letter code $value has incorrect number of letters (correct = $num_letters)"; + } + return undef; +} + +# Determine if a code entered by the user in a helper is valid. +# valid depends on the code type and the type of code selected. +# The type of code selected can either be numeric or +# Alphabetic. If alphabetic, the code, in fact is a simple +# substitution cipher for the actual numeric code: 0->A, 1->B ... +# We'll be nice and be case insensitive for alpha codes. +# Parameters: +# code_value - the value of the code the user typed in. +# code_option - The code type selected from the set in the scantron format +# table. +# Returns: +# undef - The code is valid. +# other - An error message indicating what's wrong. +# +sub is_code_valid { + my ($code_value, $code_option) = @_; + my ($code_type, $code_length) = ('letter', 6); # defaults. + open(FG, $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab'); + foreach my $line () { + my ($name, $type, $length) = (split(/:/, $line))[0,2,4]; + if($name eq $code_option) { + $code_length = $length; + if($type eq 'number') { + $code_type = 'number'; + } + } + } + my $valid; + if ($code_type eq 'number') { + return &is_valid_numeric_code($code_value, $code_length); + } else { + return &is_valid_alpha_code($code_value, $code_length); + } + +} # Compare two students by name. The students are in the form # returned by the helper: @@ -108,7 +229,46 @@ sub latex_header_footer_remove { $text =~ s/\\documentclass([^&]*)\\begin{document}//; return $text; } +# +# If necessary, encapsulate text inside +# a minipage env. +# necessity is determined by the problem_split param. +# +sub encapsulate_minipage { + my ($text) = @_; + if (!($env{'form.problem.split'} =~ /yes/i)) { + $text = '\begin{minipage}{\textwidth}'.$text.'\end{minipage}'; + } + return $text; +} +# +# The NUMBER_TO_PRINT and SPLIT_PDFS +# variables interact, this sub looks at these two parameters +# and comes up with a final value for NUMBER_TO_PRINT which can be: +# all - if SPLIT_PDFS eq 'all'. +# 1 - if SPLIT_PDFS eq 'oneper' +# section - if SPLIT_PDFS eq 'sections' +# - if SPLIT_PDFS eq 'usenumber' +# +sub adjust_number_to_print { + my $helper = shift; + my $split_pdf = $helper->{'VARS'}->{'SPLIT_PDFS'}; + + if ($split_pdf eq 'all') { + $helper->{'VARS'}->{'NUMBER_TO_PRINT'} = 'all'; + } elsif ($split_pdf eq 'oneper') { + $helper->{'VARS'}->{'NUMBER_TO_PRINT'} = 1; + } elsif ($split_pdf eq 'sections') { + $helper->{'VARS'}->{'NUMBER_TO_PRINT'} = 'section'; + } elsif ($split_pdf eq 'usenumber') { + # Unmodified. + } else { + # Error!!!! + + croak "bad SPLIT_PDFS: $split_pdf in lonprintout::adjust_number_to_print"; + } +} sub character_chart { my $result = shift; @@ -315,6 +475,7 @@ sub character_chart { $result =~ s/&(\#252|uuml);/\\\"{u}/g; $result =~ s/&(\#253|yacute);/\\\'{y}/g; $result =~ s/&(\#255|yuml);/\\\"{y}/g; + $result =~ s/&\#295;/\\ensuremath\{\\hbar\}/g; $result =~ s/&\#952;/\\ensuremath\{\\theta\}/g; #Greek Alphabet $result =~ s/&(alpha|\#945);/\\ensuremath\{\\alpha\}/g; @@ -541,14 +702,15 @@ sub get_name { if (!defined($udom)) { $udom=$env{'user.domain'}; } my $plainname=&Apache::loncommon::plainname($uname,$udom); if ($plainname=~/^\s*$/) { $plainname=$uname.'@'.$udom; } - $plainname=&Apache::lonxml::latex_special_symbols($plainname,'header'); + # $plainname=&Apache::lonxml::latex_special_symbols($plainname,'header'); + $plainname = &escape_LaTeX($plainname); return $plainname; } sub get_course { my $courseidinfo; if (defined($env{'request.course.id'})) { - $courseidinfo = &Apache::lonxml::latex_special_symbols(&Apache::lonnet::unescape($env{'course.'.$env{'request.course.id'}.'.description'}),'header'); + $courseidinfo = &Apache::lonxml::latex_special_symbols(&unescape($env{'course.'.$env{'request.course.id'}.'.description'}),'header'); } return $courseidinfo; } @@ -631,15 +793,13 @@ sub details_for_menu { sub latex_corrections { - - my ($number_of_columns,$result,$selectionmade) = @_; - + my ($number_of_columns,$result,$selectionmade,$answer_mode) = @_; # $result =~ s/\\includegraphics{/\\includegraphics\[width=\\minipagewidth\]{/g; $result =~ s/\$number_of_columns/$number_of_columns/g; - if ($selectionmade ne '1') { - $result =~ s/(\\end{document})/\\strut\\vspace\*{-4 mm}\\newline\\noindent\\makebox\[\\textwidth\/$number_of_columns\]\[b\]{\\hrulefill}\\newline\\noindent\\tiny Printed from LON-CAPA\\copyright MSU{\\hfill} Licensed under GNU General Public License $1/; + if ($selectionmade eq '1' || $answer_mode eq 'only') { + $result =~ s/(\\end{document})/\\strut\\vskip 0 mm\\noindent\\makebox\[\\textwidth\/$number_of_columns\]\[b\]{\\hrulefill}\\newline\\noindent\\tiny Printed from LON-CAPA\\copyright MSU{\\hfill} Licensed under GNU General Public License $1/; } else { - $result =~ s/(\\end{document})/\\strut\\newline\\noindent\\makebox\[\\textwidth\/$number_of_columns\]\[b\]{\\hrulefill}\\newline\\noindent\\tiny Printed from LON-CAPA\\copyright MSU{\\hfill} Licensed under GNU General Public License $1/; + $result =~ s/(\\end{document})/\\strut\\vspace\*{-4 mm}\\newline\\noindent\\makebox\[\\textwidth\/$number_of_columns\]\[b\]{\\hrulefill}\\newline\\noindent\\tiny Printed from LON-CAPA\\copyright MSU{\\hfill} Licensed under GNU General Public License $1/; } $result =~ s/(\\end{longtable}\s*)(\\strut\\newline\\noindent\\makebox\[\\textwidth\/$number_of_columns\]\[b\]{\\hrulefill})/$2$1/g; $result =~ s/(\\end{longtable}\s*)\\strut\\newline/$1/g; @@ -663,7 +823,6 @@ sub latex_corrections { } $result =~ s/(\\end{tabular})\s*\\vskip 0 mm/$1/g; $result =~ s/(\\begin{enumerate})\s*\\noindent/$1/g; - return $result; } @@ -698,13 +857,15 @@ sub IndexCreation { sub print_latex_header { my $mode=shift; - my $output='\documentclass[letterpaper]{article}'; - if (($mode eq 'batchmode') || (!$env{'request.role.adv'})) { + my $output='\documentclass[letterpaper,twoside]{article}'; + if (($mode eq 'batchmode') || (!$perm{'pav'})) { $output.='\batchmode'; } $output.='\newcommand{\keephidden}[1]{}\renewcommand{\deg}{$^{\circ}$}'."\n". + '\usepackage{multirow}'."\n". '\usepackage{longtable}\usepackage{textcomp}\usepackage{makeidx}'."\n". '\usepackage[dvips]{graphicx}\usepackage{epsfig}'."\n". + '\usepackage{wrapfig}'. '\usepackage{picins}\usepackage{calc}'."\n". '\newenvironment{choicelist}{\begin{list}{}{\setlength{\rightmargin}{0in}'."\n". '\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.05in}'."\n". @@ -724,16 +885,19 @@ sub print_latex_header { sub path_to_problem { my ($urlp,$colwidth)=@_; + $urlp=&Apache::lonnet::clutter($urlp); + my $newurlp = ''; $colwidth=~s/\s*mm\s*$//; #characters average about 2 mm in width if (length($urlp)*2 > $colwidth) { - my @elements = split '/',$urlp; + my @elements = split('/',$urlp); my $curlength=0; foreach my $element (@elements) { + if ($element eq '') { next; } if ($curlength+(length($element)*2) > $colwidth) { - $newurlp .= '|\vskip -1 mm \noindent \verb|'; - $curlength=0; + $newurlp .= '|\vskip -1 mm \verb|'; + $curlength=length($element)*2; } else { $curlength+=length($element)*2; } @@ -772,11 +936,14 @@ sub get_textwidth { sub unsupported { - my ($currentURL,$mode)=@_; + my ($currentURL,$mode,$symb)=@_; if ($mode ne '') {$mode='\\'.$mode} my $result.= &print_latex_header($mode); - if ($currentURL=~/\/ext\//) { - $result.=' \strut \\\\ THIS IS EXTERNAL RESOURCE WITH URL \strut \\\\ '.$currentURL.' '; + if ($currentURL=~m|^(/adm/wrapper/)?ext/|) { + $currentURL=~s|^(/adm/wrapper/)?ext/|http://|; + my $title=&Apache::lonnet::gettitle($symb); + $title = &Apache::lonxml::latex_special_symbols($title); + $result.=' \strut \\\\ '.$title.' \strut \\\\ '.$currentURL.' '; } else { $result.=$currentURL; } @@ -786,6 +953,49 @@ sub unsupported { # +# List of recently generated print files +# +sub recently_generated { + my $r=shift; + my $prtspool=$r->dir_config('lonPrtDir'); + my $zip_result; + my $pdf_result; + opendir(DIR,$prtspool); + + my @files = + grep(/^$env{'user.name'}_$env{'user.domain'}_printout_(\d+)_.*\.(pdf|zip)$/,readdir(DIR)); + closedir(DIR); + + @files = sort { + my ($actime) = (stat($prtspool.'/'.$a))[10]; + my ($bctime) = (stat($prtspool.'/'.$b))[10]; + return $bctime <=> $actime; + } (@files); + + foreach my $filename (@files) { + my ($ext) = ($filename =~ m/(pdf|zip)$/); + my ($cdev,$cino,$cmode,$cnlink, + $cuid,$cgid,$crdev,$csize, + $catime,$cmtime,$cctime, + $cblksize,$cblocks)=stat($prtspool.'/'.$filename); + my $result="". + &mt('Generated [_1] ([_2] bytes)', + &Apache::lonlocal::locallocaltime($cctime),$csize). + '
'; + if ($ext eq 'pdf') { $pdf_result .= $result; } + if ($ext eq 'zip') { $zip_result .= $result; } + } + if ($zip_result) { + $r->print('

'.&mt('Recently generated printout zip files')."

\n" + .$zip_result); + } + if ($pdf_result) { + $r->print('

'.&mt('Recently generated printouts')."

\n" + .$pdf_result); + } +} + +# # Retrieve the hash of page breaks. # # Inputs: @@ -794,27 +1004,29 @@ sub unsupported { # A reference to a page break hash. # # +#use Data::Dumper; +#sub dump_helper_vars { +# my ($helper) = @_; +# my $helpervars = Dumper($helper->{'VARS'}); +# &Apache::lonnet::logthis("Dump of helper vars:\n $helpervars"); +#} sub get_page_breaks { my ($helper) = @_; my %page_breaks; - + foreach my $break (split /\|\|\|/, $helper->{'VARS'}->{'FINISHPAGE'}) { $page_breaks{$break} = 1; } - return %page_breaks; } sub output_data { my ($r,$helper,$rparmhash) = @_; my %parmhash = %$rparmhash; - my $html=&Apache::lonxml::xmlbegin(); - my $bodytag=&Apache::loncommon::bodytag('Preparing Printout'); - $r->print(< - -LON-CAPA output for printing - -$bodytag -Please stand by while processing your print request, this may take some time ... ENDPART + my $start_page = &Apache::loncommon::start_page('Preparing Printout',$js); + my $msg = &mt('Please stand by while processing your print request, this may take some time ...'); + $r->print($start_page."\n

\n$msg\n

\n"); # fetch the pagebreaks and store them in the course environment # The page breaks will be pulled into the hash %page_breaks which is @@ -909,7 +1120,8 @@ ENDPART $cleanURL=$currentURL; } $selectionmade = 1; - if ($cleanURL=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) { + if ($cleanURL!~m|^/adm/| + && $cleanURL=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) { my $rndseed=time; my $texversion=''; if ($helper->{'VARS'}->{'ANSWER_TYPE'} ne 'only') { @@ -932,19 +1144,28 @@ ENDPART } $form{'rndseed'}=$rndseed; &Apache::lonnet::appenv(%moreenv); - &Apache::lonnet::delenv('form.counter'); - &Apache::lonxml::init_counter(); + + &Apache::lonxml::clear_problem_counter(); + $resources_printed .= $currentURL.':'; $texversion.=&Apache::lonnet::ssi($currentURL,%form); - &Apache::lonnet::delenv('form.counter'); + + &Apache::lonxml::clear_problem_counter(); + &Apache::lonnet::delenv('request.filename'); } + # current document with answers.. no need to encap in minipage + # since there's only one answer. + if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') || ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) { $form{'problem_split'}=$parmhash{'problem_stream_switch'}; $form{'grade_target'}='answer'; $form{'answer_output_mode'}='tex'; $form{'rndseed'}=$rndseed; + if ($helper->{'VARS'}->{'probstatus'} eq 'exam') { + $form{'problemtype'}='exam'; + } $resources_printed .= $currentURL.':'; my $answer=&Apache::lonnet::ssi($currentURL,%form); if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') { @@ -974,7 +1195,8 @@ ENDPART if ($currentURL=~m/\.page\s*$/) { ($result,$number_of_columns) = &page_cleanup($result); } - } elsif ($currentURL=~/\.sequence$/ && $helper->{'VARS'}->{'construction'} eq '1') { + } elsif ($cleanURL!~m|^/adm/| + && $currentURL=~/\.sequence$/ && $helper->{'VARS'}->{'construction'} eq '1') { #printing content of sequence from the construction space my $flag_latex_header_remove = 'NO'; my $rndseed=time; @@ -1011,10 +1233,14 @@ ENDPART if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') { $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/; } else { + # If necessary, encapsulate answer in minipage: + $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'}); - $texversion.='\vskip 0 mm \noindent\textbf{'.&Apache::lonnet::gettitle($helper->{'VARS'}->{'symb'}).'}\vskip 0 mm '; - $texversion.=&path_to_problem ($currentURL,$LaTeXwidth); - $texversion.='\vskip 1 mm '.$answer.'\end{document}'; + my $body ='\vskip 0 mm \noindent\textbf{'.&Apache::lonnet::gettitle($helper->{'VARS'}->{'symb'}).'}\vskip 0 mm '; + $body.=&path_to_problem($urlp,$LaTeXwidth); + $body.='\vskip 1 mm '.$answer.'\end{document}'; + $body = &encapsulate_minipage($body); + $texversion.=$body; } } if ($flag_latex_header_remove ne 'NO') { @@ -1036,14 +1262,15 @@ ENDPART } if ($helper->{VARS}->{'construction'} eq '1') {$result=~s/(\\begin{document})/$1 \\fbox\{RANDOM SEED IS $rndseed\} /;} $result .= '\end{document}'; - } elsif ($cleanURL=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) { + } elsif ($cleanURL=~/\/(smppg|grppg|syllabus|aboutme|bulletinboard)$/) { $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'}; if ($currentURL=~/\/syllabus$/) {$currentURL=~s/\/res//;} $resources_printed .= $currentURL.':'; my $texversion=&Apache::lonnet::ssi($currentURL,%form); $result .= $texversion; } else { - $result.=&unsupported($currentURL,$helper->{'VARS'}->{'LATEX_TYPE'}); + $result.=&unsupported($currentURL,$helper->{'VARS'}->{'LATEX_TYPE'}, + $helper->{'VARS'}->{'symb'}); } } elsif (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems') or ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems_pages') or @@ -1071,8 +1298,10 @@ ENDPART my $flag_page_in_sequence = 'NO'; my @master_seq=split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'}; my $prevassignment=''; - &Apache::lonnet::delenv('form.counter'); - &Apache::lonxml::init_counter(); + + &Apache::lonxml::clear_problem_counter(); + + my $pbreakresources = keys %page_breaks; for (my $i=0;$i<=$#master_seq;$i++) { # Note due to document structure, not allowed to put \newpage @@ -1083,16 +1312,19 @@ ENDPART $result.="\\newpage\n"; } } - my (undef,undef,$urlp)=&Apache::lonnet::decode_symb($master_seq[$i]); + my ($sequence,undef,$urlp)=&Apache::lonnet::decode_symb($master_seq[$i]); $urlp=&Apache::lonnet::clutter($urlp); $form{'symb'}=$master_seq[$i]; - my ($sequence)=&Apache::lonnet::decode_symb($master_seq[$i]); - my $assignment=&Apache::lonxml::latex_special_symbols(&Apache::lonnet::gettitle($sequence),'header'); #tittle of the assignment which contains this problem + + my $assignment=&Apache::lonxml::latex_special_symbols(&Apache::lonnet::gettitle($sequence),'header'); #title of the assignment which contains this problem if ($selectionmade==7) {$helper->{VARS}->{'assignment'}=$assignment;} if ($i==0) {$prevassignment=$assignment;} my $texversion=''; - if ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) { + if ($urlp!~m|^/adm/| + && $urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) { $resources_printed .= $urlp.':'; + + &Apache::lonxml::remember_problem_counter(); $texversion.=&Apache::lonnet::ssi($urlp,%form); if ($urlp=~/\.page$/) { ($texversion,my $number_of_columns_page) = &page_cleanup($texversion); @@ -1100,12 +1332,7 @@ ENDPART $texversion =~ s/\\end{document}\d*/\\end{document}/; $flag_page_in_sequence = 'YES'; } - my $lonidsdir=$r->dir_config('lonIDsDir'); - my $envfile=$env{'user.environment'}; - $envfile=~/\/([^\/]+)\.id$/; - $envfile=$1; - &Apache::lonnet::transfer_profile_to_env($lonidsdir,$envfile); - my $current_counter=$env{'form.counter'}; + if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') || ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) { # Don't permanently pervert the %form hash @@ -1113,16 +1340,20 @@ ENDPART $answerform{'grade_target'}='answer'; $answerform{'answer_output_mode'}='tex'; $resources_printed .= $urlp.':'; + + &Apache::lonxml::restore_problem_counter(); my $answer=&Apache::lonnet::ssi($urlp,%answerform); - &Apache::lonnet::appenv(('form.counter' => $current_counter)); + if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') { $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/; } else { if ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library)$/) { $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'}); - $texversion.='\vskip 0 mm \noindent\textbf{'.&Apache::lonnet::gettitle($urlp).'}\vskip 0 mm '; - $texversion.=&path_to_problem ($urlp,$LaTeXwidth); - $texversion.='\vskip 1 mm '.$answer; + my $body ='\vskip 0 mm \noindent\textbf{'.&Apache::lonnet::gettitle($master_seq[$i]).'}\vskip 0 mm '; + $body .= &path_to_problem ($urlp,$LaTeXwidth); + $body .='\vskip 1 mm '.$answer; + $body = &encapsulate_minipage($body); + $texversion .= $body; } else { $texversion=''; } @@ -1141,11 +1372,15 @@ ENDPART my $courseidinfo = &get_course(); if (defined($courseidinfo)) { $courseidinfo=' - '.$courseidinfo } $prevassignment=$assignment; - $result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\lhead{\\textit{\\textbf{'.$name.'}}'.$courseidinfo.' \\hfill \\thepage \\\\ \\textit{'.$assignment.'}}} \vskip 5 mm '; + if ($numberofcolumns eq '1') { + $result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\lhead{\\textit{\\textbf{'.$name.'}}'.$courseidinfo.' \\hfill \\thepage \\\\ \\textit{'.$assignment.'}}} \vskip 5 mm '; + } else { + $result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\fancyhead[LO]{\\textit{\\textbf{'.$name.'}}'.$courseidinfo.' \\hfill \\thepage \\\\ \\textit{'.$assignment.'}}} \vskip 5 mm '; + } } $result .= $texversion; $flag_latex_header_remove = 'YES'; - } elsif ($urlp=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) { + } elsif ($urlp=~/\/(smppg|grppg|syllabus|aboutme|bulletinboard)$/) { $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'}; if ($urlp=~/\/syllabus$/) {$urlp=~s/\/res//;} $resources_printed .= $urlp.':'; @@ -1158,7 +1393,8 @@ ENDPART $result .= $texversion; $flag_latex_header_remove = 'YES'; } else { - $texversion=&unsupported($urlp,$helper->{'VARS'}->{'LATEX_TYPE'}); + $texversion=&unsupported($urlp,$helper->{'VARS'}->{'LATEX_TYPE'}, + $master_seq[$i]); if ($flag_latex_header_remove ne 'NO') { $texversion = &latex_header_footer_remove($texversion); } else { @@ -1169,7 +1405,7 @@ ENDPART } if (&Apache::loncommon::connection_aborted($r)) { last; } } - &Apache::lonnet::delenv('form.counter'); + &Apache::lonxml::clear_problem_counter(); if ($flag_page_in_sequence eq 'YES') { $result =~ s/\\usepackage{calc}/\\usepackage{calc}\\usepackage{longtable}/; } @@ -1194,14 +1430,28 @@ ENDPART # Each element of the students array is of the form: # username:domain:section:last, first:status # + # Note that student sort is not compatible with printing + # 1 section per pdf...so that setting overrides. # - if ($helper->{'VARS'}->{'student_sort'} eq 1) { + if (($helper->{'VARS'}->{'student_sort'} eq 1) && + ($helper->{'VARS'}->{'SPLIT_PDFS'} ne "sections")) { @students = sort compare_names @students; } + &adjust_number_to_print($helper); + if ($helper->{'VARS'}->{'NUMBER_TO_PRINT'} eq '0' || $helper->{'VARS'}->{'NUMBER_TO_PRINT'} eq 'all' ) { $helper->{'VARS'}->{'NUMBER_TO_PRINT'}=$#students+1; } + # If we are splitting on section boundaries, we need + # to remember that in split_on_sections and + # print all of the students in the list. + # + my $split_on_sections = 0; + if ($helper->{'VARS'}->{'NUMBER_TO_PRINT'} eq 'section') { + $split_on_sections = 1; + $helper->{'VARS'}->{'NUMBER_TO_PRINT'} = $#students+1; + } my @master_seq=split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'}; #loop over students @@ -1215,6 +1465,8 @@ ENDPART if ($helper->{'VARS'}->{'PRINT_DISCUSSIONS'} eq 'yes') {$moreenv{'problem_split'}='yes';} my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Print Status','Class Print Status',$#students+1,'inline','75'); my $student_counter=-1; + my $i = 0; + my $last_section = (split(/:/,$students[0]))[2]; foreach my $person (@students) { my $duefile="/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.due"; @@ -1223,7 +1475,15 @@ ENDPART print $temp_file "1969\n"; } $student_counter++; - my $i=int($student_counter/$helper->{'VARS'}{'NUMBER_TO_PRINT'}); + if ($split_on_sections) { + my $this_section = (split(/:/,$person))[2]; + if ($this_section ne $last_section) { + $i++; + $last_section = $this_section; + } + } else { + $i=int($student_counter/$helper->{'VARS'}{'NUMBER_TO_PRINT'}); + } my ($output,$fullname, $printed)=&print_resources($r,$helper, $person,$type, \%moreenv,\@master_seq, @@ -1245,7 +1505,9 @@ ENDPART my $num_todo=$helper->{'VARS'}->{'NUMBER_TO_PRINT_TOTAL'}; my $code_name=$helper->{'VARS'}->{'ANON_CODE_STORAGE_NAME'}; my $old_name=$helper->{'VARS'}->{'REUSE_OLD_CODES'}; - + my $single_code = $helper->{'VARS'}->{'SINGLE_CODE'}; + my $selected_code = $helper->{'VARS'}->{'CODE_SELECTED_FROM_LIST'}; + my $code_option=$helper->{'VARS'}->{'CODE_OPTION'}; open(FH,$Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab'); my ($code_type,$code_length)=('letter',6); @@ -1258,6 +1520,7 @@ ENDPART } my %moreenv = ('textwidth' => &get_textwidth($helper,$LaTeXwidth)); $moreenv{'problem_split'} = $parmhash{'problem_stream_switch'}; + $moreenv{'instructor_comments'}='hide'; my $seed=time+($$<<16)+($$); my @allcodes; if ($old_name) { @@ -1267,6 +1530,19 @@ ENDPART $code_type=$result{"type\0$old_name"}; @allcodes=split(',',$result{$old_name}); $num_todo=scalar(@allcodes); + } elsif ($selected_code) { # Selection value is always numeric. + $num_todo = 1; + @allcodes = ($selected_code); + } elsif ($single_code) { + + $num_todo = 1; # Unconditionally one code to do. + # If an alpha code have to convert to numbers so it can be + # converted back to letters again :-) + # + if ($code_type ne 'number') { + $single_code = &letters_to_num($single_code); + } + @allcodes = ($single_code); } else { my %allcodes; srand($seed); @@ -1389,12 +1665,17 @@ ENDPART } #-------------------------------------------------------- corrections for the different page formats $result = &page_format_transformation($papersize,$laystyle,$numberofcolumns,$helper->{'VARS'}->{'PRINT_TYPE'},$result,$helper->{VARS}->{'assignment'},$helper->{'VARS'}->{'TABLE_CONTENTS'},$helper->{'VARS'}->{'TABLE_INDEX'},$selectionmade); - $result = &latex_corrections($number_of_columns,$result,$selectionmade); - for (my $i=1;$i<=$#print_array;$i++) {$print_array[$i] = &latex_corrections($number_of_columns,$print_array[$i],$selectionmade);} - #changes page's parameters for the one column output + $result = &latex_corrections($number_of_columns,$result,$selectionmade, + $helper->{'VARS'}->{'ANSWER_TYPE'}); + for (my $i=1;$i<=$#print_array;$i++) { + $print_array[$i] = + &latex_corrections($number_of_columns,$print_array[$i], + $selectionmade, + $helper->{'VARS'}->{'ANSWER_TYPE'}); + } if ($numberofcolumns == 1) { $result =~ s/\\textwidth\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textwidth= $helper->{'VARS'}->{'pagesize.width'} $helper->{'VARS'}->{'pagesize.widthunit'} /; - $result =~ s/\\textheight\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textheight $helper->{'VARS'}->{'pagesize.height'} $helper->{'VARS'}->{'pagesize.heightunit'} /; + $result =~ s/\\textheight\s*=?\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textheight $helper->{'VARS'}->{'pagesize.height'} $helper->{'VARS'}->{'pagesize.heightunit'} /; $result =~ s/\\evensidemargin\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\evensidemargin= $helper->{'VARS'}->{'pagesize.lmargin'} $helper->{'VARS'}->{'pagesize.lmarginunit'} /; $result =~ s/\\oddsidemargin\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\oddsidemargin= $helper->{'VARS'}->{'pagesize.lmargin'} $helper->{'VARS'}->{'pagesize.lmarginunit'} /; } @@ -1453,7 +1734,7 @@ ENDPART my $URLback=''; #link to original document if ($helper->{'VARS'}->{'construction'} ne '1') { #prints published resource - $URLback=&Apache::lonnet::escape('/adm/flip?postdata=return:'); + $URLback=&escape('/adm/flip?postdata=return:'); } else { #prints resource from the construction space $URLback='/'.$helper->{'VARS'}->{'filename'}; @@ -1473,7 +1754,7 @@ ENDPART 'cgi.'.$identifier.'.selection' => $selectionmade, 'cgi.'.$identifier.'.tableofcontents' => $helper->{'VARS'}->{'TABLE_CONTENTS'}, 'cgi.'.$identifier.'.tableofindex' => $helper->{'VARS'}->{'TABLE_INDEX'}, - 'cgi.'.$identifier.'.role' => $env{'request.role.adv'}, + 'cgi.'.$identifier.'.role' => $perm{'pav'}, 'cgi.'.$identifier.'.numberoffiles' => $#print_array, 'cgi.'.$identifier.'.studentnames' => $student_names, 'cgi.'.$identifier.'.backref' => $URLback,); @@ -1483,30 +1764,22 @@ ENDPART "cgi.$identifier.coursedom" => $cdom, "cgi.$identifier.resources" => $resources_printed); -$r->print(<print(< Continue - - +$end_page FINALEND } -sub num_to_letters { - my ($num) = @_; - my @nums= split('',$num); - my @num_to_let=('A'..'Z'); - my $word; - foreach my $digit (@nums) { $word.=$num_to_let[$digit]; } - return $word; -} sub get_CODE { my ($all_codes,$num,$seed,$size,$type)=@_; my $max='1'.'0'x$size; my $newcode; while(1) { - $newcode=sprintf("%06d",int(rand($max))); + $newcode=sprintf("%0".$size."d",int(rand($max))); if (!exists($$all_codes{$newcode})) { $$all_codes{$newcode}=1; if ($type eq 'number' ) { @@ -1530,13 +1803,27 @@ sub print_resources { $namepostfix="\\\\Name: "; $fullname = "CODE - ".$moreenv->{'CODE'}; } + # Fullname may have special latex characters that need \ prefixing: + # + my $i = 0; #goes through all resources, checks if they are available for #current student, and produces output - &Apache::lonnet::delenv('form.counter'); - &Apache::lonxml::init_counter(); + &Apache::lonxml::clear_problem_counter(); my %page_breaks = &get_page_breaks($helper); + my @format_array = split(/\|/,$helper->{'VARS'}->{'FORMAT'}); + my $columns_in_format = $format_array[1]; + # + # end each student with a + # Special that allows the post processor to even out the page + # counts later. Nasty problem this... it would be really + # nice to put the special in as a postscript comment + # e.g. \special{ps:\ENDOFSTUDENTSTAMP} unfortunately, + # The special gets passed the \ and dvips puts it in the output file + # so we will just rely on prntout.pl to strip ENDOFSTUDENTSTAMP from the + # postscript. Each ENDOFSTUDENTSTAMP will go on a line by itself. + # foreach my $curresline (@{$master_seq}) { if (defined $page_breaks{$curresline}) { @@ -1549,30 +1836,36 @@ sub print_resources { ($curresline!~ m/\.(problem|exam|quiz|assess|survey|form|library)$/)) ) { my ($map,$id,$res_url) = &Apache::lonnet::decode_symb($curresline); if (&Apache::lonnet::allowed('bre',$res_url)) { - if ($res_url=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) { + if ($res_url!~m|^ext/| + && $res_url=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) { $printed .= $curresline.':'; + + &Apache::lonxml::remember_problem_counter(); + my $rendered = &Apache::loncommon::get_student_view($curresline,$username,$userdomain,$env{'request.course.id'},'tex',$moreenv); - my $lonidsdir=$r->dir_config('lonIDsDir'); - my $envfile=$env{'user.environment'}; - $envfile=~/\/([^\/]+)\.id$/; - $envfile=$1; - &Apache::lonnet::transfer_profile_to_env($lonidsdir,$envfile); - my $current_counter=$env{'form.counter'}; + if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') || ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) { # Use a copy of the hash so we don't pervert it on future loop passes. my %answerenv = %{$moreenv}; $answerenv{'answer_output_mode'}='tex'; $answerenv{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'}; + + &Apache::lonxml::restore_problem_counter(); + my $ansrendered = &Apache::loncommon::get_student_answers($curresline,$username,$userdomain,$env{'request.course.id'},%answerenv); - &Apache::lonnet::appenv(('form.counter' => $current_counter)); + if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') { $rendered=~s/(\\keephidden{ENDOFPROBLEM})/$ansrendered$1/; } else { - $rendered=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'}); - $rendered.='\vskip 0 mm \noindent\textbf{'.&Apache::lonnet::gettitle($curresline).'}\vskip 0 mm '; - $rendered.=&path_to_problem ($curresline,$LaTeXwidth); - $rendered.='\vskip 1 mm '.$ansrendered; + + + my $header =&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'}); + my $body ='\vskip 0 mm \noindent\textbf{'.&Apache::lonnet::gettitle($curresline).'}\vskip 0 mm '; + $body .=&path_to_problem($res_url,$LaTeXwidth); + $body .='\vskip 1 mm '.$ansrendered; + $body = &encapsulate_minipage($body); + $rendered = $header.$body; } } if ($remove_latex_header eq 'YES') { @@ -1581,23 +1874,19 @@ sub print_resources { $rendered =~ s/\\end{document}//; } $current_output .= $rendered; - } elsif ($res_url=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) { + } elsif ($res_url=~/\/(smppg|grppg|syllabus|aboutme|bulletinboard)$/) { $printed .= $curresline.':'; my $rendered = &Apache::loncommon::get_student_view($curresline,$username,$userdomain,$env{'request.course.id'},'tex',$moreenv); - my $lonidsdir=$r->dir_config('lonIDsDir'); - my $envfile=$env{'user.environment'}; - $envfile=~/\/([^\/]+)\.id$/; - $envfile=$1; - &Apache::lonnet::transfer_profile_to_env($lonidsdir,$envfile); - my $current_counter=$env{'form.counter'}; + if ($remove_latex_header eq 'YES') { $rendered = &latex_header_footer_remove($rendered); } else { $rendered =~ s/\\end{document}//; } $current_output .= $rendered.'\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\strut \vskip 0 mm \strut '; + } else { - my $rendered = &unsupported($res_url,$helper->{'VARS'}->{'LATEX_TYPE'}); + my $rendered = &unsupported($res_url,$helper->{'VARS'}->{'LATEX_TYPE'},$curresline); if ($remove_latex_header ne 'NO') { $rendered = &latex_header_footer_remove($rendered); } else { @@ -1615,12 +1904,25 @@ sub print_resources { if ($usersection ne '') {$courseidinfo.=' - Sec. '.$usersection} my $currentassignment=&Apache::lonxml::latex_special_symbols($helper->{VARS}->{'assignment'},'header'); if ($current_output=~/\\documentclass/) { - $current_output =~ s/\\begin{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent\\lhead{\\textit{\\textbf{$fullname}}$courseidinfo \\hfill \\thepage \\\\ \\textit{$currentassignment}$namepostfix}}\\vskip 5 mm /; + if ($columns_in_format == 1) { + $current_output =~ s/\\begin{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent\\lhead{\\textit{\\textbf{$fullname}}$courseidinfo \\hfill \\thepage \\\\ \\textit{$currentassignment}$namepostfix}}\\vskip 5 mm /; + } else { + $current_output =~ s/\\begin{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent\\fancyhead[LO]{\\textit{\\textbf{$fullname}}$courseidinfo \\hfill \\thepage \\\\ \\textit{$currentassignment}$namepostfix}}\\vskip 5 mm /; + + } } else { my $blankpages = ''; for (my $j=0;$j<$helper->{'VARS'}->{'EMPTY_PAGES'};$j++) {$blankpages.='\clearpage\strut\clearpage';} - $current_output = '\strut\vspace*{-6 mm}\\newline\\noindent\\makebox[\\textwidth/$number_of_columns][b]{\\hrulefill}\vspace*{-2 mm}\\newline\\noindent{\\tiny Printed from LON-CAPA\\copyright MSU{\\hfill} Licensed under GNU General Public License }\\newpage '.$blankpages.'\setcounter{page}{1}\noindent\parbox{\minipagewidth}{\noindent\\lhead{\\textit{\\textbf{'.$fullname.'}}'.$courseidinfo.' \\hfill \\thepage \\\\ \\textit{'.$currentassignment.'}'.$namepostfix.'}} \vskip 5 mm '.$current_output; + if ($columns_in_format == 1) { + $current_output = '\strut\vspace*{-6 mm}\\newline\\noindent\\makebox[\\textwidth/$number_of_columns][b]{\\hrulefill}\vspace*{-2 mm}\\newline\\noindent{\\tiny Printed from LON-CAPA\\copyright MSU{\\hfill} Licensed under GNU General Public License }\\newpage '.$blankpages.'\setcounter{page}{1}\noindent\parbox{\minipagewidth}{\noindent\\lhead{\\textit{\\textbf{'.$fullname.'}}'.$courseidinfo.' \\hfill \\thepage \\\\ \\textit{'.$currentassignment.'}'.$namepostfix.'}} \vskip 5 mm '.$current_output; + } else { + $current_output = '\strut\vspace*{-6 mm}\\newline\\noindent\\makebox[\\textwidth/$number_of_columns][b]{\\hrulefill}\vspace*{-2 mm}\\newline\\noindent{\\tiny Printed from LON-CAPA\\copyright MSU{\\hfill} Licensed under GNU General Public License }\\newpage '.$blankpages.'\setcounter{page}{1}\noindent\parbox{\minipagewidth}{\noindent\\fancyhead[LO]{\\textit{\\textbf{'.$fullname.'}}'.$courseidinfo.' \\hfill \\thepage \\\\ \\textit{'.$currentassignment.'}'.$namepostfix.'}} \vskip 5 mm '.$current_output; + } } + # + # Close the student bracketing. + # + $current_output .= "\n\\special{ps:ENDOFSTUDENTSTAMP}\n"; return ($current_output,$fullname, $printed); } @@ -1628,37 +1930,20 @@ sub print_resources { sub handler { my $r = shift; - my $helper; + + &init_perm(); -# my $loaderror=&Apache::lonnet::overloaderror($r); -# if ($loaderror) { return $loaderror; } -# $loaderror= -# &Apache::lonnet::overloaderror($r, -# $env{'course.'.$env{'request.course.id'}.'.home'}); -# if ($loaderror) { return $loaderror; } - - my $result = printHelper($r); - if (!ref($result)) { - return $result; + + + my $helper = printHelper($r); + if (!ref($helper)) { + return $helper; } - $helper = $result; -# my $key; -# foreach $key (keys %{$helper->{'VARS'}}) { -# $r->print(' '.$key.'->'.$helper->{'VARS'}->{$key}.'<-
'); -# } -# foreach $key (keys %env) { -# $r->print(' '.$key.'->'.$env{$key}.'<-
'); -# } -# return OK; my %parmhash=&Apache::lonnet::coursedescription($env{'request.course.id'}); -# my $key; -# foreach $key (keys %parmhash) { -# $r->print(' '.$key.'->'.$parmhash{$key}.'<-
'); -# } -# + # If a figure conversion queue file exists for this user.domain @@ -1682,7 +1967,21 @@ sub addMessage { Apache::lonhelper::message->new(); } -use Data::Dumper; + + +sub init_perm { + undef(%perm); + $perm{'pav'}=&Apache::lonnet::allowed('pav',$env{'request.course.id'}); + if (!$perm{'pav'}) { + $perm{'pav'}=&Apache::lonnet::allowed('pav', + $env{'request.course.id'}.'/'.$env{'request.course.sec'}); + } + $perm{'pfo'}=&Apache::lonnet::allowed('pav',$env{'request.course.id'}); + if (!$perm{'pfo'}) { + $perm{'pfo'}=&Apache::lonnet::allowed('pfo', + $env{'request.course.id'}.'/'.$env{'request.course.sec'}); + } +} sub printHelper { my $r = shift; @@ -1727,23 +2026,29 @@ sub printHelper { $helper->declareVar("showallfoils"); # The page breaks can get loaded initially from the course environment: + # But we only do this in the initial state so that they are allowed to change. + # - if((!defined($env{"form.CURRENT_STATE"})) || - ($env{'form.CURRENT_STATE'} == "START")) { - $helper->{VARS}->{FINISHPAGE} = ""; # In case they did a back e.g. - } - - + # $helper->{VARS}->{FINISHPAGE} = ''; &Apache::loncommon::restore_course_settings('print', {'pagebreaks' => 'scalar', 'lastprinttype' => 'scalar'}); - - if("$helper->{VARS}->{PRINT_TYPE}" eq "$env{'form.lastprinttype'}") { - $helper->{VARS}->{FINISHPAGE} = $env{'form.pagebreaks'}; - } + if($helper->{VARS}->{PRINT_TYPE} eq $env{'form.lastprinttype'}) { + if (!defined ($env{"form.CURRENT_STATE"})) { + + $helper->{VARS}->{FINISHPAGE} = $env{'form.pagebreaks'}; + } else { + my $state = $env{"form.CURRENT_STATE"}; + if ($state eq "START") { + $helper->{VARS}->{FINISHPAGE} = $env{'form.pagebreaks'}; + } + } + + } + # This will persistently load in the data we want from the # very first screen. @@ -1761,6 +2066,7 @@ sub printHelper { if ($env{'form.url'}) { $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($helper->{VARS}->{'postdata'}); } + } if ($env{'form.symb'}) { @@ -1806,9 +2112,6 @@ sub printHelper { } my $userCanSeeHidden = Apache::lonnavmaps::advancedUser(); - my $userPriviledged = ($env{'request.role'}=~m/^cc\./ or - $env{'request.role'}=~m/^in\./ or - $env{'request.role'}=~m/^ta\./); Apache::lonhelper::registerHelperTags(); @@ -1850,9 +2153,7 @@ sub printHelper { $helper->declareVar('SEQUENCE'); - # Useful for debugging: Dump the help vars -# $r->print(Dumper($helper->{VARS})); -# $r->print($map); + # If we're in a sequence... if (($helper->{'VARS'}->{'construction'} ne '1') && @@ -1893,10 +2194,10 @@ HELPERFRAGMENT &Apache::lonxml::xmlparse($r, 'helper', $helperFragment); } - # If the user is privileged, allow them to print all + # If the user has pfo (print for otheres) allow them to print all # problems and resources in the entier course, optionally for selected students - if ($userPriviledged && - ($helper->{VARS}->{'postdata'}=~/\/res\// || $helper->{VARS}->{'postdata'}=~/\/(syllabus|smppg|aboutme|bulletinboard)$/)) { + if ($perm{'pfo'} && + ($helper->{VARS}->{'postdata'}=~/\/res\// || $helper->{VARS}->{'postdata'}=~/\/(syllabus|smppg|grppg|aboutme|bulletinboard)$/)) { push @{$printChoices}, ['Problems from entire course', 'all_problems', 'ALL_PROBLEMS']; push @{$printChoices}, ['Resources from entire course', 'all_resources', 'ALL_RESOURCES']; @@ -1928,7 +2229,19 @@ ALL_PROBLEMS push @{$printChoices}, ["".&mt('Problems')." ".&mt('from')." $sequenceTitle ".&mt('for')." ".&mt('selected students')."", 'problems_for_students', 'CHOOSE_STUDENTS']; push @{$printChoices}, ["".&mt('Problems')." ".&mt('from')." $sequenceTitle ".&mt('for')." ".&mt('anonymous students')."", 'problems_for_anon', 'CHOOSE_ANON1']; } + + # resource_selector will hold a few states that: + # - Allow resources to be selected for printing. + # - Determine pagination between assignments. + # - Determine how many assignments should be bundled into a single PDF. + # TODO: + # Probably good to do things like separate this up into several vars, each + # with one state, and use REGEXPs at inclusion time to set state names + # and next states for better mix and match capability + # my $resource_selector=< + PRINT_FORMATTING
Select resources for the assignment
@@ -1937,6 +2250,8 @@ ALL_PROBLEMS return $symbFilter; + +
How should the results be printed?
Start each student\'s assignment on a new page/column (add a pagefeed after each assignment) @@ -1944,20 +2259,29 @@ ALL_PROBLEMS Add two empty pages/column after each student\'s assignment Add three empty pages/column after each student\'s assignment -
Number of assignments printed at the same time:
- "all" + PAGESIZE +
How do you want assignments split into PDF files?
+ + All assignments in a single PDF file + Each PDF contains exactly one section + Each PDF contains exactly one assignment + + Specify the number of assignments per PDF: + +
RESOURCE_SELECTOR &Apache::lonxml::xmlparse($r, 'helper', < - Select sort order Sort by section then student Sort by students across sections. - $resource_selector +


+ + $resource_selector CHOOSE_STUDENTS my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; @@ -1969,6 +2293,40 @@ CHOOSE_STUDENTS if ($name =~ /^type\0/) { next; } $namechoice.=''.$name.''; } + + + my %code_values; + my %codes_to_print; + foreach my $key (@names) { + %code_values = &Apache::grades::get_codes($key, $cdom, $cnum); + foreach my $key (keys(%code_values)) { + $codes_to_print{$key} = 1; + } + } + + my $code_selection = "\n"; + foreach my $code (sort {uc($a) cmp uc($b)} (keys(%codes_to_print))) { + my $choice = $code; + if ($code =~ /^[A-Z]+$/) { # Alpha code + $choice = &letters_to_num($code); + } + push(@{$helper->{DATA}{ALL_CODE_CHOICES}},[$code,$choice]); + } + if (%codes_to_print) { + $code_selection .=' + Choose single code from list + + + + push(@{$state->{CHOICES}},@{$helper->{DATA}{ALL_CODE_CHOICES}}); + + +
+ '.$/; + + } + + open(FH,$Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab'); my $codechoice=''; foreach my $line () { @@ -1984,13 +2342,14 @@ CHOOSE_STUDENTS } &Apache::lonxml::xmlparse($r, 'helper', < - PAGESIZE -
-
Number of anonymous assignments to print? + SELECT_PROBLEMS +
Number of anonymous assignments to print: if (((\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}+0) < 1) && - !\$helper->{'VARS'}{'REUSE_OLD_CODES'}) { + !\$helper->{'VARS'}{'REUSE_OLD_CODES'} && + !\$helper->{'VARS'}{'SINGLE_CODE'} && + !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) { return "You need to specify the number of assignments to print"; } return undef; @@ -2006,15 +2365,34 @@ CHOOSE_STUDENTS $codechoice -
-
+

+
+ Enter a CODE to print: + + + if(!\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'} && + !\$helper->{'VARS'}{'REUSE_OLD_CODES'} && + !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) { + return &Apache::lonprintout::is_code_valid(\$helper->{'VARS'}{'SINGLE_CODE'}, + \$helper->{'VARS'}{'CODE_OPTION'}); + } else { + return undef; # Other forces control us. + } + + +

+ $code_selection + + Reprint a set of saved CODEs: + $namechoice +

- $resource_selector + $resource_selector CHOOSE_ANON1 @@ -2025,6 +2403,8 @@ CHOOSE_ANON1 $resource_selector=< + PRINT_FORMATTING
Select resources for the assignment
@@ -2033,6 +2413,9 @@ CHOOSE_ANON1 return $symbFilter; + + + NUMBER_PER_PDF
How should the results be printed?
Start each student\'s assignment on a new page/column (add a pagefeed after each assignment) @@ -2040,30 +2423,41 @@ CHOOSE_ANON1 Add two empty pages/column after each student\'s assignment Add three empty pages/column after each student\'s assignment -
Number of assignments printed at the same time:
- "all" + PAGESIZE +
How do you want assignments split into PDF files?
+ + All assignments in a single PDF file + Each PDF contains exactly one section + Each PDF contains exactly one assignment + + Specify the number of assignments per PDF: + +
RESOURCE_SELECTOR &Apache::lonxml::xmlparse($r, 'helper', < - Sort by section then student Sort by students across sections. +


+ - $resource_selector + $resource_selector CHOOSE_STUDENTS1 &Apache::lonxml::xmlparse($r, 'helper', < - PAGESIZE -
Number of anonymous assignments to print? + SELECT_RESOURCES +
Number of anonymous assignments to print: if (((\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}+0) < 1) && - !\$helper->{'VARS'}{'REUSE_OLD_CODES'}) { + !\$helper->{'VARS'}{'REUSE_OLD_CODES'} && + !\$helper->{'VARS'}{'SINGLE_CODE'} && + !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) { return "You need to specify the number of assignments to print"; } return undef; @@ -2079,20 +2473,37 @@ CHOOSE_STUDENTS1 $codechoice -
-
+

+
+ Enter a CODE to print: + + + if(!\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'} && + !\$helper->{'VARS'}{'REUSE_OLD_CODES'} && + !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) { + return &Apache::lonprintout::is_code_valid(\$helper->{'VARS'}{'SINGLE_CODE'}, + \$helper->{'VARS'}{'CODE_OPTION'}); + } else { + return undef; # Other forces control us. + } + + +

+ $code_selection Reprint a set of saved CODEs: + $namechoice +

- $resource_selector + $resource_selector CHOOSE_ANON2 } # FIXME: That RE should come from a library somewhere. - if ((((&Apache::lonnet::allowed('bre',$subdir) eq 'F') and ($helper->{VARS}->{'postdata'}=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)/)) or defined $helper->{'VARS'}->{'construction'}) and $env{'request.role.adv'} and $subdir ne $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/') { + if ((((&Apache::lonnet::allowed('bre',$subdir) eq 'F') and ($helper->{VARS}->{'postdata'}=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)/)) or defined $helper->{'VARS'}->{'construction'}) and $perm{'pav'} and $subdir ne $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/') { push @{$printChoices}, ["".&mt('Problems')." ".&mt('from current subdirectory')." $subdir", 'problems_from_directory', 'CHOOSE_FROM_SUBDIR']; my $f = '$filename'; @@ -2132,7 +2543,8 @@ CHOOSE_FROM_SUBDIR CHOOSE_FROM_ANY_SEQUENCE return \$res->is_sequence; return $urlValue; -