#! /usr/bin/perl # Copyright 2001-2020 Leslie Richardson # This file is part of Open Admin for Schools. # Open Admin for Schools is free software; you can redistribute it # and/or modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # 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', 'Cannot open term file' => 'Cannot open term file', '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 Open' => 'Days Open', 'Days Enrolled' => 'Days Enrolled', 'Days Absent' => 'Days Absent', 'General Comments' => 'General Comments', 'Term' => 'Term', 'Teacher' => 'Teacher', 'Principal' => 'Principal', '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', 'Date' => 'Date', 'Comments' => 'Comments', 'Days per Month Override' => 'Days per Month Override', 'Student Group' => 'Student Group', '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', 'Absent' => 'Absent', 'Late' => 'Late', 'Student Name' => 'Student Name', 'Date of Birth' => 'Date of Birth', 'Teacher Name' => 'Teacher Name', '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', 'Please Log In' => 'Please Log In', 'Pre-kindergarten Class' => 'Pre-kindergarten Class', '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', 'Blank=All' => 'Blank=All', 'Periods per Day' => 'Periods per Day', 'Rank' => 'Rank', 'Demerits' => 'Demerits', 'Skipping' => 'Skipping', 'Undefined Value' => 'Undefined Value', 'Missing' => 'Missing', 'Value' => 'Value', 'Track' => 'Track', 'Only' => 'Only', 'Not Found' => 'Not Found', 'Picture' => 'Picture', 'Email' => 'Email', 'Address' => 'Address', 'Select' => 'Select', 'Post' => 'Post', 'Complete' => 'Complete', 'OR' => 'OR', 'Form' => 'Form', ); use DBI; use CGI; use CGI::Session; use Cwd; use Number::Format qw(:all); use Carp; use Time::JulianDay; my $deleteTeX = 1; my $showEmailOption = 0; # Non School Day Grades my %nonschoolgrades = ('K' => 1,'PK' => 1,'P3' => 1); # Email Configuration Values my $r_MailServer = 'richtech.ca'; my $r_NoReplyName = 'OpenAdmin Messaging System'; my $r_NoReplyEmail = 'no-reply@yoursite.net'; 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}. ": $@
\n"; die $lex{Error}. ": $@\n"; } my $schoolmode; if ( $g_BritishSchoolMode ) { $schoolmode = 1; # will there be a mode 2? } my $dsn = "DBI:$dbtype:dbname=$dbase"; $dbh = DBI->connect($dsn,$user,$password); $dbh->{mysql_enable_utf8} = 1; # 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}: $@
\n"; die "$lex{Error}: $@\n"; } } # LaTeX filter function eval require "$configpath/lib/liblatex.pl"; if ( $@ ) { print $lex{Error}. ": $@
\n"; die $lex{Error}. ": $@\n"; } # attendance library functions eval require "$configpath/lib/libattend.pl"; if ( $@ ) { print $lex{Error}. ": $@
\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 ); if ( not $r_TeacherModeOverride and $teachermode ) { # not allowed to print from teacher site print qq{
}; print qq{$lex{Teacher} $lex{'Report Card'} printing not enabled
\n}; print qq{\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$title\n}; print qq{\n}; print qq{\n}; print qq{\n}; print qq{\n}; print qq{\n}; print qq{$chartype\n\n}; print qq{[ $lex{Main} | \n}; if ( not $teachermode ) { print qq{$lex{'Report Card'} ]\n}; } print qq{

$title

\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{

$lex{Group} $lex{'Not Found'}

\n}; print qq{\n}; exit; } delete $arr{grade}; delete $arr{homeroom}; # if nonschool grades selected, load nonschool days closed. my %nonschoolday; if ( $nsdflag ) { # load nonschool dates. if ( $group eq 'grade' ) { print qq{

Cannot Load Non School Days by Grade

\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}
\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; 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}
\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{

}; print qq{$lex{Missing} $lex{Term}

\n}; print qq{\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
\n"; if ( $currtrack ne $prevtrack ) { print qq{

$lex{Track} $lex{Error}
\n}; print qq{Current:$currtrack Previous:$prevtrack
\n}; print qq{Please print by grade

\n}; # print qq{\n}; # exit; } $track = $currtrack; } } # If no track, fail! if ( not $track ) { print qq{

Missing Track

\n}; print qq{\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}
\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)
\n"; } } #foreach my $key (sort keys %students ) { print "K:$key V:$students{$key}
\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{

$lex{Grade}:$grade Periods Per Day:$g_ppd{$grade}
\n}; print qq{No grade found or Periods per day not set in configuration

\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}}, "
\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
\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
\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
\n"; # foreach my $key ( sort keys %classavg ) { print "K:$key V:$classavg{$key}
\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 # Format: key: year-month value: days # The $homeroom value will trigger the function to look for non school days for early grades. my $nsdhomeroom; if ( $nsdflag ) { $nsdhomeroom = $groupid; # groupid IS a homeroom if nsdflag is set. } # 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. $schooldaysorig{$key} = $schooldays{$key}; $schooldays{$key} = $arr{$key}; } } # print qq{School Days Hash
\n}; # foreach my $key ( keys %schooldays ) { print "K: $key Val: $schooldays{$key}
\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 "
K:$key Ref: $$termavg_ref{$key}
\n"; # foreach my $key1 ( sort keys %{ $$termavg_ref{$key} } ) { # print "Key:$key1 Val: $$termavg_ref{$key}->{$key1}
\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}
\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
\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 ) { 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 ) { 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, "
\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
\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 ) { 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 } } } else { # we're in the last term; print graduation box, if set... if ( $r_PrintYearEnd ) { prYearEnd("$firstname $middlename $lastname", $grade); } } if ( $r_Note4 ) { 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{\n}; print qq{

[ \n}; print qq{$lex{'View/Download/Print'} $lex{'Report Cards'} ]

\n}; print qq{
\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{\n}; print qq{

[ \n}; print qq{$lex{'View/Download/Print'} $lex{'Report Cards'} ]

\n}; } print qq{[ $lex{'View Log File'} ]\n}; print qq{\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; } } # Get School Months for Override my %schoolmonths = mkSchoolDays( $schoolstart, $currsdate, $dbh ); # Format: yyyy-mm; first record is blank (zeroth) # Form Start print qq{
\n}; print qq{\n}; # Get the grades my @grades; my $sth = $dbh->prepare("select distinct grade from student where grade is not NULL and grade != ''"); $sth->execute; if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } while ( my $gr = $sth->fetchrow ) { push @grades, $gr; } # Get the homerooms. my @homerooms; my $sth = $dbh->prepare("select distinct homeroom from student where homeroom is not NULL and homeroom != ''"); $sth->execute; if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } while ( my $hr = $sth->fetchrow ) { push @homerooms, $hr; # removed checking below } # Start Table. print qq{\n}; # Grades print qq{}; print qq{\n}; print qq{\n}; # Homeroom print qq{}; print qq{\n}; print qq{\n}; # Printing Date print qq{\n\n}; # Terms (to use to get courses during those term blocks). print qq{\n\n}; print qq{\n\n}; # Paper Size $defaultpapersize =~ s/paper//; # strip out word paper so lex works; from admin.conf my $defpaper = ucfirst( $defaultpapersize ); print qq{\n}; print qq{\n} ; # Font Size print qq{\n\n}; if ( $teachermode ) { print qq{\n}; foreach my $subjsec ( @subjects ) { print qq{\n}; print qq{\n}; } } # Withdrawn Students print qq{\n\n}; # One Student per File print qq{\n}; print qq{\n}; # Enable/Disable the email report card option from top of script. if ( $showEmailOption ) { # Email report card. print qq{\n}; print qq{\n}; print qq{\n}; print qq{\n}; } print qq{\n}; # Spacer print qq{\n}; # Override for Days open in month print qq{}; print qq{\n}; # Inner Table print qq{\n}; # End of Inner Table print qq{\n}; print qq{
$lex{Grade}}; if ( $schoolmode == 1 ) { print qq{/$lex{Form}}; } print qq{
$lex{OR}
$lex{Homeroom}

$lex{'Printing Date'}}; print qq{\n}; print qq{\n}; print qq{
$lex{'Start Term'}}; print qq{
$lex{'End Term'}}; print qq{
$lex{'Paper Size'}
$lex{'Font Size'}}; print qq{
$lex{'Select Subjects'}
}; print qq{$subjdesc{$subjsec} ($subjsec)
$lex{'Show Withdrawn Students'}}; print qq{
$lex{'One Student per File'}}; print qq{$lex{'For Duplexing/Stapling'}
$lex{Email} $lex{'Report Card'}
Check All Email Addresses

$lex{'Override Term Days'}
\n}; print qq{\n}; print qq{\n}; print qq{\n}; for my $ym ( sort keys %schoolmonths ) { # keys are yyyy-mm format my ($y,$m) = split('-', $ym); print qq{}; print qq{\n}; } print qq{
$lex{'Days per Month Override'}
$lex{Month}$lex{'Days Open'}
$month[$m] ($ym)
\n}; print qq{\n}; print qq{\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,inputenc,fancyhdr} $a_latex_header \\renewcommand{\\familydefault}{\\sfdefault} \\setlength{\\hoffset}{ $r_HOffset } \\setlength{\\voffset}{ $r_VOffset } \\setlength{\\headsep}{10pt} \\setlength{\\headheight}{14pt} \\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{

FAILURE for $firstname $lastname

\n}; while ( my ($subjcode, $mark ) = $sth->fetchrow ) { print "
SN:$studnum TERM:$term COURSE:$subjcode MARK:$mark
\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
\n"; if ( $avg1 >= 85 and not $failcount ) { # and $count2 >= 5 and $count3 >= 7 ) { # print "Level 1 Return

\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
\n"; if ( $avg1 >= 75 and not $failcount ) { # and $count2 >= 4 and $count3 >= 6 ) { # print "Level 2 Return

\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
\n"; if ( $avg1 >= 60 and $count2 >= 2 and $count3 >= 6 and not $failcount ) { # print "Level 3 Return

\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
\n"; if ( $avg1 >= 55 and $count2 >= 5 and not $failcount ) { # print "Level 4 (Pass) Return

\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
\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
\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
\n"; next; } # skip non-numeric mark if ( $mark =~ m/[^.0-9]/ ) { print $lex{Skipping}. ": $mark - $description ($subjcode) - $studnum
\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
\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}. ": $@
\n"; die $lex{Error}. ": $@\n"; } # Get credit and difficulty values for each subject. my $sth = $dbh->prepare("select credit, difficulty 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, $difficulty) = $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
\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 "
$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 }; 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]. "
\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
\n"; foreach my $key ( sort keys %jdclosed ) { print qq{K:$key V:$jdclosed{$key}
\n"; } print qq{End JDClosed
\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
\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{
INSIDE
\n"; } else { $daysopen += 1; } # print qq{JD:$jd Count:$daycount
\n"; } # print qq{ST:$startdate END:$enddate Count:$daycount
\n"; return "$daysopen:$daysclosed"; } #----------------- 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"; } #------------ 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. my $sth = $dbh->prepare("select pic from studentall where studnum = ?"); $sth->execute( $studnum ); if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } my $pic = $sth->fetchrow; if ( $r_ShowStudentPicture and $pic ) { # verify that file exists my $fpath = $configpath. '/admin/pic-big/'. $studnum. '.jpg'; if ( not -e $fpath ) { print "

$lex{Picture} $lex{'Not Found'}: $firstname $lastname ($studnum)

\n"; $pic = ''; # set to blank, so next section fails to try to print picture } } if ( $r_ShowStudentPicture and $pic ) { # note: must have ShowLogo on... print TEX "\\includegraphics[width=$r_StudentPictureWidth]{"; print TEX "$configpath/admin/pic-big/$studnum.jpg}\\\\\n"; } elsif ( $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; 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 ) { # Calculate the weighted average my $termPattern = $startterm. '-'. $endterm; my @weight; if ( $r_AverageWeight{$termPattern} ) { @weight = @{ $r_AverageWeight{$termPattern} }; } else { @weight = (); } unshift @weight, 0; # put in a blank value. #foreach my $wt ( @weight ) { print "W:$wt "; } my ( $totalscore, $totalweight ); my @tempeval = @eval; # in order to remove first column (objectives) shift @tempeval; foreach my $evalref ( @tempeval ) { if ( my $wt = $weight[ $evalref->[0] ] ) { # The weight for this term of subj. $totalscore += ( $wt * $evalref->[1] ); $totalweight += $wt; } elsif ( defined $evalref->[1] && $evalref->[1] ne "" ) { # if it's defined and not an empty string, count it $totalscore += $evalref->[1]; $totalweight++; } } if ( $totalweight ) { $averagemark = $totalscore / $totalweight; } else { $averagemark = 0; } $averagemark = format_number( $averagemark, $r_AveragePrecision, 0); } # 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{$grade}; 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}\n"; } # Print Out Eval Table for viewing ------- # print qq{Original Eval: $subjsec}; # print qq{}; # # foreach my $idx ( 0.. $#eval ) { # print ""; # foreach my $val ( @{ $eval[$idx] } ) { # print "\n"; # } # print "\n"; # } # print "
$idx - $eval[$idx]$val
\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 ) > 20 ) { 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
\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' are set in subject, 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; } # OLD my $width = $subjspace + ($#eval * $markspace) + ( 2 + 2 * $#eval ) * 2.1; my $width = $subjspace + ($termcount * $markspace) + ( 2 + 2 * $termcount ) * 2.1; if ( $calcavg ){ $width = $width + $markspace;} print TEX "\n\\parbox{$width mm}{\n"; foreach my $term ( sort keys %comments ) { if ( not $comments{$term} ) { next; } 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"; } print TEX "\n}\\smallskip\n\n"; # Note: brace ends 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. # 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
\n"; ( $absent{$yrmo}, $tardy{$yrmo} ) = split(':',$absrec); } # calculate enrollment, one for each month my $ymref = calcMonthlyEnrollment( $studnum, $schoolstart, $currsdate, $dbh ); 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 "
SCHOOL DAYS:",%schooldaysorig,"
\n"; #print "$student[1] $student[2] DO: $do ADO: $ado DE: $de
\n"; my $ade; # adjusted days enrolled if ( $do ) { $ade = format_number( ($de * $ado / $do), 2, 2); } 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
\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
\n"; if ( not $periods ) { $periods = '0'; } if ( not $latest ) { $lates = 0; } return "$periods:$lates" # format_number( $periods, 2); } #--------------------- sub selectEmailAddress { #--------------------- my $tempdir = shift; my @files = glob("$tempdir/*.pdf"); my $checked; if ( $checknextpage ) { $checked = qq{checked="checked"}; } # Start the form. print qq{
\n}; print qq{\n}; # cause jump to email post print qq{\n}; # pass directory containing the files. # Start the table. print qq{\n}; print qq{\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, "
\n"; # print name print qq{\n}; } print qq{\n}; print qq{
$lex{Student}$lex{Email} $lex{Address}
$r{firstname} $r{lastname}\n}; foreach my $field ( 'email','par1_email','par2_email') { if ( $r{$field} ) { print qq{}; print qq{$emailtypes{$field}: $r{$field}
\n} }; } print qq{
\n}; exit; } #------------ sub postEmail { #------------ # foreach my $key ( sort keys %arr ) { print "K:$key V:$arr{$key}
\n"; } if ( not $r_MailServer ) { # fail print qq{

$lex{Error}: Mail Server not defined

\n}; print qq{\n}; exit; } use Email::Sender; my $tempdir = $arr{tempdir}; delete $arr{tempdir}; my $re = qr/$tempdir\//; # regular expression # 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}: $@
\n"; die "$lex{Error}: $@\n"; } } my $sth = $dbh->prepare("select lastname, firstname, email, par1_email, par2_email from studentall where studnum = ?"); print qq{

Addresses Mailed

\n\n}; print qq{

$lex{Email} $lex{Complete}

\n}; print qq{[ $lex{'View Log File'} - $lex{'Report Card'} ]\n}; print qq{

[ $lex{Main} ]

\n}; print qq{\n}; exit; } # End of postEmail