#! /usr/bin/perl # Copyright 2001-2009 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 = ('Report Card Generation' => 'Report Card Generation', 'Main' => 'Main', 'Report Card' => 'Report Card', 'teacher' => 'teacher', 'principal' => 'principal', 'combo' => 'combo', 'No grade found or Periods per day not set in admin.conf' => 'No grade found or Periods per day not set in admin.conf', 'Cannot open term file' => 'Cannot open term file', 'View/Download/Print Report Cards' => 'View/Download/Print Report Cards', 'View Log File' => 'View Log File', 'Report to Parents' => 'Report to Parents', 'Grade' => 'Grade', 'Homeroom Teacher(s)' => 'Homeroom Teacher(s)', 'Evaluation and Comment Key' => 'Evaluation and Comment Key', 'Class Average' => 'Class Average', 'Attendance' => 'Attendance', 'Days Open' => 'Days Open', 'Days Enrolled' => 'Days Enrolled', 'Days Absent' => 'Days Absent', 'Periods Late' => 'Periods Late', 'Additional Comments' => 'Additional 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 records for student' => 'Duplicate Evaluation records for student', 'Average' => 'Average', 'Final' => 'Final', 'No Quality Score for' => 'No Quality Score for', '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', 'Alternate Report Card System' => 'Alternate Report Card System', 'Student Name' => 'Student Name', 'Date of Birth' => 'Date of Birth', 'Teacher Name' => 'Teacher Name', 'Principal' => 'Principal', 'Vice-Principal' => 'Vice-Principal', 'Period(s)' => 'Period(s)', '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', 'Effective Date' => 'Effective 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', ); use DBI; use CGI; use CGI::Session; use Date::Business; use Cwd; use Number::Format format_number; # To Do: fix the ppd override for teacher mode. # $r_AverageWeight{ $termPattern } = ( 1 => 0.30, 2 => 0.35, 3 => 0.35 ) ; # termPattern is starterm-endterm. # 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) # ---------------------------- # More global repcard.conf to fix: $markfield # This is no longer optional, and is wired to the first field (a1) for # all numeric entries. # Set Sizes for text area for each paper size. # $r_a4paper_textwidth = '184mm'; # $r_a4paper_textheight = '272mm'; # $r_letterpaper_textwidth = '190mm'; # $r_letterpaper_textheight = '250mm'; # $r_legalpaper_textwidth = '190mm'; # $r_legalpaper_textheight = '325mm'; 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"; } # report card config file eval require "$configpath/etc/repcard.conf"; if ( $@ ) { print $lex{Error}. ": $@
\n"; die $lex{Error}. ": $@\n"; } if ( $r_TeacherModeOverride ) { $teachermode = 0; } # filter latex 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"; } if ( $teachermode ) { # Load Teacher overrides eval require "$configpath/etc/repcardOVR.conf"; if ( $@ ) { print $lex{Error}. ": $@
\n"; die $lex{Error}. ": $@\n"; } } # Get current dir so know what CSS to display; if (getcwd() =~ /tcgi/){ # we are in tcgi $css = $tchcss; } my $q = new CGI; my %arr = $q->Vars; my $dsn = "DBI:$dbtype:dbname=$dbase"; $dbh = DBI->connect($dsn,$user,$password); $dbh->{mysql_enable_utf8} = 1; my $session; if ( $teachermode ) { # we are running in teacher site. # Get Session $session = new CGI::Session("driver:$dbtype;serializer:FreezeThaw", undef,{Handle => $dbh}) or die CGI::Session->errstr; if ( not $session->param('logged_in') ){ $userid = $session->param('userid'); print $q->header( -charset, $charset ); print "

". $lex{'Please Log In'}. "

\n"; print "\n"; die; } # Ok, we have a login. Values below we have in environment. $userid = $session->param('userid'); $duration = $session->param('duration'); $session->expire('logged_in', $duration ); print $session->header( -charset, $charset ); } else { # normal mode in cgi (admin site) print $q->header( -charset, $charset ); } # 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"; } # Set Paper Size, text width and height my ( $papersize, $textwidth, $textheight ); if ( $arr{papersize} eq $lex{Letter} ) { $papersize = 'letterpaper'; $textwidth = $r_letterpaper_textwidth; $textheight = $r_letterpaper_textheight; } elsif ( $arr{papersize} eq $lex{Legal} ) { $papersize = 'legalpaper'; $textwidth = $r_legalpaper_textwidth; $textheight = $r_legalpaper_textheight; } elsif ( $arr{papersize} eq $lex{A4} ) { $papersize = 'a4paper'; $textwidth = $r_a4paper_textwidth; $textheight = $r_a4paper_textheight; } # Print HTML Page Header print "$doctype\n". $lex{'Report Card Generation'}. " \n"; print "\n"; print "\n"; print "\n"; print "\n"; print "$chartype\n\n"; print "[ ". $lex{Main}. " | \n"; print "". $lex{'Report Card'}. " ]\n"; if ( $teachermode ) { print "$userid \n"; } if ( not $arr{page} ) { showStartPage(); } delete $arr{page}; # no longer needed. # remove extra values from %arr; leave only month values. my $group = $arr{group}; # also reset group to either grade or homeroom. if ( $group eq $lex{Grade} ) { $group = 'grade'; } else { $group = 'homeroom'; } my $groupid = $arr{groupid}; my $fontsize = $arr{fontsize}; my $override = $arr{override}; my $showwithdrawn = $arr{showwithdrawn}; my $sterm = $arr{sterm}; my $eterm = $arr{eterm}; my $oneStudentPerFile; if ( $arr{onestudentperfile} ) { $oneStudentPerFile = 1; } my $alternateReportCard; if ( $arr{alternatereportcard} ) { $alternateReportCard = 1; } delete $arr{group}; delete $arr{groupid}; delete $arr{fontsize}; delete $arr{override}; delete $arr{onestudentperfile}; delete $arr{alternatereportcard}; delete $arr{showwithdrawn}; delete $arr{eterm}; delete $arr{sterm}; #extract the subjec's, if any 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; foreach my $subjsec ( @subjects ) { my $sth = $dbh->prepare("select sequence, description from subject where subjsec = ?"); $sth->execute( $subjsec ); if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } my ( $sequence, $description ) = $sth->fetchrow; $subjects{"$sequence$description"} = $subjsec; } # Show withdrawn students, as well, if they have data. if ( $showwithdrawn ) { $studenttable = 'studentall'; } else { $studenttable = 'student'; } # 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"; } # Get a grade in order to get correct PPD ( which may be different for each grade ) # IN FACT this stuff should get the LARGEST PPD #(in case of multigraded classroom with different PPD?) my $grade; if ( $group eq 'homeroom' ) { # Get the grade for this class $sth = $dbh->prepare("select distinct grade from student where homeroom = ?"); $sth->execute( $groupid ); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } $grade = $sth->fetchrow; } else { $grade = $groupid; } # $PPD is Important Variable from admin.conf # periods per day set via grade; needed for attendance calculations my $periodsperday = $g_ppd{$grade}; if ( not $periodsperday and not $teachermode ) { print $lex{Grade}. ": $grade PPD: $g_ppd{$grade} \n"; print $lex{'No grade found or Periods per day not set in admin.conf'}. "!
\n"; die; } # this is ugly; fix later with better ppd method for teacher mode (Nov3/08) if ( $teachermode ) { $periodsperday = $r_defaultppd; } # Read in the term(s) my ($term, @terms, %terms); open(TERM, "$configpath/etc/term") || die $lex{'Cannot open term file'}. "!\n"; # slurp file my $termdata; { local $/; $termdata = ; close FH;} my @terms = split /\n/, $termdata; $term = $terms[0]; # multiTrack variable is set in the admin.conf file. if ( $multiTrack ) { # Are we in multiTrack mode? If so, reset term. for my $t (1..$#terms) { my ($key, $val) = split /:/, $terms[$t]; $terms{$key} = $val; # Form is e:3 (elementary: term 3) } my $grp = $g_termtype{$grade}; if ( $terms{$grp} ) { $term = $terms{$grp}; } } # Note: Multitrack schools can have different terms for same time period. # This script now looks for this. It didn't previously. # 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 $clasavg in repcard.conf is 1; # $markfield = 'a1'; - now located in repcard.conf. my %classavg; if ( $r_clasavg ){ # create %classavg - class average hash. # First Find all subjects done this term. (actually a subjsec field) $sth = $dbh->prepare("select distinct subjcode from eval where term = '$term' order by subjcode desc"); $sth->execute; if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr;} my $subjcount = $sth->rows; # Loop through each subjsec (subject-section) for (1..$subjcount){ my $subjsec = $sth->fetchrow; $sth1 = $dbh->prepare("select $markfield from eval where term = '$term' and subjcode = '$subjsec'"); $sth1->execute; if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr;} my $rows = $sth1->rows; if ($rows < 1){ next;} # skip if no records. my $totalmark = 0; while (my $mark = $sth1->fetchrow){ $totalmark += $mark; } my $average = format_number( $totalmark / $rows, 0 ); $classavg{$subjsec} = $average; } } # End of Class Average Calculations (creates %classavg) # Calculate number of days in the terms for my $trm ( 1..$term ) { $termdays{$trm} = calcTermDays($g_termstart{$trm},$g_termend{$trm}); } # Format: key: year-month value: days my %schooldays = mkSchoolDays( $schoolstart, $currsdate ); 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}; } } #foreach my $key ( keys %schooldays ) { print "K: $key Val: $schooldays{$key}
\n"; } # What is the order of the school months? my @schoolmonths = mkSchoolMonths($currsdate); # uses currsdate = yyyy-mm-dd; # Format: yyyy-mm; first record is blank (zeroth) # print "The schooldays hash is:
",@schoolmonths,"
\n"; my ($tempdir, $shortname, $filename); if ( not $oneStudentPerFile ) { $shortname = "repcard$$"; $filename = "$shortname.tex"; open( TEX,">$filename" ) || die "Can't open tex file"; 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"; } if ( not %students ) { # then we need to find some... 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; } } 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}; $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 a1 != '' and studnum = ?"); $sth1->execute( $term, $studnum ); if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; } my $evcount = $sth1->fetchrow; if ( not $evcount ) { next; } # skip kids with blank values this term. } 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. } if ( $alternateReportCard ) { studentAltRepcard( $studnum, $lastname, $firstname, $middlename, $grade, $homeroom, $birthdate ); if ( $oneStudentPerFile ) { # we also have to do the close for this student; # build pdf and put into tempdir; append to pdflog$$.txt 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.*"); } next; # skip to next student } # Print the heading section for each new report card prTexHead( $grade, $lastname, $firstname, $middlename, $birthdate, $provnum ); # 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 ) { # set in repcard.conf my @teachname = (); $sth1 = $dbh->prepare("select sal, firstname, lastname from staff where homeroom = ? and grade = ? and position = ? "); # Note: $position set in repcard.conf to the teacher position.. 'Classroom Teacher' $sth1->execute( $homeroom, $grade, $r_position ); if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } # Fancy Stuff in case more than one teacher for that room. my $teachrows = $sth1->rows; while (my ($sal, $firstname, $lastname) = $sth1->fetchrow ) { push @teachname, "$sal $firstname $lastname"; } if ( @teachname ) { # only print if they exist. prHomeroomTeachers( @teachname ); } } # put in rule divider print TEX "\\hrulefill \n\\smallskip\n\n"; if ( $r_showGradeScheme ) { # set in repcard.conf print_grade_scheme( $grade ); } # End of head section for each new report card. # print a Note 2 - if set in repcard.conf if ( $r_note2 ) { print TEX "\\begin{center}{\\it $r_note2}\\end{center}\n\n"; } my %mysubjects = (); if ( not %subjects ) { # then create %mysubjects for this student... # Find eval records for this student ~~updated for Additional Comments $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 and s.description != '$additionalcomments' order by s.sequence"); $sth1->execute( $studnum ); if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } while ( my ( $subjsec, $seq, $startrptperiod ) = $sth1->fetchrow ) { while ( length( $seq ) < 4 ) { # pad with leading zeros $seq = '0'. $seq; } $mysubjects{"$seq$subjsec"} = $subjsec; } } else { %mysubjects = %subjects; } #print "SN: $studnum SUB:", %mysubjects, "
\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"; } # Now Loop through all subjects of this student foreach my $key ( sort keys %mysubjects ) { my $subjsec = $mysubjects{ $key }; # req'd since mysubjects for sorting only # Check for enrollment ( an issue with teacher mode ) my $sth1 = $dbh->prepare("select count(*) from eval where studnum = ? and subjcode = ?"); $sth1->execute( $studnum, $subjsec ); if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } my $count = $sth1->fetchrow; if ( $count < 1 ) { next; } # next subject # Get this subject's info... $sth1 = $dbh->prepare("select * from subject where subjsec = ?"); $sth1->execute( $subjsec ); if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } my $subjref = $sth1->fetchrow_hashref; my $sequence = $subjref->{sequence}; my $startrptperiod = $subjref->{startrptperiod}; # skip if this subject hasn't started yet. if ( $startrptperiod > $eterm ) { next; } my @objdesc = (); # objective descriptions my $objectivecount; for my $i ( 1 .. 20 ) { my $fieldname = 'q'. $i; if ( $subjref->{$fieldname} ) { $objdesc[$i] = $subjref->{$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. @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. if ( $r_TermDisplayLeading ) { # pad front of subject my $leadidx = $sterm; # $sterm is passed starting term to print. while ( $leadidx < $startrptperiod ) { # $startrptperiod is from subject record. my @temp = (); $temp[ $#objdesc ] = ''; # dimension that thar array. push @eval, [ @temp ]; $leadidx++; } } # 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 > $eterm or $evalterm < $sterm ) { next; } # not there yet, or skipping earlier. # Set values into GPA Hash if ( $evalref->{$markfield} ) { # markfield comes from repcard.conf $gpa{$subjsec}[$evalterm] = $evalref->{$markfield}; } # Check for largest term ( so know how many gpa calcs to do). if ( $evalterm > $biggestterm ) { $biggestterm = $evalterm; } if ( $arFilter ){ # filter for trailing AR string. See repcard.conf $evalref->{$markfield} =~ s/\d+AR/AR/i; } # 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 records for student'}. ":\n"; print " $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 ]; # Fixed! was eval[$evalterm] = [ @temp ] } # Done stuffing eval recs into eval array (with reference). if ( $r_TermDisplayTrailing ) { # pad front of subject my $trailidx = $lastterm; # $sterm is passed starting term to print. while ( $trailidx < $eterm ) { # $startrptperiod is from subject record. my @temp = (); $temp[ $#objdesc ] = ''; # dimension that thar array. push @eval, [ @temp ]; $trailidx++; } } prSubject( $subjsec, $studnum, $currterm, $sterm, $eterm, \@eval ); # print subject. prComment( $subjsec, $studnum, $sterm, $eterm ); # print the comments (all) } # End of this subject; loop to print the next. # Now do the GPA row... if ( $r_calcgpa ) { calcGPA(\%gpa, $biggestterm ); print TEX "\\smallskip\n\n"; } # Now do the Ranking if ( $r_ShowRanking ) { #calcRanking(\%gpa, $biggestterm ); #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 ) { 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 ); # Additional comments } # Now finish off the report card; last term gets the promotion format. # There are 3 signature fns: Teacher, Principal, or Combo. Pick your mix. if ( $term != $r_finalterm ){ # Also... if no $teachersign value, then not shown... if ( $r_teachersign eq $lex{teacher} ){ prTeacherSig(); #Teacher Signature } elsif ( $r_teachersign eq $lex{principal} ){ prPrincipalSig(); #Principal Signature } elsif ( $r_teachersign eq $lex{combo}) { prComboSig(); # Combination Signature (both teacher / principal side by side.) } # print if we have a showTearoff (or not updated) if ( $r_showTearoff or not defined $r_showTearoff ){ if ( $r_PrintParentSig ) { # block them together $tearoffblock = 1; } prTearoff(); } # print a signature line for parents 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"); } } # 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. print "

". $lex{'Report Card Generation'}. "

\n"; if ( $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 "

\n"; print $lex{'View/Download/Print Report Cards'}. "

\n"; } else { # all in one. # Print ending of report #print TEX "\\end{center}\n"; print TEX "\\end{document}\n"; close TEX; system("$pdflatex $filename >pdflog$$.txt"); if ( $teachermode ) { $downloaddir = $tchdownloaddir; } system("mv $shortname.pdf $downloaddir"); system("mv pdflog$$.txt $downloaddir"); system("rm -f $shortname.*"); print "

\n"; print $lex{'View/Download/Print Report Cards'}. "

\n"; } print "[ ". $lex{'Report Card'}. " | \n"; print "". $lex{'View Log File'}. " ]\n"; print "
\n"; # ====== End of Main Section ================ #---------------- sub showStartPage { #---------------- my @subjects = (); my %subjdesc = (); if ( $teachermode ) { # we are running in teacher site # Get their subjects my $sth = $dbh->prepare("select subjsec, description from subject where teacher like '%($userid)' order by sequence, description "); $sth->execute; 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 = mkSchoolMonths( $currsdate ); # Format: yyyy-mm; first record is blank (zeroth) #print "Months:",@schoolmonths,"
\n"; # print group and groupid selection input form. print "

". $lex{'Report Card'}. "

\n"; print "
\n"; print "\n"; print "
\n"; print "\n"; print "\n\n"; print "\n\n "; print "\n\n"; print "\n\n"; # Paper Size $defaultpapersize =~ s/paper//; # strip out word paper so lex works; from admin.conf my $defpaper = ucfirst( $defaultpapersize ); print "\n\n "; print "\n\n "; if ( $teachermode ) { print "\n"; foreach my $subjsec ( @subjects ) { print "\n"; print "\n"; } } print "\n\n"; print "\n\n"; print "\n\n"; print "\n"; print "
". $lex{'Student Group'}. ""; print "\n "; print ""; if ( $teachermode ) { print q{ }. $lex{'Blank=All'}; } print "
". $lex{'Effective Date'}. ""; print "\n"; print "\n"; print "
". $lex{'Start Term'}. ""; print "
". $lex{'End Term'}. ""; print "
". $lex{'Paper Size'}. ""; print "
". $lex{'Font Size'}. ""; print "
". $lex{'Select Subjects'}. "
"; print "$subjdesc{$subjsec} ($subjsec)
". $lex{'Show Withdrawn Students'}. ""; print "
". $lex{'One Student per File'}. ""; print " "; print $lex{'For Duplexing/Stapling'}. "
". $lex{'Alternate Report Card System'}. ""; print "
\n"; print "
". $lex{'Override Term Days'}; print "
\n"; print "\n"; print "\n"; print "\n"; for my $i (1..$#schoolmonths) { my ($y,$m) = split /-/,$schoolmonths[$i]; print "\n"; } print "
". $lex{'Days per Month Override'}. "
". $lex{Month}. "". $lex{'Days Open'}; print "
$month[$m] ($schoolmonths[$i])"; print ""; print "
\n"; print "
\n"; print "
\n"; print "\n"; print "\n"; exit; } # end of showStartPage #-------------------- sub studentAltRepcard { #-------------------- # print single student report card to TEX file handle (already open). my ($studnum, $lastname, $firstname, $middlename, $grade, $homeroom, $birthdate) = @_; # Find Homeroom Teacher(s) my @teachers; my $sth = $dbh->prepare("select distinct lastname, firstname from staff where homeroom = ? order by lastname, firstname"); $sth->execute( $homeroom ); while ( my ($lastname, $firstname) = $sth->fetchrow ) { push @teachers, "$firstname $lastname"; } print TEX "\\thispagestyle{empty}\n\\setcounter{page}{1}\n"; print TEX "\\rhead{$firstname $middlename $lastname -- \\thepage}\n\\begin{center}\n"; print TEX "\\includegraphics[width=$r_Altdivlogowidth]{"; print TEX "$configpath/etc/$r_Divlogofile}\n"; print TEX "\\parbox[b]{$r_Altaddresswidth}{ "; print TEX "{\\Large $g_Divisionname\n\\vspace{$r_Altspacer} } }\n\n"; # second brace end of parbox. print TEX "\\vspace{15mm}\n"; print TEX "\\includegraphics[width=$r_Altlogowidth]{"; print TEX "$configpath/etc/$r_Altlogofile}\\quad \n\n"; print TEX "\\end{center}\n\n"; print TEX "\\vspace{15mm}\n"; # Student Identity print TEX "\\parbox{\\textwidth}{\\Large "; print TEX $lex{'Student Name'}. " {\\bf $firstname $lastname}\n\n"; print TEX $lex{'Date of Birth'}. " {\\bf $birthdate}\n\n"; print TEX $lex{'Teacher Name'}; foreach my $teacher ( @teachers ) { print TEX " {\\bf $teacher}\\quad\n"; } print TEX "\n\n"; print TEX $lex{Term}. " {\\bf $term}\n\n"; print TEX '{\\bf '. $schoolname. q{ }. $lex{'Pre-kindergarten Class'}. "}\n"; print TEX "}\n"; # End of Parbox above... print TEX "\\newpage\n\n"; # Next Page, Start all Subjects for this student. # Step 1 - get the subjects this student is enrolled in in this term, in order my $sth = $dbh->prepare("select distinct s.subjsec, s.description from rc_subject as s, rc_obj_eval as e, rc_objective as o where s.subjsec = o.subjsec and o.id = e.objid and e.studnum = ? and term = ? order by s.sequence, s.description"); $sth->execute( $studnum, $term ); if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } while ( my ( $subjsec, $subjdesc ) = $sth->fetchrow ) { ( $subjdesc ) = latex_filter( ($subjdesc ) ); print TEX "{\\begin{tabular}{|p{3cm}|p{5cm}|p{9.1cm}|}\\hline\n"; #push @subjects, $subjsec; # Now get all objectives in order and matching choice. my $sth1 = $dbh->prepare("select o.description, e.eval from rc_objective as o, rc_obj_eval as e where o.id = e.objid and o.subjsec = ? and e.studnum = ? and e.term = ? order by o.groupseq"); $sth1->execute( $subjsec, $studnum, $term ); if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } my $first = 1; while ( my ( $description, $eval ) = $sth1->fetchrow ) { ( $description, $eval ) = latex_filter( ( $description, $eval ) ); if ( $first ) { print TEX "$subjdesc & "; # removed ($subjsec) $first = 0; } else { print TEX ' &'; } print TEX "\\raggedleft $description & $eval \\\\ \n"; } print TEX "\\hline \\end{tabular}\n\n"; } # Not optional setting; Just comment out if you want. prMonthlyAttendance( $studnum ); print TEX "\\vspace{15mm}\n"; # Hardwired for Combo Only... #prTeacherSig(); #Teacher Signature #prPrincipalSig(); #Principal Signature #} elsif ($r_teachersign eq $lex{combo}) { prComboSig(); ## Combination Signature (both teacher / principal side by side.) print TEX "\n\\newpage\n"; return; } #---------------- 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 mm}} \\pagestyle{fancy} \\lhead{$schoolname -- $schoolyear} \\rfoot{ $lex{Printed}: $currdate } \\cfoot{ } \\begin{document} EOS1 } #---------- sub calcGPA { #---------- my $gpa_ref = shift; my $maxterm = shift; eval require "../../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 mm}|"; for ( 1..$maxterm ){ print TEX "p{$r_markspace mm}|";} print TEX "}\\hline\n"; print TEX "\\rowcolor[gray]{ $r_grayscale }"; print TEX "\\bf ". $lex{Term}. q{ }. $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 ( $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 for'}. " $letter\n"; next; # skip to next subject. } my $quality = $letterToQual{ $letter } + $difficulty; $termGPQuality += $quality * $credit; $totalGPQuality += $quality * $credit; $termAttempts += $credit; if ( $letter ne $failletter ) { $termCredits += $credit; $totalCredits += $credit; } # If not a fail and also not a pass/fail course if ( $letter ne $passletter ) { $totalGPCredits += $credit; $termGPCredits += $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 ), 2 ); } 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), 2 ); } 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 { #--------------- # this calculates the number of schooldays in a date range # taking school holidays into account. # Requires: $dbh, Date::Business my ($startdate, $enddate) = @_; # It likes it in yyyymmdd format... $startdate =~ s/-//g; # strip out hyphens. $enddate =~ s/-//g; my $end = new Date::Business(DATE=>$enddate); my $start = new Date::Business(DATE=>$startdate); my $schooldays = $end->diffb($start,'prev','next'); $schooldays++; # We now have the number of school days in current term # excluding holidays/pd days. # Now find holidays my $sth = $dbh->prepare("select * from dates where to_days(date) >= to_days('$startdate') and to_days(date) <= to_days('$enddate')"); $sth->execute; if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr;} my $holidays = $sth->rows; # Number of holidays in current term. my $termdays = $schooldays - $holidays; return $termdays; } #----------------- 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 ) = @_; print TEX "\\thispagestyle{empty}\n\\setcounter{page}{1}\n"; #print TEX "\\markright{$schoolname -- $schoolyear \\hfill "; print TEX "\\rhead{$firstname $middlename $lastname -- \\thepage}\n\\begin{center}\n"; if ( $r_Showlogo ) { 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\\\\"; } print TEX "$schoolcity, $schoolprov $schoolpcode\\\\"; # Phones Lines if ( $schoolphone ) { print TEX $lex{Phone}. " $schoolphone "; if ( $r_ShowAdmins ) { print TEX "\\hfill ";} else { print TEX "\\qquad "; } } if ( $schoolfax ) { print TEX $lex{Fax}. " $schoolfax"; } print TEX "\\\\\n\n"; # Administrator Lines if ( $r_Showadmins ) { print TEX "$r_Principal \\hfill $r_Viceprincipal \\\\\n\n"; print TEX "{\\footnotesize ". $lex{Principal}; print TEX "\\hfill ". $lex{'Vice-Principal'}; print TEX "}\\\\\n\n"; } print TEX "\\vspace{$r_AddressSpacer}\n\n"; print TEX " \\end{center}}\\qquad\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 ". $lex{Grade}; print TEX " $grade ". $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 @teachers = @_; print TEX "\\begin{center}\n"; print TEX "\\setlength{\\extrarowheight}{0pt}\n"; print TEX "\\begin{tabular}{ll}\n{\\small\\bf "; print TEX $lex{'Homeroom 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.conf my $schemeAlt1 = $r_evalschAlt1{$grade}; my $first; if ( @{$r_eval{$scheme}} ) { $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 $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"; } } # end of print grade scheme #------------ sub prSubject { # Print subject entry #------------ # @eval array set with current subjsec, and refs... # $sterm, and $eterm 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, $sterm, $eterm, $evalref ) = @_; my @eval = @{ $evalref }; # Get subject info for this subject; my $sth = $dbh->prepare("select description, teacher, startrptperiod, endrptperiod, calcavg from subject where subjsec = ?"); $sth->execute( $subjsec ); if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } my ( $description, $teacher, $startterm, $endterm, $calcavg ) = $sth->fetchrow; if ( $calcavg eq 'N' ) { $calcavg = 0; } # # 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 ); # Eval Table Transformation Directives # Typical for British type schools $r_ColumnTransform{'Exam'} = [ 1, 3 ]; my $maxcols = $#eval; # Given eval[cols][rows] or eval[term][objective] my $maxrows = $#{$eval[0]}; # Loop through objective transforms, if any foreach my $objective ( keys %r_ColumnTransform ) { # Find index of the objective to transform into column my $objrowidx; for my $idx ( 1 .. $maxrows ) { if ( $eval[0][$idx] eq $objective ) { $objrowidx = $idx; last; } } if ( not $objrowidx ) { next; } # jump out if no objective to do. # Hash of the new columns to be created; $newcols{term} my %newcols = (); foreach my $val ( @{ $r_ColumnTransform{$objective} } ) { $newcols{$val} = 1; } # rewrite and remove objective row and put into @tempvalues; my @transeval = (); my @tempvalues = (); # rewrite without objective row of interest. for my $colidx ( 0 .. $maxcols ) { $transeval[$colidx] = [ ]; # ref to new array. for my $rowidx ( 0 .. $maxrows ) { if ( $rowidx == $objrowidx ) { $tempvalues[$colidx] = $eval[$colidx][$rowidx]; } else { push @{ $transeval[$colidx] }, $eval[$colidx][$rowidx]; } } } # rewrite and add in extra cols my @neweval = (); foreach my $colref ( @transeval ) { push @neweval, $colref; my $term = $colref->[0]; if ( $newcols{ $term } ) { # want new column after this term col my $arrayref = [ ]; # create new blank array ref. $arrayref->[0] = $objective. ":$term"; $arrayref->[1] = $tempvalues[ $term ]; push @neweval, $arrayref; } } # done rewrite with new cols; # DEBUG - print out 2D array #my $maxcols = $#neweval; #my $maxrows = $#{$neweval[0]}; #print "New Eval: $subjsec"; #print ""; #for my $rowidx ( 0 .. $maxrows ) { # print ""; # for my $colidx ( 0 .. $maxcols ) { # print "\n"; # } # print "\n"; #} #print "
$neweval[$colidx][$rowidx]
\n"; # DEBUG End @eval = @neweval; } # end of Transforms # 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; } else { $totalscore += $evalref->[1]; if ( $evalref->[1] ) { # if we have a score, add a weight; $totalweight++; } } } if ( $totalweight ) { $averagemark = $totalscore / $totalweight; } else { $averagemark = 0; } $averagemark = format_number( $averagemark, 0, 0); } # Check if we should add the Personal Growth Key... if ( $personal_growth_flag ) { # print row with objectives... my $key = $r_pdevalgrp{$grade}; if ( @{ $r_pdeval{$key} } ) { # if we have a non blank objective group... print TEX "{\\sf\\large\\bf $description ". $lex{'Evaluation Key'}. " }\n\n"; } for my $item ( @{ $r_pdeval{$key} } ){ ( $item ) = latex_filter( $item ); print TEX "$item\n\n"; } print TEX "\\setlength{\\textwidth}{$textwidth}\n"; } #------- # print "Original Eval: $subjsec"; # print ""; # # 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 mm}|"; foreach my $ref ( @eval ) { print TEX "p{$r_markspace mm}|"; } if ( $calcavg ){ print TEX "p{$r_markspace mm}|"; } print TEX "}\\hline\n"; # pull off first column of objectives my @objectives = @{ shift @eval }; shift @objectives; # remove top blank one. @objectives = latex_filter( @objectives ); # my $size = @objectives; # print "Obj: $size "; # foreach my $ob ( @objectives ) { print "#$ob:"; } # print "
\n"; # Get Teacher Information my ($tch,$tid) = split /\(/, $teacher; $tid =~ s/\)//; if ( not $tid ) { $tid = $tch; } # for when we remove name from userid fld my $sth = $dbh->prepare("select sal, firstname, lastname from staff where userid = ? "); $sth->execute( $tid ); if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } my ($sal, $firstname, $lastname) = $sth->fetchrow; my $subjectteacher; if ( $lastname ) { $subjectteacher = "($sal $lastname)"; } # Print Term Line with Subject name, Teacher and term numbers. print TEX "\\rowcolor[gray]{ $r_grayscale }"; print TEX "{\\sf\\large\\bf $description} $subjectteacher"; foreach my $ref ( @eval ) { my $title = $ref->[0]; # top of column if ( $r_ColumnDisplay{ $title } ) { # if defined, reset $title = $r_ColumnDisplay{ $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 = calcSubjectAttendance( $subjsec, $studnum ); if ( $absents == 0 ) { $absents = '0'; } # so it shows... my $objcount = 1; foreach my $objective ( @objectives ) { # Skip showing 'Mark' objective and show attendance if ( $r_ShowSubjectAttendance and $objcount == 1 ) { # only on line 1 # # if ( defined $absents ) { print TEX $lex{Absent}. " $absents ". $lex{'Period(s)'}; 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; } # #} elsif ( $objective ne $lex{Mark} ) { # 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 prSubject #------------ sub prComment { # print all the comments. #------------ my ( $subjsec, $studnum, $sterm, $eterm ) = @_; 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 >= $sterm and $term <= $eterm ) { $comments{$term} = $comment; } } if ( not %comments ) { return; } my $sth = $dbh->prepare("select calcavg from subject where subjsec = ?"); $sth->execute( $subjsec ); if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } my $calcavg = $sth->fetchrow; # Figure out Comment Width. my $width = $r_subjspace + ($#eval * $r_markspace) + ($#eval * 0.6); if ( $calcavg ){ $width = $width + $r_markspace;} print TEX "\n\\parbox{$width mm}{\n"; foreach my $term ( sort keys %comments ) { if ( not $comments{$term} ) { next; } my ($comment) = latex_filter ( $comments{$term} ); $comment =~ s/\s*[\n|\r]/ /g; print TEX "\n{\\bf ". $lex{Term}. " $term:} {\\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: @schoolmonths - ordering of school months. # %schooldays - days in each month in hash. # $periodsperday - number of periods in the school day. # calculate attendance, one for each month. for ( 1..$#schoolmonths ) { my $absrec = calcMonthlyAttendance($studnum, $schoolmonths[$_], $periodsperday, $currsdate, \%lex ); ( $absent{$_}, $tardy{$_} ) = split /:/,$absrec; #print "SN:$studnum MN:$schoolmonths[$_] AB:$absent{$_} #LT:$tardy{$_}
\n"; } # calculate enrollment, one for each month # First find starting value for $active... was student enrolled at start my $sth = $dbh->prepare("select type from transfer where studnum = ? and to_days(date) >= to_days('$schoolstart') order by date desc"); $sth->execute( $studnum ); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;} my $etype = $sth->fetchrow; my $sth1 = $dbh->prepare("select lastname, firstname from studentall where studnum = ?"); $sth1->execute( $studnum ); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;} my ($lastname, $firstname) = $sth1->fetchrow; # If withdraw during year or no record, must have been enrolled at start if ($etype eq 'withdraw' or not $etype){ $active = 1;} else { $active = 0;} #print "$lastname, $firstname ETYPE: $etype ACT: $active
\n"; for my $monthidx (1..$#schoolmonths){ my $enrolrec = calcMonthlyEnrollment( $studnum, $schoolmonths[ $monthidx ], $active); ( $enrolled{ $monthidx }, $active ) = split /:/, $enrolrec; #print "---SN: $studnum ACT: $active
\n"; #print "SN:$studnum Month:$schoolmonths[$monthidx] ACT:$active
\n"; } # Print Start of Attendance Table print TEX "\\begin{center}\n"; # Setup Table print TEX "\\medskip\n\\begin{tabular}{|p{32mm}|\n"; for (1..$#schoolmonths){ print TEX "p{8mm}|"; } print TEX "}\n"; # Print Heading Line my $colcount = $#schoolmonths + 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"; for (1..$#schoolmonths){ my ($yr,$mn) = split /-/, $schoolmonths[$_]; print TEX "& \\hfil $s_month[$mn] \\hfil \n"; } print TEX "\\\\\\hline\n"; # Print Days Open print TEX "{\\large\\bf ". $lex{'Days Open'}. "}\n"; my $daysopen; for my $idx (1..$#schoolmonths){ if ( $idx == $#schoolmonths and not $override ) { # last month in schoolmonths array. # We are at end of current period... find the last day of this term. # $term =~ s/\s//g; # strip any spaces in the $term value... # my ($myear, $mmonth, $mday) = split /-/, $g_termend{ $term }; #print "Y: $myear M:$mmonth D:$mday
\n"; if ( $schoolmonths[$idx] eq "$myear-$mmonth" ) { # We are in last month of term. $daysopen = calcDaysBetween( "$myear-$mmonth-01" , $g_termend{ $term } ); #$daysopen += 2; # add on either end day (1st and last day of term). print TEX "& \\hfil $daysopen \\hfil \n"; #print "DAYS OPEN: $daysopen
\n"; } else { print TEX "& \\hfil $schooldays{$schoolmonths[$idx]} \\hfil \n"; } } else { print TEX "& \\hfil $schooldays{$schoolmonths[$idx]} \\hfil \n"; } } print TEX "\\\\\\hline\n"; # Print Days Enrolled print TEX "{\\large\\bf ". $lex{'Days Enrolled'}. "}\n"; for my $idx (1..$#schoolmonths){ if ($schooldays{$schoolmonths[$idx]} != $enrolled{$idx} and $override and $enrolled{$idx} ) { my $do = $schooldaysorig{$schoolmonths[$idx]}; # Days Open my $ado = $schooldays{$schoolmonths[$idx]}; # Adjusted Days Open my $de = $enrolled{$idx}; # Days Enrolled. #print "
SCHOOL DAYS:",%schooldaysorig,"
\n"; #print "$student[1] $student[2] DO: $do ADO: $ado DE: $de
\n"; my $ade = format_number( ($de * $ado / $do), 2); print TEX "& \\hfil $ade \\hfil \n"; #print "$student[1] $student[2] MON: $schoolmonths[$idx] override
\n"; } else { if ( $idx == $#schoolmonths and $daysopen ) { # last month... print TEX "& \\hfil $daysopen \\hfil \n"; # was: $enrolled{$idx}; $daysopen set above. } else { print TEX "& \\hfil $enrolled{$idx} \\hfil \n"; } } } print TEX "\\\\\\hline\n"; # Print Days Absent print TEX "{\\large\\bf ". $lex{'Days Absent'}. "}\n"; for (1..$#schoolmonths){ $absent{$_} = format_number( $absent{$_}, 2, 0); print TEX "& \\hfil $absent{$_} \\hfil\n"; } print TEX "\\\\ \\hline\n"; # Print Periods Late print TEX "{\\sf\\large\\bf ". $lex{'Periods Late'}. "}\n"; for ( 1..$#schoolmonths ){ print TEX "& \\hfil $tardy{$_} \\hfil\n"; } print TEX "\\\\ \\hline\n"; # Finish Attendance Box print TEX "\\end{tabular}\n"; print TEX "\\end{center}\n"; print TEX "\\bigskip\n"; } #----------------- sub prAttendance { # UNUSED: REMOVE in 4.00+ Older Attendance Block (not Monthly, but Term based ) #----------------- # calculate attendance for (1..$term){ $absrec = calcAttendance($studnum, $g_termstart{$_},$g_termend{$_}, $periodsperday); ($absent{$_},$tardy{$_}) = split /:/,$absrec; } # Print Start of Attendance Table print TEX "\\newpage \\begin{center}{\\sf\\bf\\Large "; print TEX $lex{Attendance}. "}\n\n"; print TEX "\\medskip\n\\begin{tabular}{|p{2in}|\n"; for (1..$term){ print TEX "p{0.75in}|"; } # Print Title Line print TEX "}\\hline \n \\rowcolor[gray]{ $r_grayscale }\n"; for (1..$term){ print TEX "& \\hfil Term $_ \\hfil \n"; } print TEX "\\\\\\hline\n"; # Print Days Open print TEX "{\\sf\\large\\bf ". $lex{'Days Open'}. "}\n"; for (1..$term){ print TEX "& \\hfil $termdays{$_} \\hfil \n"; } print TEX "\\\\\\hline\n"; # Print Days Absent print TEX "{\\sf\\large\\bf ". $lex{'Days Absent'}. "}\n"; for (1..$term){ print TEX "& \\hfil $absent{$_} \\hfil\n"; } print TEX "\\\\ \\hline\n"; # Print Periods Late print TEX "{\\sf\\large\\bf ". $lex{'Periods Late'}. "}\n"; for (1..$term){ print TEX "& \\hfil $tardy{$_} \\hfil\n"; } print TEX "\\\\ \\hline\n"; # Finish Attendance Box print TEX "\\end{tabular}\\end{center}\n \\bigskip\n"; } # End of Attendance #---------------- sub prAddComments { #---------------- my $studnum = shift; # Updated to show additional comment data for each student. # Now get student information for this student for this term. my $sth = $dbh->prepare("select eval.id, eval.comment, eval.term from eval,subject where subject.description = '$additionalcomments' and subject.subjsec = eval.subjcode and eval.studnum = '$studnum' order by eval.term, eval.subjcode"); $sth->execute; if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;} print TEX "{\\bf ". $lex{'Additional Comments'}. ":}\n\n"; my $currterm = -1; my $prevterm; while (my ($id,$comment,$trm) = $sth->fetchrow) { if (not $comment) { next; } $comment =~ s/\s*[\n\r]/ /g; #print "I:$id S:$studnum T:$trm C:$comment
\n"; $prevterm = $currterm; $currterm = $trm; if ($prevterm != $currterm) { print TEX "{\\bf ". $lex{Term}. " $currterm:} "; } ($comment) = latex_filter(($comment)); # list context required by sub 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 {\\small "; print TEX $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{Date}. ":} {\\it $currdate}\n\n"; print TEX "{\\bf ". $lex{Comments}. ":}\n\n"; if ( $tearoffblock ) { print TEX "} \n "; } } #------------ sub prYearEnd { #------------ my $studentname = shift; my ($yearstart,$yearend) = split /-/, $schoolyear; # global my $nextgrade; if ($grade eq 'PK'){ $nextgrade = 'K';} elsif ($grade eq 'K'){ $nextgrade = 1;} else { $nextgrade = $grade + 1;} my $tempTex = $r_placementTex; # Replace variables. $tempTex =~ s/%studentname%/$studentname/; $tempTex =~ s/%nextgrade%/$nextgrade/; $tempTex =~ s/%schoolyearend%/$yearend/; 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; # 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 eq $absentUnexcused ) { $periods += $count; } elsif ( $reason eq $lateUnexcused ) { if ( $r_LateAbsentRatio ) { $periods += ( $count / $r_LateAbsentRatio ); } else { $periods += $count / 3; # default to 3 Late = 1 Absent } } # No other reasons affecting. } #print "P:$periods
\n"; if ( not defined $periods ) { return undef; } elsif ( not $periods ) { $periods = '0'; } return format_number( $periods, 2); }