#! /usr/bin/perl 
#  Copyright 2001-2020 Leslie Richardson

#  This file is part of Open Admin for Schools.

#  Open Admin for Schools is free software; you can redistribute it 
#  and/or modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2 of 
#  the License, or (at your option) any later version.


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

my %lex = ('Attendance Profiles' => 'Attendance Profiles',
	   'Attendance' => 'Attendance',
	   'Cannot open tex file' => 'Cannot open tex file',
	   'Enrollment' => 'Enrollment',
	   'Not Found' => 'Not Found',
	   'Periods Per Day' => 'Periods Per Day',
	   'Perfect Attendance' => 'Perfect Attendance',
	   'View/Download' => 'View/Download',
	   'View Log File' => 'View Log File',
	   'Total' => 'Total',
	   'Absent' => 'Absent',
	   'Late' => 'Late',
	   'Excused' => 'Excused',
	   'Unexcused' => 'Unexcused',
	   'times' => 'times',
	   'day(s)' => 'day(s)',
	   'Main' => 'Main',
	   'Name' => 'Name',
	   'Select' => 'Select',
	   'Withdrawn Students' => 'Withdrawn Students',
	   'Subject' => 'Subject',
	   'Sort by' => 'Sort by',
	   'Select' => 'Select',
	   'Grade' => 'Grade',
	   'Homeroom' => 'Homeroom',
	   'Start Date' => 'Start Date',
	   'End Date' => 'End Date',
	   'Show' => 'Show',
	   'Continue' => 'Continue',
	   'No Student(s) Found' => 'No Student(s) Found',
	   'Days' => 'Days',
	   'Period' => 'Period',
	   'Error' => 'Error',
	   'Blank=All' => 'Blank=All',
	   'Band' => 'Band',
	   'Summary Records' => 'Summary Records',
	   'Count' => 'Count',
	   'Reason' => 'Reason',
	   'Teacher' => 'Teacher',
	   'Homeroom' => 'Homeroom',
	   'Font Size' => 'Font Size',
	   'Paper Size' => 'Paper Size',
	   'Letter' => 'Letter',
	   'Legal' => 'Legal',
	   'A4' => 'A4',
	   'Date' => 'Date',
	   'Not Found' => 'Not Found',
	   'Description' => 'Description',

	);


my $grayshade = '0.80';
my $self = "rptattprof.pl";

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

} else {
    $configpath = '../..'; # go back two to get to etc.
}

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

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

# load latex filtering (for subject description field, band)
eval require "$configpath/lib/liblatex.pl";
if ( $@ ) {
    print $lex{Error}. " $@<br>\n";
    die $lex{Error}. " $@\n";
}



# Do a check for attendance strings
if ( not $absentUnexcused or not $lateUnexcused or 
     not $lateString or not $absentString ) { 
    print "<h3>$lex{Error}: $lex{Attendance} $lex{Description} $lex{'Not Found'}</h3>\n";
    print "</body></html>\n";
    exit;
}


# Get current dir so know what CSS to display and shift to teacher settings.
if ( getcwd() =~ /tcgi/ ) { # we are in tcgi
    $css = $tchcss;
    $homepage = $tchpage;
    $downloaddir = $tchdownloaddir;
    $webdownloaddir = $tchwebdownloaddir;
}


my $maxlines = 28;
my $shortname = "attprofile$$";
my $filename = "$shortname.tex";

# Set AM/PM Hash for use converting 2 period day to AM/PM
%ampm = ( 1 => 'AM', 2 => 'PM');

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

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


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

# rounding format
my $fmt = new Number::Format(-decimal_fill => '1', -decimal_digits => '2');


my ($wdselectflag, $currselectflag);
if ( $arr{wdselectflag} ) { # We have selected withdrawn students to print.
    $wdselectflag = 1;
    delete $arr{wdselectflag};
}
if ( $arr{currselectflag} ) { # We have selected withdrawn students to print.
    $currselectflag = 1;
    delete $arr{currselectflag};
}




my $sortorder = "homeroom, lastname, firstname";
if ( $arr{sortorder} eq 'name' ) {
    $sortorder = "lastname, firstname";
} elsif ( $arr{sortorder} eq 'grade' ) {
    $sortorder = "grade, lastname, firstname";
} elsif ( $arr{sortorder} eq 'band' ) {
    $sortorder = "band, lastname, firstname";
} elsif ( $arr{sortorder} eq 'room' ) {
    $sortorder = "homeroom, lastname, firstname";
}
if ( $arr{sortorder} ) { delete $arr{sortorder}; }


my $select;
if ( $arr{group} ) {
    if ( $arr{select} eq $lex{Grade} ) { # Find this grade;
	my $grp = $dbh->quote( $arr{group} );
	$select = "where grade = $grp";
    } elsif ( $arr{select} eq $lex{Homeroom} ) {
	my $grp = $dbh->quote( $arr{group} );
	$select = "where homeroom = $grp";
    } elsif ( $arr{select} eq $lex{Band} ) {
	my $grp = $dbh->quote( $arr{group} );
	$select = "where band = $grp";
    }
}


# print page header
my $title = $lex{'Attendance Profiles'};

print qq{$doctype\n<html><head><title>$lex{'Attendance Profiles'}</title>\n};
print qq{<link rel="stylesheet" href="$css" type="text/css">\n};

print qq{<link rel="stylesheet" type="text/css" media="all" };
print qq{href="/js/calendar-blue.css" title="blue">\n};
print qq{<script type="text/javascript" src="/js/calendar.js"></script>\n};
print qq{<script type="text/javascript" src="/js/lang/calendar-en.js"></script>\n};
print qq{<script type="text/javascript" src="/js/calendar-setup.js"></script>\n};


print qq{$chartype\n</head><body>\n};
print qq{[ <a href="$homepage">$lex{Main}</a>\n};
if ( not $teachermode ) { print qq{ | <a href="$attpage">$lex{Attendance}</a>\n}; }
print qq{ ]\n};

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


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

if ( not $arr{page} ) {
    showStartPage();
} elsif ( $arr{page} == 1) {
    delete $arr{page};
    if ( $arr{selectstud} eq 'withdrawn' ) {
	selectWithdrawn();
    } elsif (  $arr{selectstud} eq 'current' ) {
	selectCurrent();
    } # else just fall through to normal printing.
} elsif ($arr{page} == 2) {
    delete $arr{page};
}


# Passed variables: start and end dates for reporting period.
if ( not $arr{startdate} or not $arr{enddate} ) {
    print qq{<h1>$lex{'Start Date'} $lex{Or} $lex{'End Date'} $lex{'Not Found'}</h1>\n};
    print qq{</body></html>\n};
    exit;
}

my $startdate = $arr{startdate};
my $enddate = $arr{enddate};


# Perfect Attendance Option
my $perfectattendance;
if ( $arr{perfectattendance} ) {
    $perfectattendance = 1;
    delete $arr{perfectattendance};
}



# Now create a hash to store student numbers of students to print (if
# not selected from withdrawn).

if ( not $wdselectflag and not $currselectflag ) {
    # we are doing a normal print run of active students
    my $sth = $dbh->prepare("select studnum from student $select
     order by $sortorder");
    $sth->execute;
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $studnum = $sth->fetchrow) {
	push @students, $studnum;
    }

} else { # we have a selected student group to print

    foreach my $sn (keys %arr) {
	if ( $sn eq 'papersize' or $sn eq 'fontsize' or 
	     $sn eq 'startdate' or $sn eq 'enddate' ) { next; } 
	push @students, $sn;
    }
}

# print qq{Students: @students<br>\n};


if ( @students ) { # We have students to print; setup LaTeX file.

    open(TEX,">$filename") || die $lex{'Cannot open tex file'};

    my ( $papersize, $textwidth, $textheight );

    if ( $arr{papersize} eq $lex{Letter} ) {
	$papersize = 'letterpaper';
	$textwidth = $g_letterpaper_textwidth;
	$textheight = $g_letterpaper_textheight;
    } elsif ( $arr{papersize} eq $lex{Legal} ) {
	$papersize = 'legalpaper';
	$textwidth = $g_legalpaper_textwidth;
	$textheight = $g_legalpaper_textheight;
    } elsif ( $arr{papersize} eq $lex{A4} ) {
	$papersize = 'a4paper';
	$textwidth = $g_a4paper_textwidth;
	$textheight = $g_a4paper_textheight;
    } 

    my $fontsize = $arr{fontsize}. 'pt';

    print TEX "\\documentclass[ $fontsize,$papersize]{article}
\\usepackage{array,colortbl,multicol,inputenc}
$a_latex_header
\\pagestyle{empty}
\\setlength{\\textwidth}{ $textwidth }
\\setlength{\\textheight}{ $textheight }
\\setlength{\\hoffset}{-25mm}
\\setlength{\\voffset}{-36mm}
\\setlength{\\extrarowheight}{2pt}
\\setlength{\\parindent}{0pt}\n";

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

} else {
    print "<h3>$lex{'No Student(s) Found'}</h3>\n";
    print "</body></html>\n";
    exit;
}


my $sth = $dbh->prepare("select lastname, firstname, grade, homeroom, band 
  from studentall where studnum = ?");


foreach my $studnum ( @students ) {

    # get rest of student data.
    $sth->execute($studnum);
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    my ( $lastname, $firstname, $grade, $homeroom, $band ) = $sth->fetchrow; 

    ($band) = latex_filter($band);
    
    my $tardytot = 0;
    my $absenttot = 0;
    
    my $tardyu = 0;
    my $tardye = 0;
    my $absentu = 0;
    my $absente = 0;

    
    my @enrollblocks = findEnrollmentBlocks( $studnum, $startdate, $enddate, $dbh );


    # Setup to fetch Attendance Records
    my $sth1 = $dbh->prepare("select absdate, reason, period, subjsec from attend  
     where studentid = ? and 
     to_days(absdate) >= to_days('$startdate') and 
     to_days(absdate) <= to_days('$enddate') 
     order by absdate, period ");
    $sth1->execute( $studnum );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    my $absrows = $sth1->rows;

    # Skip student if not showing perfect attendance
    # if ( not $perfectattendance and $absrows < 1 ) { next; }

    # Get teacher and homeroom data (if any), print Enrollment changes.
    $sth2 = $dbh->prepare("select sal, firstname, lastname from staff as s, staff_multi as sm
       where sm.userid = s.userid and sm.field_name = 'homeroom' and sm.field_value = ?");
    $sth2->execute( $homeroom );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    my ($tsal, $tfirstname, $tlastname) = $sth2->fetchrow;
    my $teacher;
    if ($tlastname){ $teacher = $lex{Teacher}. ":& $tsal $tfirstname $tlastname\\\\ \n"; }
    my $hroom;
    if ( $homeroom ) { $hroom = $lex{Homeroom}. ":& $homeroom\\\\ \n"; }


    # Start of Printing for this student
    print TEX "\\center {\\sf\\huge $schoolname $lex{'Attendance Profiles'} } \\\\ \n\\bigskip";
    print TEX "{\\Large $firstname $lastname} $withdrawn \\\\ \n \\bigskip\n";
    print TEX "\\begin{tabular}{r|l} \n \\hline\n$teacher $hroom\n \\hline\n";
    if ( $band ) {
	print TEX $lex{Band}. "& {\\bf $band} \\\\ \\hline\n";
    }
    print TEX "\\end{tabular}\n\n";


    # Enrollment Section
    if ( @enrollblocks ) {

	print TEX "\\hrulefill\\\\\n{\\large\\sf $lex{Enrollment} }\\\\ \n\\medskip\n";

	print TEX "\\begin{tabular}{|l|l|r|}\\hline\n";
	print TEX "\\rowcolor[gray]{0.85}$lex{'Start Date'} & $lex{'End Date'} & $lex{Days}\\\\ \\hline\n";

	foreach my $ref ( @enrollblocks ) {
	    my $days = calcDaysOpen( $ref->{start}, $ref->{end}, $dbh);
	    print TEX  "$ref->{start} & $ref->{end} & $days \\\\ \\hline\n";
	}

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



    # Now print the periods absent.
    # Calculate periods into days 
    my $periods = $g_ppd{$grade};
    if ( not $grade ) {
	print "<p><b>$lex{Error}: $lex{Grade} $lex{'Not Found'}";
	print " $firstname $lastname</b></p></body></html>\n";
	next;

    } elsif ( not $periods ) {  # We don't have this grade's periods defined.
	print "$lex{Error}: $lex{'Periods Per Day'} $lex{'Not Found'} - $lex{Grade} $grade";
	print "\n<br>$firstname $lastname</body></html>\n";
	next;
    }

    my (%subjectslate, %subjectsabs); # hold subject information, if any...
    if ( $absrows > 0 ) {  # then we have absences; loop through doing calcs.

	if ( $arr{summary} ) { # print Summary Values only
	    printSummaryRecords( $studnum );

	} else { # print it all...

	    print TEX "\\hrulefill\\\\ \n\\setlength{\\premulticols}{5pt}\n";
	    print TEX "\\setlength{\\postmulticols}{5pt}\n";
	    print TEX "\\begin{multicols}{2}\n\\raggedright\n";
     
	    for ($i=1; $i<=$absrows; $i++) {
		my ($absdate, $reason, $period, $subjsec) = $sth1->fetchrow;
		
		# Convert to AM/PM format if 2 periods per day
		if ($periods == 2){  # $periods defined on line 226 above
		    $period = $ampm{$period}; # ampm hash defined at top.
		}

		# Fixes for crud in reasons for attendance.
		$reason =~ s/[^A-Za-z\s]//g;

		# Do the calcs for reasons
		if ($reason eq $lateUnexcused){
		    $tardyu++;
		    if ($subjsec) { $subjectslate{$subjsec}++; } # only for unexcused.
		} elsif ($reason =~ m/$lateString/) {
		    $tardye++;
		} elsif ($reason eq $absentUnexcused){
		    $absentu++;
		    if ($subjsec) { $subjectsabs{$subjsec}++; } # only for unexcused.
		} elsif ($reason =~ m/$absentString/){
		    $absente++;
		} else { # unknown reason...
		    print "<h3>$lex{Error}:";
		    print " $reason - $absdate - ". $lex{Period}. " $period<br>\n";
		    print "$firstname $lastname ($studnum)<br>\n";
		}
		
		print TEX "$absdate-$period $reason\\\\ \n";   
	    }

	    my $daysabsentu = $fmt->format_number( $absentu/$periods, 2);
	    my $daysabsente = $fmt->format_number( $absente/$periods, 2);
	    my $daysabsenttot = $fmt->format_number( $daysabsente + $daysabsentu, 2);

	    $tardytot = $tardye + $tardyu;

	    print TEX "\\end{multicols}\n\n\\hrulefill\\\\ \n\\bigskip\n";
	    print TEX "\\begin{tabular}{r|l}\\hline\n";
	    print TEX $lex{Late}. ' '. $lex{Unexcused}," & $tardyu ",$lex{times},"\\\\\n"; 
	    print TEX $lex{Late}. ' '. $lex{Excused}, "& $tardye ", $lex{times}, " \\\\\n";
	    print TEX $lex{Total}. ' '. $lex{Late}, "& $tardytot ", $lex{times}, "\\\\\n";
	    print TEX "\\hline\n", $lex{Absent}. ' '. $lex{Unexcused}, "& $daysabsentu ";
	    print TEX $lex{'day(s)'}, "\\\\\n";
	    print TEX $lex{Absent}. ' '. $lex{Excused}, "& $daysabsente ", $lex{'day(s)'}, "\\\\\n";
	    print TEX $lex{Total}. ' ', $lex{Absent}, "& $daysabsenttot ", $lex{'day(s)'}, "\\\\\n";
	    print TEX "\\hline\n\\end{tabular}\n";


	} # end of Complete or Summary Records

	# Subject Attendance
	printSubjectAttendance($studnum, $arr{startdate}, $arr{enddate} );

	print TEX "\\newpage\n\n";

    } else {  # Perfect Attendance
	print TEX "\\bigskip {\\huge $lex{'Perfect Attendance'}! } \\newpage \n\n";
    }

} # End of Student Loop

print TEX "\\end{document}";
close TEX;

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


print qq{<h1><a href="/download/$shortname.pdf">\n};
print qq{$lex{'View/Download'} $lex{'Attendance Profiles'}</a></h1>\n};

print qq{[ };
if ( not $teachermode ) { print qq{<a href="$attpage">$lex{Attendance}</a> |\n}; }

print qq{<a href="$webdownloaddir/pdflog$$.txt">$lex{'View Log File'}</a> ]\n};
print qq{</body></html>\n};




#----------------------
sub printSummaryRecords {
#----------------------

    my $studnum = shift;  # must be passed student records.

    my $sth = $dbh->prepare("select distinct reason, period, count(period) from attend
     where studentid = ? and
     to_days(absdate) >= to_days('$startdate') and 
     to_days(absdate) <= to_days('$enddate') 
     group by reason, period  order by period, reason");
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    $sth->execute( $studnum );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }

    print TEX "\\begin{tabular}{r|l|l}\\hline\n";
    print TEX "\\rowcolor[gray]{$grayshade} $lex{Reason} & $lex{Period} & $lex{Count}";
    print TEX "\\\\ \\hline\n";
    while ( my ( $reason, $period, $count ) = $sth->fetchrow ) {
	print TEX "$reason & $period & $count \\\\ \\hline\n";
    }
    print TEX "\\end{tabular}\n";

}

#-----------------------
sub printCompleteRecords {
#-----------------------

    my $studnum = shift;

    # Setup to fetch Attendance Records
    my $sth1 = $dbh->prepare("select absdate, reason, period, subjsec from attend  
     where studentid = ? and 
     to_days(absdate) >= to_days('$startdate') and 
     to_days(absdate) <= to_days('$enddate') 
     order by absdate, period ");
    $sth1->execute( $studnum );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    my $absrows = $sth1->rows;

    my (%subjectslate, %subjectsabs); # hold subject information, if any...
    if ( $absrows > 0 ) {  # then we have absences; loop through doing calcs.

	print TEX "\\hrulefill\\\\ \n\\setlength{\\premulticols}{5pt}\n";
	print TEX "\\setlength{\\postmulticols}{5pt}\n";
	print TEX "\\begin{multicols}{2}\n\\raggedright\n";
     
	for ($i=1; $i<=$absrows; $i++) {
	    my ($absdate, $reason, $period, $subjsec) = $sth1->fetchrow;

	    # Convert to AM/PM format if 2 periods per day
	    if ($periods == 2){  # $periods defined on line 226 above
		$period = $ampm{$period}; # ampm hash defined at top.
	    }

	    # Fixes for crud in reasons for attendance.
	    $reason =~ s/[^A-Za-z\s]//g;

	    # Do the calcs for reasons
	    if ($reason eq $lateUnexcused){
		$tardyu++;
		if ($subjsec) { $subjectslate{$subjsec}++; } # only for unexcused.
	    } elsif ($reason =~ m/$lateString/) {
		$tardye++;
	    } elsif ($reason eq $absentUnexcused){
		$absentu++;
		if ($subjsec) { $subjectsabs{$subjsec}++; } # only for unexcused.
	    } elsif ($reason =~ m/$absentString/){
		$absente++;
	    } else { # unknown reason...
		print "<b>". $lex{'Unknown reason'};
		print ":</b> $reason - $absdate - ". $lex{Period}. " $period<br>\n";
		print "$firstname $lastname ($studnum)<br>\n";
	    }

	    print TEX "$absdate-$period $reason\\\\ \n";   
	}

	my $daysabsentu = $fmt->format_number( $absentu/$periods, 2);
	my $daysabsente = $fmt->format_number( $absente/$periods, 2);
	my $daysabsenttot = $fmt->format_number( $daysabsente + $daysabsentu, 2);

	$tardytot = $tardye + $tardyu;

	print TEX "\\end{multicols}\n\n\\hrulefill\\\\ \n\\bigskip\n";
	print TEX "\\begin{tabular}{r|l}\\hline\n";
	print TEX $lex{Late}. ' '. $lex{Unexcused}," & $tardyu ",$lex{times},"\\\\\n"; 
	print TEX $lex{Late}. ' '. $lex{Excused}, "& $tardye ", $lex{times}, " \\\\\n";
	print TEX $lex{Total}. ' '. $lex{Late}, "& $tardytot ", $lex{times}, "\\\\\n";
	print TEX "\\hline\n", $lex{Absent}. ' '. $lex{Unexcused}, "& $daysabsentu ";
	print TEX $lex{'day(s)'}, "\\\\\n";
	print TEX $lex{Absent}. ' '. $lex{Excused}, "& $daysabsente ", $lex{'day(s)'}, "\\\\\n";
	print TEX $lex{Total}. ' ', $lex{Absent}, "& $daysabsenttot ", $lex{'day(s)'}, "\\\\\n";
	print TEX "\\hline\n\\end{tabular}\n";

	print TEX "\\newpage\n\n";

    } else {  # Perfect Attendance
	print TEX "\\bigskip {\\huge ", $lex{'Perfect Attendance'}, "! } \\newpage \n\n";
    }

} # end of printCompleteRecords



#-------------------------
sub printSubjectAttendance {
#-------------------------

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

    # Find subjects where student is absent...
    my $sth = $dbh->prepare("select distinct subjsec from attend
     where studentid = ? and 
     to_days(absdate) >= to_days('$startdate') and 
     to_days(absdate) <= to_days('$enddate') and 
     subjsec != '' and subjsec is not null and subjsec != 'NULL'");

    $sth->execute( $studnum );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    my $subjrows = $sth->rows;
    if ( $subjrows < 1 ) { return; }


    # Setup for printing subject lates/absences
    print TEX "\n\\bigskip\n\n";
    print TEX "\\begin{tabular}{|l|c|c|}\\hline\n";
    print TEX "\\rowcolor[gray]{$grayshade}",$lex{Subject};
    print TEX '&',$lex{Absent},'&',$lex{Late}," \\\\ \\hline\n";

    my $sth1 = $dbh->prepare("select description from subject where subjsec = ?");
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }

    my $sth2 = $dbh->prepare("select count(*)from attend
     where studentid = ? and subjsec = ? and reason = ? and
     to_days(absdate) >= to_days('$startdate') and 
     to_days(absdate) <= to_days('$enddate')");
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }


    while ( my $subjsec = $sth->fetchrow ) { # loop through all subjects

	$sth1->execute( $subjsec );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $desc = $sth1->fetchrow;
	( $desc ) = latex_filter( $desc ); # watch for &, etc

	# Lates
	$sth2->execute($studnum, $subjsec, $lateUnexcused );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $lates = $sth2->fetchrow;

	# Absences
	$sth2->execute($studnum, $subjsec, $absentUnexcused );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $absents = $sth2->fetchrow;

	print TEX "$desc ($subjsec) & $absents ";
	print TEX "& $lates \\\\ \\hline\n";

    }

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


} # end of printSubjectAttendance



#------------------
sub selectWithdrawn {  # select withdrawn students to print.
#------------------

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

    delete $arr{checknext}; # not needed for withdrawn students.
    delete $arr{group};
    delete $arr{select}; # Grade or Homeroom value. not needed.
    delete $arr{selectstud};

    # what's left?
#    print qq{<div>what's left?</div>\n};
#    foreach my $key ( sort keys %arr ) { print "K:$key V:$arr{$key}<br>\n"; }

    
    # Get count of withdrawn students in studentwd table
    my $sth = $dbh->prepare("select count(*) from studentwd");
    $sth->execute;
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    my $studcount = $sth->fetchrow;
    
    print qq{<p><b>$studcount $lex{'Withdrawn Students'}</b></p>\n};

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

    print qq{<input type="hidden" name="fontsize" value="$arr{fontsize}">\n};
    print qq{<input type="hidden" name="papersize" value="$arr{papersize}">\n};

    print qq{<table cellpadding="3" cellspacing="0" border="1">\n};
    print qq{<tr><th>$lex{Name}</th><th>$lex{Select}</th></tr>\n};
    print qq{<tr><td colspan="2" class="cn">};
    print qq{<input type="submit" value="$lex{Select}"></td></tr>\n};

    my $sth = $dbh->prepare("select studid,lastname, firstname, studnum from studentwd
      order by lastname, firstname");
    $sth->execute;
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }

    for (1..$studcount) {
	my ($studid, $lastname, $firstname, $studnum) = $sth->fetchrow;
	print qq{<tr><td><b>$lastname</b>, $firstname ($studnum)</td><td>};
	print qq{<input type="checkbox" name="$studnum" value="1"></td></tr>\n};
    }

    print qq{<tr><td colspan="2" align="center">};
    print qq{<input type="submit" value="$lex{Select}"></td></tr>\n};
    print qq{</table></form></body></html>\n};

    exit;

}

#-----------------
sub selectCurrent {
#-----------------

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

    my $checked;
    if ( $arr{checknext} ) {
	$checked = qq{checked = "checked"};
	delete $arr{checknext};
    }

    my $grouptype = 'grade';
    if ( $arr{select} eq 'homeroom' ) {
	$grouptype = 'homeroom';
    }
    delete $arr{select}; # Grade or Homeroom value.
    
    
    my @studgroup;
    if ( $arr{group} ) {
	@studgroup = split(/\s+/, $arr{group});
    } else { # everyone.
	my $sth = $dbh->prepare("select distinct $grouptype from student 
				where $grouptype is not NULL and $grouptype != '' order by $grouptype");
	$sth->execute;
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	while ( my $val = $sth->fetchrow ) {
	    push @studgroup, $val;
	}
    }
    delete $arr{group};

    delete $arr{selectstud}; # not needed now.
    
    # what's left? (4 values: start/end dates, fontsize, papersize)
#    print qq{<div>what's left?</div>\n};
#    foreach my $key ( sort keys %arr ) { print "K:$key V:$arr{$key}<br>\n"; }


    print qq{<form action="$self" method="post">};
    print qq{<input type="hidden" name="startdate" value="$arr{startdate}">\n};
    print qq{<input type="hidden" name="enddate" value="$arr{enddate}">\n};
    print qq{<input type="hidden" name="fontsize" value="$arr{fontsize}">\n};
    print qq{<input type="hidden" name="papersize" value="$arr{papersize}">\n};
    print qq{<input type="hidden" name="currselectflag" value="1">\n};
    
    print qq{<input type="hidden" name="page" value="2">\n};

    
    # Loop over all groups (the space separated ones).
    foreach my $group ( sort {$a <=> $b} @studgroup ) { # loop over grades or homerooms
    
	# Start Table.
	my $caption = ucfirst $grouptype. qq{ $group};
	print qq{<table cellpadding="3" cellspacing="0" border="1" style="margin-bottom:1em;">\n};
	print qq{<caption style="font-size:120%;font-weight:bold;">$caption</caption>\n};
	print qq{<tr><th>$lex{Name}</th><th>$lex{Select}</th></tr>\n};
	print qq{<tr><td colspan="2" class="cn">};
	print qq{<input type="submit" value="$lex{Select}"></td></tr>\n};
	
	my $sth = $dbh->prepare("select studid,lastname, firstname, studnum from student
          where $grouptype = ?  order by lastname, firstname");
	$sth->execute( $group );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }

	while (my ($studid, $lastname, $firstname, $studnum) = $sth->fetchrow ) {
	    print qq{<tr><td><b>$lastname</b>, $firstname ($studnum)</td><td>};
	    print qq{<input type="checkbox" name="$studnum" value="1" $checked></td></tr>\n};
	}

	print qq{<tr><td colspan="2" align="center">};
	print qq{<input type="submit" value="$lex{Select}"></td></tr>\n};
	print qq{</table>\n};

    } # end of this group

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

    exit;




} # end of selectCurrent



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

    # Get default papersize
    my $papersize = $defaultpapersize;
    $papersize =~ s/paper//; # strip off the 'paper' ending;
    $papersize = ucfirst( $papersize );


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

    print qq{<table cellpadding="3" cellspacing="0" border="0">\n};
    print qq{<tr><td class="bra">$lex{'Sort by'}\n};
    print qq{</td><td><select name="sortorder">\n};
    print qq{<option value="name">$lex{Name}</option>\n};
    print qq{<option value="room">$lex{Homeroom}</option>\n};
    print qq{<option value="grade">$lex{Grade}</option>\n};
    print qq{<option value="band">$lex{Band}</option>\n};
    print qq{</select></td></tr>\n};

    print qq{<tr><td class="bra">$lex{Select}\n};
    print qq{</td><td><select name="select"><option>$lex{Grade}</option>\n};
    print qq{<option>$lex{Homeroom}</option>\n};
    print qq{<option>$lex{Band}</option>\n};
    print qq{</select>\n};
    print qq{<input type="text" name="group" size="14"> };
    print qq{Separate multiple groups with Spaces, $lex{'Blank=All'}</td></tr>\n};

    # Blank Row
    print qq{<tr><td colspan="2"><hr></td></tr>\n};

    # Dates
    print qq{<tr><td class="bra">$lex{'Start Date'}</td>\n};
    print qq{<td><input type="text" name="startdate" id="sdate" size="10" value="$schoolstart">\n};
    print qq{<button type="reset" id="start_trigger">...</button>\n};
    print qq{</td></tr>\n};

    print qq{<tr><td class="bra">$lex{'End Date'}</td>};
    print qq{<td><input type="text" name="enddate" id="edate" size="10" value="$schoolend">\n};
    print qq{<button type="reset" id="end_trigger">...</button></td></tr>\n};

#    print qq{<tr><td></td><td><b>$lex{Or}</b></td></tr>\n};
  
=head   
    # Terms
    print qq{<tr><td class="bra">$lex{'Start Term'}</td>\n};
    print qq{<td><select name="startterm"><option></option>\n};

    my $sth = $dbh->prepare("select distinct startrptperiod from subject where startrptperiod is not null and startrptperiod != ''");
    $sth->execute;
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $sterm = $sth->fetchrow ) {
	print qq{<option>$sterm</option>};
    }
    print qq{</select></td></tr>\n};

    print qq{<tr><td class="bra">$lex{'End Term'}</td>};
    print qq{<td><select name="endterm"><option></option>\n};

    my $sth = $dbh->prepare("select distinct endrptperiod from subject where endrptperiod is not null and endrptperiod != ''");
    $sth->execute;
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $eterm = $sth->fetchrow ) {
	print qq{<option>$eterm</option>};
    }
    print qq{</select></td></tr>\n};
=cut

    # Blank Row
    print qq{<tr><td colspan="2"><hr></td></tr>\n};

    
    # Select Withdrawn
    print qq{<tr><td class="bra">Select $lex{'Withdrawn Students'}</td><td>\n};
    print qq{<input type="radio" name="selectstud" value="withdrawn"></td></tr>\n};

    # Select Current Students
    print qq{<tr><td class="bra">Select Current Students</td><td>\n};
    print qq{<input type="radio" name="selectstud" value="current"></td></tr>\n};

    # Blank Row
    print qq{<tr><td colspan="2"><hr></td></tr>\n};
    

    # Paper Size
    print qq{<tr><td class="bra">$lex{'Paper Size'}</td>\n};
    print qq{<td class="la"><select name="papersize">};
    if ( $papersize ) { print qq{<option>$papersize</option>\n}; }
    print qq{<option>$lex{Letter}</option>};
    print qq{<option>$lex{A4}</option>};
    print qq{<option>$lex{Legal}</option>};
    print qq{</select></td></tr>\n};
    
    # Font Size
    print qq{<tr><td class="bra">$lex{'Font Size'}</td>\n};
    print qq{<td class="la"><select name="fontsize">};
    print qq{<option>12</option><option>11</option><option>10</option>\n};
    print qq{</select></td></tr>\n};

    # Summary Only
    print qq{<tr><td class="bra">$lex{Show} $lex{'Summary Records'}</td><td>\n};
    print qq{<input type="checkbox" name="summary" value="1"></td></tr>\n};


    # Perfect Attendance
    print qq{<tr><td class="bra">$lex{Show} $lex{'Perfect Attendance'}</td><td>\n};
    print qq{<input type="checkbox" name="perfectattendance" value="1"></td></tr>\n};

    # Check Next Page (student selection).
    print qq{<tr><td class="bra">Check Next Page</td><td>\n};
    print qq{<input type="checkbox" name="checknext" value="1" checked></td></tr>\n};

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


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

    print qq{<script type="text/javascript">
     Calendar.setup({
        inputField     :    "sdate", // id of the input field
        ifFormat       :    "%Y-%m-%d", // format of the input field
        button         :    "start_trigger", // trigger for the calendar (button ID)
        singleClick    :    false,        // double-click mode
        step           :    1             // show all years in drop-down boxes 
    });

    Calendar.setup({
        inputField     :    "edate", // id of the input field
        ifFormat       :    "%Y-%m-%d", // format of the input field
        button         :    "end_trigger", // trigger for the calendar (button ID)
        singleClick    :    false,        // double-click mode
        step           :    1             // show all years in drop-down boxes
    });
   </script>\n};

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

    exit;

}
