--- loncom/interface/lonprintout.pm 2011/06/06 10:53:09 1.590
+++ loncom/interface/lonprintout.pm 2011/09/15 16:02:18 1.598
@@ -2,7 +2,7 @@
# The LearningOnline Network
# Printout
#
-# $Id: lonprintout.pm,v 1.590 2011/06/06 10:53:09 foxr Exp $
+# $Id: lonprintout.pm,v 1.598 2011/09/15 16:02:18 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -123,7 +123,7 @@ sub create_incomplete_folder_selstud_hel
my $format_chooser = &generate_format_selector($helper,
'Format of the print job',
- '','CHOOSE_STUDENTS_INCOMPLETE_FORMAT'); # end state.
+ 'CHOOSE_STUDENTS_INCOMPLETE_FORMAT'); # end state.
return $resource_chooser . $student_chooser . $format_chooser;
}
@@ -172,7 +172,6 @@ sub create_incomplete_course_helper {
my $format = &generate_format_selector($helper,
'Format of the print job',
- '',
'INCOMPLETE_PROBLEMS_COURSE_FORMAT'); # end state.
return $resource_chooser . $people_chooser . $format;
@@ -395,21 +394,25 @@ CHOOSE_ANON1
return $result;
}
+# Returns the XML for choosing how assignments are to be formatted
+# that text must still be parsed by the helper xml parser.
+# Parameters: 3 (required)
+
+# helper - The helper; $helper->{'VARS'}->{'PRINT_TYPE'} used
+# to check if splitting PDFs by section can be offered.
+# title - Title for the current state.
+# this_state - State name of the chooser.
+
sub generate_format_selector {
- my ($helper,$title,$nextstate, $thisstate) = @_;
+ my ($helper,$title,$this_state) = @_;
my $secpdfoption;
- my $state = 'PRINT_FORMATTING';
- if ($thisstate) {
- $state = $thisstate;
- }
unless (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_anon') ||
($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_anon_page') ||
($helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_anon') ) {
$secpdfoption = 'Each PDF contains exactly one section';
}
return <
- $nextstate
+
How should the results be printed?
Start each student\'s assignment on a new page/column (add a pagefeed after each assignment)
@@ -432,6 +435,101 @@ RESOURCE_SELECTOR
#-----------------------------------------------------------------------
+# Determine if a resource is incomplete given the map:
+# Parameters:
+# $username - Name of user for whom we are checking.
+# $domain - Domain of user we are checking.
+# $map - map name.
+# Returns:
+# 0 - map is not incomplete.
+# 1 - map is incomplete.
+#
+sub incomplete {
+ my ($username, $domain, $map) = @_;
+
+
+ my $navmap = Apache::lonnavmaps::navmap->new($username, $domain);
+
+
+ if (defined($navmap)) {
+ my $res = $navmap->getResourceByUrl($map);
+ my $result = $res->is_incomplete();
+ return $result;
+ } else {
+ return 1;
+ }
+}
+#
+# When printing for students, the resoures and order of the
+# resources may need to be altered if there are folders with
+# random selectiopn or random ordering (or both) enabled.
+# This sub computes the set of resources to print for a student
+# modified both by random ordering and selection and filtered
+# to only those that are in the original set selcted to be printed.
+#
+# Parameters:
+# $helper - The helper we need $helper->{'VARS'}->{'symb'}
+# to construct the navmap and the iteration.
+# $seq - The original set of resources to print
+# (really an array of resource names
+# $who - Student/domain for whome the sequence will be generated.
+#
+# Implicit inputs:
+# $
+# Returns:
+# reference to an array of resources that can be passed to
+# print_resources.
+#
+sub master_seq_to_person_seq {
+ my ($helper, $seq, $who) = @_;
+
+
+ my ($username, $userdomain, $usersection) = split(/:/, $who);
+
+ # Toss the sequence up into a hash so that we have O(1) lookup time.
+ # on the items that come out of the user's list of resources.
+ #
+
+ my %seq_hash = map {$_ => 1} @$seq;
+ my @output_seq;
+
+ my ($map, $id, $url) = &Apache::lonnet::decode_symb($helper->{VARS}->{'symb'});
+ my $navmap = Apache::lonnavmaps::navmap->new($username, $userdomain);
+ my $iterator = $navmap->getIterator($navmap->firstResource(),
+ $navmap->finishResource(),
+ {}, 1);
+ my %nonResourceItems = (
+ $iterator->BEGIN_MAP => 1,
+ $iterator->BEGIN_BRANCH => 1,
+ $iterator->END_BRANCH => 1,
+ $iterator->END_MAP => 1,
+ $iterator->FORWARD => 1,
+ $iterator->BACKWARD => 1
+
+ ); # These items are not resources but appear in the midst of iteration.
+
+ # Iterate on the resource..select the items that are randomly selected
+ # and that are in the seq_has. Presumably the iterator will take care
+ # of the random ordering part of the deal.
+ #
+ my $curres;
+ while ($curres = $iterator->next()) {
+ #
+ # Only process resources..that re not removed by randomout...
+ #
+ if (! exists $nonResourceItems{$curres} && ! $curres->randomout()) {
+ my $symb = $curres->symb();
+ if (exists $seq_hash{$symb}) {
+ push(@output_seq, $symb);
+ }
+ }
+ }
+
+
+ return \@output_seq; # for now.
+
+}
+
# Fetch the contents of a resource, uninterpreted.
# This is used here to fetch a latex file to be included
@@ -606,7 +704,6 @@ sub ssi_with_retries {
$ssi_last_error_resource = $resource;
$ssi_last_error = $response->code . " " . $response->message;
$content='\section*{!!! An error occurred !!!}';
- &Apache::lonnet::logthis("Error in SSI resource: $resource Error: $ssi_last_error");
}
return $content;
@@ -622,7 +719,6 @@ sub get_student_view_with_retries {
$ssi_last_error_resource = $curresline.' for user '.$username.':'.$userdomain;
$ssi_last_error = $response->code . " " . $response->message;
$content='\section*{!!! An error occurred !!!}';
- &Apache::lonnet::logthis("Error in SSI (student view) resource: $curresline Error: $ssi_last_error User: $username:$userdomain");
}
return $content;
@@ -2222,13 +2318,12 @@ sub print_construction_sequence {
#BZ 5209
# 2 map_incomplete_problems_seq Print incomplete problems from the current
# folder in student context.
-# 101 map_incomplete_problems_people_seq Print incomplete problems from the
+# 5 map_incomplete_problems_people_seq Print incomplete problems from the
# current folder in privileged context.
-# 102 incomplete_problems_selpeople_course Print incomplete problems for
+# 5 incomplete_problems_selpeople_course Print incomplete problems for
# selected people from the entire course.
#
# Item 101 has much the same processing as 8,
-# Item 102 has much the same processing as 8.
#
# Differences: Item 101, 102 require per-student filtering of the resource
# set so that only the incomplete resources are printed.
@@ -2724,14 +2819,18 @@ ENDPART
} elsif (($print_type eq 'problems_for_students') ||
($print_type eq 'problems_for_students_from_page') ||
($print_type eq 'all_problems_students') ||
- ($print_type eq 'resources_for_students')){
+ ($print_type eq 'resources_for_students') ||
+ ($print_type eq 'incomplete_problems_selpeople_course') ||
+ ($print_type eq 'map_incomplete_problems_people_seq')){
#-- prints assignments for whole class or for selected students
my $type;
if (($print_type eq 'problems_for_students') ||
($print_type eq 'problems_for_students_from_page') ||
- ($print_type eq 'all_problems_students') ) {
+ ($print_type eq 'all_problems_students') ||
+ ($print_type eq 'incomplete_problems_selpeople_course') ||
+ ($print_type eq 'map_incomplete_problems_people_seq')) {
$selectionmade=5;
$type='problems';
} elsif ($print_type eq 'resources_for_students') {
@@ -2788,7 +2887,6 @@ ENDPART
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";
if (-e $duefile) {
my $temp_file = Apache::File->new('>>'.$duefile);
@@ -2804,9 +2902,10 @@ ENDPART
} else {
$i=int($student_counter/$helper->{'VARS'}{'NUMBER_TO_PRINT'});
}
+ my $actual_seq = master_seq_to_person_seq($helper, \@master_seq, $person);
my ($output,$fullname, $printed)=&print_resources($r,$helper,
$person,$type,
- \%moreenv,\@master_seq,
+ \%moreenv, $actual_seq,
$flag_latex_header_remove,
$LaTeXwidth);
$resources_printed .= ":";
@@ -2832,17 +2931,24 @@ ENDPART
my $code_option=$helper->{'VARS'}->{'CODE_OPTION'};
my @lines = &Apache::grades::get_scantronformat_file();
- my ($code_type,$code_length)=('letter',6);
+ my ($code_type,$code_length,$bubbles_per_row)=('letter',6,10);
foreach my $line (@lines) {
- my ($name,$type,$length) = (split(/:/,$line))[0,2,4];
+ chomp($line);
+ my ($name,$type,$length,$bubbles_per_item) =
+ (split(/:/,$line))[0,2,4,17];
if ($name eq $code_option) {
$code_length=$length;
if ($type eq 'number') { $code_type = 'number'; }
+ chomp($bubbles_per_item);
+ if (($bubbles_per_item ne '') && ($bubbles_per_item > 0)) {
+ $bubbles_per_row = $bubbles_per_item;
+ }
}
}
my %moreenv = ('textwidth' => &get_textwidth($helper,$LaTeXwidth));
$moreenv{'problem_split'} = $parmhash{'problem_stream_switch'};
$moreenv{'instructor_comments'}='hide';
+ $moreenv{'bubbles_per_row'} = $bubbles_per_row;
my $seed=time+($$<<16)+($$);
my @allcodes;
if ($old_name) {
@@ -3159,7 +3265,17 @@ sub print_resources {
my ($username,$userdomain,$usersection) = split /:/,$person;
my $fullname = &get_name($username,$userdomain);
my $namepostfix = "\\\\"; # Both anon and not anon should get the same vspace.
- if ($person =~ 'anon') {
+ #
+ # Figure out if we need to filter the output by
+ # the incomplete problems for that person
+ #
+ my $print_type = $helper->{'VARS'}->{'PRINT_TYPE'};
+ my $print_incomplete = 0;
+ if (($print_type eq 'map_incomplete_problems_people_seq') ||
+ ($print_type eq 'incomplete_problems_selpeople_course')) {
+ $print_incomplete = 1;
+ }
+ if ($person eq 'anonymous') {
$namepostfix .="Name: ";
$fullname = "CODE - ".$moreenv->{'CODE'};
}
@@ -3168,6 +3284,7 @@ sub print_resources {
#
my $i = 0;
+ my $actually_printed = 0; # Count of resources printed.
#goes through all resources, checks if they are available for
#current student, and produces output
@@ -3184,6 +3301,7 @@ sub print_resources {
# so we will just rely on prntout.pl to strip ENDOFSTUDENTSTAMP from the
# postscript. Each ENDOFSTUDENTSTAMP will go on a line by itself.
#
+
my $syllabus_first = 0;
foreach my $curresline (@{$master_seq}) {
if (defined $page_breaks{$curresline}) {
@@ -3196,6 +3314,10 @@ sub print_resources {
if ( !($type eq 'problems' &&
($curresline!~ m/\.(problem|exam|quiz|assess|survey|form|library|page)$/)) ) {
my ($map,$id,$res_url) = &Apache::lonnet::decode_symb($curresline);
+ if ($print_incomplete && !&incomplete($username, $userdomain, $res_url)) {
+ next;
+ }
+ $actually_printed++; # we're going to print one.
if (&Apache::lonnet::allowed('bre',$res_url)) {
if ($res_url!~m|^ext/|
&& $res_url=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) {
@@ -3209,6 +3331,7 @@ sub print_resources {
$rendered = &print_latex_header().$rendered;
}
}
+;
if ($remove_latex_header eq 'YES') {
$rendered = &latex_header_footer_remove($rendered);
} else {
@@ -3220,6 +3343,8 @@ sub print_resources {
# 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();
@@ -3294,6 +3419,20 @@ sub print_resources {
}
if (&Apache::loncommon::connection_aborted($r)) { last; }
}
+ # If we are printing incomplete it's possible we don't have
+ # anything to print. The print subsystem is not so good at handling
+ # that so we're going to generate a stub that says there are no
+ # incomplete resources for the person.
+ #
+
+ if ($actually_printed == 0) {
+ $current_output = &encapsulate_minipage("\\vskip -10mm \nNo incomplete resources\n \\vskip 100 mm { }\n");
+ if ($remove_latex_header eq "NO") {
+ $current_output = &print_latex_header() . $current_output;
+ } else {
+ $current_output = &latex_header_footer_remove($current_output);
+ }
+ }
if ($syllabus_first) {
$current_output =~ s/\\\\ Last updated:/Last updated:/
@@ -3718,7 +3857,7 @@ sub printHelper {
}
push(@{$printChoices},
- [&mt('Selected Incomplete [_1]Problems[_2] from folder [_3]' . $textSuffix,
+ [&mt('Selected [_1]Incomplete Problems[_2] from folder [_3]' . $textSuffix,
'', '',
''. $sequenceTitle . ''),
$printSelector,
@@ -3765,7 +3904,7 @@ sub printHelper {
# BZ 5209 - incomplete problems from entire course:
push(@{$printChoices},
- [&mtn('Selected incomplete Problems from entire course for selected people'),
+ [&mtn('Selected Incomplete Problems from entire course for selected people'),
'incomplete_problems_selpeople_course', 'INCOMPLETE_PROBLEMS_COURSE_RESOURCES']);
my $helperFragment = &create_incomplete_course_helper($helper); # Create needed states.
@@ -3838,7 +3977,7 @@ ALL_PROBLEMS
}
my $randomly_ordered_warning =
- &get_randomly_ordered_warning($helper,$map);
+ &get_randomly_ordered_warning($helper, $map);
# resource_selector will hold a few states that:
# - Allow resources to be selected for printing.
@@ -3857,14 +3996,9 @@ ALL_PROBLEMS
$map,
$isProblem, '', $symbFilter,
$start_new_option);
- my $secpdfoption;
- unless (($helper->{'VARS'} eq 'problems_for_anon') ||
- ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_anon_page') ||
- ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_anon') ) {
- $secpdfoption = 'Each PDF contains exactly one section';
- }
$resource_selector .= &generate_format_selector($helper,
- 'How should results be printed?').
+ 'How should results be printed?',
+ 'PRINT_FORMATTING').
&generate_resource_chooser('CHOOSE_STUDENTS_PAGE',
'Select Problem(s) to print',
"multichoice='1' addstatus='1' closeallpages ='1'",
@@ -3998,10 +4132,9 @@ ALL_PROBLEMS
RESOURCE_SELECTOR
- my $nextstate = 'NUMBER_PER_PDF';
$resource_selector .= &generate_format_selector($helper,
'Format of the print job',
- $nextstate);
+ 'PRINT_FORMATTING');
&Apache::lonxml::xmlparse($r, 'helper', <