#! /usr/bin/perl
#  Copyright 2001-2026 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: 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)
#   4) Get a count of all objectives (all courses) and all students. 
#   Then decide on a paper size and orientation. Since the priority is
#   for a per student list (one student per line), the priority is:
#   letter landscape, legal landscape

my %lex = ('Crosstab' => 'Crosstab',
	   'Mark Report' => 'Mark Report',
	   'Report Card System disabled. Please contact secretary.' => 
	     'Report Card System disabled. Please contact secretary.',
	   'Grade' => 'Grade',
	   'Page' => 'Page',
	   'Trm' => 'Trm',
	   'View/Download' => 'View/Download',
	   'Report Card' => 'Report Card',
	   'Main' => 'Main',
	   'Error' => 'Error',
	   'Papersize' => 'Papersize',
	   'Continue' => 'Continue',
	   'Legal' => 'Legal',
	   'Letter' => 'Letter',
	   'A4' => 'A4',
	   'Term' => 'Term',
	   'Subject' => 'Subject',
	   'or' => 'or',
	   'Blank=Current' => 'Blank=Current',
	   'No Student(s) Found' => 'No Student(s) Found',
	   'Select' => 'Select',
	   'Homeroom' => 'Homeroom',
	   'View Log File' => 'View Log File',
	   'Subject' => 'Subject',
	   'Font Size' => 'Font Size',
	   
	   );

my $self = 'rptsummxtab.pl';

use DBI;
use CGI;

# Constants
# These two settings control the vertical height of the header.
my $objectivelength = 36; # number of characters to truncate objectives to.
my $offset = "36mm"; # Strut length in print_header fn.

my $maxstudents = 21; # Number of student rows per page; if you adjust above, 
# this may have to change also.

my $maxlegalcols = 36; # maximum number of columns per printed page.
my $maxlettercols = 28;


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

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


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] $mday, $year";

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

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



# Get the values from configuration system
my $sth = $dbh->prepare("select datavalue from conf_system where dataname = ?");
foreach my $val ( qw( r_MarkField r_SupressSubject r_AdditionalComments )) {
    $sth->execute( $val  );
    my $datavalue = $sth->fetchrow;
    eval $datavalue;
    if ( $@ ) {
	print $lex{Error}. " $@<br>\n";
	die $lex{Error}. " $@\n";
    }
}


# Print the Page Header
my $title = "$lex{Crosstab} $lex{'Mark Report'}";
print qq{$doctype\n<html><head><title>$title</title>\n};
print qq{<link rel="stylesheet" href="$css" type="text/css">\n};
print qq{$chartype\n</head><body>\n};
print qq{[ <a href="$homepage">$lex{Main}</a> |\n};
print qq{<a href="$reppage">$lex{'Report Card'}</a> ]\n};

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


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


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


# Check for entry errors
my $inputcount;
foreach my $val ( qw( grade homeroom subjsec )) {
    if ( $arr{$val} ) { $inputcount++; }
}
if ( $inputcount != 1 ) {
    print qq{<h1>$lex{Select} $lex{Error}</h1>\n};
    print qq{</body></html>\n};
    exit;    
}


# passed values
my $grade = $arr{grade};
delete $arr{grade};

my $homeroom = $arr{homeroom};
delete $arr{homeroom};

my $subjsec = $arr{subjsec};
delete $arr{subjsec};

my $term = $arr{term};
delete $arr{term};


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

if ( $arr{papersize} eq 'letter' or not $arr{papersize} ) {
    $papersize = 'letterpaper';
    $textwidth = $g_letterpaper_textwidth;
    $textheight = $g_letterpaper_textheight;
    $maxcolumns = $maxlettercols;

} elsif ( $arr{papersize} eq 'legal' ) {
    $papersize = 'legalpaper';
    $textwidth = $g_legalpaper_textwidth;
    $textheight = $g_legalpaper_textheight;
    $maxcolumns = $maxlegalcols;

} elsif ( $arr{papersize} eq 'a4' ) {
    $papersize = 'a4paper';
    $textwidth = $g_a4paper_textwidth;
    $textheight = $g_a4paper_textheight;
    $maxcolumns = $maxlettercols;

} 
delete $arr{papersize}; # no longer needed.


if ( $arr{maxstudents} ) {
   $maxstudents = $arr{maxstudents};
}
delete $arr{maxstudents};


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


# Get Students First; by grade or subject enrollment
my ( %studfirstname, %studlastname, @students);
if ( $grade ) {
    my $sth = $dbh->prepare("select studnum, lastname, firstname from student
        where grade = ? order by lastname, firstname");
    $sth->execute( $grade );
    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
    while ( my $ref = $sth->fetchrow_hashref ) {
	my %r = %$ref;
	$studfirstname{ $r{studnum}} = $r{firstname};
	$studlastname{ $r{studnum}} = $r{lastname};
	push @students, $r{studnum};
    }

} elsif ( $homeroom ) {
    my $sth = $dbh->prepare("select studnum, lastname, firstname from student
        where homeroom = ? order by lastname, firstname");
    $sth->execute( $homeroom );
    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
    while ( my $ref = $sth->fetchrow_hashref ) {
	my %r = %$ref;
	$studfirstname{ $r{studnum}} = $r{firstname};
	$studlastname{ $r{studnum}} = $r{lastname};
	push @students, $r{studnum};
    }


} else { # a single subject-section course
    my $sth = $dbh->prepare("select distinct s.studnum, s.lastname, s.firstname 
     from studentall as s, eval as e where s.studnum = e.studnum and
     e.subjcode = ? order by lastname, firstname");
    $sth->execute( $subjsec );
    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
    while ( my $ref = $sth->fetchrow_hashref ) {
	my %r = %$ref;
	$studfirstname{ $r{studnum}} = $r{firstname};
	$studlastname{ $r{studnum}} = $r{lastname};
	push @students, $r{studnum};
    }

}

if ( not @students ) {
    print qq{<h1>$lex{'No Student(s) Found'}</h1>\n};
    print qq{</body></html>\n};
    exit;
}

@studary; # global for passing to page print.
foreach my $studnum ( @students ) {
    my @temp;
    push @temp, $studnum;
    push @temp, $studlastname{$studnum};
    push @temp, $studfirstname{$studnum};
    push @studary, \@temp;
}
    

# Test
#my $tcount = 1;
#foreach my $studnum (@students) {
#    print qq{<div>$tcount - $studnum $studname{$studnum}</div>\n};
#    $tcount++;
#}

$studcount = scalar @students;
# print qq{Student Count: $studcount \n};

my %subjects;  # hash of $subjects{subjsec} = 1 format

if ( $grade or $homeroom ) {

    # Select subject-section by grade and term; even though called subjcode, its subjsec
    my $sth1 = $dbh->prepare("select distinct subjcode from eval where term = ? and studnum = ?");
    
    # Collect all the courses taken by this group of students.
    foreach my $studnum ( @students ) {
#	print "SN:$studnum $studname{$studnum}<br> ";
	$sth1->execute( $term, $studnum ); 
	if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	while ( my $subjsec = $sth1->fetchrow ) {
#	    print "SU:$subjsec<br>\n";
	    $subjects{$subjsec} = 1;
	}

    } # End of Course Selection loop.

    
} else { # we have selected a single course only;
    $subjects{$subjsec} = 1;
}

# Print out %subjects hash to see what we have...
# foreach my $subjsec ( sort keys %subjects ){ print qq{<div>$subjsec</div>\n}; }


my $objcount = 0; # Count Objectives...
my $subjectbreakpoint = 0;

# Add their subjects (and objectives) to a 2D array called fullsubjary
# Each row in array has subjsec, and then objectives.

foreach my $subjsec ( sort keys %subjects) {

    # Skip Unwanted Courses (attendance only, etc)
    my ($subjcode, $dud) = split(/-/, $subjsec);
    if (   $r_SupressSubject{$subjsec} or $r_SupressSubject{$subjcode} or 
	   $r_AdditionalComments{$subjsec} or $r_AdditionalComments{$subjcode} ) {
	next; 
    }


    # 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 $sref = $sth->fetchrow_hashref;
    my %crs = %$sref;

    %crs = latex_filter( %crs );

    # print qq{<div>Sub:$subjsec -  $crs{description}</div>\n};
    
    my $objref;
    push @$objref, $subjsec;

#    print "<div>SUB:$subjsec</div>\n";

    # Loop over all (possible) objectives;
    foreach my $idx (1..20) {
	my $key = 'q'. $idx;

#	print "K:$key $crs{$key}/ ";
	
	if ( $crs{$key} ) { # we have an objective
	    
    	    # Truncate the objective length, if necessary. $objectivelength set at top of script
	    if (length($crs{$key} ) > $objectivelength){ 
		$crs{$key} = substr($crs{$key},0,$objectivelength);
	    }

	    # Add small desc or subjsec to first objective
	    if ( $idx == 1 ) { # first objective
		if ( $crs{smdesc} ) {
		    $crs{$key} = "{\\bf $crs{smdesc} } ".$crs{$key}; #Add SDesc-1stobj
		} else { # no short description for this course (smdesc), use subjsec
		    $crs{$key} = "{\\bf $subjsec} ".$crs{$key};
		}
	    }

#	    print "<div>$subjsec - $key - $crs{$key}</div>\n";
	    
	    push @$objref,$crs{$key}; $objcount++;
	} 
    }
    
    if ( not @$objref[1] ) { # no objectives, add in a single mark one. index 0 is the subjsec
	push @$objref, qq{$subjsec Mark};
	$objcount++;
#	print "<div>Added mark objective for $subjsec</div>\n";
    }
    
#    print qq{OBJ:$objcount BP:$subjectbreakpoint <br>\n};
    
    if ( $objcount > $maxcolumns ) {
	# push subjbreakpoint into subject break array
	push @subjbreakary,$subjectbreakpoint;
	$objcount = 0; # reset objective count
    } 
    # This is incremented AFTER the test for too large.
    $subjectbreakpoint++;
    # objcount is reset, but subjectbreakpoint keeps going/growing.

    push @fullsubjary, $objref;  # Make 2D array

}

# Test print full subject array.
#foreach my $subj ( @fullsubjary ){
#    print qq{<br>Sub:$subj /  $$subj[0] \n};
#    foreach my $val ( @{ $subj }) {
#	print qq{VAL:$val<br>\n};
#    }
#}


# Now get break points for subjects and students.
# print qq{Subject Break points: ", @subjbreakary, "<br>\n};

for ( 0..( $studcount - 1 ) ) {
    if ($_ % ($maxstudents - 1) == 0 and $_ != 0){
	# Minus 1 since we use array index (1 less)
	push @studbreakary, $_;
    }
}
push @studbreakary, $studcount; # put in the end...

#print qq{<br>Student Break Array: ",@studbreakary,"<br>\n};


# Setup TEX Code
$shortname = "summarkxtab$$";
$filename = "$shortname.tex";

open(TEX,">$filename") || die "Can't open tex file";

print TEX "\\documentclass[$fontsize,$papersize,landscape]{article}
\\usepackage{array,rotating,noto}
\\pagestyle{empty}
\\setlength{\\textwidth}{$textwidth}
\\setlength{\\textheight}{$textheight}
\\setlength{\\hoffset}{-20mm}
\\setlength{\\voffset}{-65mm}
\\setlength{\\evensidemargin}{0mm}
\\setlength{\\oddsidemargin}{0mm}
\\setlength{\\tabcolsep}{1pt}
\\setlength{\\extrarowheight}{4pt}\n";

# removed $a_latex_header and also inputenc (not with utf8 engines)

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


$pagecount = 1;
$currstud = 0;
foreach my $studbreak ( @studbreakary ) {
    $prevstud = $currstud;
    $currstud = $studbreak;

    $currsubj = 0;
    foreach my $subjbreak (@subjbreakary){
	$prevsubj = $currsubj;
	$currsubj = $subjbreak;

	&print_page($prevstud,$currstud -1,$prevsubj,$currsubj - 1,$pagecount);
	$pagecount++;
    }
    &print_page($prevstud, $currstud - 1,$currsubj,$#fullsubjary,$pagecount); 
    $pagecount++;

}

$logfile = "pdflog$$.txt";

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

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

print qq{[ <a href="$reppage">$lex{'Report Card'}</a> |\n};
print qq{<a href="$webdownloaddir/$logfile">$lex{'View Log File'}</a> ]\n};

system("$pdflatex $filename > $logfile");
system("mv $shortname.pdf $downloaddir");
system("mv $logfile $downloaddir");
system("rm -f $shortname.*");

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



#---------------
sub print_header {
#---------------
    # passed starting and ending values(indexes) for subject, pagenum
    my ($startsubj, $endsubj, $pagenum) = @_;
  
    print TEX "\\begin{tabular}{>{\\raggedright}b{49mm}";
    for (my $i = $startsubj; $i <= $endsubj; $i++){
	$subjref = $fullsubjary[$i];
	for (1..$#$subjref) { print TEX "p{6.15mm}";}
    }

    # Print the first cell.
    print TEX "}\n\\rule{0pt}{$offset}{\\bf\\large $schoolname}\\\\
     $currdate\\\\ ". $lex{Page}. ":~$pagenum  ". $lex{Trm}. ":~$term\\\\ ";
    if ( $grade ){
	print TEX $lex{Grade}. ": $grade\\\\";
    } elsif ( $homeroom ) {
	print TEX $lex{Homeroom}. ": $homeroom\\\\";
    } else {
	print TEX $lex{'Subject'}. ": $subjsec\\\\";
    }

    # Print the next cells.
    $count = 0;
    for (my $i = $startsubj; $i <= $endsubj; $i++){
	$subjref = $fullsubjary[$i];

	#if ($count != 0){print TEX "&";}
	#print TEX "\\begin{rotate}{45}{\\small $$subjref[1]}\\end{rotate}"; 

	for (1..$#$subjref) {
	    print TEX "&\n\\begin{rotate}{45}{\\small $$subjref[$_]}";
	    print TEX "\\end{rotate}"; 
	    $count++;
	}
    }

    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}|";} # C type is defined in TeX hdr
    }
    print TEX "}\\hline\n";

}


#--------------
sub print_page {
#--------------
    # print a single page when passed start, end values for students
    #  as well as courses. (ie. defining a block)

    my ($startstud, $endstud, $startsubj, $endsubj,$pagenum) = @_;

    # print qq{Page $pagenum Stud: $startstud - $endstud \n};
    # print qq{Sub: $startsubj - $endsubj<br>\n};

    print_header($startsubj, $endsubj, $pagenum);

    my $studcount = 1;
    # foreach $studref (@$studary){
    for ($j = $startstud; $j <= $endstud; $j++){
	$studref = $studary[$j];
	# print qq{<div>Studref: $studref / $studary[$j] / $j / @{$studary[$j]}</div>\n};
	my $lastname = $$studref[1];
	my $firstname = $$studref[2];
	my $studnum = $$studref[0];

	print TEX "$lastname, $firstname";

	# Loop through each subject for this student and print eval results.

	for ($i = $startsubj; $i <= $endsubj; $i++){
	    $subjref = $fullsubjary[$i];

	    # Get his/her evaluation for this subject in this term

	    my $subjsec = $$subjref[0];
	    my $locobjcount = $#$subjref; # Number of objectives.

	    # print qq{ SUB: $subjsec OBJ: $locobjcount \n};

	    $sth1 = $dbh->prepare("select * from eval where 
              studnum = ? and term = ? and subjcode = ?");
	    $sth1->execute( $studnum, $term, $subjsec );
	    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	    my $cref = $sth1->fetchrow_hashref;
	    my %c = %$cref;
	    
#	    my $count = $locobjcount + 6;  # 7 is the first result in eval rec.
	    # for (7..$count){
	    foreach my $idx (1..$locobjcount) {
		my $key = 'a'. $idx;
		$c{$key} =~ s/\%//g; # strip percent signs
		#		print TEX "&\\hfil {\\footnotesize $evalrec[$_]}\\hfil ";
		print TEX "&\\hfil {\\footnotesize $c{$key} }\\hfil ";
		
	    }
	}
	print TEX "\\\\\\hline\n";
	if (not ($studcount % 3)){ print TEX "\\hline\n";} # put in spacers.
	$studcount++;

    }  # End of Student For 

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

} # End of print_page function


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

    # Find all the grades
    my @grades;
    my $sth = $dbh->prepare("select distinct grade from student");
    $sth->execute;
    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
    while ( my $grade = $sth->fetchrow ) {
	push @grades, $grade;
    }

    # Find all the homerooms
    my @homerooms;
    $sth = $dbh->prepare("select distinct homeroom from student");
    $sth->execute;
    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
    while ( my $homeroom = $sth->fetchrow ) {
	push @homerooms, $homeroom;
    }

    # Find the courses
    $sth = $dbh->prepare("select subjsec, description from subject");
    $sth->execute;
    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
    while ( my ( $subjsec, $desc ) = $sth->fetchrow ) {

	# Skip Unwanted Courses
	my ($subjcode, $dud) = split('-', $subjsec);
	if (   $r_SupressSubject{$subjsec} or $r_SupressSubject{$subjcode} or 
	       $r_AdditionalComments{$subjsec} or $r_AdditionalComments{$subjcode} ) {
	    next; 
	}

	$subjects{"$desc ($subjsec)"} = $subjsec;
    }

    # Find the terms
    my @terms;
    $sth = $dbh->prepare("select distinct term from eval 
      where term is not NULL and term != '' order by term");
    $sth->execute;
    if ( $DBI::errstr ){ print $DBI::errstr; die $DBI::errstr; }
    while ( my  $trm = $sth->fetchrow ) {
	push @terms, $trm;
    }


    print qq{<form action="$self" method="post">\n};
    print qq{<input type="hidden" name="page" value="1">\n};
    print qq{<table cellspacing="0" cellpadding="3" border="0" style="border:1px solid gray;padding:0.4em;">\n};

    print qq{<tr><td colspan="2" class="bla">Select Students by</td></tr>\n};
    
    # Grade
    print qq{<tr><td class="bra">$lex{Grade}</td>};
    print qq{<td><select name="grade"><option value=""></option>\n};
    foreach my $grade ( sort { $a <=> $b} @grades ) {
	print qq{<option>$grade</option>};
    }
    print qq{</select></td></tr>\n};

    # OR
    print qq{<tr><td class="bra">$lex{or}</td><td></td></tr>\n};

    # Homeroom
    print qq{<tr><td class="bra">$lex{Homeroom}</td><td><select name="homeroom"><option value=""></option>\n};
    foreach my $homeroom ( sort { $a <=> $b} @homerooms ) {
	print qq{<option>$homeroom</option>};
    }
    print qq{</select></td></tr>\n};

    # OR
    print qq{<tr><td class="bra">$lex{or}</td><td></td></tr>\n};
    
    # Course
    print qq{<tr><td class="bra">Course</td><td><select name="subjsec"><option value=""></option>\n};
    foreach my $desc ( sort keys %subjects ) {
	print qq{<option value="$subjects{$desc}">$desc</option>};
    }
    print qq{</select></td></tr>\n};

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


    # Get the Term
    print qq{<tr><td class="bra"><i>$lex{Term}</i></td>\n};
    print qq{<td class="la"><select name="term">};

    foreach my $trm ( @terms ) {
	print qq{<option value="$trm">$trm</option>\n};
    }
    print qq{</select></td></tr>\n};

    # Max Students per Page
    print qq{<tr><td class="bra"><i>Max Students</i></td>\n};
    print qq{<td class="la"><input style="width:4ch;" type="text" name="maxstudents" value="$maxstudents">};
    print qq{ per page</td></tr>\n};

    
    # Get Paper Size
    print qq{<tr><td class="bra"><i>Paper Size</i></td><td class="la">\n};
    print qq{<select name="papersize"><option value="letter">$lex{Letter}</option>};
    print qq{<option value="legal">$lex{Legal}</option>};
    print qq{<option value="a4">$lex{A4}</option></select></td></tr>\n};

    # Font Size
    print qq{<tr><td class="bra">$lex{'Font Size'}</td>\n<td>};
    print qq{<select name="fontsize">}; # <option>$r_FontSize</option>\n};
    print qq{<option value="$g_DefaultFontSize">$g_DefaultFontSize pt</option>};
    foreach my $fs ( @g_FontSizes ) {
	if ($fs eq $g_DefaultFontSize ) { next; }
	print qq{<option value="$fs">$fs pt</option>};
    }
    print qq{</select></td></tr>\n};

    


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

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

    exit;
}
