#! /usr/bin/perl # Copyright 2001-2023 Leslie Richardson # This file is part of Open Admin for Schools. # This is a DUAL RUN script. It runs in /tcgi and also /cgi/repcard. # Outline: This prints a full xtab report for a single grade/course. All # objectives are perpendicular. # Outline: 1) Find all the students in the group (class/section/grade). # 2) Loop through all eval records for the selected term to find all # of the courses. # 3) Load all courses into a 2D array. Baseref->Arrayptr1->[0], etc. # Order by subjsec, name of subject, then any objectives next (start # at array index 2) my %lex = ('Year End' => 'Year End', 'Report' => 'Report', 'Missing' => 'Missing', 'Group' => 'Group', 'Grade' => 'Grade', 'Homeroom' => 'Homeroom', 'View/Download' => 'View/Download', 'Download' => 'Download', 'File' => 'File', 'Teacher' => 'Teacher', 'Principal' => 'Principal', 'View Log File' => 'View Log File', 'Report Card' => 'Report Card', 'Main' => 'Main', 'Short Subject Descriptions' => 'Short Subject Descriptions', 'Note' => 'Note', 'Page' => 'Page', 'Term' => 'Term', 'No Student(s) Found' => 'No Student(s) Found', 'Y' => 'Y', 'Error' => 'Error', 'Continue' => 'Continue', 'Select by' => 'Select by', 'Paper Size' => 'Paper Size', 'Letter' => 'Letter', 'A4' => 'A4', 'Legal' => 'Legal', 'Student(s)' => 'Student(s)', 'Output' => 'Output', 'Combine failed' => 'Combine failed', 'End' => 'End', 'OR' => 'OR', 'Cannot open' => 'Cannot open', 'Form' => 'Form', ); my $self = 'rptfinalsumm.pl'; use DBI; use CGI; use Cwd; use Number::Format qw(:all); # Constants # These two settings control the vertical height of the header. my $objectivelength = 36; # number of characters to truncate objectives to. my $offset = "25mm"; # Strut length in print_header fn. my $maxstudents = 32; # Number of student rows per page; if you adjust above, # this may have to change also. my $maxlegalcols = 16; # maximum number of columns per printed page. my $maxlettercols = 16; # Get current dir so know what path for config files. my $configpath; if (getcwd() =~ /tcgi/){ # we are in tcgi $configpath = '..'; # go back one to get to etc. } else { $configpath = '../..'; # go back two to get to etc. } eval require "$configpath/etc/admin.conf"; if ( $@ ) { print $lex{Error}. ": $@
\n"; die $lex{Error}. ": $@\n"; } eval require "$configpath/etc/repcard.conf"; if ( $@ ) { print $lex{Error}. ": $@
\n"; die $lex{Error}. ": $@\n"; } eval require "$configpath/lib/liblatex.pl"; if ( $@ ) { print $lex{Error}. ": $@
\n"; die $lex{Error}. ": $@\n"; } eval require "$configpath/lib/libattend.pl"; 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 ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $iddst) = localtime(time); $year = $year + 1900; $mon++; $wday++; my $currlongdate = "$dow[$wday], $month[$mon] $mday, $year"; my $currdate = "$month[$mon] $year"; # $mday removed if (length($mon) == 1){ $mon = '0'.$mon;} if (length($mday) == 1){ $mday = '0'.$mday;} my $currsdate = "$year-$mon-$mday"; my $dsn = "DBI:$dbtype:dbname=$dbase"; my $dbh = DBI->connect($dsn,$user,$password); $dbh->{mysql_enable_utf8} = 1; my $q = new CGI; print $q->header( -charset, $charset ); my %arr = $q->Vars; my $term = $arr{term}; # Print the Page Header my $title = "$lex{'Year End'} $lex{Report}"; print qq{$doctype\n$title $chartype\n\n}; print qq{
[ $lex{Main} \n}; if ( not (getcwd() =~ tcgi) ) { # not running in tcgi print qq{| $lex{'Report Card'}\n}; } print qq{ ]
\n}; print qq{

$title

\n}; if ( not $arr{page} ) { showStartPage(); } else { delete $arr{page}; # foreach my $key (sort keys %arr ) { print qq{K:$key V:$arr{$key}
\n}; } if ( not $arr{term} ) { print qq{

Missing End Term

\n}; print qq{\n}; exit; } if ( not $arr{grade} and not $arr{homeroom} ) { print qq{

Missing Grade/Homeroom

\n}; print qq{\n}; exit; } if ( $arr{output} eq 'pdf' ) { delete $arr{output}; makePDF(); } elsif ( $arr{output} eq 'csv') { delete $arr{output}; makeCSV(); } } #---------- sub makeCSV { #---------- #foreach my $key ( sort keys %arr ) { print qq{K:$key V:$arr{$key}
\n}; } use Text::CSV_XS; my $csv = Text::CSV_XS->new( {binary => 1} ); # End term my $endterm = $arr{term}; # final term delete $arr{term}; # Join sections my $joinsection; if ( $arr{joinsection} ) { $joinsection = $arr{joinsection}; delete $arr{joinsection}; } # group and group_value my $group = 'grade'; my $group_value = $arr{grade}; if ( $arr{homeroom} ) { $group_value = $arr{homeroom}; $group = 'homeroom'; } if ( not $group_value ) { print qq{

Missing Grade/Homeroom value

\n}; print qq{\n}; exit; } # Get Students First; by grade or homeroom. my $sth = $dbh->prepare("select studnum, lastname, firstname, grade, homeroom from student where $group = ? order by lastname, firstname"); $sth->execute( $group_value ); if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; } my (%names, %grades,%homerooms); # names{studnum} = "last,first"; %grades{grade}[studnum]; while ( my $ref = $sth->fetchrow_hashref ) { my %r = %$ref; $names{$r{studnum}} = qq{$r{lastname}, $r{firstname}}; $homerooms{$r{studnum}} = $r{homeroom}; push @{ $grades{$r{grade}} }, $r{studnum}; # so we have sorted students. # @test = @{ $grades{$r{grade}} }; # not used. } if ( not %names ) { print qq{

$lex{'No Student(s) Found'}

\n}; print qq{\n}; exit; } # Open output file # my $filename = "rptfinal$$.csv"; my $filename = "rptfinal$$.csv"; open (EX,">$filename") || die $lex{'Cannot open'}. " $fileName"; # Get Courses my $sth1 = $dbh->prepare("select distinct subjcode from eval where term = ? and studnum = ?"); # Collect all the courses taken by this group of students. my %courses; # note a hash so we can get multiple subjsec of same key value. foreach my $grade ( sort keys %grades ) { foreach my $studnum ( @{ $grades{$grade}} ) { $sth1->execute( $term, $studnum ); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } while ( my $subjsec = $sth1->fetchrow ) { # Skip Unwanted Courses my ($subjcode, $section) = split('-', $subjsec); if ( $r_SupressSubject{$subjsec} or $r_SupressSubject{$subjcode} or $r_AdditionalComments{$subjsec} or $r_AdditionalComments{$subjcode} ) { next; } $courses{$subjsec} = 1; } } } if ( not %courses ) { print qq{

No Courses Found!

\n}; print qq{\n}; exit; } my %courseinfo; # $courseinfo{subjsec} = ref; my @courses; # set in loop below, giving correct ordering, just in case. my %sections; # sections{subjcode}{subjsec} = 1; foreach my $subjsec ( sort keys %courses ){ my ($subjcode, $section) = split('-', $subjsec); # Get Course Information; pull in full record $sth = $dbh->prepare("select * from subject where subjsec = ?"); $sth->execute( $subjsec ); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } my $ref = $sth->fetchrow_hashref; my %r = %$ref; $sections{$subjcode}{$subjsec} = 1; $courseinfo{$subjsec} = $ref; # If no short description, then long version truncated into short desc. if ( not $r{smdesc} ){ if ( length( $r{description} ) > $objectivelength ) { $r{smdesc} = substr( $r{description},0,$objectivelength); # trunc full desc } else { # length is ok. $r{smdesc} = $r{description}; } } push @courses, $subjsec; } # end of course loop # print qq{Courses:@courses
Sections:}, %sections, "
\n"; if ($joinsection) { # make courses into subject code version. @courses = sort keys %sections; } use Text::CSV_XS; my $csv = Text::CSV_XS->new( {binary => 1} ); # Header Line my @line; my $groupname; if ( $group eq 'grade' ) { $groupname ="$lex{Grade} $group_value"; } else { $groupname = "$lex{Homeroom} $group_value"; } push @line, 'HRm'; push @line, $groupname; if ( $joinsection ) { foreach my $subjcode ( @courses ) { my @tempsec = sort keys %{ $sections{$subjcode}}; # get all subjsecs for this course. # we'll only use the first one to get description my %r = %{ $courseinfo{$tempsec[0]}}; # was subj my $desc = $r{smdesc}; if ( $arr{coursedesc} eq 'subjsec' ) { $desc = $subjsec; } elsif ( $arr{coursedesc} eq 'both' ) { $desc = $r{smdesc}. qq{ - $subjsec}; } push @line, $desc; } } else { # show all sections. foreach my $subjsec ( @courses ) { my %r = %{ $courseinfo{$subjsec}}; my $desc = $r{smdesc}; if ( $arr{coursedesc} eq 'subjsec' ) { $desc = $subjsec; } elsif ( $arr{coursedesc} eq 'both' ) { $desc = $r{smdesc}. qq{ - $subjsec}; } push @line, $desc; } } push @line, "Attend"; push @line, "Promotion"; if ( $csv->combine( @line ) ) { my $record = $csv->string; print EX $record, "\r\n"; } else { my $err = $csv->error_input; print qq{$lex{'Combine failed'}: $err\n\n}; } # End of Header Line my $sth1 = $dbh->prepare("select grade from studentall where studnum = ?"); my $sth2 = $dbh->prepare("select count(*) from student where studnum = ?"); my $sth3 = $dbh->prepare("select endrptperiod from subject where subjsec = ?"); my $sth4 = $dbh->prepare("select calcavg from subject where subjsec = ?"); my $sth5 = $dbh->prepare("select $r_MarkField, term from eval where studnum = ? and subjcode = ?"); # equiv to $subjsec # foreach my $grade ( sort keys %grades ) { # my @student = @{ $grades{$grade} }; # for my $studnum ( @student ) { # print "SN:$studnum
\n"; # } # } # Student Loop foreach my $grade ( sort keys %grades ) { my @students = @{ $grades{$grade}}; foreach my $studnum ( @students ) { my @line; # grade; needed for ppd. $sth1->execute( $studnum ); if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;} my $gr = $sth1->fetchrow; # # Find $active value (ie. currently enrolled ) $sth2->execute( $studnum ); if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;} my $active = $sth2->fetchrow; # # calc attendance values for this student # several values from admin.conf config file. my $dayspresent = calcMyAttendance($studnum, $schoolstart, $schoolend, $g_ppd{$gr},$active); $dayspresent = format_number($dayspresent, 2, 2); push @line, $homerooms{$studnum}; push @line, "$names{$studnum} ($studnum)"; #-------------------- if ( $joinsection ) { # Loop through each course for this student and print eval results. foreach my $subjcode (@courses) { my $testavg; # calculated in the sections below foreach my $subjsec ( sort keys %{ $sections{$subjcode}} ) { # Get the calcavg value (N or Y); $sth4->execute( $subjsec ); if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; } my $calcavg = $sth4->fetchrow; if ( $calcavg eq $lex{Y} ) { # find average using r_AverageWeight by term $sth5->execute( $studnum, $subjsec ); if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; } my ($totalscore, $totalweight); while ( my ($score,$term) = $sth5->fetchrow ) { if ( $score =~ m/\d/){ # if a digit... if (not $r_AverageWeight{$term} ) { # Error print qq{

No Average Weight (r_AverageWeight) defined }; print qq{for this term: $term

\n}; print qq{\n}; exit; } my $wt = $r_AverageWeight{$term}; #The weight for this term $totalscore += ( $wt * $score ); $totalweight += $wt; #print qq{
Score:$score Term:$term Weight:$wt
\n} } } if ( $totalweight ){ # We have some tests. $testavg = $totalscore / $totalweight; $testavg = format_number( $testavg, 1,1); } else { $testavg = ' '; } # print qq{
$subjsec Term $endterm Mark $testavg
\n}; } else { # We just find the final term mark # course and get that term's value from eval table; # Get End Reporting period for final mark # $sth3->execute( $subjsec ); # if ($DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } # my $endterm = $sth3->fetchrow; my $sth = $dbh->prepare("select $r_MarkField from eval where studnum = ? and term = ? and subjcode = ?"); $sth->execute( $studnum, $endterm, $subjsec ); if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; } $testavg = $sth->fetchrow; $testavg =~ s/\%//; # strip any percents. # print qq{
$subjsec Term $endterm Mark $testavg
\n}; } if ( $testavg =~ m/\d/ ) { last; } # we have our number. } # end of subjsec loop push @line, $testavg; } # end of courses loop } else { # end of joinsection loop; normal course loop below # Loop through each course for this student and print eval results. foreach my $subjsec (@courses) { my $testavg; # for this course # Get the calcavg value (N or Y); $sth4->execute( $subjsec ); if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; } my $calcavg = $sth4->fetchrow; if ( $calcavg eq $lex{Y} ) { # find average using r_AverageWeight by term $sth5->execute( $studnum, $subjsec ); if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; } my ($totalscore, $totalweight); while ( my ($score,$term) = $sth5->fetchrow ) { if ( $score =~ m/\d/){ # if a digit... if (not $r_AverageWeight{$term} ) { # Error print qq{

No Average Weight (r_AverageWeight) defined }; print qq{for this term: $term

\n}; print qq{\n}; exit; } my $wt = $r_AverageWeight{$term}; #The weight for this term $totalscore += ( $wt * $score ); $totalweight += $wt; # print qq{
Score:$score Term:$term Weight:$wt
\n} } } if ( $totalweight ){ # We have some tests. $testavg = $totalscore / $totalweight; $testavg = format_number( $testavg, 1,1); } else { $testavg = ' '; } # print qq{
$subjsec Term $endterm Mark $testavg
\n}; } else { # We just find the final term mark # course and get that term's value from eval table; # Get End Reporting period for final mark # $sth3->execute( $subjsec ); # if ($DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } # my $endterm = $sth3->fetchrow; my $sth = $dbh->prepare("select $r_MarkField from eval where studnum = ? and term = ? and subjcode = ?"); $sth->execute( $studnum, $endterm, $subjsec ); if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; } $testavg = $sth->fetchrow; $testavg =~ s/\%//; # strip any percents. # print qq{
$subjsec Term $endterm Mark $testavg
\n}; } push @line, $testavg; } # end of courses loop } # end of non section join. push @line, $dayspresent; # print qq{Line:", @line, "
\n}; if ( $csv->combine( @line ) ) { my $record = $csv->string; print EX $record, "\r\n"; } else { my $err = $csv->error_input; print qq{$lex{'Combine failed'}: $err\n\n}; } $studcount++; } # End of Student Loop } # end of grades loop # alter for tcgi (teacher) functioning if ( getcwd() =~ tcgi ) { $downloaddir = $tchdownloaddir; $webdownloaddir = $tchwebdownloaddir; } close EX; system("mv $filename $downloaddir"); print qq{

[ }; print qq{$lex{Download} CSV $lex{File} ]

\n}; print qq{\n}; exit; } # end of makeCSV #---------- sub makePDF { #---------- # foreach my $key ( sort keys %arr ) { print qq{K:$key V:$arr{$key}
\n}; } # Join sections my $joinsection; if ( $arr{joinsection} ) { $joinsection = $arr{joinsection}; delete $arr{joinsection}; } # Set Local Term Value my $endterm = $arr{term}; delete $arr{term}; # group and group_value my $group = 'grade'; my $group_value = $arr{grade}; if ( $arr{homeroom} ) { $group_value = $arr{homeroom}; $group = 'homeroom'; } if ( not $group_value ) { print qq{

Missing Grade/Homeroom value

\n}; print qq{\n}; exit; } # Set paper size. my ( $papersize, $textheight, $textwidth, $maxcolumns ); if ( $arr{papersize} eq 'legal' ) { $textwidth = $g_legalpaper_textwidth; $textheight = $g_legalpaper_textheight; $papersize = 'legalpaper'; $maxcolumns = $maxlegalcols; } elsif ( $arr{papersize} eq 'a4' ) { $textwidth = $g_a4paper_textwidth; $textheight = $g_a4paper_textheight; $papersize = 'a4paper'; $maxcolumns = $maxlettercols; } else { # Letter $textwidth = $g_letterpaper_textwidth; $textheight = $g_letterpaper_textheight; $papersize = 'letterpaper'; $maxcolumns = $maxlettercols; } # $schoolstart and $schoolend defined in the admin.conf config file. my $schoolDaysInYear = calcDaysOpen($schoolstart,$schoolend, $dbh); # print qq{School Days: $schoolDaysInYear\n}; # Must be passed a grade or homeroom. if ( not $group_value ) { print qq{

$lex{Missing} $lex{Group}

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

$lex{'No Student(s) Found'}

\n}; print qq{\n}; exit; } # Setup TEX Code my $shortname = "summarkend$$"; my $filename = "$shortname.tex"; open(TEX,">$filename") || die "Can't open tex file"; # removed landscape here... print TEX "\\documentclass[10pt,$papersize]{article} \\usepackage{array,rotating,inputenc} $a_latex_header \\pagestyle{empty} \\setlength{\\textwidth}{$textwidth} \\setlength{\\textheight}{$textheight} \\setlength{\\hoffset}{-20mm} \\setlength{\\voffset}{-13mm} \\setlength{\\topmargin}{0in} \\setlength{\\headheight}{0mm} \\setlength{\\headsep}{0mm} \\setlength{\\parindent}{0mm} \\setlength{\\evensidemargin}{0mm} \\setlength{\\oddsidemargin}{0mm} \\setlength{\\tabcolsep}{1pt} \\setlength{\\extrarowheight}{4pt}\n"; print TEX "\\begin{document}\\begin{center}\n"; if ($divisionname){ print TEX "{\\huge\\sf $divisionname}\n\n"; } else { print TEX "{\\huge\\sf $schoolname}\n\n"; } print TEX "{\\bf\\large $lex{'Year End'} $lex{Report}}\n\n"; print TEX "{\\bf\\large "; if ( $group eq 'grade' ) { print TEX $lex{Grade}; } else { print TEX $lex{Homeroom}; } print TEX " $group_value -- $schoolyear}"; print TEX "\\end{center}\n\n"; # Collect all the courses taken by this group of students. # $sections{subjcode}{$subjsec} = 1; all sections for this subject code my (@courses, %desc, %desccode, %sections, %subjects ); # refactor layout my $sth1 = $dbh->prepare("select distinct subjcode from eval where term = ? and studnum = ?"); # subjcode is really subjsec # put all subjsec, subjcode into hashes; no array yet. foreach my $studnum ( @students ) { $sth1->execute( $endterm, $studnum); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } while ( my $subjsec = $sth1->fetchrow ) { my ($subjcode,$section) = split('-', $subjsec); if ( $r_SupressSubject{$subjsec} or $r_SupressSubject{$subjcode} or $r_AdditionalComments{$subjsec} or $r_AdditionalComments{$subjcode} ) { next; } $desccode{$subjcode} = $s{smdesc}; # put in the small description. $sections{$subjcode}{$subjsec} = 1; # collect all sections $subjects{$subjsec} = 1; } } # This will give us the unique values for courses my $sth = $dbh->prepare("select * from subject where subjsec = ?"); foreach my $subjsec ( sort keys %subjects ){ my ($subjcode, $dud) = split('-', $subjsec); # Get Course Information; pull in full subject record $sth->execute( $subjsec ); if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; } my $ref = $sth->fetchrow_hashref; my %s = %$ref; %s = latex_filter( %s ); # put courses in order push @courses, $subjsec; # If no short description, then long versions truncated and used. if ( not $s{smdesc} ) { # was 37 in array if ( length( $s{description} ) > $objectivelength ) { # was index 2 $s{smdesc} = substr( $s{description},0,$objectivelength); # trunc full desc } else { $s{smdesc} = $s{description}; } } $desc{$subjsec} = $s{smdesc}; $desccode{$subjcode} = $s{smdesc}; # for joinsession values. } if ( $joinsection ) { @courses = sort keys %sections; %desc = %desccode; # descriptions based on subject code } $pagecount = 1; # print qq{Full Students:@students
}; # print qq{ Full CRS:@courses
\n}; my @permstudents = @students; # used to repopulate the loop, if one runs out, but not both. my @permcourses = @courses; # put in the students and courses that will fit on a single page. my (@tempcrs,@tempstud, $crscount,$studcount); while ( @courses and @students ) { # Get students for this page while ( my $studnum = shift @students ) { push @tempstud, $studnum; # my $studcount = @tempstud; # print qq{Student Count:$studcount Max:$maxstudents
\n}; if ( @tempstud > $maxstudents ) { last; } } # Get Courses for this page. while ( my $crs = shift @courses ) { push @tempcrs, $crs; # my $crscount = @tempcrs; # print qq{Course Count:$crscount Max:$maxcolumns
\n}; if ( @tempcrs >= $maxcolumns ) { last; } } # print "Temp Stud:@tempstud
\n"; # print qq{CRS:@tempcrs
\n}; my $grpval = qq{$group:$group_value}; &print_page(\@tempcrs, \@tempstud, \%desc, \%students, \%sections, $joinsection, $pagecount,$grpval); @tempcrs = (); @tempstud = (); # zero the arrays. $pagecount++; if ( @courses or @students ) { # we need to keep going until both are empty if ( not @courses ) { # run out of courses but not students. @courses = @permcourses; } if ( not @students ) { @students = @permstudents; } print TEX "\\newpage\n\n"; # new page since we have to keep going. } } print TEX "\n\\parbox{152mm}{\\vspace{13mm}\\underline{\\hspace{63mm}}"; print TEX "\\hfill\\underline{\\hspace{63mm}}\n\n"; print TEX "{\\small ". $lex{Teacher}. "}\\hfill{\\small ". $lex{Principal}. "}}\n"; print TEX "\\end{document}\n"; close TEX; # alter for teacher tcgi functioning if ( getcwd() =~ tcgi ) { $downloaddir = $tchdownloaddir; $webdownloaddir = $tchwebdownloaddir; } system("$pdflatex $filename > pdflog$$.txt"); system("mv $shortname.pdf $downloaddir"); system("mv pdflog$$.txt $downloaddir"); system("rm -f $shortname.*"); print qq{

\n}; print qq{$lex{'View/Download'} $title

\n}; print qq{[ $lex{'Report Card'} | \n}; print qq{$lex{'View Log File'} ]\n}; if ( $missingflag ) { print qq{

$lex{Note}: }; print qq{$lex{Missing} $lex{'Short Subject Descriptions'}
\n}; print qq{ Full length subject descriptions are being used. This will
\n}; print qq{look somewhat ugly, but does indicate the subject.

\n}; } print qq{\n}; exit; } # end of makePDF #-------------- sub print_page { #-------------- # print a single page when passed start, end values for students # as well as subjects. (ie. defining a block) my ( $crsref, $studref, $descref, $studrecref, $sectionref, $joinsection, $pagenum, $grpval) = @_; my ($group,$group_value) = split(':', $grpval); my @crs = @$crsref; my @students = @$studref; my %desc = %$descref; my %sections = %$sectionref; # sections{$subjcode}{$subjsec} # more than one subjsec # %students{studnum} = ref to record my %studref = %$studrecref; # contains lastname, firstname, grade, homeroom # print "Course:@crs
Students:@students
Desc:", %desc, "
\n"; # Print Header print TEX "\\begin{tabular}{p{49mm}"; foreach my $crs ( @crs ) { print TEX "p{6.15mm}"; } # Print section for attendance and promotion text. print TEX "p{7mm}l"; # Note Left Alignment here. print TEX "}\n\\parbox[b]{47mm}{\\raggedright{\\bf\\large $schoolname}\\\\ $currdate\\hfill\\\\ $lex{Page}:~$pagenum $lex{Term}:~$term\\\\ "; if ( $group eq 'grade' ){ print TEX $lex{Grade}. ": $group_value } \n"; } else { print TEX $lex{Homeroom}. ": $group_value } \n"; } foreach my $subjsec ( @crs ) { my $desc = $desc{$subjsec}; print TEX "&\\begin{rotate}{90}{\\small\\bf $desc}\\end{rotate}"; } print TEX "&\\rule{0mm}{2mm}\\begin{sideways}{\\small\\bf Attend }\\end{sideways}"; print TEX "&\\parbox[b]{50mm} {\\raggedright\\small P=Complete~Promotion, R=Repeating~Years~Work, SP=Social~Promotion, MA=Modified/Alt~Program}"; print TEX "\\\\\n\\end{tabular}\n\n"; # Now print header section WITH dividers print TEX "\\begin{tabular}{p{45mm}|"; foreach my $crs ( @crs ) { print TEX "p{6mm}|"; } # Print section for attendance and promotion text. print TEX "p{12mm}|p{25mm}|"; print TEX "}\\hline\n"; # end of printing header. # get studid from studnum to check for active (current student) my $sth = $dbh->prepare("select studid from student where studnum = ?"); # Setup for reading subject table calcavg value. my $sth2 = $dbh->prepare("select calcavg from subject where subjsec = ?"); my $sth3 = $dbh->prepare("select endrptperiod from subject where subjsec = ?"); # Get student marks my $sth4 = $dbh->prepare("select $r_MarkField, term from eval where studnum = ? and subjcode = ?"); #is really $subjsec my $studcount = 1; foreach my $studnum ( @students ) { my %s = %{ $studref{$studnum} }; my $lastname = $s{lastname}; my $firstname = $s{firstname}; my $gr = $s{grade}; my $hr = $s{homeroom}; # Find $active value (ie. currently enrolled ) $sth->execute( $studnum ); if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;} my $active = $sth->fetchrow; # calc attendance values for this student # print "Start:$schoolstart End:$schoolend GR:$gr Active:$active
\n"; my $dayspresent = calcMyAttendance($studnum, $schoolstart, $schoolend, $g_ppd{$gr}, $active); $dayspresent = format_number($dayspresent, 2, 2); print TEX "$lastname, $firstname "; # Loop through each course for this student and print eval results. foreach my $subjsec (@crs) { # Get his/her evaluation for this course in this term my $testavg; if ( $joinsection ) { # loop through all sections looking for a value foreach my $subsec ( sort keys %{ $sections{$subjsec}} ) { # subjsec is really subjcode # Get the calcavg value (N or Y); $sth2->execute( $subsec ); if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; } my $calcavg = $sth2->fetchrow; if ( $calcavg eq $lex{Y} ) { # weighted average of terms (using r_AverageWeight) # who cares?? We're only getting a single mark from $r_MarkField # my $locobjcount = $#$subjref; # Number of objectives. # print qq{ CRS:$subjsec OBJ: $locobjcount \n}; my ($totalscore, $totalweight); $sth4->execute( $studnum, $subsec ); if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; } while ( my ($score,$term) = $sth4->fetchrow ) { if ( $score =~ m/\d/){ # if a digit... if ( not $r_AverageWeight{$term} ) { # Error print qq{

No Average Weight (r_AverageWeight) defined }; print qq{for this term $term

\n}; print qq{\n}; exit; } my $wt = $r_AverageWeight{$term}; #The weight for this term $totalscore += ( $wt * $score ); $totalweight += $wt; } } if ( $totalweight ){ # We have some tests. $testavg = $totalscore / $totalweight; $testavg = format_number( $testavg, 1,1); } else { $testavg = ' '; } } else { # We just find the endreporting period for this # course and get that term's value from eval table; # Get End Reporting period for final mark, since not passed to this function. $sth3->execute( $subsec ); if ($DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } my $endrptperiod = $sth3->fetchrow; my $sth1 = $dbh->prepare("select $r_MarkField from eval where studnum = ? and term = ? and subjcode = ?"); $sth1->execute( $studnum, $endrptperiod, $subsec ); if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; } $testavg = $sth1->fetchrow; $testavg =~ s/\%//; # strip any percents. } if ( $testavg =~ m/\d/ ) { last; } # we have our number. } # end of subjsec loop in %sections } else { # Get the calcavg value (N or Y); $sth2->execute( $subjsec ); if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; } my $calcavg = $sth2->fetchrow; if ( $calcavg eq $lex{Y} ) { # weighted average of terms (using r_AverageWeight) # who cares?? We're only getting a single mark from $r_MarkField # my $locobjcount = $#$subjref; # Number of objectives. # print qq{ CRS:$subjsec OBJ: $locobjcount \n}; my ($totalscore, $totalweight); $sth4->execute( $studnum, $subjsec ); if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; } while ( my ($score,$term) = $sth4->fetchrow ) { if ( $score =~ m/\d/){ # if a digit... if ( not $r_AverageWeight{$term} ) { # Error print qq{

No Average Weight (r_AverageWeight) defined }; print qq{for this term $term

\n}; print qq{\n}; exit; } my $wt = $r_AverageWeight{$term}; #The weight for this term $totalscore += ( $wt * $score ); $totalweight += $wt; } } if ( $totalweight ){ # We have some tests. $testavg = $totalscore / $totalweight; $testavg = format_number( $testavg, 1,1); } else { $testavg = ' '; } } else { # We just find the endreporting period for this # subject and get that term's value from eval table; # Get End Reporting period for final mark, since not passed to this function. $sth3->execute( $subjsec ); if ($DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; } my $endrptperiod = $sth3->fetchrow; my $sth1 = $dbh->prepare("select $r_MarkField from eval where studnum = ? and term = ? and subjcode = ?"); $sth1->execute( $studnum, $endrptperiod, $subjsec ); if ($DBI::errstr) {print $DBI::errstr; die $DBI::errstr; } $testavg = $sth1->fetchrow; $testavg =~ s/\%//; # strip any percents. } } # end of non joinsection # Note not really a 'test average' if a final mark only. print TEX "&\\hfil{\\small $testavg}\\hfil"; } print TEX "&\\hfil $dayspresent \\hfil& "; # End of line (with space) print TEX "\\\\\\hline\n"; if (not ($studcount % 3)){ print TEX "\\hline\n";} # put in spacers. $studcount++; } # End of Student For print TEX "\\end{tabular}\n\n"; } # End of print_page function #---------------- sub showStartPage { #---------------- print qq{
\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 } print qq{\n}; # Grades print qq{}; print qq{\n}; print qq{\n}; # Homeroom print qq{}; print qq{\n}; print qq{\n}; # Term Select # Find all of the term end dates my $sth = $dbh->prepare("select distinct endrptperiod from subject order by endrptperiod"); $sth->execute; if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; } print qq{\n}; # Output Type print qq{\n}; print qq{\n}; # Join sections into a single group for that course. print qq{\n}; print qq{\n}; # CSV Course Name Option print qq{\n}; print qq{\n\n}; # Students / Page print qq{\n}; print qq{\n}; # Paper Size print qq{\n}; print qq{\n\n}; # Continue print qq{\n}; print qq{
$lex{'Select by'} $lex{Grade}}; if ( $schoolmode == 1 ) { print qq{/$lex{Form}}; } print qq{
$lex{OR}
$lex{'Select by'} $lex{Homeroom}

Course $lex{End} $lex{Term}}; print qq{
$lex{Output} Type
Join All Sections }; print qq{Show all students in the sections together
CSV - Course Desc Type
PDF - $lex{'Student(s)'}/$lex{Page}}; print qq{
PDF $lex{'Paper Size'}
\n}; print qq{
\n}; print qq{\n}; exit; } #----------------- sub calcMyAttendance { #----------------- my ($studnum, $startdate, $enddate, $periodsperday,$active) = @_; my @enrolblocks = findEnrollmentBlocks($studnum, $schoolstart, $currsdate, $dbh); my $absent = 0; my $daysEnrolled = 0; my $late = 0; foreach my $block (@enrolblocks){ my $start = $block->{start}; my $end = $block->{end}; # print qq{ST: $start END: $end }; my $blocklength = calcDaysOpen($start,$end, $dbh); # print qq{BlockLen: $blocklength
\n}; $daysEnrolled += $blocklength; #print qq{STUD: $studnum ST: $start END: $end\n}; my $sth = $dbh->prepare("select * from attend where studentid='$studnum' and to_days(absdate) >= to_days('$start') and to_days(absdate) <= to_days('$end') order by absdate,period"); $sth->execute; if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;} while (@absence = $sth->fetchrow){ if ($absence[3] =~ /$absentString/) { $absent++; } #if ($absence[3] =~ /$lateString/) { $late++; } } #print qq{ABS: $absent
\n}; } if ( not $periodsperday ) { print qq{PPD: $periodsperday not defined for $studnum
\n}; } my $present; if ( $periodsperday ) { $absent = $absent/$periodsperday; #convert periods into days $present = $daysEnrolled - $absent; } else { $present = 0; } return $present; } # Not used #--------------- sub print_header { #--------------- # passed starting and ending values(indexes) for subject, pagenum my ($startsubj, $endsubj, $pagenum) = @_; print TEX "\\begin{tabular}{p{49mm}"; for (my $i = $startsubj; $i <= $endsubj; $i++){ $subjref = $fullsubjary[$i]; for (1..$#$subjref) { print TEX "p{6.15mm}";} } # Print section for attendance and promotion text. print TEX "p{7mm}l"; # Note Left Alignment here. print TEX "}\n\\parbox[b]{47mm}{\\raggedright{\\bf\\large $schoolname}\\\\ $currdate\\hfill\\\\ $lex{Page}:~$pagenum $lex{Term}:~$term\\\\ "; if ( $group eq 'grade' ){ print TEX $lex{Grade}. ": $group_value } &\n"; } else { print TEX $lex{Homeroom}. ": $group_value } &\n"; } $count = 0; for ($i = $startsubj; $i <= $endsubj; $i++){ $subjref = $fullsubjary[$i]; if ($i != $startsubj){print TEX "&";} print TEX "\\begin{rotate}{90}{\\small $$subjref[1]}\\end{rotate}"; for (2..$#$subjref) { print TEX "&\\begin{rotate}{90}{\\small $$subjref[$_]}\\end{rotate}"; } } print TEX "&\\rule{0mm}{2mm}\\begin{sideways}{\\small\\bf Attend }\\end{sideways}"; print TEX "&\\parbox[b]{50mm} {\\raggedright\\small P=Complete~Promotion, R=Repeating~Years~Work, SP=Social~Promotion, MA=Modified/Alt~Program}"; print TEX "\\\\\n\\end{tabular}\n\n"; # Now print header section WITH dividers print TEX "\\begin{tabular}{p{45mm}|"; # foreach $subjref (@fullsubjary){ for ( my $i = $startsubj; $i <= $endsubj; $i++ ) { $subjref = $fullsubjary[$i]; for ( 1 .. $#$subjref ) { print TEX "p{6mm}|";} } # Print section for attendance and promotion text. print TEX "p{12mm}|p{25mm}|"; print TEX "}\\hline\n"; }