#! /usr/bin/perl
#  Copyright 2001-2024 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.

# Outline: Print the report cards for a single grade or homeroom.

# Customizations: Note ANY customizations for this school here
#  along with line numbers and/or markers to find them...

my %lex = ('Generate' => 'Generate',
	   'Main' => 'Main',
	   'Report Cards' => 'Report Cards',
	   'Report Card' => 'Report Card',
	   'View/Download/Print' => 'View/Download/Print',
	   'View Log File' => 'View Log File',
	   'Report to Parents' => 'Report to Parents',
	   'Grade' => 'Grade',
	   'Teacher(s)' => 'Teacher(s)',
	   'Evaluation and Comment Key' => 'Evaluation Key',
	   'Class Average' => 'Class Average',
	   'Attendance' => 'Attendance',
	   'Days Enrolled' => 'Days Enrolled',
	   'Days Absent' => 'Days Absent',
	   'General Comments' => 'General Comments',
	   'Term' => 'Term',
	   'Teacher' => 'Teacher',
	   'Please tear off this portion and return it to the school' =>
	     'Please tear off this portion and return it to the school',
	   'in the report envelope with any comments and your signature' =>
	     'in the report envelope with any comments and your signature',
	   'Parent/Guardian Signature' => 'Parent/Guardian Signature',
	   'Student' => 'Student',
	   'Comments' => 'Comments',
	   'Days per Month Override' => 'Days per Month Override',
	   'Homeroom' => 'Homeroom',
	   'Days Open' => 'Days Open',
	   'Month' => 'Month',
	   'Continue' => 'Continue',
	   'Duplicate Evaluation Record' => 
	      'Duplicate Evaluation Record',
	   'Average' => 'Average',
	   'No Quality Score' => 'No Quality Score',
	   'Error' => 'Error',
	   'Printed' => 'Printed',
	   'Override Term Days' => 'Override Term Days',
	   'Font Size' => 'Font Size',
	   'One Student per File' => 'One Student per File',
	   'GPA' => 'GPA',
	   'Current Year GPA' => 'Current Year GPA',
	   'Phone' => 'Phone',
	   'Fax' => 'Fax',
	   'Principal' => 'Principal',
	   'Vice-Principal' => 'Vice-Principal',
	   'Periods' => 'Periods',
	   'Evaluation Key' => 'Evaluation Key',
	   'Select Subjects' => 'Select Subjects',
	   'For Duplexing/Stapling' => 'For Duplexing/Stapling',
	   'Show Withdrawn Students' => 'Show Withdrawn Students',
	   'Subject' => 'Subject',
	   'Mark' => 'Mark',
	   'Printing Date' => 'Printing Date',
	   'Absent' => 'Absent',
	   'Late' => 'Late',
	   'Letter' => 'Letter',
	   'Legal' => 'Legal',
	   'A4' => 'A4',
	   'Paper Size' => 'Paper Size',
	   'Start Term' => 'Start Term',
	   'End Term' => 'End Term',
	   'Rank' => 'Rank',
	   'Demerits' => 'Demerits',
	   'Skipping' => 'Skipping',
	   'Undefined Value' => 'Undefined Value',
	   'Missing' => 'Missing',
	   'Track' => 'Track',
	   'Not Found' => 'Not Found',
	   'Picture' => 'Picture',
	   'Email' => 'Email',
	   'Address' => 'Address',
	   'Post' => 'Post',
	   'Complete' => 'Complete',

	   'OR' => 'OR',
	   'Form' => 'Form',
	   'Group' => 'Group',

	   );

use DBI;
use CGI;
use Cwd;
use Number::Format qw(:all);
use Carp;
use Time::JulianDay;
use Encode qw(encode decode);

my $deleteTeX = 1; # change to zero to check the generated TeX files.
my $showEmailOption = 0;
my $skipPictures = 1; # turn on with a 1 to override all student pictures

#my $r_DescMaxLength = 30; # used on line ~2524; # now in configuration.


# Non School Day Grades
my %nonschoolgrades = ('K' => 1,'PK' => 1,'P3' => 1);


my $message = "Dear Parents of <\@firstname\@> <\@lastname\@>,

Attached is a copy of the report card for <\@firstname\@>.

Sincerely,

<\@r_Principal\@>

<\@schoolname\@>
<\@schooladdr1\@>
<\@schooladdr2\@>
";


# These new config values control whether the subject printing will
# have empty cells before or after in situation where the current term
# is later, and for a second semester class it will produce blank
# cells before the current subject while for a first semester subject
# (already done), it will show blanks after.

# $r_TermDisplayLeading = 1; 
# Allows current later starting subjects to display back to start (with blanks)

# $r_TermDisplayTrailing = 1; # effectively sets ending display term to current term
# Allows completed subjects to extend to current term (with blanks)
# ----------------------------


my $self = 'rptrepcard.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";
}

my $schoolmode;
if ( $g_BritishSchoolMode ) {
    $schoolmode = 1; # will there be a mode 2?
}

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



# populate jdclosed with dates from dates table; used by calcTermDays;
my %jdclosed;
my $sth = $dbh->prepare("select date, dayfraction from dates 
  where date is not NULL and date != ''");
$sth->execute;
if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }

while ( my ( $date, $dayfraction ) = $sth->fetchrow ) {
    my $jd = julian_day( split( '-', $date ) );
    $jdclosed{$jd} = $dayfraction;
}


# load report card configuration
my $sth = $dbh->prepare("select id, datavalue from conf_system where filename = 'repcard' 
			order by dataname");
$sth->execute;
if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
while (	my ($id, $datavalue) = $sth->fetchrow ) {
    eval $datavalue;
    if ( $@ ) {
	print "$lex{Error}: $@<br>\n";
	die "$lex{Error}: $@\n";
    }
}

# turn off picture mode directly in report card, override all other config settings.
if ( $skipPictures ) {
    undef $r_ShowStudentPicture;
}


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

# Filter any r_NoteX found. (only done once here.)
foreach my $note ( $r_Note1, $r_Note2, $r_Note3, $r_Note4 ){
    if ( defined $note ) {
	($note) = latex_filter($note);
    }
}


# attendance library functions
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 and shift to teacher settings.
if ( getcwd() =~ /tcgi/ ) { # we are in tcgi
    $css = $tchcss;
    $homepage = $tchpage;
    $downloaddir = $tchdownloaddir;
    $webdownloaddir = $tchwebdownloaddir;
    $reppage = $tchpage;
}


my $q = new CGI;
my %arr = $q->Vars;

print $q->header( -charset, $charset );

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

if ( not $r_TeacherModeOverride and $teachermode ) {  # not allowed to print from teacher site
    print qq{<div style="color:blue;margin:2em;font-size:150%;">};
    print qq{$lex{Teacher} $lex{'Report Card'} printing not enabled</div>\n};
    print qq{</body></html>\n};
    exit;
}


# Set Date
my ( $currsdate, $currdate);
if ( not $arr{date} ) {
    my ($sec, $min, $hour, $mday, $mon, $year, $wday, 
	$yday, $iddst) = localtime(time);
    $year = $year + 1900;
    $mon++;
    $wday++;
    if ( length($mon) == 1 ) { $mon = '0'. $mon; }
    if ( length($mday) == 1 ) { $mday = '0'. $mday; }
    $currsdate = "$year-$mon-$mday";
    $currdate = "$dow[$wday], $month[$mon] $mday, $year";

} else { # we have a passed value;
    my ( $yr, $mo, $da ) = split('-', $arr{date});
    if ( length($mo) == 1 ) { $mo = '0'. $mo; }
    if ( length($da) == 1 ) { $da = '0'. $da; }
    $currsdate = "$yr-$mo-$da";
    $currdate = "$month[$mo] $da, $yr";
}



# Print HTML Page Header
my $title = "$lex{Generate} $lex{'Report Cards'}";
print qq{$doctype\n<html><head><title>$title</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="$reppage">$lex{'Report Card'}</a> ]\n};
} 

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



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

} elsif ( $arr{page} == 1 ) {
    delete $arr{page};
    # do nothing, and fall through

} elsif ( $arr{page} == 2 ) {
    delete $arr{page};
    postEmail();
}


# remove extra values from %arr; leave only month values.
my ($group, $groupid, $nsdflag );
if ( $arr{grade} ) {
    $group = 'grade';
    $groupid = $arr{grade};
    if ( $nonschoolgrades{ $groupid } ) {
	$nsdflag = 1;
    }

} elsif ( $arr{homeroom} ) {
    $group = 'homeroom';
    $groupid = $arr{homeroom};

    # Check if this homeroom has nonschooldays grade values
    my $sth = $dbh->prepare("select distinct grade from student where homeroom = ?");
    $sth->execute( $groupid );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $grade = $sth->fetchrow ) {
	if ( $nonschoolgrades{ $grade } ) {
	    $nsdflag = 1;
	}
    }
    
} else { # nothing selected; fail.
    print qq{<h3>$lex{Group} $lex{'Not Found'}</h3>\n};
    print qq{</body></html>\n};
    exit;
}

delete $arr{grade};
delete $arr{homeroom};

=head
# if nonschool grades selected, load nonschool days closed.
my %nonschoolday;
if ( $nsdflag ) { # load nonschool dates.
    
    if ( $group eq 'grade' ) { 
	print qq{<h3>Cannot Load Non School Days by Grade</h3>\n};
    } else { # we have a homeroom
	my $sth = $dbh->prepare("select * from dates_homeroom");
	$sth->execute;
	if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	while ( my $ref = $sth->fetchrow_hashref ) {
	    my %r = %$ref;
	    $nonschoolday{ $r{homeroom} }{ $r{date} }++; # don't worry about the period, just count them.
	}

#	foreach my $hroom ( sort keys %nonschooldays  ) {
#	    foreach my $date ( sort keys %{ $nonschooldays{$hroom}} ) {
#		print qq{HR:$hroom DATE:$date Period:$nonschoolday{$hroom}{$date}<br>\n};
#	    }
#	}

	if ( $grouptype eq 'homeroom' ) {
	    my $hroom = $groupvalue;
	    foreach my $date ( sort keys %{ $nonschoolday{$hroom} } ) {
		my ($y,$m,$d) = split('-',$date);
		$d =~ s/^0//; # strip leading zeros.
		if ( not $daysclosed{$d} ) { # add it in.
		    my $fraction = $nonschoolday{$hroom}{$date} / 2;
		    $daysclosed += $fraction;
		    $daysclosed{$d} = $fraction;
		}
	    }
	}
    }

} # end of nsdflag;
=cut




my $fontsize = $arr{fontsize};
my $override = $arr{override};
my $showwithdrawn = $arr{showwithdrawn};
my $startterm = $arr{startterm};
my $endterm = $arr{endterm};
my $oneStudentPerFile =  $arr{onestudentperfile};
my $emailRepcard = $arr{emailrepcard};
my $checknextpage = $arr{checknextpage};

# activate oneStudentPerFile if doing report card emails.
if ( $emailRepcard ) {
    $oneStudentPerFile = 1;
}

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

delete $arr{group};
delete $arr{groupid};
delete $arr{fontsize};
delete $arr{override};
delete $arr{onestudentperfile};
delete $arr{showwithdrawn};
delete $arr{endterm};
delete $arr{startterm};
delete $arr{emailrepcard};
delete $arr{checknextpage};


# Fail if missing the terms.
if ( not $startterm or not $endterm ) {
    print qq{<p style="font-size:140%;font-weight:bold;">};
    print qq{$lex{Missing} $lex{Term}</p>\n};
    print qq{</body></html>\n};
    exit;
}


# Set Paper Size, text width and height
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;
}



# Set the Track.
my $track;
if ( $group eq 'grade' ) {
    $track = $g_MTrackTermType{ $groupid };

} else { # check homeroom for track issues (ie. 2 different tracks, same room
    my $sth = $dbh->prepare("select distinct grade from student where homeroom = ? order by grade");
    $sth->execute( $groupid );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    
    my ($currtrack, $prevtrack);
    while ( my $gr = $sth->fetchrow ) {
	if ( not $prevtrack ) { 
	    $prevtrack = $g_MTrackTermType{ $gr };
	} else {
	    $prevtrack = $currtrack;
	}
	$currtrack = $g_MTrackTermType{ $gr };

	# print "Grade:$gr Curr:$currtrack Prev:$prevtrack<br>\n";

	if ( $currtrack ne $prevtrack ) {
	    print qq{<h3>$lex{Track} $lex{Error}<br>\n};
	    print qq{Current:$currtrack Previous:$prevtrack<br>\n};
	    print qq{Please print by grade</h3>\n};
#	    print qq{</body></html>\n};
#	    exit;
	}
	$track = $currtrack;
	
    }
}

# If no track, fail!
if ( not $track ) { 
    print qq{<h3>Missing Track</h3>\n};
    print qq{</body></html>\n};
    exit;
}


=head
#extract the subjec's, if any  ( in TEACHER mode );
foreach my $key (sort keys %arr ) { 
    if ( $arr{$key} == -1 ) {
	#print "K:$key V:$arr{$key}<br>\n"; 
	push @subjects, $key;
	delete $arr{$key};
    }
}



my %subjects;
my $sth = $dbh->prepare("select sequence, description from subject where subjsec = ?");
foreach my $subjsec ( @subjects ) {
    $sth->execute( $subjsec );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    my ( $sequence, $description ) = $sth->fetchrow;
    $subjects{"$sequence$description"} = $subjsec;
}
=cut


# Show withdrawn students, as well, if they have data.
if ( $showwithdrawn ) {
    $studenttable = 'studentall';
} else {
    $studenttable = 'student';
}

=head
# Get %students, to match @subjects; none in normal mode; key will provide sort order
my $sth = $dbh->prepare("select distinct e.studnum, s.lastname, s.firstname from eval as e,
   $studenttable as s where s.studnum = e.studnum and subjcode = ?");

foreach my $subjsec ( @subjects ) { # find the students for this, if any (not normally)
    $sth->execute( $subjsec );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my ( $studnum, $lastname, $firstname ) = $sth->fetchrow ) {
	$students{"$lastname$firstname$studnum"} = $studnum;
	#print "$firstname $lastname ($studnum)<br>\n";

    }
}

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


# Get a grade in order to get correct PPD (Periods per day that attendance is done).
my $periodsperday;
if ( $group eq 'homeroom' ) { # Get the grade for this class
    my $sth = $dbh->prepare("select distinct grade from student where homeroom = ?");
    $sth->execute( $groupid );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $gr = $sth->fetchrow ) {
	my $tempppd = $g_ppd{$gr};
	if ( $tempppd > $periodsperday ) { $periodsperday = $tempppd; }
    }
	
} else {
    $periodsperday = $g_ppd{$groupid};
}

if ( not $periodsperday and not $teachermode ) {
    print qq{<h3>$lex{Grade}:$grade  Periods Per Day:$g_ppd{$grade}<br>\n};
    print qq{No grade found or Periods per day not set in configuration</h3>\n};
    exit;
}



my %homeroomTeachers; # homeroomTeachers{homeroom} = @names.
if ( $r_ShowHomeroomTeacher ) {  # set in repcard.conf

    # Get all homeroom userid values.....
    my %rooms;
    my $sth1 = $dbh->prepare("select sal, firstname, lastname from staff where userid = ?");
    
    my $sth = $dbh->prepare("select id, userid, field_value from staff_multi 
			    where field_name = 'homeroom'");
    $sth->execute;
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my ($id, $userid, $hr) = $sth->fetchrow ) {
	if ( not $userid or not $hr ) { next; } # just in case....
	$rooms{$hr}{$userid} = 1;
    }

    foreach my $hr ( keys %rooms ) {
	
	my @tch;
	foreach my $userid ( keys %{ $rooms{$hr} } ) {
	    # Get Name
	    $sth1->execute( $userid );
	    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	    my ($sal, $firstname, $lastname ) = $sth1->fetchrow;
	    push @tch, "$sal $firstname $lastname";
	} 
	
	if ( @tch ) {
	    $homeroomTeachers{$hr} = \@tch;
	}
	
    }
    
} # end of ShowHomeroomTeacher
    

#foreach my $hr ( sort keys %homeroomTeachers ) {
#    print qq{HR:$hr  TCH:}, @{ $homeroomTeachers{$hr}}, "<br>\n";
#}



# CLASS AVERAGE
# Calculate the class averages for all subjects in the current term.
#  Easier than doing this just for subjects in current grade, since they
#  may take subjects from another grade level, etc.
#  Only do this if $r_classavg in repcard.conf is 1;


my %classavg;
if ( $r_ClassAvg ){ # create %classavg - class average hash.

    # First Find all courses done this term. (actually a subjsec field)
    $sth = $dbh->prepare("select distinct subjcode from eval
     where term = '$endterm' and subjcode is not NULL and subjcode != '' order by subjcode desc");
    $sth->execute;
    if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr;}

    my $sth1 = $dbh->prepare("select id, $r_MarkField from eval
      where term = '$endterm' and subjcode = ?");

    # Loop through each subjsec (subject-section)
    while ( my $subjsec = $sth->fetchrow ) {
#	print "Subjsec:$subjsec<br>\n";
	$sth1->execute( $subjsec );
	if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr;}

	my $totalmark = 0;
	my $totalcount++;
	while ( my ($id, $mark) = $sth1->fetchrow ){
#	    print "ID:$id Mark:$mark<br>\n";
	    $mark =~ s/\%//; # strip any percent signs.
	    if ( $mark =~ m/\d+/ ) { # if we have digits...
		$totalmark += $mark;
		$totalcount++;
	    }
	}

	my $average;
	if ( $totalcount ) {
	    $average = format_number( $totalmark / $totalcount, $r_AveragePrecision );
	} else {
	    $average = 0;
	}
	$classavg{$subjsec} = $average;
    }
} # End of Class Average Calculations (creates %classavg)

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

=head
# Calculate number of days in the terms
for my $trm ( $starterm..$endterm ) {

    my $val = calcTermDays($g_MTrackTerm{$track}{$trm}{'start'}, 
			   $g_MTrackTerm{$track}{$trm}{'end'},
			   \%jdclosed );
    my ($open,$closed) = split(':', $val);

    $termdays{$trm} = $open;
}
=cut


my $nsdhomeroom; # this is really the student group (homeroom or with GR: prefix the grade);
if ( $group eq 'grade' ) {
    $nsdhomeroom = qq{GR:$groupid};
} else {
    $nsdhomeroom = $groupid; # homeroom;
}


# IF nsdhomeroom is passed, then mkSchoolDays will also look for those days closed also.
my %schooldays = mkSchoolDays( $schoolstart, $currsdate, $dbh, $nsdhomeroom );



if ( $override ){ # we are overriding days per month...
    foreach my $key ( sort keys %arr ) { # %arr now contains all the months of interest.
	if ( $key eq 'date' or $key eq 'papersize' ) { next; }
	$schooldaysorig{$key} = $schooldays{$key};
	$schooldays{$key} = $arr{$key}; 
    }
}

# print qq{School Days Hash<br>\n};
# foreach my $key ( keys %schooldays ) { print "K: $key Val: $schooldays{$key}<br>\n"; }


my ($tempdir, $shortname, $filename);
if ( not $oneStudentPerFile ) {
    $shortname = "repcard$$";
    $filename = "$shortname.tex";

    open( TEX,">", $filename ) || die "Can't open tex file\n";
    prTexDocStart(); # print document preamble.

} else { # we are doing one student per file; create temporary folder.
    $tempdir = "tempdir$$";
    system("mkdir $tempdir");
    open( LOG,">pdflog$$.txt" ) || die "Can't open LOG file\n";
} 


# Get Students
my $sth = $dbh->prepare("select studnum, lastname, firstname, homeroom
   from $studenttable where $group = ? order by homeroom, lastname, firstname");
$sth->execute( $groupid );
if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
while ( my ( $studnum, $lastname, $firstname, $homeroom ) = $sth->fetchrow ) {
    $students{"$homeroom$lastname$firstname$studnum"} = $studnum;
}



# Calculate Term Average for student and Ranking
my $termavg_ref;
if ( $r_ShowTermAverage or $r_ShowRanking or $r_ShowGradeCategory ) {
    # Other functions depend on this hash_ref.

    my $sth = $dbh->prepare("select id, $r_MarkField from eval where term = ? and studnum = ?");

    # $termavg_ref->{$term}->{$studnum} = average.
    foreach my $key ( sort keys %students ) {
	my $studnum = $students{$key};
	foreach my $trm ( $startterm .. $endterm ) {

	    my ( $markcount, $marktotal );
	    $sth->execute( $trm, $studnum );
	    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	    while ( my ( $ignore, $mark ) = $sth->fetchrow ) {
		if ( $mark =~ m/[.0-9]+/ ) { # is a number
		    $markcount++;
		    $marktotal += $mark;
		}
	    }

	    my $avg;

	    if ( $markcount ) {
		$avg = $marktotal / $markcount;
	    } else {
		$avg = 0;
	    }

	    $termavg_ref->{$trm}->{$studnum} = $avg;

	}
    }
}
    
# Print Out termavg double hash.
#    foreach my $key ( sort keys %$termavg_ref ) {
#	print "<br>K:$key Ref: $$termavg_ref{$key}<br>\n";
#	foreach my $key1 ( sort keys %{ $$termavg_ref{$key} } ) {
#	    print "Key:$key1  Val: $$termavg_ref{$key}->{$key1}<br>\n";
#	}
#    }
# end of TermAvg calc; not showing these values until later in table.



my $rank_ref;
if ( $r_ShowRanking ) {

    # Now create ranking hash for each term.
    foreach my $trm ( $startterm .. $endterm ) {
	my $prevavg = -1;
	my $rank = 1;
	my $count = 1;
	my %average = %{ $$termavg_ref{$trm} }; # setup hash to do.

	foreach my $studnum ( sort { $average{$b} <=> $average{$a} } keys %average ) {

	    if ( $average{$studnum} != $prevavg ) { # normal operation.
		$rank_ref->{$trm}->{$studnum} = $count;
		#$rank{$studnum} = $count;
		$prevavg = $average{$studnum};
		$rank = $count;
	    } else { # if the average is same as previous...
		$rank_ref->{$trm}->{$studnum} = $rank;
		#$rank{$studnum} = $rank;
	    }

	    #print "Count: $count Term:$trm Student:$studnum Average:$average{$studnum}";
	    #print " Rank: $rank_ref->{$trm}->{$studnum}<br>\n";
	    $count++;
	}

    } # end of %rank creation.

} # end of Ranking section.



my $sth = $dbh->prepare("select lastname, firstname, initial, grade, 
 homeroom, birthdate, provnum from $studenttable where studnum = ?");


# Loop through all students, one report card each.
foreach my $key ( sort keys %students ) {
    my $studnum = $students{$key};

    # Get Student Info
    $sth->execute( $studnum );
    my ( $lastname, $firstname, $middlename, $grade, $homeroom, 
	 $birthdate, $provnum ) = $sth->fetchrow;

    if ( $r_SkipBlankReportCard ) {

	# Check that she/he actually has some info in database.
	my $sth1 = $dbh->prepare("select count(*) from eval 
         where term >= ? and term <= ? and studnum = ?"); # and a1 != ''
	$sth1->execute( $startterm, $endterm, $studnum );
	if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; }

	my $evcount = $sth1->fetchrow;
	if ( not $evcount ) { next; } # skip kids with blank values for terms
    }


    if ( $oneStudentPerFile ) {

	# Create this student's filename
	my ($lname, $fname);
	$fname = $firstname; $lname = $lastname;
	$fname =~ s/\W|\-//g; # remove 'nonword' characters
	$lname =~ s/\W|\-//g;
	if ( length($lname) > 12 ) { $lname = substr $lname, 0, 12; }
	if ( length($fname) > 8 ) { $fname = substr $fname, 0, 8; }
	#print "LN: $lname  FN: $fname<br>\n";
	$shortname = "$lname$fname-$studnum";
	$filename = "$shortname.tex";

	open( TEX,">$filename" ) || die "Can't open tex file";
	prTexDocStart(); # print document preamble.
	
    }


    # Print the heading section for each new report card
    prTexHead( $grade, $lastname, $firstname, $middlename, $birthdate, $provnum, $studnum );

    # print a Note 1 - if set in repcard.conf
    if ( $r_Note1 ) {
	# Check if we have a mapping and for this grade.
	my %map = map { $_ => 1} @r_MapNote1;
	if ( not @r_MapNote1 or ( $map{$grade} )) {
	    print TEX "\\fbox{\\parbox[b]{\\textwidth}{ ";
	    print TEX "\\begin{center}{\\it $r_Note1}\\end{center} }}\n\n";
	}
    }
    
    # print homeroom teachers for this student (if any).
    if ( $r_ShowHomeroomTeacher and $homeroomTeachers{$homeroom} ) {  # set in repcard.conf
	prHomeroomTeachers( $homeroom, @{ $homeroomTeachers{$homeroom}} );
    }

    # put in rule divider
    print TEX "\\hrulefill \n\\smallskip\n\n";


    # Attendance 1 - print block
    if ( $r_ShowMonthlyAttendance == 1 ) {
	prMonthlyAttendance( $studnum );
    }


    if ( $r_ShowGradeScheme ) {  # set in repcard.conf
	print_grade_scheme( $grade );
    }
    # End of head section for each new report card.

    if ( $r_ShowMonthlyAttendance == 2 ) {
	prMonthlyAttendance( $studnum );
    }


    # print a Note 2 - if set in repcard.conf
    if ( $r_Note2 ) {
	# Check if we have a mapping and for this grade.
	my %map = map { $_ => 1} @r_MapNote2;
	if ( not @r_MapNote2 or ( $map{$grade} )) {
	    print TEX "\\fbox{\\parbox[b]{\\textwidth}{ ";
	    print TEX "\\begin{center}{\\it $r_Note2}\\end{center} }}\n\n";
	}
    }


    my %mycourses;

    # Find eval records for this student
#    my $sth1 = $dbh->prepare("select distinct e.subjcode, s.sequence, 
#      s.startrptperiod from eval as e, subject as s where 
#      e.studnum = ? and e.subjcode = s.subjsec order by s.sequence");

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

    # Get Subjects for this student in this term range.
    my $sth1 = $dbh->prepare("select distinct subjcode from eval where 
      studnum = ? and term >= $startterm and term <= $endterm");
    $sth1->execute( $studnum );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my  $subjsec = $sth1->fetchrow ) {

	# skip if member of %r_SupressSubject or %r_AdditionalComments
	my ($tsubjcode, $dud) = split('-', $subjsec ); 
	if ( $r_SupressSubject{$tsubjcode} or $r_SupressSubject{$subjsec} or
	     $r_AdditionalComments{$tsubjcode} or $r_AdditionalComments{$subjsec} ) {

	    next; 
	}

	
	$sth2->execute( $subjsec );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $seq = $sth2->fetchrow;

	while ( length( $seq ) < 4 ) { # pad with leading zeros
	    $seq = '0'. $seq;
	}
	$mycourses{"$seq$subjsec"} = $subjsec;
    }

#    print "SN: $studnum  SUB:", %mycourses, "<br>\n";
    

    my $firstsubjectflag = 1; # mark if still at first subject

    # Initialize the GPA hash.
    my %gpa;
    my $biggestterm; # track largest term values in subjects

    if ( $r_CenterSubjects ) {
	print TEX "\\begin{center}\n";
    }


    my $sth1 = $dbh->prepare("select * from subject where subjsec = ?");
    
    # Now Loop through all courses of this student
    foreach  my $key ( sort keys %mycourses ) {

	my $subjsec = $mycourses{ $key }; # req'd since mycourses for sorting only
	
	# Get this subject's info...
	$sth1->execute( $subjsec );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $subjref = $sth1->fetchrow_hashref;
	my %s = %$subjref;
	
#	my $sequence = $subjref->{sequence};
#	my $startrptperiod = $subjref->{startrptperiod};
#	my $endrptperiod = $subjref->{endrptperiod};
#	my $subjcode = $subjref->{subjcode};


	#=== Various Skip Reasons
	# skip if this subject hasn't started yet.
	if ( $s{startrptperiod} > $endterm ) { next; }
	# skip if all done.
	if ( $startterm > $s{endrptperiod} ) { next; }

	

	my @objdesc; # objective descriptions
	my $objectivecount;
	for my $i ( 1 .. 20 ) {
	    my $fieldname = 'q'. $i;
	    if ( $s{$fieldname} ) {
		$objdesc[$i] = $s{$fieldname};
		$objectivecount = $i;
	    }
	}
	if ( not @objdesc ) { # no objectives, put in 1 for mark;
	    $objdesc[1] = $lex{Mark};
	    $objectivecount = 1;
	}


	# Start setting up eval data structure: array of arrays.
	my @eval;
	# Sets first column with description of objectives ( by q1, q2, etc)
	$eval[0] = [ @objdesc ];
	# Testing: foreach my $desc ( @{ $eval[0] } ) { print "$desc<br>\n"; }

	# Do Any Leading Blanks here.
=head	
	if ( $r_TermDisplayLeading ) { # pad front of subject
	    my $leadidx = $startterm;  # $startterm is passed starting term to print.
	    while ( $leadidx < $s{startrptperiod} ) { # $startrptperiod is from subject record.
		my @temp = ();
		$temp[ $#objdesc ] = ''; # dimension that thar array.
		push @eval, [ @temp ];
		$leadidx++;
	    }
	}
=cut

	# Now pull in the records for this subject for this student
	# Pull in full records
	$sth2 = $dbh->prepare("select * from eval where studnum = ?
          and subjcode = ? order by eval.term");
	$sth2->execute( $studnum, $subjsec ) ;
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }

	# read eval records for each term of this subject.
	my $currtrm = 0; 
	my $prevtrm; # for error checking for redundant records below.
	my $lastterm; # last term value in @eval; used for trailing blank cells.

	while ( my $evalref = $sth2->fetchrow_hashref ){ # load temp eval record

	    my $evalterm = $lastterm = $evalref->{term};
	    if ( $evalterm > $endterm or $evalterm < $startterm ) { next; } 
	    # not there yet, or skipping earlier.

	    # Set values into GPA Hash
	    if ( defined $evalref->{$r_MarkField} ) { # markfield comes from repcard.conf
		$gpa{$subjsec}[$evalterm] = $evalref->{$r_MarkField};
	    }

	    # Check for largest term ( so know how many gpa calcs to do).
	    if ( $evalterm > $biggestterm ) { $biggestterm = $evalterm; }

	    # Error Checking for any mistakes in eval records
	    $prevtrm = $currtrm; $currtrm = $evalterm;
	    if ( $currtrm == $prevtrm){ 
		# Error! two eval records with the same term value.
		print $lex{'Duplicate Evaluation Record'}. ":\n";
		print "$lex{Student}: $studnum - $lex{Subject}:";
		print "$subjnum - $lex{Term}:$currtrm.\n";
		print "Contact Les Richardson\n";
	    }

	    # use array slice to put in eval record fields with possible values
	    my @temp = ();
	    push @temp, $evalterm;
	    for my $i ( 1 .. $objectivecount ) {
		$fieldname = 'a'. $i;
		push @temp, $evalref->{$fieldname};
	    }

 	    push @eval, [ @temp ];

	} # Done stuffing eval recs into eval array (with reference).


	if ( $r_TermDisplayTrailing ) { # pad end of course, if necessary.
	    my $trailidx = $lastterm;  # lastterm is last term in @eval
	    while ( $trailidx < $s{endrptperiod} ) { # was $endterm
		my @temp = ();
		$temp[ $#objdesc ] = ''; # dimension that thar array.
		push @eval, [ @temp ];
		$trailidx++;
	    }
	}


	prCourse( $subjsec, $studnum, $currterm, $startterm, $endterm, \@eval ); # print course;

	prComment( $subjsec, $studnum, $startterm, $endterm ); # print the comments (all)


    } # End of this course; loop to print the next.


    # Now do the GPA row...
    if ( $r_CalcGPA ) {
	calcGPA(\%gpa, $biggestterm );
	print TEX "\\smallskip\n\n";
    }

    # Now show the Ranking / Demerits / Term Average / Grade Category
    if ( $r_ShowRanking or $r_ShowTermAverage or $r_ShowDemerits or $r_ShowGradeCategory ) {
	showRankDemAvgBlock( $studnum, $grade );
	print TEX "\\smallskip\n\n";
    }


    # End Subject Centering, if turned on.
    if ( $r_CenterSubjects ) {
	print TEX "\\end{center}\n";
    }


    # Start a new page for attendance, etc.
    if ( $r_NewPageBeforeAttendance ) {
	print TEX "\\newpage\n";
    }


    # Attendance - print block
    if ( $r_ShowMonthlyAttendance == 3) {
	prMonthlyAttendance( $studnum );
    }


    if ( $teachermode ) {
	print TEX "\\vspace{10mm}\n\n";
    } else {
	print TEX "\n\n"; # to push over additional comments.
    }

    if ( $r_ShowAdditionalComments ) {
	prAddComments( $studnum, $startterm, $endterm ); # Additional comments
    }

    if ( $r_ShowMonthlyAttendance == 4 ) {
	prMonthlyAttendance( $studnum );
    }

    if ( $r_Note3 ) {

	# Check if we have a mapping and for this grade.
	my %map = map { $_ => 1} @r_MapNote3;
	if ( not @r_MapNote3 or ( $map{$grade} )) {
	    print TEX "\\fbox{\\parbox[b]{\\textwidth}{ ";
	    print TEX "\\begin{center}{\\it $r_Note3}\\end{center} }}\n";
	    print TEX "\\vspace{6mm}\n\n";
	}
    }


    # Now finish off the report card; last term gets the promotion format.
    # There are 3 signature fns: Teacher, Principal, or Combo. Pick your mix.

    # Placement Text block
    my $blockFlag; # indicates if a placement block is used with this grade level
    if ( $r_PlacementTex{ "$r_PlacementIndex{ $grade }" } ) {
	$blockFlag = 1; 
    }

    if ( $endterm != $r_FinalTerm{$grade} or not $blockFlag ){ 
	# not final term or no Placement Block ( even IF final term)

	# Also... if no $teachersign value, then not shown...
	if ( $r_TeacherSign eq 'teacher' ){
	    prTeacherSig();  #Teacher Signature

	} elsif ( $r_TeacherSign eq 'principal' ){
	    prPrincipalSig();  #Principal Signature

	} elsif ( $r_TeacherSign eq 'combo' ) {
	    prComboSig(); 
	    # Combination Signature (both teacher / principal side by side.)
	}
	
	# print if we have a showTearoff (or not updated)
	if ( $r_ShowTearoff ){
	    if ( $r_PrintParentSig ) { # block them together
		$tearoffblock = 1;
	    }
	    prTearoff(); 

	    # print a signature line for parents on tear off line.
	    if ( $r_PrintParentSig ) {
		prParentSig( $currdate, $lastname, $firstname, $middlename ); # Parent Signature
	    } elsif ( $tearoffblock ) { # close off the parbox
		print TEX "} \n ";
	    }
	}
    
    } else { # we're in the last term; print graduation box, if set...
	if ( $r_PrintYearEnd ) {
	    prYearEnd("$firstname $middlename $lastname", $grade);
	}
    }

    if ( $r_Note4 ) {
	# Check if we have a mapping and for this grade.
	my %map = map { $_ => 1} @r_MapNote4;
	if ( not @r_MapNote4 or ( $map{$grade} )) {
	    print TEX "\\fbox{\\parbox[b]{\\textwidth}{ ";
	    print TEX "\\begin{center}{\\it $r_Note4}\\end{center} }}\n\n";
	}
    }

    
    # End Section for this student.
    if ( $oneStudentPerFile ) {
	# build pdf and put into tempdir; append to pdflog$$.txt
	#print TEX "\\end{center}\n";
	print TEX "\\end{document}\n";
	close TEX;

	print LOG "\n\n$firstname $lastname ($studnum)\n-----------------\n";
	system("$pdflatex $filename >>pdflog$$.txt");
	system("mv $shortname.pdf $tempdir");
	system("rm -f $shortname.*");
    } else {
	print TEX "\\newpage\n"; # new page for next student.
    }

}  # End of Main Loop; Back to Next Student.


# Final section
# Done report card, now setup the web page.
if ( $emailRepcard ) {
    selectEmailAddress( $tempdir );
    # this will then cause skip to final email post function.
    
} elsif ( $oneStudentPerFile ) {
    # create single zip and copy all zip to webdownload dir; pdflog$$.txt too.
    $shortname = "repcard$$";
    system("zip $shortname.zip $tempdir/* >> pdflog$$.txt");
    system("mv $shortname.zip $downloaddir");
    system("mv pdflog$$.txt $downloaddir");
    system("rm -r $tempdir");

    print qq{<table cellspacing="0" cellpadding="3" border="0" };
    print qq{style="padding:1em;margin:0.5em;border:1px solid gray;">\n};
    print qq{<tr><td><h1>[ <a href="$webdownloaddir/$shortname.zip">\n};
    print qq{$lex{'View/Download/Print'} $lex{'Report Cards'}</a> ]</h1>\n};
    print qq{</td></tr></table>\n};

} else { # all in one.

    # Print ending of report
    print TEX "\\end{document}\n";
    close TEX;

    system("$pdflatex $filename >pdflog$$.txt");
   
    system("mv $shortname.pdf $downloaddir");
    system("mv pdflog$$.txt $downloaddir");
    if ( $deleteTeX ) { # set at top
	system("rm -f $shortname.*");
    }

    print qq{<table cellspacing="0" cellpadding="3" border="0" };
    print qq{style="padding:1em;margin:0.5em;border:1px solid gray;">\n};
    print qq{<tr><td><h1>[ <a href="$webdownloaddir/$shortname.pdf">\n};
    print qq{$lex{'View/Download/Print'} $lex{'Report Cards'}</a> ]</h1></td></tr></table>\n};

}

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




# ====== End of Main Section ================


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

    my ( @subjects, %subjdesc );
    
    if ( $teachermode ) { # we are running on teacher site
	# Get their subjects
	my $sth = $dbh->prepare("select subjsec, description from subject 
          where teacher = ? order by sequence, description ");
	$sth->execute( $userid );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	while ( my ( $subjsec, $description ) = $sth->fetchrow ) {
	    push @subjects, $subjsec;
	    $subjdesc{ $subjsec } = $description;
	}

    }


    # Form Start
    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;
    }
    @grades = sort {$a <=> $b} @grades;

    # Get School Months for Override; use the largest grade
    # (less chance of lowest grade closure issue)
    my $topgrade = $grades[-1];
    my %schoolmonths = mkSchoolDays( $schoolstart, $currsdate, $dbh, "GR:$topgrade" );
    # Format: yyyy-mm; first record is blank (zeroth)


    # 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
    }


    # Start Table.
    print qq{<table cellspacing="0" cellpadding="3" border="0" };
    print qq{style="padding:1em;margin:0.5em;border:1px solid gray;">\n};


    # Grades
    print qq{<tr><td class="bra">$lex{Grade}};
    if ( $schoolmode == 1 ) {
	print qq{/$lex{Form}};
    }
    print qq{</td>};
    print qq{<td class="la"><select name="grade"><option></option>\n}; 
    foreach my $gr ( @grades ) { # sorted above
	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{Homeroom}</td>};
    print qq{<td class="la"><select name="homeroom"><option></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};
    
    
    # Printing Date
    print qq{<tr><td class="bra">$lex{'Printing Date'}</td>\n<td>};
    print qq{<input type="text" name="date" id="date" size="10" value="$currsdate">\n};
    print qq{<button type="reset" id="start_trigger">...</button>\n};
    print qq{</td></tr>\n};

    
    # Terms  (to use to get courses during those term blocks).
    print qq{<tr><td class="bra">$lex{'Start Term'}</td>\n<td>};
    print qq{<input type="text" name="startterm" size="4"></td></tr>\n};
    print qq{<tr><td class="bra">$lex{'End Term'}</td>\n<td>};
    print qq{<input type="text" name="endterm" size="4"></td></tr>\n};


    # Paper Size
    $defaultpapersize =~ s/paper//; # strip out word paper so lex works; from admin.conf
    my $defpaper = ucfirst( $defaultpapersize );

    print qq{<tr><td class="bra">$lex{'Paper Size'}</td>\n};
    print qq{<td><select name="papersize"><option>$lex{$defpaper}</option>\n};
    my @sizes = qw(Letter A4 Legal);
    foreach my $size ( @sizes ) {
	if ( $size eq $defpaper ) { next; }
	print qq{<option>$lex{$size}</option>};
    }
    print qq{</select></td></tr>\n} ;

    # Font Size
    print qq{<tr><td class="bra">$lex{'Font Size'}</td>\n<td>};
    print qq{<select name="fontsize"><option>$r_FontSize</option>\n};
    print qq{<option>10pt</option><option>11pt</option><option>12pt</option></select></td></tr>\n};


    if ( $teachermode ) {
	print qq{<tr><td><b>$lex{'Select Subjects'}</b></td><td></td></tr>\n};
	foreach my $subjsec ( @subjects ) {
	    print qq{<tr><td class="bra" style="background-color:#DDD;">};
	    print qq{$subjdesc{$subjsec} ($subjsec)</td>\n};
	    print qq{<td><input type="checkbox" name="$subjsec" value="-1"></td></tr>\n};
	}
    }


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

    # One Student per File
    print qq{<tr><td class="bra">$lex{'One Student per File'}</td>\n};
    print qq{<td><input type="checkbox" name="onestudentperfile" value="1">};
    print qq{$lex{'For Duplexing/Stapling'}</td></tr>\n};

    # Enable/Disable the email report card option from top of script.
    if ( $showEmailOption ) {
	# Email report card.
	print qq{<tr><td class="bra">$lex{Email} $lex{'Report Card'}</td>\n};
	print qq{<td><input type="checkbox" name="emailrepcard" value="1"></td></tr>\n};

	print qq{<tr><td class="bra">Check All Email Addresses</td>\n};
	print qq{<td><input type="checkbox" name="checknextpage" value="1"></td></tr>\n};
	
    }

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


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

    
    # Override for Days open in month
    print qq{<tr><td class="bra">$lex{'Override Term Days'}</td>};
    print qq{<td><input type="checkbox" name="override" value="1"></td></tr>\n};

    # Inner Table
    print qq{<tr><td colspan="2">\n};
    print qq{<table cellspacing="0" cellpadding="3" border="1">\n};
    print qq{<tr><th colspan="2">$lex{'Days per Month Override'}</th></tr>\n};
    print qq{<tr><th>$lex{Month}</th><th>$lex{'Days Open'}</th></tr>\n};

    
    for my $ym ( sort keys %schoolmonths ) { # keys are yyyy-mm format
	my ($y,$m) = split('-', $ym);
	print qq{<tr><td><b>$month[$m]</b> ($ym)</td>};
	print qq{<td><input type="text" name="$ym" size="4"></td></tr>\n};
    }
    print qq{</table></td></tr>\n};
    # End of Inner Table
    
    print qq{<tr><td></td><td><input type="submit" value="$lex{Continue}"></td></tr>\n};

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

    print qq{<script type="text/javascript">
    Calendar.setup({
    inputField     :    "date", // 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 (not evry other year as default)
    });
    </script>\n};

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

    exit;

} # end of showStartPage


#----------------
sub prTexDocStart {
#----------------

# Preamble and Head of Document

    # $papersize, $textwidth and $textheight set at top of script.
    print TEX <<"EOS1";  
\\documentclass[ $fontsize, $papersize, oneside]{article}
\\usepackage{array,graphicx,multicol,colortbl,fancyhdr,noto}
%$a_latex_header
\\renewcommand{\\familydefault}{\\sfdefault}

\\setlength{\\hoffset}{ $r_HOffset }
\\setlength{\\voffset}{ $r_VOffset }

\\setlength{\\headsep}{10pt}
\\setlength{\\headheight}{14.5pt}
\\setlength{\\topmargin}{0in}

\\setlength{\\textwidth}{ $textwidth }
\\setlength{\\textheight}{ $textheight }

\\setlength{\\parindent}{0pt}
\\setlength{\\evensidemargin}{0in}
\\setlength{\\oddsidemargin}{0in}
\\setlength{\\extrarowheight}{4pt}
\\pagestyle{headings}
\\newcolumntype{G}{>{\\columncolor[gray]{ $r_GrayScale }}p{$r_SubjSpace}}

\\pagestyle{fancy}
\\lhead{$schoolname -- $schoolyear}
\\rfoot{ $lex{Printed}: $currdate }
\\cfoot{ }

\\begin{document}
EOS1

}


#----------------------
sub showRankDemAvgBlock {
#----------------------

    my ($studnum, $grade)  = @_;

    print TEX "\\bigskip\n";

    # Start TeX head
    print TEX "\\begin{tabular}{|p{$r_SubjSpace}|";
    for ( $startterm .. $endterm ){ print TEX "p{$r_MarkSpace}|"; }
    print TEX "}\\hline\n";

    my $track = $g_MTrackTermType{ $grade };

    # Do Header
    print TEX "\\rowcolor[gray]{ $r_GrayScale }";
    foreach my $term ( $startterm .. $endterm )  { #loop through all terms
	my $title;
	if ( $g_TermDisplay{$track}{$term} ) {
	    $title = $g_TermDisplay{$track}{$term};
	} else { $title = $term; }
	print TEX "& \\hfil $title \\hfil"; 
    }
    print TEX "\\\\ \\hline\n";

    # Do Average
    if ( $r_ShowTermAverage ) {
	#print TEX "\\rowcolor[gray]{ $r_GrayScale }";
	print TEX "\\bf ". $lex{Average};
	# Loop through each term displaying the average
	foreach my $term ( $startterm .. $endterm )  { #loop through all terms
	    my $average = format_number( $termavg_ref->{$term}->{$studnum} , $r_AveragePrecision );
	    print TEX "&\\hfil $average \\hfil "; # change to GPA value...
	} # End of terms loop
	print TEX "\\\\ \\hline\n";
    }

    # Do Rank
    if ( $r_ShowRanking ) {
	#print TEX "\\rowcolor[gray]{ $r_GrayScale }";
	print TEX "\\bf ". $lex{Rank};
	# Loop through each term displaying the average
	foreach my $term ( $startterm .. $endterm )  { #loop through all terms
	    my $rank = $rank_ref->{$term}->{$studnum};
	    print TEX "&\\hfil $rank \\hfil "; # change to GPA value...
	} # End of terms loop
	print TEX "\\\\ \\hline\n";
    }


    # Do Grade Category
    if ( $r_ShowGradeCategory ) {
	#print TEX "\\rowcolor[gray]{ $r_GrayScale }";
	print TEX "\\bf ". $lex{Grade}; # really Grade Category

	foreach my $term ( $startterm .. $endterm )  { #loop through all terms
	    my $gradecategory = calcGradeCategory( $studnum, $term );
	    print TEX "&\\hfil $gradecategory \\hfil ";
	} # End of terms loop

	print TEX "\\\\ \\hline\n";

    } # end of showGradeCategory


    # Do Demerits
    if ( $r_ShowDemerits ) {
	#print TEX "\\rowcolor[gray]{ $r_GrayScale }";
	print TEX "\\bf ". $lex{Demerits};
	foreach my $term ( $startterm .. $endterm )  { #loop through all terms
	    my $start = $g_MTrackTerm{$track}{$term}{'start'};
	    my $end = $g_MTrackTerm{$track}{$term}{'end'};

	    my $sth = $dbh->prepare("select sum( demerit ) from disc_ident i, disc_event e where 
              e.id = i.eventid and studnum = ? and 
              to_days(e.date) >= to_days('$start') and 
              to_days(e.date) <= to_days('$end') ");           

	    $sth->execute( $studnum );
	    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	    my $demerits = $sth->fetchrow;
	    if ( not $demerits ) { $demerits = '0'; }

	    print TEX "&\\hfil $demerits \\hfil "; # change to GPA value...

	} # End of terms loop

	print TEX "\\\\ \\hline\n";
    } # end of showDemerits;

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


} # end of showRankDemAvgBlock



#--------------------
sub calcGradeCategory {
#--------------------

    my ( $studnum, $term ) = @_;

    # Now in configuration system.
    # my %r_GCDisplay = ( '1' => 'I', '2' => 'II', '3' => 'III', '4' => 'P', '5' => 'U' );
    
    my %dud; # just need a blank hash.

    # Find if any marks below a fail value; don't count blanks.
    my $failmark = 55;
    my $sth = $dbh->prepare("select count(*) from eval 
      where studnum = ? and term = ? and $r_MarkField is not null
      and $r_MarkField != '' and $r_MarkField < $failmark ");
    $sth->execute( $studnum, $term );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    my $failcount = $sth->fetchrow;

    my $sth1 = $dbh->prepare("select lastname, firstname from studentall where studnum = ?");
    
    if ( $failcount ) { # display the values

	# Get Name
	$sth1->execute( $studnum );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my ($lastname, $firstname) = $sth1->fetchrow;

	# Display Courses and Marks
	my $sth = $dbh->prepare("select subjcode, $r_MarkField from eval 
          where studnum = ? and term = ?");
	$sth->execute( $studnum, $term );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	print qq{<h4>FAILURE for $firstname $lastname</h4>\n};
	while ( my ($subjcode, $mark )  = $sth->fetchrow ) {
	    print "<div>SN:$studnum TERM:$term COURSE:$subjcode MARK:$mark</div>\n";
	}
    }
    
    
    # Level 1
    my $avg1 = calcTopAverage( $studnum, $term );
#    my %names = ('English' => '1' );
#    my $count2 = calcTopCount( $studnum, $term, 70, \%names,1 );
#    my $count3 = calcTopCount( $studnum, $term, 55, \%dud, 1 );

    # print "Studnum:$studnum Level:1  A1:$avg1  C2:$count2 C3:$count3<br>\n";
    if ( $avg1 >= 85  and not $failcount ) { # and $count2 >= 5 and $count3 >= 7 ) {
	# print "Level 1 Return<br><br>\n";
	return $r_GCDisplay{1};
    }

    # Level 2
    $avg1 = calcTopAverage( $studnum, $term );
#    $count2 = calcTopCount( $studnum, $term, 70,\%dud,1 );
#    %names = ('English' => '1' );
#    $count3 = calcTopCount( $studnum, $term, 55, \%names, 1 );

    # print "Studnum:$studnum Level:2  A1:$avg1  C2:$count2 C3:$count3<br>\n";
    
    if ( $avg1 >= 75 and not $failcount ) { # and $count2 >= 4 and $count3 >= 6 ) {
	# print "Level 2 Return<br><br>\n";
	return $r_GCDisplay{2};
    }

    # otherwise just...
    
    return;
    
=head
    # Level 3
    $avg1 = calcTopAverage( $studnum, $term );
    $count2 = calcTopCount( $studnum, $term, 70,\%dud, 1);
    %names = ('English' => '1' );
    $count3 = calcTopCount( $studnum, $term, 55, \%names, 1);

    # print "Studnum:$studnum Level:3  A1:$avg1  C2:$count2 C3:$count3<br>\n";

    if ( $avg1 >= 60 and $count2 >= 2 and $count3 >= 6 and not $failcount ) {
	# print "Level 3 Return<br><br>\n";
	return $r_GCDisplay{3};
    }


    # Level 4 - Pass 
    $avg1 = calcTopAverage( $studnum, $term );
    $count2 = calcTopCount( $studnum, $term, 55,\%dud,1 );

    # print "Studnum:$studnum Level:4 (Pass)  A1:$avg1  C2:$count2<br>\n";
    if ( $avg1 >= 55 and $count2 >= 5 and not $failcount ) {
	# print "Level 4 (Pass) Return<br><br>\n";
	return $r_GCDisplay{4};
    }

    
    # Fail
    return $r_GCDisplay{5};
=cut


} # end of calcGradeCategory



#-----------------
sub calcTopAverage { # Find Averages for GradeCategory Results
#-----------------
    
    my ( $studnum, $term, $subjnum, $name_ref ) = @_; 
    # student number, term, number of subject to avg, names of subj to include in avg (hash ref)


    my $sth = $dbh->prepare("select $r_MarkField, subjcode from eval 
      where studnum = ? and term = ? order by $r_MarkField desc");
    $sth->execute( $studnum, $term );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }

    my $sth1= $dbh->prepare("select description from subject where subjsec = ?");
    
    my ($subjcount, $marktotal );
    my (%marks, %found );

    while ( my ( $mark, $subjcode ) = $sth->fetchrow ) {

	# skip if member of %r_SupressSubject or AdditionalComments
	my ($tsubjcode, $dud) = split('-', $subjcode ); 
	if ( $r_SupressSubject{$tsubjcode} or $r_SupressSubject{$subjcode} or
	     $r_AdditionalComments{$tsubjcode} or $r_AdditionalComments{$subjcode} ) {

	    next; 
	}


	# Get course description.
	$sth1->execute( $subjcode );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $description = $sth1->fetchrow;

	if ( not defined $mark ) { # NULL value in table
	    print "$lex{Skipping}: $lex{'Undefined Value'}";
	    print " $description ($subjcode) - $studnum<br>\n";
	    next;
	}

	if ( $name_ref ) { # we have names to store and check against.
	    $marks{ $subjcode } = $mark; # store mark in hash.
	    foreach my $name ( keys  %{ $name_ref } ) {
		if ( $description =~ m/($name)/ ) { # subject match

		    $found{ $subjcode } = $mark;
		    delete $$name_ref{ $name };
		    last;
		}
	    }
	}

	$mark =~ s/\s+//g; # strip any spaces.
	if ( $mark =~ m/[^.0-9]/ or not $mark ) { # non-numeric mark or no value
	    print qq{$lex{Skipping}: $mark - $description ($subjcode) - $studnum<br>\n};
	    next;
	}

	$marktotal += $mark;
	$subjcount++;
	if ( not $name_ref and $subjcount == $subjnum ) { # no names and enough subjects
	    my $average;
	    if ( $subjcount ) { # not zero.
		$average = $marktotal / $subjcount;
		return $average;
	    } else {
		return undef;
	    }
	}
    } # end of data retrieval loop.

    # just find overall average for this term.
    if ( not defined $subjnum or $subjcount < $subjnum ) { 
	if ( $subjcount ) {
	    my $average = $marktotal / $subjcount;
	    return $average;

	} else {
	    return undef;
	}
    }


    # else here.... we should have some names, etc.
    # check %found and if anything left in %$name_ref
    $marktotal = 0;
    $subjcount = 0;
    $subjnum -= $subjcount = keys %found; #
    foreach my $subjsec ( keys %found ) {
	delete $marks{$subjsec}; # don't want to count twice.
	$marktotal += $found{ $subjsec };
    }

    my $count;
    foreach my $subjsec ( sort { $marks{$b} <=> $marks{$a} } keys %marks ) {
	$marktotal += $marks{ $subjsec };
	$subjcount++;
	$count++;
	if ( $count == $subjnum ) { last; }
    }

    my $average;
    if ( $subjcount ) {
	$average = $marktotal / $subjcount;
	return $average;
    } else { 
	return undef;
    }

} # end of calcTopAverage



#---------------
sub calcTopCount { # Find Count of subjects above certain value, including subject names;
#---------------
    
    # returned:  number of subjects above (or >= based on $eqmode ) mark limit, must include subject names.
    # EQMODE is new

    my ( $studnum, $term, $marklimit ,$name_ref, $eqmode ) = @_; 
    # student number, term, lower mark limit, names of subj to include
    # in $subjcount returned.

    # subjects that are required to be in this group.
    my %subjects = %$name_ref;


    my $sth = $dbh->prepare("select $r_MarkField, subjcode from eval 
      where studnum = ? and term = ? order by $r_MarkField desc");
    $sth->execute( $studnum, $term );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }


    my $sth1= $dbh->prepare("select description from subject where subjsec = ?");
    my $subjcount;

    while ( my ( $mark, $subjcode ) = $sth->fetchrow ) {

	# skip if member of %r_SupressSubject or AdditionalComments
	my ($tsubjcode, $dud) = split(/-/, $subjcode ); 
	if ( $r_SupressSubject{$tsubjcode} or $r_SupressSubject{$subjcode} or
	     $r_AdditionalComments{$tsubjcode} or $r_AdditionalComments{$subjcode} ) {

	    next; 
	}

	# Get subject description for skipping.
	$sth1->execute( $subjcode );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $description = $sth1->fetchrow;

	# skip NULL value in table
	if ( not defined $mark ) { 
	    print "$lex{Skipping}: $lex{'Undefined Value'}";
	    print " $description ($subjcode) - $studnum<br>\n";
	    next;
	}

	# skip non-numeric mark
	if ( $mark =~ m/[^.0-9]/ ) { 
	    print $lex{Skipping}. ": $mark - $description ($subjcode) - $studnum<br>\n";
	    next;
	}

	# Check if a certain subject
	if ( %subjects ) { # we have names to store and check against.
	    foreach my $name ( keys  %subjects ) {
		if ( $description =~ m/($name)/ ) { # subject match
		    if ( $eqmode ) { # >= mode
			if ( $mark >= $marklimit ) {
			    $subjects{$name} = 0; # set to zero, from 1.
			}
		    } else { # > mode
			if ( $mark > $marklimit ) {
			    $subjects{$name} = 0; # set to zero, from 1.
			} 
		    }

		} # end if subject match
	    } # name loop
	}


        if ( $eqmode ) { # >= mode
	    if ( $mark >= $marklimit ) {
		$subjcount++;
	    }
	} else { # > mode
	    if ( $mark > $marklimit ) {
		$subjcount++; 
	    } 
	}

	# print "SN:$studnum SUB:$subjcode Mark: $mark  Count:$subjcount<br>\n";

    } # end of data retrieval loop.

    # check to make sure %subjects all zeroed out (ie. matched)
    foreach my $key ( keys %subjects ) {
	if ( $subjects{$key} ) {
	    return 0;
	}
    }

    return $subjcount;

} # end of calcTopCount



#----------
sub calcGPA {
#----------

    my $gpa_ref = shift;
    my $maxterm = shift;

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


    # Get credit value for each subject. # removed difficulty
    my $sth = $dbh->prepare("select credit from subject where subjsec = ?");

    # Start TeX head
    print TEX "\\begin{tabular}{|p{$r_SubjSpace}|";
    for ( 1..$maxterm ){ print TEX "p{$r_MarkSpace}|";}

    print TEX "}\\hline\n";
    print TEX "\\rowcolor[gray]{ $r_GrayScale }";
    print TEX "\\bf $lex{Term} $lex{GPA}";

    my ($totalGPQuality, $totalGPCredits); # needed for overall at end.

    # Loop through each term calculating the GPA for each term...
    foreach my $term ( 1..$maxterm )  { #loop through all terms

	my ( $termCreditTotal, $termGPTotal );
	my ( $termCredits, $termAttempts ); # not used, yet. TermCredits includes P/F courses.
	my ( $termGPCredits, $termGPQuality );

	foreach my $subjsec ( keys %{$gpa_ref} ) {

	    if ( defined $gpa_ref->{$subjsec}[$term] ) {  # If we have a value for this term..

		my $mark = $gpa_ref->{$subjsec}[$term]; # could be letter or number...

		# Get Subject Data
		$sth->execute( $subjsec );
		if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; };
		my $credit = $sth->fetchrow;
		$credit = 1 if not $credit;
		# if ( not $difficulty ) { $difficulty = 0; }

		# Convert the mark to a letter (and then to a quality score below...
		my $letter; # letter grade.
		if ( $mark =~ /[a-zA-Z]/ ) { # We have a 'letter' mark, copy into $letter 
		    $letter = $mark;
		} else { # find the matching letter for this numeric value..
		    foreach my $threshold (reverse sort keys %markToLetter ) { # large to small
			if ($mark >= $threshold) {
			    $letter = $markToLetter{$threshold};
			    # print "Mark: $mark Letter: $letter<br>\n";
			    last;
			}
		    }
		}

		# Now convert $letter to a quality score.
		# letterToQual hash in transcript.conf; add up quality scores and credit counts.
		# Check for missing Quality value in transcript.conf
		if ( ( not defined $letterToQual{ $letter } ) and 
		     ( $letter ne $passletter ) ) { 
		    print "<br>$lex{'No Quality Score'}: $letter\n";
		    next; # skip to next subject. 
		}

		# Update Attempts
		$termAttempts += $credit;

		# Now do Pass Letter settings.
		if ( $letter eq $passletter ) {
		    $termCredits += $credit;
		    $totalCredits += $credit;

		} elsif ( $letter eq $failletter ) {
		    # No additions to credits, GP credits increase to bring down avg.
		    $totalGPCredits += $credit;
		    $termGPCredits += $credit;

		} else { # calculate passing grade settings.

		    my $quality = $letterToQual{ $letter };
		    # difficulty removed
		    # if ( $quality ) { $quality += $difficulty; } # if non-zero add on difficulty factor.

		    # Update Quality scores for weighted average.
		    $termGPQuality += $quality * $credit;
		    $totalGPQuality += $quality * $credit;

		    # Update GP Credit totals for weighted average.
		    $totalGPCredits += $credit;
		    $termGPCredits += $credit;

		    # Update the credits
		    $termCredits += $credit;
		    $totalCredits += $credit;

		}

		# print "$subjsec $term ". $gpa_ref->{$subjsec}[$term]. "<br>\n";
		
	    } # End of If mark exists
	} # End of Subject Loop for this term.

	my $gpa;
	if ($termGPCredits) {
	    $gpa = format_number( ($termGPQuality / $termGPCredits ), $r_AveragePrecision );
	} 
	else { $gpa = 0; }

	print TEX "&\\hfil $gpa \\hfil "; # change to GPA value...
    
    } # End of terms loop


    my $cumgpa;
    if ($totalGPCredits) {
	$cumgpa = format_number( ($totalGPQuality / $totalGPCredits), $r_AveragePrecision );
    }
    else { $cumgpa = 0; }

    print TEX "\\\\ \\hline\n";
    print TEX "\\hfil\\bf ". $lex{'Current Year GPA'}. " $cumgpa \\hfil ";
    for ( 1..$maxterm ){ print TEX "& ";}

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


} # end of calcGPA


#---------------
sub calcTermDays {
#---------------

    # passed a start date and an end date for a term, and a ref to a
    # hash storing the closure dates in julian day format, it will
    # return a count of the days open in the month.

    # outline: convert start/end dates to jd. Loop over all days. Use modulus function to ident weekend days.

    my ($startdate, $enddate, $closeref ) = @_;
    my %jdclosed = %$closeref;

=head
    print qq{JDClosed<br>\n";
    foreach my $key ( sort keys %jdclosed ) {
	print qq{K:$key V:$jdclosed{$key}<br>\n";
    }
    print qq{End JDClosed<br>\n";
=cut

    my $startjd = julian_day(split('-',$startdate));
    my $endjd = julian_day(split('-',$enddate));

    my %modclosed; # modulus for days closed
    foreach my $inc ( 0..6 ) {
	my $testjd = $startjd + $inc;
	my $dow = day_of_week($testjd);
	if ( $dowclosed{$dow} ) { # $testjd is a closed dow
	    my $mod = $testjd % 7;
	    $modclosed{$mod} = 1;
	}
    }

#    foreach my $d ( sort keys %modclosed ) {
#	print qq{Closed Mod: $d<br>\n";
#    }

    my ($daysopen, $daysclosed);
    foreach my $jd ( $startjd..$endjd ) {

	my $dow = day_of_week( $jd );
	my $mod = $jd % 7;

	if ( $modclosed{$mod} ) { # closed for weekend
	    next;
	}

	# check if a day closed
	my $cl = $jdclosed{ $jd };
	if ( $cl  ) { # this gives us the fraction closed
	    $daysclosed += $cl;
	    # only add on the fraction of day open
	    $daysopen += (1 - $cl );
#	    print qq{<br>INSIDE<br>\n";
	} else {
	    $daysopen += 1;
	}
#	print qq{JD:$jd Count:$daycount<br>\n";

    }

    # print qq{ST:$startdate END:$enddate  Count:$daycount<br>\n";

    return "$daysopen:$daysclosed";

}


=head
#-----------------
sub calcAttendance {
#-----------------
    my ( $studnum, $startdate, $enddate, $periodsperday ) = @_;
    my $sth = $dbh->prepare("select * from attend 
     where studentid = ? and 
     to_days(absdate) >= to_days('$startdate') and 
     to_days(absdate) <= to_days('$enddate') 
     order by absdate,period");
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    $sth->execute( $studnum );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }

    my $absent = 0; my $late = 0;
    while ( my @absence = $sth->fetchrow ) {
	if ( $absence[3] =~ /$lex{Absent}/) { $absent++; }
	if ( $absence[3] =~ /$lex{Late}/) { $late++; }
    }
    if ( $periodsperday ) {
	$absent = $absent / $periodsperday; #convert periods into days
    }
    return "$absent:$late";
}
=cut


#------------ 
sub prTexHead {  # Print the head of each new report card 
#------------

    # globals: schoolname, $schoolyear
    my ($grade, $lastname, $firstname, $middlename, $birthdate, $provnum, $studnum ) = @_;

    print TEX "\\thispagestyle{empty}\n\\setcounter{page}{1}\n";

    print TEX "\\rhead{$firstname $middlename $lastname -- \\thepage}\n\\begin{center}\n";

    if ( $r_ShowLogo ) {
	if ( not $r_LogoFile and $r_logoFile ) { $r_LogoFile = $r_logoFile; }
	print TEX "\\includegraphics[width=$r_LogoWidth]{";
	print TEX "$configpath/etc/$r_LogoFile}\\quad \n";
	print TEX "\\parbox[b]{$r_SchoolAddressWidth}{\\begin{center}{";
	print TEX "\\Large\\bf $schoolname}\\\\";
	if ( $schooladdr1 ) {
	    print TEX "$schooladdr1\\\\ \n";
	}
	if ( $schoolcity or $schoolprov ) {
	    print TEX "$schoolcity, $schoolprov $schoolpcode\\\\ \n";
	}

	# Phone / Fax Line
	if ( $schoolphone and $schoolfax ) {  # use an hfill
	    print TEX qq{$lex{Phone} $schoolphone \\hfill $lex{Fax} $schoolfax};
#	    if ( $r_ShowAdmins ) { print TEX "\\hfill ";}
#	    else { print TEX "\\qquad "; }
	} elsif ( $schoolphone ) {
	    print TEX "$lex{Phone} $schoolphone ";
	} elsif ( $schoolfax ) {
	    print TEX $lex{Fax}. " $schoolfax";
	}
	if ( $schoolphone or $schoolfax ) {
	    print TEX "\\\\\n\n";
	}
	# Note:\quad is eM horizontal width, \qquad is eMM's width. 
	
	# Administrator Lines
	if ( $r_ShowAdmins ) {
	    print TEX "$r_Principal \\hfill  $r_VicePrincipal \\\\\n\n";
	    print TEX "{\\footnotesize $lex{Principal} \\hfill ";
	    if ( $r_VicePrincipal ) { print TEX $lex{'Vice-Principal'}; }
	    print TEX "}\\\\\n\n";
	}

	print TEX "\\vspace{$r_AddressSpacer}\n\n";
	print TEX " \\end{center}}\\qquad\n";  # note extra parens to close parbox.


	if ( $r_ShowStudentPicture ) { # verify that file exists
	    my $fpath = $configpath. '/admin/pic-big/'. $studnum. '.jpg';
	    if ( not -e $fpath ) {
		print qq{<h3>$lex{Picture} $lex{'Not Found'}: $firstname $lastname ($studnum)</h3>\n};
		
	    } else { # show the picture
		print TEX "\\includegraphics[width=$r_StudentPictureWidth]{";
		print TEX "$configpath/admin/pic-big/$studnum.jpg}\\\\\n";
	    }
	}
	
	if ( $r_DivLogoFile ) {
	    print TEX "\\includegraphics[width=$r_DivLogoWidth]{";
	    print TEX "$configpath/etc/$r_DivLogoFile}\\\\\n";
	}

    } else {
	print TEX "\n{\\sf\\Huge $schoolname}\n\n";
    }

    print TEX "\n\\smallskip\n{\\sf\\Large ";

    my $displaygrade = $grade;
    if ( $schoolmode == 1 ) { # British mode
	my $val = $g_FormMap{$grade};
	if ( not $val ) { $val = $grade; }
	if ( $val =~ m/F|f/ ) { # we are adding form.
	    $val =~ s/F|f/$lex{Form} /;
	} else { # put in grade text.
	    $val = "$lex{Grade} $val";
	}
	$displaygrade = $val;
	
    } else { # normal mode
	$displaygrade = qq{$lex{Grade} $displaygrade};
    }

	
    print TEX " $displaygrade ". $lex{'Report to Parents'};
    print TEX "}\n\n $currdate\n";
    print TEX "\n\\medskip\n{\\sf\\Large\\it $firstname $middlename $lastname} ";
    if ( $r_ShowProvNum and $provnum ) {
	print TEX "{\\sf($provnum)}";
    }
    print TEX "\n\n";


    print TEX "{\\sf ($birthdate)}\n\\smallskip\n\n";
    print TEX "\\end{center}\n";


} # End of prTexHead


#---------------------
sub prHomeroomTeachers {
#---------------------

    my $homeroom = shift;
    my @teachers = @_;
    print TEX "\\begin{center}\n";
    print TEX "\\setlength{\\extrarowheight}{0pt}\n";
    print TEX "\\begin{tabular}{ll}\n{\\small\\bf  ";
    print TEX "$lex{Homeroom} $homeroom $lex{'Teacher(s)'} }";
    foreach my $teach ( @teachers ){
	print TEX "& {\\it $teach} \\\\ \n";
    }
    print TEX "\\end{tabular}\n\\setlength{\\extrarowheight}{4pt}\n";
    print TEX "\\end{center}\n\n";

} # End of prHomeroomTeachers



#---------------------
sub print_grade_scheme {
#---------------------

    my $grade = shift;

    # Set Grading Scheme choice ( 'a', 'b', etc.)
    my $scheme = $r_EvalSch{$grade}; # is letter a,b,c, etc. from repcard configuration
    my $schemeAlt1 = $r_EvalSchAlt1{$grade};
    my $first;

    if ( $r_CenterSubjects ) {
	print TEX "\\begin{center}\n";
    }

    if ( @{$r_Eval{$scheme}} ) {

	# set width of section.
	my $width = $textwidth;
	$width =~ s/mm//; # strip 'mm'.
	$width -= 30;

	my $col1 = 10;
	my $col2 = $width - $col1; # rest of width;

	print TEX "\\begin{tabular}{|p{$col1 mm}|p{$col2 mm}|}\\hline\n";
	print TEX "\\multicolumn{2}{|c|}{\\sf\\large\\bf ". $lex{'Evaluation and Comment Key'};
	print TEX " }\\\\ \\hline\n";

	for my $item ( @{ $r_Eval{$scheme} } ){
	    ( $item ) = latex_filter( $item );
	    my ($itema, $itemb ) = split(/::/, $item);
	    if ( not $itemb ) { # no double colons::
		print TEX "\\multicolumn{2}{|p{$width mm}|}{$itema}\\\\ \\hline\n";
#		print TEX "\\multicolumn{2}{|l|}{$itema}\\\\ \\hline\n";
	    } else {
		print TEX "$itema &$itemb\\\\ \\hline\n";
	    }
	}
	print TEX "\\end{tabular}\n\\medskip\n\n";


#	$first = 1;
#	print TEX "\\begin{center}{\\sf\\Large ";
#	print TEX $lex{'Evaluation and Comment Key'}. "}\n\n";
#	print TEX "\\parbox[b]{$r_AssessKeyWidth}";
#	print TEX "{\\begin{multicols}{$r_AssessKeyCols}\n";

#	for my $item ( @{$r_Eval{$scheme}} ){
#	    if (not $first){ 
#		print TEX "\\\\\n";
#	    } else { 
#		$first = 0;
#	    }
#	    print TEX $item;
#	}
#	print TEX "\\end{multicols}}\n"; # Note parbox ending.
#	print TEX "\\end{center}\n";

    }


    # Now print Alt1 Eval keys, if any.
    if ( @{$r_EvalAlt1{$schemeAlt1}} ) { # assume we have something

	# set width of section.
	my $width = $textwidth;
	$width =~ s/mm//; # strip 'mm'.
	$width -= 30;
	
	my $col1 = 10;
	my $col2 = $width - $col1; # rest of width;

	print TEX "\\begin{tabular}{|p{$col1 mm}|p{$col2 mm}|}\\hline\n";
	print TEX "\\multicolumn{2}{|c|}{\\sf\\large\\bf $r_EvalAlt1Title ";
	print TEX " }\\\\ \\hline\n";

	for my $item ( @{ $r_EvalAlt1{$schemeAlt1} } ){
	    ( $item ) = latex_filter( $item );
	    my ($itema, $itemb ) = split(/::/, $item);
	    if ( not $itemb ) { # no double colons::
		print TEX "\\multicolumn{2}{|p{$width mm}|}{$itema}\\\\ \\hline\n";
#		print TEX "\\multicolumn{2}{|l|}{$itema}\\\\ \\hline\n";
	    } else {
		print TEX "$itema &$itemb\\\\ \\hline\n";
	    }
	}
	print TEX "\\end{tabular}\n\\medskip\n\n";


#	$first = 1;
#	print TEX "\\begin{center}{\\sf\\Large ";
#	print TEX $r_EvalAlt1Title. "}\n\n";
#	print TEX "\\parbox[b]{$r_AssessKeyWidth}";
#	print TEX "{\\begin{multicols}{$r_AssessKeyCols}\n";

#	for my $item ( @{$r_EvalAlt1{$schemeAlt1}} ) {
#	    if ( not $first ){
#		print TEX "\\\\\n";
#	    } else { 
#		$first = 0;
#	    }
#	    print TEX $item;
#	}
#	print TEX "\\end{multicols}}\n"; # Note parbox ending.
#	print TEX "\\end{center}\n";
 
   }

    if ( $r_CenterSubjects ) {
	print TEX "\\end{center}\n";
    }

} # end of print grade scheme



#------------
sub prCourse { # Print Course Results
#------------

    # @eval array set with current subjsec, and refs...
    # $startterm, and $endterm are starting and ending term for the report card display. 
    # This will be modified by $r_TermDisplayLeading and $r_TermDisplayTrailing values;
    my ( $subjsec, $studnum, $currterm, $startterm, $endterm, $evalref )  = @_;
    my @eval = @{ $evalref };
    

    # Get info for this course; 
    my $sth = $dbh->prepare("select description, teacher, startrptperiod, endrptperiod, calcavg,
     grade from subject where subjsec = ?");
    $sth->execute( $subjsec );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    my ( $description, $teacher, $startterm, $endterm, $calcavg, $subjgrade ) = $sth->fetchrow;

#    $desc = decode('UTF-8',$description);
#    print "NEWDESC:$description - $subjsec // Converted:$desc<br>\n";
#    if ( $description =~ m/Cree/ ){
#	exit;
#    }

    if ( $calcavg eq 'N' ) { $calcavg = 0; } #

    # Set the Track for this course based on it's grade
    my $track = $g_MTrackTermType{ $subjgrade };

    
    # Set Personal Growth Flag before latex filtering/escaping.
    my $personal_growth_flag; # flag for printing keys to personal growth evals
    if ( $description eq $r_Personal_Growth ) {
	$personal_growth_flag = 1;
    } else {
	$personal_growth_flag = 0;
    }

    # LaTeX filter subject fields
    ( $description, $teacher ) = latex_filter( $description, $teacher );

    # calculate the average mark
    my $averagemark;

    if ( $calcavg ) {
	my ( $totalscore, $totalweight );
	my @tempeval = @eval; # in order to remove first column (objectives)
	shift @tempeval;

	foreach my $evalref ( @tempeval ) {
	    my $term = $evalref->[0];
	    my $score = $evalref->[1];
	    $score =~ s/[A-Za-z]//g; # strip any non digits. Leave decimals intact.
	    if ( not defined $score ) {
		print qq{<div>No Score for $subjsec Term $term Student $studnum. Skipping</div>\n};
		next;
	    }

	    # Make sure hash %r_AverageWeight is defined for this term.
	    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;
	    }

#	    print qq{Term $term Score $score<br>\n};
	    my $wt = $r_AverageWeight{$term}; # The weight for this term of course
	    $totalscore += ( $wt * $score );
	    $totalweight += $wt;

	}

	if ( $totalweight ) {
	    $averagemark = $totalscore / $totalweight;
	} else {
	    $averagemark = 0;
	}
	$averagemark = format_number( $averagemark, $r_AveragePrecision, $r_AveragePrecision);
    }


    # Check if we should add the Personal Growth Key...
    if ( $personal_growth_flag ) {  # print row with objectives...

	# Figure out width of section.
	my $width = $textwidth;
	$width =~ s/mm//; # strip 'mm'.
	$width -= 30;

	$col1 = 10;
	$col2 = $width - $col1; # rest of width;

	print TEX "\\begin{tabular}{|p{$col1 mm}|p{$col2 mm}|}\\hline\n";

	my $key = $r_PDEvalGrp{$subjgrade};

	if ( @{ $r_PDEval{$key} } ) { # if we have a non blank objective group...
	    print TEX "\\multicolumn{2}{|c|}{\\sf\\large\\bf $description ";
	    print TEX $lex{'Evaluation Key'}. " }\\\\ \\hline\n";
	}
	for my $item ( @{ $r_PDEval{$key} } ){
	    ( $item ) = latex_filter( $item );
	    my ($itema, $itemb ) = split(/::/, $item);
	    print TEX "$itema &$itemb\\\\ \\hline\n";
	}
	print TEX "\\end{tabular}\\medskip\n\n";

    }

# Print Out Eval Table for viewing -------
#    print qq{Original Eval: $subjsec};
#    print qq{<table border="1" cellspacing="0" cellpadding="3">};
#
#    foreach my $idx ( 0.. $#eval ) {
#	print "<tr><td>$idx - $eval[$idx]</td>";
#	foreach my $val ( @{ $eval[$idx] } ) {
#	    print "<td>$val</td>\n";
#	}
#	print "</tr>\n";
#    }
#    print "</table>\n";
#--------


    print TEX "\\begin{tabular}{|p{$r_SubjSpace}|";
    foreach my $ref ( @eval ) {  print TEX "p{$r_MarkSpace}|"; }
    if ( $calcavg ){ print TEX "p{$r_MarkSpace}|"; }
    print TEX "}\\hline\n";


    # pull off first column of objectives
    my @objectives = @{ shift @eval };
    shift @objectives; # remove top blank one.
    @objectives = latex_filter( @objectives );


    # Get Teacher Information
    my $sth = $dbh->prepare("select sal, firstname, lastname 
      from staff where userid = ? ");
    $sth->execute( $teacher );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    my ($sal, $firstname, $lastname) = $sth->fetchrow;
    my $subjectteacher;
    if ( $lastname ) { 
	if ( $sal ) {
	    $subjectteacher = " ($sal $lastname)"; 
	} else { # fall back to using first name
	    $subjectteacher = " ($firstname $lastname)"; 
	}
    }


    # Print Term Line with Subject name, Teacher and term numbers.
    print TEX "\\rowcolor[gray]{ $r_GrayScale }";
    print TEX "{\\sf\\large\\bf $description}";
    if ( length( $description ) > $r_DescMaxLength ) { print TEX "\n\n"; }
    print TEX "$subjectteacher";

    foreach my $ref ( @eval ) {
	my $title = $ref->[0]; # top of column 
	if ( $g_TermDisplay{$track}{ $title } ) { # if defined, reset
	    $title = $g_TermDisplay{$track}{ $title };
	}
	print TEX "& \\hfil $title \\hfil"; 
    }


    if ( $calcavg ){ print TEX "& \\hfil ". $lex{Average}. " \\hfil"; }
    print TEX "\\\\ \\hline\n";


    # LaTeX filter characters in @eval 2D array.
    foreach my $ref ( @eval ) {
	@{$ref} = latex_filter( @{$ref} );
    }


    my ($absents, $lates) = split(':', calcSubjectAttendance( $subjsec, $studnum ));
    
    
    my $objcount = 1;
    foreach my $objective ( @objectives ) {

	# Skip showing 'Mark' objective and show attendance
	if ( $r_ShowSubjectAttendance{$subjgrade} and $objcount == 1 ) { # only on line 1

	    print TEX qq{$lex{Periods} $lex{Absent} $absents $lex{Late} $lates};
	    if ( $objective ne $lex{Mark} ) { # print rest of line blank
		foreach my $ref ( @eval ) { print TEX "& "; }
		if ( $calcavg ) { print TEX "& "; }
		print TEX "\\\\ \\hline\n\n";
		print TEX $objective;
	    }

    	} else { # print objective
	    print TEX $objective;
	}

	# Print Rest of Line
	foreach my $ref ( @eval ) {
	    print TEX "& \\hfil $ref->[$objcount]\\hfil";
	}
	if ( $calcavg and $objcount == 1 ){ # only print average for first.
	    print TEX "& \\hfil $averagemark \\hfil";
	} elsif ( $calcavg ) { 
	    print TEX "& ";
	}
	print TEX "\\\\ \\hline\n\n";

	$objcount++;

    }

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


} # End of prCourse



#------------
sub prComment { # print all the comments.
#------------

    my ( $subjsec, $studnum, $startterm, $endterm ) = @_;
    
    # startterm since we use values from the subject table instead. We
    # use endterm in case not yet at end of the course.
    
    # print "Comment:$subjsec - $studnum - Start:$startterm END:$endterm<br>\n";

    
    print TEX "\n\\smallskip\n\n"; # small space
    if ( $r_ClassAvg and $classavg{$subjsec} ){ 
	print TEX "{\\bf ". $lex{'Class Average'}. ":} $classavg{$subjsec}\n\n";
    }

    # Load comments, if any.
    my %comments;
    my $sth = $dbh->prepare("select comment, term from eval where studnum = ?
      and subjcode = ? order by term"); 
    $sth->execute( $studnum, $subjsec );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my ($comment, $term ) = $sth->fetchrow ) {
	if ( $term >= $startterm and $term <= $endterm ) {
	    $comments{$term} = $comment;
	}
    }
    if ( not %comments ) { return; }

    my $sth = $dbh->prepare("select calcavg, grade, startrptperiod, endrptperiod from 
			    subject where subjsec = ?");
    $sth->execute( $subjsec );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    my ($calcavg,$subjgrade, $start, $end) = $sth->fetchrow;
    # note 'start','end' terms are set in subject table (courses), not passed
    if ( $calcavg eq 'N' ) { $calcavg = 0; }

    my $track = $g_MTrackTermType{ $subjgrade };

    # Figure out Comment Width; assume 6pt tabcolsep (2.12mm); first 2 is subject cell
    my $subjspace  = $r_SubjSpace;
    $subjspace =~ s/mm//; # strip 'mm';
    my $markspace  = $r_MarkSpace;
    $markspace =~ s/mm//; # strip 'mm';

    if ( $endterm < $end ) { # not at end of course term.
	$end = $endterm;
    }

    
    # my $termcount = $endterm - $startterm + 1;
    my $termcount = $end - $start + 1; # now using values from the subject table (ie. course)
    if ( $termcount < 1 ) { $termcount = 1; }
    
    my $width;
    if ( $r_CommentWidth eq 'termwidth' ) {
	$width = $subjspace + ($termcount * $markspace) + ( 2 + 2 * $termcount ) * 2.1;
	if ( $calcavg ){ $width = $width + $markspace;}
	
    } elsif ( $r_CommentWidth eq 'pagewidth' ) {
	$width = $textwidth; # Set on line 1450; part of prTextDocStart
	$width =~ s/mm|\s+//g; # strip trailing 'mm' text.
	
    } elsif ( $r_CommentWidth =~ m/\d+/ ) { # must be digits
	$width = $r_CommentWidth;
	$width =~ s/\D+//g; # strip any non digits, just in case it has 'mm'.
	
    } else {
	print qq{<h3>Error setting comment width with: $r_CommentWidth</h3>\n};
	print qq{</body></html>\n};
	exit;
    }

#    print TEX "\n\\parbox{$width mm}{\n"; # moved below in case of big comments

    foreach my $term ( sort keys %comments ) {
	if ( not $comments{$term} ) { next; }
	print TEX "\n\\parbox{$width mm}{"; # start parbox.
	my $title = $g_TermDisplay{$track}{$term};

	my ($comment) = latex_filter ( $comments{$term} );
	$comment =~ s/\s*[\n|\r]/ /g;
	print TEX "\n{\\bf $title:} {\\it $comment }\n}\n"; # second parenthesis ends parbox.
    }

#    print TEX "\n}\\smallskip\n\n"; # Note: brace ends parbox.
    print TEX "\\smallskip\n\n"; # removed ending of parbox.

    print TEX "\n\\medskip\n\n";

} # End of prComment



#----------------------
sub prMonthlyAttendance {  # Version with monthly attendance info
#----------------------

    my $studnum = shift;
 
    # Needs globals:
    #  %schooldays - days in each month in hash.
    #  $periodsperday - number of periods in the school day.

    foreach my $yrmo ( sort keys %schooldays ) {
	if ( $schooldays{$yrmo} == 0 ) {
	    delete $schooldays{$yrmo};
	}
#	print qq{<div>MO:$yrmo VAL:$schooldays{$yrmo}</div>\n};
    }

    # calculate attendance, one for each month.
    foreach my $yrmo ( sort keys %schooldays ) {
	my $absrec = calcMonthlyAttendance($studnum, $yrmo, $periodsperday, $currsdate, \%lex, $dbh );
#	print "$studnum YRMO:$yrmo REC:$absrec<br>\n";
	( $absent{$yrmo}, $tardy{$yrmo} ) = split(':',$absrec);
    }


    # calculate enrollment, one for each month
    my $ymref = calcMonthlyEnrollment( $studnum, $schoolstart, $currsdate, $dbh, $nsdhomeroom );
    my %ymenrol = %$ymref;  # yyyy-mm -> start,end,days


    # Print Start of Attendance Table
     print TEX "\\begin{center}\n";

    # Setup Table
    print TEX "\\medskip\n\\begin{tabular}{|p{32mm}|\n";
    foreach my $mo ( sort keys %schooldays ) { # $mo not used
	print TEX "p{9mm}|";
    }
    print TEX "}\n";


    # Print Heading Line
    my $colcount = scalar (keys %schooldays ) + 1;
    print TEX " \\multicolumn{$colcount}{\@{}c}{\\rule{0pt}{12pt} ";
    print TEX "\\sf\\bf\\Large ". $lex{Attendance}. "}\n\n";
    print TEX "\\\\\\hline\n";


    # Print Months Line
    print TEX "\\rowcolor[gray]{ $r_GrayScale }\n";
    foreach my $mo ( sort keys %schooldays ) {
	my ($yr,$mn) = split(/-/, $mo );
	print TEX "& \\hfil $s_month[$mn] \\hfil \n";
    }
    print TEX "\\\\\\hline\n";


    # Print Days Open
    print TEX "{\\large\\bf ". $lex{'Days Open'}. "}\n";
    foreach my $yrmon ( sort keys %schooldays ) {
	print TEX "& \\hfil $schooldays{$yrmon} \\hfil \n";
    }
    print TEX "\\\\\\hline\n";


    # Print Days Enrolled
    print TEX "{\\large\\bf ". $lex{'Days Enrolled'}. "}\n";
    foreach my $yrmo ( sort keys %schooldays ){

	if ( $override ) {
	    my $do = $schooldaysorig{ $yrmo }; # Days Open
	    my $ado = $schooldays{ $yrmo };  # Adjusted Days Open

	    my $de = $ymenrol{$yrmo}{'days'};  # Days Enrolled.
	    #print "<br>SCHOOL DAYS:",%schooldaysorig,"<br>\n";
	    #print "$student[1] $student[2] DO: $do  ADO: $ado DE: $de<br>\n";

	    my $ade; # adjusted days enrolled
	    if ( $do ) {
		$ade = format_number( ($de * $ado / $do), 2, 0);
	    } else {
		$ade = 0;
	    }

	    print TEX "& \\hfil $ade \\hfil \n";

	} else {
	    print TEX "& \\hfil $ymenrol{$yrmo}{'days'} \\hfil \n"; 
	}
    }
    print TEX "\\\\\\hline\n";


    # Print Days Absent
    print TEX "{\\large\\bf ". $lex{'Days Absent'}. "}\n";
    foreach my $yrmo ( sort keys %schooldays ){
	my $abs = format_number( $absent{$yrmo}, 2, 0);
	print TEX "& \\hfil $abs \\hfil\n"; 
    }
    print TEX "\\\\ \\hline\n";


    # Print Periods Late
    print TEX "{\\sf\\large\\bf $lex{Periods} $lex{Late} }\n";
    foreach my $yrmo ( sort keys %schooldays ){ 
	print TEX "& \\hfil $tardy{ $yrmo } \\hfil\n"; 
    }
    print TEX "\\\\ \\hline\n";


    # Finish Attendance Box
    print TEX "\\end{tabular}\n";
    print TEX "\\end{center}\n"; 
    print TEX "\\bigskip\n";

}



#----------------
sub prAddComments {
#----------------

    my ( $studnum, $startterm, $endterm ) = @_;

    # Updated to show additional comment data for each student.
    # $r_AdditionalComments{$tsubjcode} or $r_AdditionalComments{$subjcode} ) {
    # Get student information for this student for this term.

    # Get the student grade, and then the track for this grade (rather than subject based)
    my $sth = $dbh->prepare("select grade from studentall where studnum = ?");
    $sth->execute(  $studnum );
    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;}
    my $grade = $sth->fetchrow;
    my $track = $g_MTrackTermType{ $grade };


    $sth = $dbh->prepare("select count(*) from eval where subjcode = ? and studnum = ?");
    my $sth1 = $dbh->prepare("select subjcode from eval where subjcode like ? and studnum = ?");

    my @subjcodes; # codes for this student

    # Loop through subjects looking for records for this student.
    foreach my $subj ( keys %r_AdditionalComments ) {

	if ( $subj =~ m/-/ ) { # has dash, thus subjsec
	    $sth->execute( $subj, $studnum );
	    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;}
	    my $count = $sth->fetchrow;
	    if ( $count > 0 ) { # we have records
		push @subjcodes, $subj;
		next;
	    }

	} else { # no dash, a subject code, use 'like' match

	    $subj = $subj. '-%';
	    $sth1->execute( $subj, $studnum );
	    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;}
	    $subjcode = $sth1->fetchrow;
	    if ( $subjcode ) { # we have records
		push @subjcodes, $subjcode;
		next;
	    }
	}
    }
    # @subjcodes now defined if any additional comment subjects enrolled

    $sth = $dbh->prepare("select comment from eval 
			 where subjcode = ? and studnum = ? and term = ?");

    print TEX "{\\bf\\Large $lex{'General Comments'}}\n\n";

    foreach my $term ( $startterm .. $endterm ) {
	my $first = 1;
	foreach my $subjcode ( @subjcodes ) {

	    $sth->execute( $subjcode, $studnum, $term );
	    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;}
	    my $comment = $sth->fetchrow;
	    if (not $comment) { next; }

	    $comment =~ s/\s*[\n\r]/ /g; # strip cr/lf
	    ($comment) = latex_filter(($comment)); # filter content

	    if ( $first ) {
		print TEX "{\\bf ". $g_TermDisplay{$track}{$term}. " $currterm:} ";
		$first = 0;
	    }

	    print TEX "$comment \n\n";
	}
    }

    print TEX "\\vspace{0.6in}\n\n";

}

 
#---------------
sub prTeacherSig {
#---------------
    print TEX "\\underline{\\hspace{2.5in}} \n\n";
    print TEX "{\\small $lex{Teacher}}\n\n \\medskip\n";
}

#-----------------
sub prPrincipalSig {
#-----------------
    print TEX "\\underline{\\hspace{2.5in}}\n\n";
    print TEX "{\\small $lex{'Principal'}}\n\n\\medskip\n";
}

#-------------
sub prComboSig { # both teacher and principal
#-------------
    print TEX "\\underline{\\hspace{2.5in}}";
    print TEX "\\hfill \\underline{\\hspace{2.5in}}\n\n";
    print TEX "{\\small $lex{Teacher}} \\hfill ";
    print TEX "{\\small $lex{'Principal'}}\n\n\\medskip\n";
}

#------------
sub prTearoff {  # print tearoff line.
#------------

    # block these 2 sections together over page breaks
    if ( $tearoffblock ) { print TEX "\\parbox{\\textwidth}{ "; } 

    print TEX "\\dotfill\n\n\\bigskip\n\n{\\bf Parents/Guardians:}\n";
    print TEX $lex{'Please tear off this portion and return it to the school'};
    print TEX " \n";
    print TEX $lex{'in the report envelope with any comments and your signature'}. ".\n";
}

#--------------
sub prParentSig { # print parent signature.
#--------------
    my ($currdate, $lastname, $firstname, $middlename) = @_;
    print TEX "\n\n\\vspace{0.5in}\n\n\\underline{\\hspace{2.5in}}\n\n";
    print TEX "{\\small $lex{'Parent/Guardian Signature'}}\n\n\\medskip\n";
    print TEX "{\\bf $lex{'Student'}:} {\\it $firstname $middlename $lastname}\n\n";
    print TEX "{\\bf $lex{Comments}:}\n\n";

    if ( $tearoffblock ) { print TEX "} \n "; } 

}


#------------
sub prYearEnd {
#------------

    my ($studentname, $grade)  = @_;

    my ($yearstart,$yearend) = split('-', $schoolyear); # global

    my ($nextgrade, $currgrade);
    
    if ($grade eq 'PK'){ $nextgrade = 'K';}
    elsif ($grade eq 'K'){ $nextgrade = 1;}
    else { $nextgrade = $grade + 1;}

    if ( $schoolmode == 1 ) { # British mode
	my $val = $g_FormMap{$nextgrade};
	if ( not $val ) { $val = $nextgrade; }
	if ( $val =~ m/F|f/ ) { # we are adding form.
	    $val =~ s/F|f/$lex{Form} /;
	} else {
	    $val = qq{$lex{Grade} $val};
	}
	$nextgrade = $val;

	# now do the same with grade to make currgrade values
	my $val = $g_FormMap{$grade};
	if ( not $val ) { $val = $grade; }
	if ( $val =~ m/F|f/ ) { # we are adding form.
	    $val =~ s/F|f/$lex{Form} /;
	} else {
	    $val = qq{$lex{Grade} $val};
	}
	$currgrade = $val;
    }
	
    
    my $key = $r_PlacementIndex{ $grade };
    my $tempTex = $r_PlacementTex{ $key };

    if ( $tempTex ) {
	# Replace variables.
	$tempTex =~ s/%studentname%/$studentname/;
	$tempTex =~ s/%nextgrade%/$nextgrade/g;
	$tempTex =~ s/%schoolyearend%/$yearend/;
	$tempTex =~ s/%currgrade%/$currgrade/;

	print TEX "\\begin{center}\n\\bigskip\n\n";
	print TEX "\\framebox[7in][c]{";
	print TEX $tempTex;  # Variable values found in repcard.conf.
	print TEX "}\\end{center}\n"; #End of Framebox also.
    }
}


#------------
sub calcFinal {
#------------
    # Passed values: ref to @eval array to do the calcs.
    my @localeval = ${shift};
    print @localeval; 
}


#------------------------
sub calcSubjectAttendance {
#------------------------

    my ( $subjsec, $studnum ) = @_; # pass subject and student.

    my ($periods,$lates); # periods absent/late

    my $sth = $dbh->prepare("select distinct reason, count(*) from attend 
      where subjsec = ? and studentid = ? group by reason");
    $sth->execute( $subjsec, $studnum );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }

    while ( my ( $reason, $count ) = $sth->fetchrow ) {
	#print "Reason: $reason Count: $count<br>\n";

	if ( $reason =~ m/$absentString/ ) {
	    $periods += $count;
	} elsif ( $reason =~ m/$lateString/ ) {
	    #if ( $r_LateAbsentRatio ) {
	    #  $periods += ( $count / $r_LateAbsentRatio );
	    # } else {
	    # $periods += $count / 3; # default to 3 Late = 1 Absent
	    # }
	    $lates += $count;
	}
	# No other reasons affecting.

    }

    #print "P:$periods<br>\n";

    if ( not $periods ) {
	$periods = '0';
    }
    if ( not $lates ) {
	$lates = 0;
    }

    
    return "$periods:$lates" # format_number( $periods, 2);

}


#---------------------
sub selectEmailAddress {
#---------------------

    my $tempdir = shift;

#    print "Temp Dir: $tempdir<br>\n";
    
    my @files = glob("$tempdir/*.pdf");

    my $checked;
    if ( $checknextpage ) { $checked = qq{checked="checked"}; }
    
    # Start the form.
    print qq{<form action="$self" method="post">\n};
    print qq{<input type="hidden" name="page" value="2">\n}; # cause jump to email post
    print qq{<input type="hidden" name="tempdir" value="$tempdir">\n}; # pass directory containing the files.


    # Start the table.
    print qq{<table cellspacing="0" cellpadding="3" border="1">\n};
    print qq{<tr><th>$lex{Student}</th><th>$lex{Email} $lex{Address}</th></tr>\n};

    my $sth = $dbh->prepare("select lastname, firstname, email, par1_email, par2_email from studentall 
       where studnum = ?");
    my %emailtypes = ( 'email' => 'Student', 'par1_email' => 'Parent 1', 'par2_email' => 'Parent 2');

    foreach my $filename ( sort @files ) {
	my ($dud,$studnum) = split('-', $filename);
	$studnum =~ s/\.pdf//;

	# find the email addresses for student and parents.
	$sth->execute( $studnum );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $ref = $sth->fetchrow_hashref;
	my %r = %$ref;
#	print "Stud:$studnum Rec:", %r, "<br>\n";

	# print name
	print qq{<tr><td class="la">$r{firstname} $r{lastname}</td><td>\n};
	foreach my $field ( 'email','par1_email','par2_email') {
	    if ( $r{$field} ) {
		print qq{<input type="checkbox" name="$studnum:$field" value="1" $checked>};
		print qq{$emailtypes{$field}: $r{$field}<br>\n}
	    };
	}
	print qq{</td></tr>\n};
    }

    print qq{<tr><td colspan="2"><input type="submit" value="$lex{Post} $lex{Email}"></td></tr>\n};
    print qq{</table></form>\n};
    exit;



}



#------------
sub postEmail  {
#------------

    # foreach my $key ( sort keys %arr ) { print "K:$key V:$arr{$key}<br>\n"; }
    # passed tempdir holding the report cards, and then all the student numbers:mail fields

    $messageformat = 'html'; # override
    
    if ( not $g_EmailServer ) { # fail
	print qq{<h3>$lex{Error}: Mail Server not defined</h3>\n};
	print qq{</body></html>\n};
	exit;
    }

    use Email::Stuffer;
    use Email::Sender;
    use Email::Sender::Transport::SMTP;

    # Config values in conf_system.
    #my $g_EmailAuthId = 'chs.dominica@gmail.com';
    #my $g_EmailAuthPwd = ''; # app password
    my $g_EmailPort = 25; # or 587 for TLS
    #my $g_EmailServer = 'smtp.gmail.com';
    #my $g_EmailNoReply = 'chs.dominica@gmail.com';
    my $g_EmailUseTLS = '0'; # use 1 or 0 (zero)

    
    # Create Transport object
    my $transport;
    if ( $g_EmailUseTLS ) {
	$transport = Email::Sender::Transport::SMTP->new({
	    host => $g_EmailServer,
	    port => $g_EmailPort,
	    ssl  => 'starttls',
	    sasl_username => $g_EmailAuthId,
	    sasl_password => $g_EmailAuthPwd
									});
    } else { # normal SMTP transport
	$transport = Email::Sender::Transport::SMTP->new({
	    host => $g_EmailServer,
	    port => $g_EmailPort,
								     });
    }    

	
    my $tempdir = $arr{tempdir};
    delete $arr{tempdir};
    my $re = qr/$tempdir\//; # regular expression

    # any values left in hash are studnum:emailfield;
    my %mailtargets;
    foreach my $key (keys %arr ) {
	my ($sn,$field) = split(':', $key);
	$mailtargets{$sn}{$field} = 1;
    }
    # We now have all mailtargets{studentnums}{email field} = 1
    
    
    # Get school address information for inclusion in form letter
    my $sth1 = $dbh->prepare("select id, datavalue, dataname from conf_system 
      where sectionname = 'schooladdress' order by dataname");
    $sth1->execute;
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my ($id, $datavalue, $dataname ) = $sth1->fetchrow ) {
	eval $datavalue;
	$address{$dataname} = $$dataname;
	if ( $@ ) {
	    print "$lex{Error}: $@<br>\n";
	    die "$lex{Error}: $@\n";
	}
    }


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

    print qq{<h3>Addresses to be Mailed</h3>\n<ul>\n};

    foreach my $file ( glob("$tempdir/*.pdf")) {

	my $tempname = $file;  # use to get student number 
	my $fullfilename = $file; # keep original

	$tempname =~ s/\.pdf//; # strip filename extension.
	$tempname =~ s/$re//;  # strip heading directory name; re defined above
	my ($dud,$studnum) = split('-', $tempname);

	# skip this student if no emails to send
	if ( not $mailtargets{$studnum} ) { next; } 


#	print qq{<div>Student Number:$studnum</div>\n};

	
	# get name and email addresses for student and parents.
	$sth->execute( $studnum );
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	my $ref = $sth->fetchrow_hashref;
	my %r = %$ref;

	
	# Add in principal/vice/school address to the hash with student record.
	%r = (%r,%address,'r_Principal' => $r_Principal,'r_VicePrincipal' => $r_VicePrincipal);
	
#	foreach my $key ( sort keys %r ) { print "K:$key V:$r{$key}<br>\n"; }

	my $subject = "$lex{'Report Card'}: $r{firstname} $r{lastname}";

	# insert variables for school, and student.
	my $newmessage = $message;
	$newmessage =~ s{\<\@(.*?)\@\>}
  	  { $r{$1} }gsex;
    
#	print "New Message:$newmessage<br>\n";
#	my @lines = split /\r\n|\n|\r/, $newmessage;
#	print "Lines<br>\n";
#	foreach my $line ( @lines ) { print "$line<br>\n"; }

	
	# Create Email object, and set some values.
	my $email = Email::Stuffer
	    ->from( $g_EmailPersona{'noreply'})
	    ->subject( $subject )
	    ->html_body( $message )
	    ->transport( $transport )
	    ;

	print qq{<div>From:$g_EmailPersona{'noreply'}</div>\n};

	
	# attach report card
	$email->attach_file($fullfilename);
	

	# Loop through up to 3 email addresses for this student.
	foreach my $field ( sort keys %{ $mailtargets{$studnum} } ) {

	    my $emailaddress = $r{$field};
	    $email->to( $emailaddress );

	    # send the message
	    my $result = $email->send();
	    
	    if ( not $result ) { # failure
		print qq{<div style="color:red;font-weight:bold;">};
		print qq{Failure for $r{firstname} $r{lastname} ($studnum) $r{homeroom} - $field - };
		print qq{$emailaddress</div>\n};
	    } else { # success
		print qq{<div style="">};
		print qq{Email sent for $r{firstname} $r{lastname} ($studnum) - $field - $emailaddress</div>\n};
	    }

		
	} # end of fields loop for each student report card (up to 3)

    } # end of loop for each file.



    # Clean up temp directory
    system("rm -r $tempdir");
    
    # system("mv pdflog$$.txt $downloaddir"); # not needed since no 


    print qq{</ul></div>\n};
    print qq{<h1>$lex{Email} $lex{Complete}</h1>\n};
    
#    print qq{[ <a href="$webdownloaddir/pdflog$$.txt">$lex{'View Log File'} - };
#    print qq{$lex{'Report Card'}</a> ]\n};

    print qq{<p>[ <a href="$homepage">$lex{Main}</a> ]</p>\n};
    print qq{</body></html>\n};

    exit;


} # End of postEmail

