#! /usr/bin/perl
#  Copyright 2001-2023 Leslie Richardson
 
#  This file is part of Open Admin for Schools.

# This is a DUAL RUN script. It runs in /tcgi and also /cgi/repcard.

# Outline: This prints a full xtab report for a single grade/course. All
# objectives are perpendicular.

# Outline: 1) Find all the students in the group (class/section/grade).
#  2) Loop through all eval records for the selected term to find all
#  of the courses.  
#  3) Load all courses into a 2D array. Baseref->Arrayptr1->[0], etc. 
#   Order by subjsec, name of subject, then any objectives next (start 
#   at array index 2)

my %lex = ('Year End' => 'Year End',
	   'Report' => 'Report',
	   'Missing' => 'Missing',
	   'Group' => 'Group',
	   'Grade' => 'Grade',
	   'Homeroom' => 'Homeroom',
	   'View/Download' => 'View/Download',
	   'Download' => 'Download',
	   'File' => 'File',
	   'Teacher' => 'Teacher',
	   'Principal' => 'Principal',
	   'View Log File' => 'View Log File',
	   'Report Card' => 'Report Card',
	   'Main' => 'Main',
	   'Short Subject Descriptions' => 'Short Subject Descriptions',
	   'Note' => 'Note',
	   'Page' => 'Page',
	   'Term' => 'Term',
	   'No Student(s) Found' => 'No Student(s) Found',
	   'Y' => 'Y',
	   'Error' => 'Error',
	   'Continue' => 'Continue',
	   'Select by' => 'Select by',
	   'Paper Size' => 'Paper Size',
	   'Letter' => 'Letter',
	   'A4' => 'A4',
	   'Legal' => 'Legal',
	   'Student(s)' => 'Student(s)',
	   'Output' => 'Output',
	   'Combine failed' => 'Combine failed',
	   'End' => 'End',
	   'OR' => 'OR',
	   'Cannot open' => 'Cannot open',
	   'Form' => 'Form',
	   
	   );

my $self = 'rptfinalsumm.pl';

use DBI;
use CGI;
use Cwd;
use Number::Format qw(:all);


# Constants
# These two settings control the vertical height of the header.
my $objectivelength = 36; # number of characters to truncate objectives to.
my $offset = "25mm"; # Strut length in print_header fn.

my $maxstudents = 32; # Number of student rows per page; if you adjust above, 
# this may have to change also.

my $maxlegalcols = 16; # maximum number of columns per printed page.
my $maxlettercols = 16;



# Get current dir so know what path for config files.
my $configpath;
if (getcwd() =~ /tcgi/){ # we are in tcgi
    $configpath = '..'; # go back one to get to etc.
} else {
    $configpath = '../..'; # go back two to get to etc.
}

eval require "$configpath/etc/admin.conf";
if ( $@ ) {
    print $lex{Error}. ": $@<br>\n";
    die $lex{Error}. ": $@\n";
}

eval require "$configpath/etc/repcard.conf";
if ( $@ ) {
    print $lex{Error}. ": $@<br>\n";
    die $lex{Error}. ": $@\n";
}

eval require "$configpath/lib/liblatex.pl";
if ( $@ ) {
    print $lex{Error}. ": $@<br>\n";
    die $lex{Error}. ": $@\n";
}

eval require "$configpath/lib/libattend.pl";
if ( $@ ) {
    print $lex{Error}. ": $@<br>\n";
    die $lex{Error}. ": $@\n";
}

# Get current dir so know what CSS to display;
if (getcwd() =~ /tcgi/){ # we are in tcgi
    $css = $tchcss;
}

my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $iddst) = localtime(time);
$year = $year + 1900;
$mon++;
$wday++;
my $currlongdate = "$dow[$wday], $month[$mon] $mday, $year";
my $currdate = "$month[$mon] $year"; # $mday removed

if (length($mon) == 1){ $mon = '0'.$mon;}
if (length($mday) == 1){ $mday = '0'.$mday;}
my $currsdate = "$year-$mon-$mday";


my $dsn = "DBI:$dbtype:dbname=$dbase";
my $dbh = DBI->connect($dsn,$user,$password);



my $q = new CGI;
print $q->header( -charset, $charset );
my %arr = $q->Vars;

my $term = $arr{term};

# Print the Page Header
my $title = "$lex{'Year End'} $lex{Report}";
print qq{$doctype\n<html><head><title>$title</title>
<link rel="stylesheet" href="$css" type="text/css">
$chartype\n</head><body style="margin:1em;">\n};

print qq{<div>[ <a href="$homepage">$lex{Main}</a> \n};
if ( not (getcwd() =~ tcgi) ) { # not running in tcgi
    print qq{| <a href="$reppage">$lex{'Report Card'}</a>\n};
}
print qq{ ]</div>\n};

print qq{<h1>$title</h1>\n};



if ( not $arr{page} ) {
    showStartPage();

} else {
    delete $arr{page};

    # foreach my $key (sort keys %arr ) { print qq{K:$key V:$arr{$key}<br>\n}; }
    
    if ( not $arr{term} ) {
	print qq{<h3>Missing End Term</h3>\n};
	print qq{</body></html>\n};
	exit;
    }

    if ( not $arr{grade} and not $arr{homeroom} ) {
	print qq{<h3>Missing Grade/Homeroom</h3>\n};
	print qq{</body></html>\n};
	exit;
    }
    
    if ( $arr{output} eq 'pdf' ) {
	delete $arr{output};
	makePDF();

    } elsif ( $arr{output} eq 'csv') {
	delete $arr{output};
	makeCSV();
    }
}



#----------
sub makeCSV {
#----------

    #foreach my $key ( sort keys %arr ) { print qq{K:$key V:$arr{$key}<br>\n}; }

    use Text::CSV_XS;

    my $csv = Text::CSV_XS->new( {binary => 1} );

    # End term
    my $endterm = $arr{term}; # final term
    delete $arr{term};

    # Join sections
    my $joinsection;
    if ( $arr{joinsection} ) {
	$joinsection = $arr{joinsection};
	delete $arr{joinsection};
    }
    
    # group and group_value
    my $group = 'grade';
    my $group_value = $arr{grade};
    
    if ( $arr{homeroom} ) {
	$group_value = $arr{homeroom};
	$group = 'homeroom';
    }
    if ( not $group_value ) {
	print qq{<h3>Missing Grade/Homeroom value</h3>\n};
	print qq{</body></html>\n};
	exit;
    }

   

    # Get Students First; by grade or homeroom.
    my $sth = $dbh->prepare("select studnum, lastname, firstname, grade, homeroom from student
			    where $group = ? order by lastname, firstname");
    $sth->execute( $group_value );
    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }

    my (%names, %grades,%homerooms);  # names{studnum} = "last,first"; %grades{grade}[studnum];
    
    while ( my $ref = $sth->fetchrow_hashref ) {
	my %r = %$ref;
	$names{$r{studnum}} = qq{$r{lastname}, $r{firstname}};
	$homerooms{$r{studnum}} = $r{homeroom};

	push @{ $grades{$r{grade}} }, $r{studnum};  # so we have sorted students.
	# @test = @{ $grades{$r{grade}} };  # not used.
    }

    if ( not %names ) {
	print qq{<h3>$lex{'No Student(s) Found'}</h3>\n};
	print qq{</body></html>\n};
	exit;
    }

    # Open output file
    # my $filename = "rptfinal$$.csv";
    my $filename = "rptfinal$$.csv";
    open (EX,">$filename") || die $lex{'Cannot open'}. " $fileName";

    
    # Get Courses
    my $sth1 = $dbh->prepare("select distinct subjcode from eval
			     where term = ? and studnum = ?");
    # Collect all the courses taken by this group of students.
    my %courses; # note a hash so we can get multiple subjsec of same key value.

    foreach my $grade ( sort keys %grades ) {
	foreach my $studnum ( @{ $grades{$grade}} ) {
	    
	    $sth1->execute( $term, $studnum );
	    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }

	    while ( my $subjsec = $sth1->fetchrow ) {

		# Skip Unwanted Courses
		my ($subjcode, $section) = split('-', $subjsec);
		if ( $r_SupressSubject{$subjsec} or $r_SupressSubject{$subjcode} or 
		     $r_AdditionalComments{$subjsec} or $r_AdditionalComments{$subjcode} ) {
		    next; 
		}

		$courses{$subjsec} = 1;
	    }
	}
    }
    
    if ( not %courses ) {
	print qq{<h3>No Courses Found!</h3>\n};
	print qq{</body></html>\n};
	exit;
    }

    my %courseinfo; # $courseinfo{subjsec} = ref;
    my @courses; # set in loop below, giving correct ordering, just in case.
    my %sections; # sections{subjcode}{subjsec} = 1;	
    
    foreach my $subjsec ( sort keys %courses ){

	my ($subjcode, $section) = split('-', $subjsec);
	
	# Get Course Information; pull in full record
	$sth = $dbh->prepare("select * from subject where subjsec = ?");
	$sth->execute( $subjsec );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my $ref = $sth->fetchrow_hashref;
	my %r = %$ref;

	
	$sections{$subjcode}{$subjsec} = 1;
	$courseinfo{$subjsec} = $ref;
	
	# If no short description, then long version truncated into short desc.
	if ( not $r{smdesc} ){
	    if ( length( $r{description} ) > $objectivelength ) { 
		$r{smdesc} = substr( $r{description},0,$objectivelength); # trunc full desc
	    } else { # length is ok.
		$r{smdesc} = $r{description};
	    }
	}

	push @courses, $subjsec;
	
    } # end of course loop

#    print qq{Courses:@courses<br>Sections:}, %sections, "<br>\n";    
    
    if ($joinsection) { # make courses into subject code version.
	@courses = sort keys %sections;
    }
    
    use Text::CSV_XS;
    my $csv = Text::CSV_XS->new( {binary => 1} );


    # Header Line
    my @line;

    my $groupname;
    if ( $group eq 'grade' ) {
	$groupname ="$lex{Grade} $group_value";
    } else {
	$groupname = "$lex{Homeroom} $group_value";
    }
    
    push @line, 'HRm';
    push @line, $groupname;


    if ( $joinsection ) {
	foreach my $subjcode ( @courses ) {
	    my @tempsec = sort keys %{ $sections{$subjcode}}; # get all subjsecs for this course.
	    # we'll only use the first one to get description
	    my %r = %{ $courseinfo{$tempsec[0]}}; # was subj
	    my $desc = $r{smdesc};
	    if ( $arr{coursedesc} eq 'subjsec' ) {
		$desc = $subjsec;
	    } elsif ( $arr{coursedesc} eq 'both' ) {
		$desc = $r{smdesc}. qq{ - $subjsec};
	    }
	    push @line, $desc;
	}
    } else { # show all sections.
	foreach my $subjsec ( @courses ) {
	    my %r = %{ $courseinfo{$subjsec}};
	    my $desc = $r{smdesc};
	    if ( $arr{coursedesc} eq 'subjsec' ) {
		$desc = $subjsec;
	    } elsif ( $arr{coursedesc} eq 'both' ) {
		$desc = $r{smdesc}. qq{ - $subjsec};
	    }
	    push @line, $desc;
	}
    }

    push @line, "Attend";
    push @line, "Promotion";

    if ( $csv->combine( @line ) ) {
	my $record = $csv->string;
	print EX $record, "\r\n";

    } else {
	my $err = $csv->error_input;
	print qq{$lex{'Combine failed'}: $err\n\n};
    }
    # End of Header Line
    
    my $sth1 = $dbh->prepare("select grade from studentall where studnum = ?");    
    my $sth2 = $dbh->prepare("select count(*) from student where studnum = ?");    
    my $sth3 = $dbh->prepare("select endrptperiod from subject where subjsec = ?");
    my $sth4 = $dbh->prepare("select calcavg from subject where subjsec = ?");

    my $sth5 = $dbh->prepare("select $r_MarkField, term from eval where 
			    studnum = ? and subjcode = ?"); # equiv to $subjsec

    
#    foreach my $grade ( sort keys %grades ) {
#	my @student = @{ $grades{$grade} };
#	for my $studnum ( @student ) {
#	    print "SN:$studnum<br>\n";
#	}
#    }
    
    # Student Loop
    foreach my $grade ( sort keys %grades ) {
	my @students = @{ $grades{$grade}};
	foreach  my $studnum ( @students ) {

	    my @line;

	    # grade; needed for ppd.
	    $sth1->execute( $studnum );
	    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;}
	    my $gr = $sth1->fetchrow; # 

	    # Find $active value (ie. currently enrolled )
	    $sth2->execute( $studnum );
	    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;}
	    my $active = $sth2->fetchrow; # 

	
	    # calc attendance values for this student
	    # several values from admin.conf config file.
	    my $dayspresent = calcMyAttendance($studnum, $schoolstart, $schoolend,
					       $g_ppd{$gr},$active);
 	    $dayspresent = format_number($dayspresent, 2, 2);


	    push @line, $homerooms{$studnum};
	    push @line, "$names{$studnum} ($studnum)";



	    
	    #--------------------
	    if ( $joinsection ) {
		# Loop through each course for this student and print eval results.
		
		foreach my $subjcode (@courses) {
		    
		    my $testavg; # calculated in the sections below
		    
		    foreach my $subjsec ( sort keys %{ $sections{$subjcode}} ) {
		
			# Get the calcavg value (N or Y);
			$sth4->execute( $subjsec );
			if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
			my $calcavg = $sth4->fetchrow;

			if ( $calcavg eq $lex{Y} ) { # find average using r_AverageWeight by term
		    
			    $sth5->execute( $studnum, $subjsec );
			    if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; }
	    
			    my ($totalscore, $totalweight);
			    while ( my ($score,$term) = $sth5->fetchrow ) {
				if ( $score =~ m/\d/){ # if a digit...
				    if (not $r_AverageWeight{$term} ) { # Error
					print qq{<h3>No Average Weight (r_AverageWeight) defined };
					print qq{for this term: $term</h3>\n};
					print qq{</body></html>\n};
					exit;
				    }
				    my $wt = $r_AverageWeight{$term}; #The weight for this term 
				    $totalscore += ( $wt * $score );
				    $totalweight += $wt;
				    #print qq{<div>Score:$score Term:$term Weight:$wt</div>\n}
				}
			    }
		
			    if ( $totalweight ){ # We have some tests.
				$testavg = $totalscore / $totalweight;
				$testavg = format_number( $testavg, 1,1);
			    } else { 
				$testavg = ' ';
			    }
			    # print qq{<div>$subjsec Term $endterm Mark $testavg</div>\n};
		    
			} else { # We just find the final term mark
			    # course and get that term's value from eval table;
			    
			    # Get End Reporting period for final mark
			    # $sth3->execute( $subjsec );
			    # if ($DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
			    # my $endterm = $sth3->fetchrow;

			    my $sth = $dbh->prepare("select $r_MarkField from eval where 
						    studnum = ? and term = ? and subjcode = ?");
			    $sth->execute( $studnum, $endterm, $subjsec );
			    if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; }
			    $testavg = $sth->fetchrow;
			    $testavg =~ s/\%//; # strip any percents.
			    # print qq{<div>$subjsec Term $endterm Mark $testavg</div>\n};
			}

			if ( $testavg =~ m/\d/ ) { last; } # we have our number.
			
		    } # end of subjsec loop

		    push @line, $testavg;
		    
		} # end of courses loop
		
	    } else { # end of joinsection loop; normal course loop below
		
		# Loop through each course for this student and print eval results.
		foreach my $subjsec (@courses) {

		    my $testavg; # for this course

		    # Get the calcavg value (N or Y);
		    $sth4->execute( $subjsec );
		    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
		    my $calcavg = $sth4->fetchrow;

		    if ( $calcavg eq $lex{Y} ) { # find average using r_AverageWeight by term
		    
			$sth5->execute( $studnum, $subjsec );
			if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; }
	    
			my ($totalscore, $totalweight);
			while ( my ($score,$term) = $sth5->fetchrow ) {
			    if ( $score =~ m/\d/){ # if a digit...
				if (not $r_AverageWeight{$term} ) { # Error
				    print qq{<h3>No Average Weight (r_AverageWeight) defined };
				    print qq{for this term: $term</h3>\n};
				    print qq{</body></html>\n};
				    exit;
				}
				my $wt = $r_AverageWeight{$term}; #The weight for this term 
				$totalscore += ( $wt * $score );
				$totalweight += $wt;
				# print qq{<div>Score:$score Term:$term Weight:$wt</div>\n}
			    }
			}
		
			if ( $totalweight ){ # We have some tests.
			    $testavg = $totalscore / $totalweight;
			    $testavg = format_number( $testavg, 1,1);
			} else { 
			    $testavg = ' ';
			}
			# print qq{<div>$subjsec Term $endterm Mark $testavg</div>\n};
		    
		    } else { # We just find the final term mark
			# course and get that term's value from eval table;

			# Get End Reporting period for final mark
			# $sth3->execute( $subjsec );
			# if ($DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
			# my $endterm = $sth3->fetchrow;

			my $sth = $dbh->prepare("select $r_MarkField from eval where 
						studnum = ? and term = ? and subjcode = ?");
			$sth->execute( $studnum, $endterm, $subjsec );
			if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; }
			$testavg = $sth->fetchrow;
			$testavg =~ s/\%//; # strip any percents.
			# print qq{<div>$subjsec Term $endterm Mark $testavg</div>\n};
		    }

		    push @line, $testavg;
		    
		} # end of courses loop

	    } # end of non section join.
	
	    
	    push @line, $dayspresent;
	    # print qq{Line:", @line, "<br>\n};

	    if ( $csv->combine( @line ) ) {
		my $record = $csv->string;
		print EX $record, "\r\n";

	    } else {
		my $err = $csv->error_input;
		print qq{$lex{'Combine failed'}: $err\n\n};
	    }

	    $studcount++;

	}  # End of Student Loop 

    } # end of grades loop
    
    # alter for tcgi (teacher) functioning
    if ( getcwd() =~ tcgi ) {
	$downloaddir = $tchdownloaddir;
	$webdownloaddir = $tchwebdownloaddir;
    }

    close EX;

    system("mv $filename $downloaddir");

    print qq{<h1>[ <a href="$webdownloaddir/$filename">};
    print qq{$lex{Download} CSV $lex{File}</a> ]</h1>\n};

    print qq{</body></html>\n};

    exit;

} # end of makeCSV



#----------
sub makePDF {
#----------

    # foreach my $key ( sort keys %arr ) { print qq{K:$key V:$arr{$key}<br>\n}; }

    # Join sections
    my $joinsection;
    if ( $arr{joinsection} ) {
	$joinsection = $arr{joinsection};
	delete $arr{joinsection};
    }
    
    # Set Local Term Value
    my $endterm = $arr{term};
    delete $arr{term};

    # group and group_value
    my $group = 'grade';
    my $group_value = $arr{grade};
    
    if ( $arr{homeroom} ) {
	$group_value = $arr{homeroom};
	$group = 'homeroom';
    }
    if ( not $group_value ) {
	print qq{<h3>Missing Grade/Homeroom value</h3>\n};
	print qq{</body></html>\n};
	exit;
    }


    # Set paper size.
    my ( $papersize, $textheight, $textwidth, $maxcolumns );

    if ( $arr{papersize} eq 'legal' ) {
	$textwidth = $g_legalpaper_textwidth;
	$textheight = $g_legalpaper_textheight;
	$papersize = 'legalpaper';
	$maxcolumns = $maxlegalcols;

    } elsif ( $arr{papersize} eq 'a4' ) {
	$textwidth = $g_a4paper_textwidth;
	$textheight = $g_a4paper_textheight;
	$papersize = 'a4paper';
	$maxcolumns = $maxlettercols;

    } else { # Letter
	$textwidth = $g_letterpaper_textwidth;
	$textheight = $g_letterpaper_textheight;
	$papersize = 'letterpaper';
	$maxcolumns = $maxlettercols;
    }

    # $schoolstart and $schoolend defined in the admin.conf config file.
    my $schoolDaysInYear = calcDaysOpen($schoolstart,$schoolend, $dbh);

    # print qq{School Days: $schoolDaysInYear\n};


    # Must be passed a grade or homeroom.
    if ( not $group_value ) {  
	print qq{<h1>$lex{Missing} $lex{Group}</h1>\n};
	print qq{</body></html>\n};
	exit;
    }

    if ( $arr{studperpage} ) {
	$maxlines = $arr{studperpage};
    } else {
	$maxlines = $maxstudents;
    }

    # Get Students First; by grade or homeroom.
    my (@students, %students);
    my $sth = $dbh->prepare("select studnum, lastname, firstname, grade, homeroom from student
			    where $group = ? order by lastname, firstname");
    $sth->execute( $group_value );
    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
    while ( $ref = $sth->fetchrow_hashref ) {
	my %s = %$ref;
	push @students, $s{studnum};
	$students{ $s{studnum} } = $ref;
    }

    if ( not @students ) {
	print qq{<h1>$lex{'No Student(s) Found'}</h1>\n};
	print qq{</body></html>\n};
	exit;
    }


    # Setup TEX Code
    my $shortname = "summarkend$$";
    my $filename = "$shortname.tex";

    open(TEX,">$filename") || die "Can't open tex file";

    # removed landscape here...
    print TEX "\\documentclass[10pt,$papersize]{article}
\\usepackage{array,rotating,inputenc}
$a_latex_header
\\pagestyle{empty}
\\setlength{\\textwidth}{$textwidth}
\\setlength{\\textheight}{$textheight}
\\setlength{\\hoffset}{-20mm}
\\setlength{\\voffset}{-13mm}
\\setlength{\\topmargin}{0in}
\\setlength{\\headheight}{0mm}
\\setlength{\\headsep}{0mm}
\\setlength{\\parindent}{0mm}
\\setlength{\\evensidemargin}{0mm}
\\setlength{\\oddsidemargin}{0mm}
\\setlength{\\tabcolsep}{1pt}
\\setlength{\\extrarowheight}{4pt}\n";

    print TEX "\\begin{document}\\begin{center}\n";

    if ($divisionname){
	print TEX "{\\huge\\sf $divisionname}\n\n";
    } else {
	print TEX "{\\huge\\sf $schoolname}\n\n";
    }

    print TEX "{\\bf\\large $lex{'Year End'} $lex{Report}}\n\n";
    print TEX "{\\bf\\large ";
    if ( $group eq 'grade' ) {
	print TEX $lex{Grade};
    } else {
	print TEX $lex{Homeroom};
    }
    print TEX " $group_value -- $schoolyear}";
    print TEX "\\end{center}\n\n";

    
    # Collect all the courses taken by this group of students.
    # $sections{subjcode}{$subjsec} = 1; all sections for this subject code
    my (@courses, %desc, %desccode, %sections, %subjects ); # refactor layout

    my $sth1 = $dbh->prepare("select distinct subjcode from eval
			     where term = ? and studnum = ?"); # subjcode is really subjsec

    # put all subjsec, subjcode into hashes; no array yet.
    foreach my $studnum ( @students ) {

	$sth1->execute( $endterm, $studnum);
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } 
	while ( my $subjsec = $sth1->fetchrow ) {
	    my ($subjcode,$section) = split('-', $subjsec);

	    if ( $r_SupressSubject{$subjsec} or $r_SupressSubject{$subjcode} or 
		 $r_AdditionalComments{$subjsec} or $r_AdditionalComments{$subjcode} ) {
		next; 
	    }

	    $desccode{$subjcode} =  $s{smdesc}; # put in the small description.
	    
	    $sections{$subjcode}{$subjsec} = 1; # collect all sections
	    $subjects{$subjsec} = 1;
	}
    }
    # This will give us the unique values for courses

    
    my $sth = $dbh->prepare("select * from subject where subjsec = ?");

    foreach my $subjsec ( sort keys %subjects ){

	my ($subjcode, $dud) = split('-', $subjsec);

	# Get Course Information; pull in full subject record
	$sth->execute( $subjsec );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my $ref = $sth->fetchrow_hashref;
	my %s = %$ref;
	
	%s = latex_filter( %s );

	# put courses in order
	push @courses, $subjsec;

	# If no short description, then long versions truncated and used.
	if ( not $s{smdesc} ) { # was 37 in array
	    if ( length( $s{description} ) > $objectivelength ) {  # was index 2
		$s{smdesc} = substr( $s{description},0,$objectivelength); # trunc full desc
	    } else {
		$s{smdesc} = $s{description};
	    }
	}

	$desc{$subjsec} = $s{smdesc};
	$desccode{$subjcode} = $s{smdesc}; # for joinsession values.
	
    }

    if ( $joinsection ) {
	@courses = sort keys %sections;
	%desc = %desccode; # descriptions based on subject code
    }

    
    $pagecount = 1;

#    print qq{Full Students:@students<br>};
#    print qq{ Full CRS:@courses<br>\n};
    my @permstudents = @students; # used to repopulate the loop, if one runs out, but not both.
    my @permcourses = @courses; 
    

    # put in the students and courses that will fit on a single page.
    my (@tempcrs,@tempstud, $crscount,$studcount);

    while ( @courses and @students ) { 
    
	# Get students for this page
	while ( my $studnum = shift @students ) {
	    push @tempstud, $studnum;
#	    my $studcount = @tempstud;
#	    print qq{Student Count:$studcount  Max:$maxstudents<br>\n};
	    if ( @tempstud > $maxstudents ) { last; }
	}

	# Get Courses for this page.
	while ( my $crs = shift @courses ) {
	    push @tempcrs, $crs;
#	    my $crscount = @tempcrs;
#	    print qq{Course Count:$crscount Max:$maxcolumns<br>\n};
	    if ( @tempcrs >= $maxcolumns ) { last; }
	}
	
#	print "Temp Stud:@tempstud<br>\n";
#	print qq{CRS:@tempcrs<br>\n};

	my $grpval = qq{$group:$group_value};
	
	&print_page(\@tempcrs, \@tempstud, \%desc, \%students, \%sections,
		    $joinsection, $pagecount,$grpval);
	@tempcrs = (); @tempstud = (); # zero the arrays.
    
	$pagecount++;

	if ( @courses or @students ) { # we need to keep going until both are empty
	    if ( not @courses ) {  # run out of courses but not students.
		@courses = @permcourses;
	    }
	    if ( not @students ) {
		@students = @permstudents;
	    }
	    print TEX "\\newpage\n\n"; # new page since we have to keep going.
	}
    }


    print TEX "\n\\parbox{152mm}{\\vspace{13mm}\\underline{\\hspace{63mm}}";
    print TEX "\\hfill\\underline{\\hspace{63mm}}\n\n";
    print TEX "{\\small ". $lex{Teacher}. "}\\hfill{\\small ". $lex{Principal}. "}}\n";
    print TEX "\\end{document}\n";
    close TEX;

    
    # alter for teacher tcgi functioning
    if ( getcwd() =~ tcgi ) {
	$downloaddir = $tchdownloaddir;
	$webdownloaddir = $tchwebdownloaddir;
    }

    system("$pdflatex $filename > pdflog$$.txt");
    system("mv $shortname.pdf $downloaddir");
    system("mv pdflog$$.txt $downloaddir");
    system("rm -f $shortname.*");

    print qq{<h1><a href="$webdownloaddir/$shortname.pdf">\n};
    print qq{$lex{'View/Download'} $title</a></h1>\n};
    print qq{[ <a href="$reppage">$lex{'Report Card'}</a> | \n};
    print qq{<a href="$webdownloaddir/pdflog$$.txt">$lex{'View Log File'}</a> ]\n};

    if ( $missingflag ) {
	print qq{<p><b>$lex{Note}:</b> };
	print qq{$lex{Missing} $lex{'Short Subject Descriptions'}<br>\n};
	print qq{ Full length subject descriptions are being used. This will<br>\n};
	print qq{look somewhat ugly, but does indicate the subject.</p>\n};
    }

    print qq{</body></html>\n};

    exit;

} # end of makePDF




#--------------
sub print_page {
#--------------

    # print a single page when passed start, end values for students
    # as well as subjects. (ie. defining a block)

    my ( $crsref, $studref, $descref, $studrecref, $sectionref, $joinsection, $pagenum, $grpval) = @_;
    my ($group,$group_value) = split(':', $grpval);
    
    my @crs = @$crsref;
    my @students = @$studref;
    my %desc = %$descref;
    my %sections = %$sectionref; # sections{$subjcode}{$subjsec} # more than one subjsec
    # %students{studnum} = ref to record
    my %studref = %$studrecref; # contains lastname, firstname, grade, homeroom
    
#    print "Course:@crs<br> Students:@students <br>Desc:", %desc, "<br>\n";



    
    # Print Header
    print TEX "\\begin{tabular}{p{49mm}";
    foreach my $crs ( @crs ) {
	print TEX "p{6.15mm}";
    }
    # Print section for attendance and promotion text.
    print TEX "p{7mm}l"; # Note Left Alignment here.

    print TEX "}\n\\parbox[b]{47mm}{\\raggedright{\\bf\\large $schoolname}\\\\
     $currdate\\hfill\\\\ $lex{Page}:~$pagenum  $lex{Term}:~$term\\\\ ";

    
    if ( $group eq 'grade' ){
    	print TEX $lex{Grade}. ": $group_value } \n";
    } else {
    	print TEX $lex{Homeroom}. ": $group_value } \n";
    }

    
    foreach my $subjsec ( @crs ) {
	my $desc = $desc{$subjsec};
	print TEX "&\\begin{rotate}{90}{\\small\\bf $desc}\\end{rotate}"; 
    }
    print TEX "&\\rule{0mm}{2mm}\\begin{sideways}{\\small\\bf Attend }\\end{sideways}"; 
    print TEX "&\\parbox[b]{50mm}
    {\\raggedright\\small P=Complete~Promotion, R=Repeating~Years~Work,
    SP=Social~Promotion, MA=Modified/Alt~Program}";

    print TEX "\\\\\n\\end{tabular}\n\n";

    
    # Now print header section WITH dividers
    print TEX "\\begin{tabular}{p{45mm}|";
    foreach my $crs ( @crs ) {
	print TEX "p{6mm}|";
    }
    # Print section for attendance and promotion text.
    print TEX "p{12mm}|p{25mm}|";
    print TEX "}\\hline\n";
    # end of printing header.

    
    # get studid from studnum to check for active (current student)
    my $sth = $dbh->prepare("select studid from student where studnum = ?");
    
    # Setup for reading subject table calcavg value.
    my $sth2 = $dbh->prepare("select calcavg from subject where subjsec = ?");
    
    my $sth3 = $dbh->prepare("select endrptperiod from subject where subjsec = ?");

    # Get student marks
    my $sth4 = $dbh->prepare("select $r_MarkField, term from eval where 
			     studnum = ? and subjcode = ?"); #is really $subjsec

    
    my $studcount = 1;

    foreach my $studnum ( @students ) {
	my %s = %{ $studref{$studnum} };
	my $lastname = $s{lastname};
	my $firstname = $s{firstname};
	my $gr = $s{grade};
	my $hr = $s{homeroom};

	# Find $active value (ie. currently enrolled )
	$sth->execute( $studnum );
	if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;}
	my $active = $sth->fetchrow;

	# calc attendance values for this student
#	print "Start:$schoolstart End:$schoolend GR:$gr Active:$active<br>\n";
	my $dayspresent = calcMyAttendance($studnum, $schoolstart, $schoolend, $g_ppd{$gr}, $active); 
	$dayspresent = format_number($dayspresent, 2, 2);

	print TEX "$lastname, $firstname ";

	
	# Loop through each course for this student and print eval results.
	foreach my $subjsec (@crs) {

	    # Get his/her evaluation for this course in this term
	    my $testavg;

	    if ( $joinsection ) { # loop through all sections looking for a value
		foreach my $subsec ( sort keys %{ $sections{$subjsec}} ) { # subjsec is really subjcode
	    
		    # Get the calcavg value (N or Y);
		    $sth2->execute( $subsec );
		    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
		    my $calcavg = $sth2->fetchrow;
	    
		    if ( $calcavg eq $lex{Y} ) { # weighted average of terms (using r_AverageWeight)

			# who cares?? We're only getting a single mark from $r_MarkField
			# my $locobjcount = $#$subjref; # Number of objectives.
			# print qq{ CRS:$subjsec OBJ: $locobjcount \n};
		
			my ($totalscore, $totalweight);
		
			$sth4->execute( $studnum, $subsec );
			if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; }

			while ( my ($score,$term) = $sth4->fetchrow ) {
			    if ( $score =~ m/\d/){ # if a digit...
				if ( not $r_AverageWeight{$term} ) { # Error
				    print qq{<h3>No Average Weight (r_AverageWeight) defined };
				    print qq{for this term $term</h3>\n};
				    print qq{</body></html>\n};
				    exit;
				}
				my $wt = $r_AverageWeight{$term}; #The weight for this term 
				$totalscore += ( $wt * $score );
				$totalweight += $wt;
			    }
			}
		
			if ( $totalweight ){ # We have some tests.
			    $testavg = $totalscore / $totalweight;
			    $testavg = format_number( $testavg, 1,1);
			} else { 
			    $testavg = ' ';
			}

		    } else { # We just find the endreporting period for this
			# course and get that term's value from eval table;

			# Get End Reporting period for final mark, since not passed to this function.
			$sth3->execute( $subsec );
			if ($DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
			my $endrptperiod = $sth3->fetchrow;

			
			my $sth1 = $dbh->prepare("select $r_MarkField from eval where 
						 studnum = ? and term = ? and subjcode = ?");
			$sth1->execute( $studnum, $endrptperiod, $subsec );
			if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; }
			$testavg = $sth1->fetchrow;
			$testavg =~ s/\%//; # strip any percents.

		    }
		    if ( $testavg =~ m/\d/ ) { last; } # we have our number.
		    
		} # end of subjsec loop in %sections

	    } else {
		
		# Get the calcavg value (N or Y);
		$sth2->execute( $subjsec );
		if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
		my $calcavg = $sth2->fetchrow;
	    
		if ( $calcavg eq $lex{Y} ) { # weighted average of terms (using r_AverageWeight)

		    # who cares?? We're only getting a single mark from $r_MarkField
		    # my $locobjcount = $#$subjref; # Number of objectives.
		    # print qq{ CRS:$subjsec OBJ: $locobjcount \n};
		
		    my ($totalscore, $totalweight);
		
		    $sth4->execute( $studnum, $subjsec );
		    if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; }

		    while ( my ($score,$term) = $sth4->fetchrow ) {
			if ( $score =~ m/\d/){ # if a digit...
			    if ( not $r_AverageWeight{$term} ) { # Error
				print qq{<h3>No Average Weight (r_AverageWeight) defined };
				print qq{for this term $term</h3>\n};
				print qq{</body></html>\n};
				exit;
			    }
			    my $wt = $r_AverageWeight{$term}; #The weight for this term 
			    $totalscore += ( $wt * $score );
			    $totalweight += $wt;
			}
		    }
		
		    if ( $totalweight ){ # We have some tests.
			$testavg = $totalscore / $totalweight;
			$testavg = format_number( $testavg, 1,1);
		    } else { 
			$testavg = ' ';
		    }

		} else { # We just find the endreporting period for this
		    # subject and get that term's value from eval table;

		    # Get End Reporting period for final mark, since not passed to this function.
		    $sth3->execute( $subjsec );
		    if ($DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
		    my $endrptperiod = $sth3->fetchrow;

		    my $sth1 = $dbh->prepare("select $r_MarkField from eval where 
					     studnum = ? and term = ? and subjcode = ?");
		    $sth1->execute( $studnum, $endrptperiod, $subjsec );
		    if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; }
		    $testavg = $sth1->fetchrow;
		    $testavg =~ s/\%//; # strip any percents.

		}
	    } # end of non joinsection 
		

	    # Note not really a 'test average' if a final mark only.
	    print TEX "&\\hfil{\\small $testavg}\\hfil";
    
	}

	print TEX "&\\hfil $dayspresent \\hfil& "; # End of line (with space)
	print TEX "\\\\\\hline\n";
	if (not ($studcount % 3)){ print TEX "\\hline\n";} # put in spacers.
	$studcount++;

    }  # End of Student For 

    print TEX "\\end{tabular}\n\n";

} # End of print_page function



#----------------
sub showStartPage {
#----------------

    print qq{<form action="$self" method="post">\n};
    print qq{<input type="hidden" name="page" value="1">\n};

    # Get the grades
    my @grades;
    my $sth = $dbh->prepare("select distinct grade from student 
      where grade is not NULL and grade != ''");
    $sth->execute;
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $gr = $sth->fetchrow ) {
	push @grades, $gr;
    }


    # Get the homerooms.
    my @homerooms;
    my $sth = $dbh->prepare("select distinct homeroom from student where 
     homeroom is not NULL and homeroom != ''");
    $sth->execute;
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $hr = $sth->fetchrow ) {
	push @homerooms, $hr; # removed checking below
    }

    
    print qq{<table cellpadding="3" cellspacing="0" border="0" };
    print qq{style="border:1px solid gray;padding:0.4em;">\n};

    # Grades
    print qq{<tr><td class="bra">$lex{'Select by'} $lex{Grade}};
    if ( $schoolmode == 1 ) {
	print qq{/$lex{Form}};
    }
    print qq{</td>};
    print qq{<td class="la"><select name="grade"><option value=""></option>\n}; 
    foreach my $gr ( sort {$a <=> $b} @grades ) {
	my $displaygrade = $gr;
	if ( $schoolmode == 1 ) { # British mode
	    my $val = $g_FormMap{$gr};
	    if ( not $val ) { $val = $gr; }
	    if ( $val =~ m/F|f/ ) { # we are adding form.
		$val =~ s/F|f/$lex{Form} /;
	    }
	    $displaygrade = $val;
	}
	print qq{<option value="$gr">$displaygrade</option>};
    }
    print qq{</select></td></tr>\n};

    print qq{<tr><td class="bcn" colspan="2">$lex{OR}</td><td></td></tr>\n};
    
    # Homeroom
    print qq{<tr><td class="bra">$lex{'Select by'} $lex{Homeroom}</td>};
    print qq{<td class="la"><select name="homeroom"><option value=""></option>\n}; 
    foreach my $hr ( sort {$a <=> $b} @homerooms ) {
	print qq{<option>$hr</option>};
    }
    print qq{</select></td></tr>\n};
    
    print qq{<tr><td colspan="2"><hr></td></tr>\n};

    
    # Term Select
    # Find all of the term end dates
    my $sth = $dbh->prepare("select distinct endrptperiod from subject order by endrptperiod");
    $sth->execute;
    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }

    print qq{<tr><td class="bra">Course $lex{End} $lex{Term}</td><td class="la">};
    print qq{<select name="term"><option value=""></option>\n};
    while ( my $endterm = $sth->fetchrow ) {
	if ( not $endterm ) { next; }
	print qq{<option value="$endterm">$endterm</option>\n};
    }
    print qq{</select></td></tr>\n};

    # Output Type
    print qq{<tr><td class="bra">$lex{Output} Type</td>\n};
    print qq{<td><select name="output"><option value="pdf">PDF</option>\n};
    print qq{<option value="csv">CSV</option></select></td></tr>\n};

    # Join sections into a single group for that course.
    print qq{<tr><td class="bra">Join All Sections</td>\n};
    print qq{<td><input type="checkbox" name="joinsection" value="1"> };
    print qq{Show all students in the sections together </td></tr>\n};
    

    # CSV Course Name Option
    print qq{<tr><td class="bra">CSV - Course Desc Type</td>\n};
    print qq{<td><select name="coursedesc">};
    print qq{<option value="smdesc">Small Description</option>\n};
    print qq{<option value="subjsec">Subject-Section</option>\n};
    print qq{<option value="both">Both</option>\n};
    print qq{</select></td></tr>\n\n};

    # Students / Page
    print qq{<tr><td class="bra">PDF - $lex{'Student(s)'}/$lex{Page}</td>\n};
    print qq{<td><input type="text" name="studperpage" size="4" value="$maxstudents">};
    print qq{</td></tr>\n};


    # Paper Size
    print qq{<tr><td class="bra">PDF $lex{'Paper Size'}</td>\n};
    print qq{<td><select name="papersize">};
    print qq{<option value="letter">$lex{Letter}</option>\n};
    print qq{<option value="a4">$lex{A4}</option>\n};
    print qq{<option value="legal">$lex{Legal}</option>\n};
    print qq{</select></td></tr>\n\n};

    
    # Continue
    print qq{<tr><td></td><td class="la">\n};
    print qq{<input type="submit" value="$lex{Continue}"></td></tr>\n};

    print qq{</table></form>\n};
    print qq{</body></html>\n};

    exit;

}



#-----------------
sub calcMyAttendance {
#-----------------

    my ($studnum, $startdate, $enddate, $periodsperday,$active) = @_;

    my @enrolblocks = findEnrollmentBlocks($studnum, $schoolstart, $currsdate, $dbh);

    my $absent = 0; my $daysEnrolled = 0; my $late = 0; 

    foreach my $block (@enrolblocks){
	my $start = $block->{start};
	my $end = $block->{end};
	# print qq{ST: $start END: $end };
	my $blocklength = calcDaysOpen($start,$end, $dbh);
	# print qq{BlockLen: $blocklength<br>\n};
	$daysEnrolled += $blocklength;
	#print qq{STUD: $studnum ST: $start END: $end\n};

	my $sth = $dbh->prepare("select * from attend 
          where studentid='$studnum' and 
          to_days(absdate) >= to_days('$start') and 
          to_days(absdate) <= to_days('$end') 
          order by absdate,period");
	$sth->execute;
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}

	while (@absence = $sth->fetchrow){
	    if ($absence[3] =~ /$absentString/) { $absent++; }
	    #if ($absence[3] =~ /$lateString/) { $late++; }
	}
	#print qq{ABS: $absent<br>\n};
    }


    if ( not $periodsperday ) { 
	print qq{PPD: $periodsperday not defined for $studnum<br>\n}; 
    }

    my $present;
    if ( $periodsperday ) {
	$absent = $absent/$periodsperday; #convert periods into days
	$present = $daysEnrolled - $absent;
    } else {
	$present = 0;
    }

    return $present;
}



# Not used
#---------------
sub print_header {
#---------------

    # passed starting and ending values(indexes) for subject, pagenum
    my ($startsubj, $endsubj, $pagenum) = @_;
  
    print TEX "\\begin{tabular}{p{49mm}";
    for (my $i = $startsubj; $i <= $endsubj; $i++){
	$subjref = $fullsubjary[$i];
	for (1..$#$subjref) { print TEX "p{6.15mm}";}
    }
    # Print section for attendance and promotion text.
    print TEX "p{7mm}l"; # Note Left Alignment here.


    print TEX "}\n\\parbox[b]{47mm}{\\raggedright{\\bf\\large $schoolname}\\\\
     $currdate\\hfill\\\\ $lex{Page}:~$pagenum  $lex{Term}:~$term\\\\ ";

    if ( $group eq 'grade' ){
	print TEX $lex{Grade}. ": $group_value } &\n";
    } else {
	print TEX $lex{Homeroom}. ": $group_value } &\n";
    }

    $count = 0;
    for ($i = $startsubj; $i <= $endsubj; $i++){
	$subjref = $fullsubjary[$i];

	if ($i != $startsubj){print TEX "&";}
	print TEX "\\begin{rotate}{90}{\\small $$subjref[1]}\\end{rotate}"; 
	for (2..$#$subjref) {
	    print TEX "&\\begin{rotate}{90}{\\small $$subjref[$_]}\\end{rotate}"; 
	}
    }
    print TEX "&\\rule{0mm}{2mm}\\begin{sideways}{\\small\\bf Attend }\\end{sideways}"; 
    print TEX "&\\parbox[b]{50mm}
    {\\raggedright\\small P=Complete~Promotion, R=Repeating~Years~Work,
    SP=Social~Promotion, MA=Modified/Alt~Program}";

    print TEX "\\\\\n\\end{tabular}\n\n";

    # Now print header section WITH dividers
    print TEX "\\begin{tabular}{p{45mm}|";

    # foreach $subjref (@fullsubjary){

    for ( my $i = $startsubj; $i <= $endsubj; $i++ ) {
	$subjref = $fullsubjary[$i];
	for ( 1 .. $#$subjref ) { print TEX "p{6mm}|";}
    }
    # Print section for attendance and promotion text.
    print TEX "p{12mm}|p{25mm}|";
    print TEX "}\\hline\n";

}
