#!/usr/bin/perl
#  Copyright 2001-2022 Leslie Richardson

#  This file is part of Open Admin for Schools.


# Passed Values: Subject/Section value (passed as subjsec). 

# change right side values for alternate languages, let me know of any mistakes
my %lex = ('All' => 'All',
	   'All Groups' => 'All Groups',
	   'All Terms' => 'All Trm',
	   'Please Log In' => 'Please Log In',
	   'No User Id' => 'No User Id',
	   'No Password' => 'No Password',
	   'Select Course' => 'Select Course',
	   'Delete' => 'Delete',
	   'Add' => 'Add',
	   'Assessment Item' => 'Assessment Item',
	   'Del Item' => 'Del Item',
	   'Reports' => 'Reports',
	   'Rpt' => 'Rpt',
	   'Adjust the weights of individual assessment items' => 
	   'Adjust the weights of individual assessment items',
	   'Weight Item' => 'Weight Item',
	   'Adjust the weightings of groups of assessment items' =>
	   'Adjust the weightings of groups of assessment items',
	   'Weight Grp' => 'Weight Grp',
	   'Post (copy) student averages to the report card system' =>
	   'Post (copy) student averages to the report card system',
	   'Post' => 'Post',
	   'Export these grades to a CSV file' => 
	   'Export these grades to a CSV file',
	   'Exp' => 'Exp',
	   'Maintenance: Sortorder, Withdraw, etc' => 
	   'Maintenance: Sortorder, Withdraw, etc',
	   'Mtce' => 'Mtce',
	   'Edit multiple scores at the same time' =>
	   'Edit multiple scores at the same time',
	   'MultiEdit' => 'MultiEdit',
	   'No Maximum Score for Test' => 'No Maximum Score for Test',
	   'Main' => 'Main',
	   'Search' => 'Search',
	   'Error' => 'Error',
	   'Log Out' => 'Log Out',
	   'Assessments' => 'Assessments',
	   'Test Weight' => 'Test Weight',
	   'Test Average' => 'Test Average',
	   'Avg' => 'Avg',
	   'Version' => 'Version',
	   'Gradebook' => 'Gradebook',
	   'NA' => 'NA',
	   'No Tests Found' => 'No Tests Found',
	   'Score' => 'Score',
	   
	);

my $self = 'gbmain.pl';
my $version = '2024-05-23';
my $specchar = '*';  # causes this test to be skipped in calculating avg.

my $minimumtime = 1;  # Minimum time for cookie duration.
my $maximumtime = 60;  # Max cookie time.
my $defaulttime = 30;  # Default cookie time.

my $altcolor = '#3B7'; #1B6 Complement to the 063 green of teacher site.
my $maincolor = '#063'; 

use DBI;
use CGI::Session;
use CGI qw/:escape unescape/;
use Number::Format qw(round);

my $q = CGI->new;
my %arr = $q->Vars; # Get passed values

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

# only for testing.
# print $q->header( -charset, $charset );

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

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

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

# calcAverage and mkstudnum
eval require "./libgbook.pl";
if ( $@ ) {
    print $lex{Error}. " $@<br>\n";
    die $lex{Error}. " $@<br>\n";
}


# needed to $additionalcomments subject so that it can be skipped.
eval require "../../etc/repcard.conf";
if ( $@ ) {
    print $lex{Error}. " $@<br>\n";
    die $lex{Error}. " $@<br>\n";
}

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


my ($sec, $min, $hour, $mday, $mon, $year, $wday, 
 $yday, $iddst) = localtime(time);
$year = $year + 1900;
$mon++;
$wday++;
$currdate = "$dow[$wday], $month[$mon] $mday, $year";


# Define Userid
my $userid;
if ($arr{userid}) {
    $userid = $arr{userid};
}

# define term. This will pass through session setup and be defined in
# session if it exists, and otherwise will be read from session. If it
# doesn't exist in the session, it will be set to the $lex{'All Terms'}
# value.
my $term;  # current term
if ( $arr{term} ) {
    $term = $arr{term};
}


# Define View and Subview
my ($view, $subview);

if ($arr{vw} and $arr{subview}){
    $view = $arr{vw}; 
    $subview = $arr{subview};
} elsif ($arr{vw}) { # only is defined, split it.
    my ($g,$sg) = split(':',$arr{vw});
    if ($sg){ # vw contains a subgroup...
	$subview = $sg;
	$view = $g;
    } else { # no subgroup
	$view = $arr{vw};
	$subview = $lex{All};
    }
}

# Define $subjsec
my $subjsec;
if ($arr{subjsec}){
    $subjsec = $arr{subjsec};
}


my $session = new CGI::Session("driver:$dbtype;serializer:FreezeThaw",
 undef,{Handle => $dbh}) or die CGI::Session->errstr;


# Check for Logout
if ($arr{logout}){
    $session->delete;
    $session->flush;
    print $q->header( -charset, $charset );
    login( $lex{'Please Log In'} );
    print qq{</body></html>\n};
    exit;
}


# Get/Set  Session Values (a defined userid means it was passed)
if ($userid){ # we want to login, passed userid/password pair.

    # Check password/userid against database (-1 no user, -2 wrong password;
    my $error = &checkPassword($arr{userid}, $arr{password}, $dbh);
    if ($error == -1){ print $q->header( -charset, $charset ); &login($lex{'No User Id'}); die;}
    if ($error == -2){ print $q->header( -charset, $charset ); &login($lex{'No Password'}); die; }

    $cookietime = checkCookieTime( $arr{duration} );

    # Set values for userid and logged_in in session
    $session->param('logged_in','1');
    $session->expire('logged_in',$cookietime);
    $session->param('userid',$arr{userid});
    $session->param('duration', $cookietime );

} else { # check logged_in value in session
    my $logged_in = $session->param(logged_in);
    if (not $logged_in){
        print $q->header( -charset, $charset );
        login( $lex{'Please Log In'} ); 
        exit;
    }
    # Ok, we have a login. Values below we have in environment.

    $userid = $session->param('userid');
    $duration = $session->param('duration');

    if ( not ( $duration =~ m/\+/)) { # add + and m if not present
	$duration = checkCookieTime( $duration );
    }
    $session->expire('logged_in',$duration);

} # End of check for logged_in value



# Read or Write Session for views
if ($view){ # could be reset, if so update session.
    $session->param('view',$view);
} else { $view = $session->param('view');}

if ($subview){ 
    $session->param('subview',$subview);
} else { $subview = $session->param('subview');}


# Read/Write session for term
if ($term){ # if already defined we use that to set session value
    $session->param('term',$term); 
} else { # term not defined. try to check from session.  
    my $tempterm = $session->param('term'); 
    if (not $tempterm) { # not in session either...  
	# Set session and term to all terms.
	$session->param('term',$lex{'All Terms'}); 
	$term = $lex{'All Terms'}; 
    } else { # we have a session value... use it;
	$term = $tempterm; 
    } 
} # $term is now defined from passed value, session, or to default allterms.



# Read/Write Session for subjsec
if ($subjsec){ 
    $session->param('subjsec',$subjsec);
} else { 
    $subjsec = $session->param('subjsec');
}

$session->flush;
print $session->header( -charset, $charset );


# Get the subject description, grade information
$sth = $dbh->prepare("select description,smdesc, grade from subject where subjsec = ?");
$sth->execute( $subjsec );
if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;}
my ($description,$smdesc, $grade) = $sth->fetchrow;

# Set the grade and track.
my $track = $g_MTrackTermType{$grade};

# Set the Dates for test selection by term.
my ($dstart,$dend); # Start and End dates
if ($term ne $lex{'All Terms'}) { # set selection dates
    my $trm = $term;
    $trm =~ s/\D//g; # strip non-digits cruft.
    $dstart = $g_MTrack{$track}{$trm}{'start'};
    $dend = $g_MTrack{$track}{$trm}{'end'};
}


# Get the other course desc and subjsec; stuff into 'subjects' array.
$sth = $dbh->prepare("select description, smdesc, subjsec, subjcode from subject 
  where teacher = ? order by description, section");
$sth->execute( $userid );
if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}
while ( my ($description, $smdesc, $subjsec, $subjcode ) = $sth->fetchrow){

    # skip Additional Comments / Supress Subjects  from repcard configuration
    if ( $r_AdditionalComments{$subjsec}  or $r_AdditionalComments{$subjcode} ) { next; }
    if ( $r_SupressSubject{$subjsec} or $r_SupressSubject{$subjcode} ) { next; }

    if ( not $smdesc ) { $smdesc = substr($description,0,15); }
    $smdesc =~ s/\(//g; # strip opening brackets.
    $description =~ s/\(//g;

    push @subjects,$subjsec;
    $smdesc{$subjsec} = $smdesc;
    $desc{$subjsec} = $description;

}

# Creates array controlling student sort order.
my @studnum = mkStudNum($subjsec, $showwithdrawn, $dbh);


# get tests for this course
$sth = $dbh->prepare("select name, id, score, weight, description, grp 
  from gbtest where subjsec = ? order by tdate");
$sth->execute( $subjsec );
if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}
while (my ($name,$id,$score,$weight,$desc,$grp) = $sth->fetchrow){
    # skip the 'sortorder' test
    if ($name eq 'sortorder'){ next; }
    my $sg;
    ($grp,$sg) = split /:/,$grp;
    $name =~ s/://g; # strip colons, if any.
    push @test, "$name:$id:$score:$desc:$grp:$sg";
    $weight{$id} = $weight; # used for calculating averages.
    $maxscore{$id} = $score;
}
# Now done putting in the tests.

# Load the group weights from the current subject;
$sth = $dbh->prepare("select markscheme from subject where subjsec = ?");
$sth->execute( $subjsec );
if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
my $markscheme = $sth->fetchrow;

# build a %groupweight hash from values in markscheme.
my @fields = split (/[\n|\r]/, $markscheme);
my %groupweight;
foreach my $fld (@fields) { 
    if ($fld) {
	#print qq{F:$fld<br>\n};
	my ($grp, $percent) = split(/=/, $fld);
	$groupweight{$grp} = $percent;
    }
}

# Find the groups for this subject, and push into a group array
#  Also create a $groupref to point to subgroups of a top group.
#  ie. $groupref{term1} -> test,homework,labs as $groupref{term1}[0] = test
$sth = $dbh->prepare("select distinct grp 
  from gbtest where subjsec = ? and grp != '' order by grp");
$sth->execute( $subjsec );
if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}

my $currgroup = '-1';
my $prevgroup;
my @group;

while ( my $grp = $sth->fetchrow ){
    if ( not $grp ){ next;}
    my ($topgroup,$subgroup) = split(/:/,$grp);

    $prevgroup = $currgroup;
    $currgroup = $topgroup;

    if ($subgroup){ # push into hash of array elements
	push @{$groupref{$topgroup}},$subgroup;
    }
    if ($prevgroup ne $currgroup){
	push @group, $topgroup; 
    }
}

if ( $arr{page} eq 'frame' ) { # display the frame
    delete $arr{page};
    mkIframe();
}


# Heading of Document
print qq{$doctype\n<html><head><title>$lex{Gradebook} $lex{Main}</title>\n};
print qq{<link rel="stylesheet" href="$tchcss" type="text/css">\n};
print qq{<style type="text/css">\n};
print qq{ input { padding:0;margin:0;}\n};
print qq{ td.nobrk { white-space:nowrap; overflow:hidden;}</style>\n};

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



# Stop and Display Courses, if no course code-section
if ( not $subjsec ) {

    print qq{[ <a href="$tchpage">$lex{Main}</a> ]<br>\n};
    print qq{<form action="$self" method="post">\n};
    
    print qq{<table cellspacing="0" cellpadding="3" border="1" style="margin:1em 0;">\n};
    print qq{<tr><th>$lex{'Select Course'}</th></tr>\n};    
    
    foreach my $subjsec ( @subjects ){ # courses with full descriptions
	print qq{<tr><td class="bla"><input type="radio" name="subjsec" value="$subjsec"> };
	print qq{$desc{$subjsec} ($subjsec)</td></tr>\n};
    }

    print qq{<tr><td style="background-color:#DDD;">};
    print qq{<input type="checkbox" name="showwithdrawn" value="1"> };
    print qq{Show Withdrawn Students</td></tr>\n};

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

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

}


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

# Selection Form for New Course or Group
print qq{<form action="$tchpage" method="get" style="margin:0;padding:0;display:inline;">\n};
print qq{<table cellpadding="2" cellspacing="0" border="0" style="display:inline;">\n};
print qq{<tr><td>};
print qq{<input type="submit" value="$lex{Main}" style="padding:0;margin:0;display:inline;">};
print qq{</td></tr></table></form>\n};

print qq{<form style="margin:0;padding:0;display:inline;" action="$self" method="post">\n};
print qq{<table cellpadding="2" cellspacing="0" border="0" style="display:inline;">\n};

print qq{<tr><td>};
print qq{<input type="submit" value="$lex{'Select Course'}"></td>\n};

print qq{<td><select name="subjsec">\n};
print qq{<option value="$subjsec">$smdesc{$subjsec} ($subjsec)</option>\n};

foreach my $subj ( @subjects ){
    if ( $subj eq $subjsec ) { next; }
    print qq{<option value="$subj">$smdesc{$subj} ($subj)</option>\n};
}
print qq{</select></td>\n};

# Print Group Options
print qq{<td><select name="vw">};
if ( defined $view ){
    print qq{<option>$view</option><option>$lex{'All Groups'}</option>\n};
} else { # just put up all groups view...
    print qq{<option>$lex{'All Groups'}</option>\n};
}
foreach my $gp ( @group ){ 
    if ($gp eq $view) { next; }
    print qq{<option>$gp</option>};
}
print qq{</select></td>\n};


# Print Subgroup Options
if ($groupref{$view}) {
    print qq{<td><select name="subview">\n};
    if ($subview ne $lex{All}){ print qq{<option>$subview</option>\n}; }
    print qq{<option>$lex{All}</option>\n};
    foreach my $sg ( @{$groupref{$view}} ){ 
	print qq{<option>$sg</option>};
    }
    print qq{</select></td>\n};
}


# Print Term Options
print qq{<td><select name="term">\n};
if ($term eq $lex{'All Terms'}) {
    print qq{<option>$lex{'All Terms'}</option>\n};
    
} else {
    print qq{<option value="$term">$g_TermDisplay{$track}{$term}</option>\n};
    print qq{<option>$lex{'All Terms'}</option>\n};
}


# Get the terms.
$sth = $dbh->prepare("select distinct term from eval where subjcode = ? order by term");
$sth->execute( $subjsec );
if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}
while ( my $trm = $sth->fetchrow ) {
    print qq{<option value="$trm">$g_TermDisplay{$track}{$trm}</option>};
}
print qq{</select></td>\n};


# Display Course Name and end Form
print qq{<td style="color:$maincolor;">};
print qq{ $description</td></tr></table></form>\n};


## Print Methods Line ##
print qq{<div id="methods" style="padding:4px;">\n};

print qq{<form action="testadd.pl" method="post" style="display:inline;padding:0;margin:0;" 
 title="$lex{Add} $lex{'Assessment Item'}">\n};
print qq{<input type="submit" value="$lex{Add} $lex{'Assessment Item'}" style="padding:0;margin:0;">\n};
print qq{</form>\n};

print qq{<form action="gbTestDelete.pl" method="post" style="display:inline;"
 title="$lex{Delete} $lex{'Assessment Item'}">\n};
print qq{<input type="submit" value="$lex{'Del Item'}"></form>\n};

print qq{<form action="rptMenu.pl" method="post" style="display:inline;"
 title="$lex{Gradebook} $lex{Reports}">\n};
print qq{<input type="submit" value="$lex{Rpt}"></form>\n};

print qq{<form action="weightadj.pl" method="post" style="display:inline;"
 title="$lex{'Adjust the weights of individual assessment items'}">\n};
print qq{<input type="submit" value="$lex{'Weight Item'}"></form>\n};

print qq{<form action="weightgrp.pl" method="post" style="display:inline;" 
 title="$lex{'Adjust the weightings of groups of assessment items'}">\n};
print qq{<input type="submit" value="$lex{'Weight Grp'}"></form>\n};

print qq{<form action="post.pl" method="post" style="display:inline;"
 title="$lex{'Post (copy) student averages to the report card system'}">\n};
print qq{<input type="submit" value="$lex{Post}"></form>\n};

#print qq{<form action="export.pl" method="post" style="display:inline;"
# title="$lex{'Export these grades to a CSV file'}">\n};
#print qq{<input type="submit" value="$lex{Exp}"></form>\n};

print qq{<form action="mtcemenu.pl" method="post" style="display:inline;"
 title="$lex{'Maintenance: Sortorder, Withdraw, etc'}">\n};
print qq{<input type="submit" value="$lex{Mtce}"></form>\n};

print qq{<form action="gbSearch.pl"  method="post" style="display:inline;"
 title="Search for low student scores, averages">\n};
print qq{<input type="submit" value="$lex{Search}"></form>\n};

print qq{</div>\n};
#### End of Methods Line ###


# Outer Table...################
print qq{<table cellpadding="0" cellspacing="0" border="0">\n};
print qq{<tr><td valign="top">\n};


# Print the table header
print qq{<table cellpadding="3" cellspacing="0" border="1"  id="table_main">\n};
print qq{<tr style="background-color:$maincolor;">
<td class="cn"><span style="color:white;">$lex{Assessments}</span></td>
<td class="cn"><span style="color:white;">$lex{Avg}</span></td></tr>\n};


# Print the Edit Rows for the tests.
print qq{<tr valign="middle" style="background-color: $altcolor;">\n};
print qq{<td class="cn"><a href="multiedit.pl" };
print qq{title="$lex{'Edit multiple scores at the same time'}"\n}; 
print qq{style="color:white;">$lex{MultiEdit}</a>};
print qq{</td><td></td></tr>\n};
# End of Edit Rows


=head
# Populate tests array for use by 'calcaverage' sub.
my $sth = $dbh->prepare("select id, score, weight from gbtest where subjsec = ? and name != 'sortorder'");
$sth->execute( $subjsec );
if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}

my $sth1 = $dbh->prepare("select name from gbtest where id = ?");

# Loop Through all tests...skipping sortorder.
while ( my ($id, $maxscore, $weight) = $sth->fetchrow ) {
    if ( not $maxscore or $maxscore == 0){ # Get name, flag error and skip.

	$sth1->execute( $id );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}
	my $testname = $sth1->fetchrow;
	
	print qq{ $lex{'No Maximum Score for Test'}: $testname ($id); skipping...<br>\n}; 
	next; 
    }

    push @tests,"$id:$maxscore:$weight";
}
=cut


# Print the students and their marks;
my $studcount;

my $sth = $dbh->prepare("select lastname, firstname from studentall where studnum = ?");
# Check for withdrawn.
my $sth1 = $dbh->prepare("select count(*) from studentwd where studnum = ?");

foreach my $studnum (@studnum) {

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

    # check for withdrawn
    $sth1->execute( $studnum );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}
    my $wd = $sth1->fetchrow;
    
    my $avg = calcAverage($studnum, $subjsec, \%weight, \%groupweight, \%maxscore, $dbh);

    $lastname =~ s/\s+/&nbsp;/g;  # replace spaces with non-breaking space.
    $firstname =~ s/\s+/&nbsp;/g;

    if ( $wd ) {
	$lastname = qq{<span style="color:red;">WD $lastname</span>};
    }
    
    print qq{<tr><td class="nobrk"><b>$lastname</b>, $firstname</td>\n};
    print qq{<td>$avg</td></tr>\n};
    $studcount++;
}
# End Student Loop


# Print the Test Average Row;
print qq{<tr style="background-color: #CCC;">
 <td colspan="2" class="cn">$lex{'Test Average'}</td></tr>\n};


# Print the Test Weighting Row
print qq{<tr style="background-color: $altcolor;">
 <td colspan="2" class="cn">$lex{'Test Weight'}</td></tr>\n};


# Print the Assessment Row (again)
print qq{<tr style="background-color:$maincolor;"><td colspan="2" style="text-align:center;">\n};
print qq{<span style="color:white;">$lex{Assessments}</span></td></tr>\n};
print qq{</table>\n};


# Some Javascript here for resizing...
print qq{<script type="text/javascript">
 <!-- 
 function resize_iframe() {
  document.getElementById("iframe_main").height=document.getElementById("table_main").offsetHeight + 24;
  document.getElementById("iframe_main").width=document.body.offsetWidth-document.getElementById("table_main").offsetWidth;
 }
 -->
 </script>\n};

# Bottom Section Below tables.
print qq{<div style="padding:4px; line-height: 140%;">};
print qq{[ $specchar = NA | \n};
print qq{<form action="$self" method="post" style="display:inline;padding:0;margin:0;">\n};
print qq{<input type="hidden" name="logout" value="1">\n};
print qq{<input type="submit" value="$lex{'Log Out'}"></form><br>\n};

print qq{<span style="margin: 0.2em; border:1px solid black; font-size:80%;\n};
print qq{padding: 2px 6px; background-color:$altcolor;">};
print qq{$lex{Version}: $version</span></div>\n};

my $group;
if ($view ne $lex{'All Groups'}){
    $group = $view;
}

# Figure out the iframe height
my $frameheight = $studcount * 27 + 130; # 138 for the other 4 rows...

my $newgroup = escape($group);

# Do the IFrame
my $showwd = $showwithdrawn; # to keep things short below.
print qq{</td><td valign="top">\n};

print qq{<iframe src="gbmain.pl?page=frame&showwithdrawn=$showwd"};
print qq{ width="600" \n height="$frameheight" id="iframe_main" };
print qq{frameborder="0" style="padding:0;margin:0;" onload="resize_iframe()"></iframe>\n};
# Below Iframe content here.

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


#-----------
sub mkIframe { # replace gbframe.pl script
#-----------

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

    my $cellview = 'p'; # override old passed value


    if ( $datestart ) {
	$dateStartSelect = "and to_days(tdate) > to_days('$datestart')";
    }
    if ( $dateend ) {
	$dateEndSelect = "and to_days(tdate) < to_days('$dateend')";
    }

    my $groupSelect;
    if ( $grp ) {
	$groupSelect = "and grp = '$grp'";
    }

    my @test; # reset from main script run.
    # Now lookup tests for this class.
    my $sth = $dbh->prepare("select name, id, score, description, grp, tdate 
     from gbtest where subjsec = ? $dateStartSelect $dateEndSelect $groupSelect 
     order by tdate desc, name");
    $sth->execute( $subjsec );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }

    my $first = 1; # check for a test.
    while ( my ( $name,$id,$score, $desc,$grp,$tdate) = $sth->fetchrow ) {
	# skip the 'sortorder' test
	if ($name eq 'sortorder'){ next; }
	
	my $sg;
	($tgrp,$sg) = split(':',$grp );
	$name =~ s/://g; # strip colons, if any.
	push @test, "$name:$id:$score:$desc:$grp:$sg:$tdate";
	$first = 0;
    }
    if ( $first ) { # no tests.
	print qq{<h3>$lex{'No Tests Found'}</h3>\n};
#	print qq{<div>Course:$subjsec<br>\n};
#	print qq{StartDate:$datestart<br>\n};
#	print qq{End Date:$dateend<br>\n};
#	print qq{Group:$groupSelect</div>\n};
	print qq{</body></html>\n};
	exit;
    }

    # Now done putting in the tests.


    # Now get distinct groups for colors; populate %grpcolor;
    my $colornumber = 0;
    $sth = $dbh->prepare("select distinct grp from gbtest 
      where subjsec = ? and name != 'sortorder' order by grp"); 
    $sth->execute( $subjsec );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $grp = $sth->fetchrow ) {
	$grpcolor{$grp} = $colornumber;
	$colornumber++;
    }


    # Now lookup ALL tests to find $totalweight and %weight.
    $sth = $dbh->prepare("select id,name, weight from gbtest 
      where subjsec = ?"); # do ALL tests (assess items)
    $sth->execute( $subjsec );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}
    my $totalweight; # used further down for average / weight...
    while ( my ( $id,$name,$wt ) = $sth->fetchrow ) {
	# skip the 'sortorder' test
	if ( $name eq 'sortorder' ){ next; }

	$weight{$id} = $wt; # used for calculating averages.
	$totalweight += $wt;
    }
    # Now done putting in the weights (totalweight and weight hash)


    # Find the groups for this subject, and push into a group array
    #  Also create a $groupref to point to subgroups of a top group.
    #  ie. $groupref{term1} -> test,homework,labs as $groupref{term1}[0] = test
    $sth = $dbh->prepare("select distinct grp from gbtest where subjsec = ? order by grp");
    $sth->execute( $subjsec );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}

    my $currgroup = '-1';
    my $prevgroup;
    my @group;

    while (my $grp = $sth->fetchrow){
	if ( not $grp ){ next; }
	my ( $topgroup,$subgroup ) = split ':',$grp;

	$prevgroup = $currgroup;
	$currgroup = $topgroup;

	if ($subgroup){ # push into hash of array elements
	    push @{$groupref{$topgroup}},$subgroup;
	}
	if ($prevgroup ne $currgroup){
	    push @group, $topgroup; 
	}
    }


    # Load groups or subgroup and associate colors with them;
    my %groupcolor;
    if ($view eq $lex{All} or 
	($view ne $lex{All} and not $groupref{$subview}) ){ 
	# all groups; or no subs 
	for (0..$#group){ $groupcolor{$group[$_]} = $g_color[$_]; }
    } else {
	for (0..$#{$groupref{$view}}){ 
	    $groupcolor{${$groupref{$view}}[$_]} = $g_color[$_];
	}
    }


    # Heading of Document
    print qq{$doctype\n<html><head><title>$title</title>\n};
    print qq{<link rel="stylesheet" href="$tchcss" type="text/css">\n};
    print qq{<style type="text/css">body { padding:0; margin:0;}\n};
    print qq{ input { padding:0;margin:0;}\n};
    print qq{ td.nobrk { white-space:nowrap; overflow:hidden; }\n};
    print qq{A { color: white; }</style>\n};
    print qq{</head><body>\n};

    # Print the table header
    print qq{<table cellpadding="3" cellspacing="0" border="1">\n}; 


    # Print Test Header Section
    print qq{<tr style="text-align:center;background-color:$maincolor;">};
    print qq{<td>&nbsp;</td>\n};
    foreach my $test ( @test ) {
	my ( $name, $id, $score, $desc, $grp, $sg, $tdate ) = split(':', $test);
	$name =~ s/^\s+//g; # strip any spaces.
	$name =~ s/-|\.//g; # strip any dash/periods
	
	if ( length($name) > 6 ){ 
	    $sname = substr($name,0,6);
	} else { 
	    $sname = $name; 
	}

	print qq{<td style="white-space:nowrap;"><a href="gbTestEdit.pl?id=$id" };
	print qq{title="$name: $desc ($grp) $tdate" target="_top">$sname</a>};
	print qq{</td>\n};
    }
    print qq{</tr>\n};
    # End of Test Header


    # Print the Edit Rows for the tests.
    print qq{<tr valign="middle" style="background-color:$altcolor;"><td></td>\n};
    foreach my $test (@test) {
	my ($name, $id, $score, $desc, $grp, $sg, $tdate) = split(':', $test);
	print qq{<td style="text-align:center;}; # more follows!
	if ($view eq $lex{All} or ( $subview eq $lex{All} and not $groupref{$view}) ) { 
	    print qq{background-color:$g_color[$grpcolor{$grp}];"> \n};
	} else {
	    print qq{background-color:$g_color[$grpcolor{$grp}];$subview">\n};
	}
	print qq{<a href="scoreAdd.pl?id=$id" target="_top" };
	print qq{title="$desc ($grp) $tdate (x/$score)" style="color:black;">$lex{Score}</a></td>\n};

    } # End of Test Loop
    print qq{</tr>\n};
    # End of Edit Rows


    # Prep for name retrieval
   my $sth1 = $dbh->prepare("select lastname, firstname from studentall where studnum = ?");

    # Print the students and their marks;
    foreach my $studnum ( @studnum ) {
	
	# Get Student Name
	$sth1->execute( $studnum );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my ($lastname, $firstname) = $sth1->fetchrow;

	my $initials = substr($lastname,0,3).substr($firstname,0,1);
	print qq{<tr><td><b>$initials</b></td>};

	my ($totalscore,$testcount); # totalscore for these tests, count of tests.
	
	my $sth = $dbh->prepare("select score from gbscore where testid = ? and studnum = ?");
	my $sth1 = $dbh->prepare("select count(*) from gbscore where testid = ? and studnum = ?");
	
	foreach my $test ( @test ){

	    my ($name,$testid,$maxscore,$desc,$grp,$sg,$tdate) = split(':',$test);
	    
	    # Testing Code for errors; there shouldn't be more than 1 record
	    $sth1->execute($testid, $studnum);
	    my $tcount = $sth1->fetchrow;
	    if ($tcount > 1){
		print qq{</table><b>};
		print qq{<h3>$lex{Error}: More than 1 score for this test for:};
		print qq{$firstname $lastname  $name ($testid)!</h3></body></html>\n}; 
		exit "School:$schoolname - $subjsec - More than 1 record for test $name ($testid)\n";
	    }

	    # Get Score
	    $sth->execute($testid, $studnum);
	    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	    my $score = $sth->fetchrow;
	    
	    my $testaverage;

	    if ($score =~ m/\d/){ #if score is a digit...
		$totalscore += ($weight{$id} * $score / $maxscore);
		$testaverage = round( $score / $maxscore * 100, 1);

		print qq{<td class="cn" };
		if ($testaverage > 100){ print qq{style="color:red;"}; }
		print q{>};
		
		if ($cellview eq 's'){
		    print $score;
		    
		} elsif ($cellview eq 'p') {
		    print qq{$testaverage%};
		} else { # print them both...
		    print qq{$score<br>($testaverage%)};
		}
		print qq{</td>\n};
		
	    } elsif ($score eq $specchar) { #skip calcs for specialchar 
		$testaverage = $lex{NA};
		print qq{<td class="cn">$score&nbsp;($lex{NA})</td>\n};
		
	    } elsif (not defined $score){
		print qq{<td class="cn" };
		print qq{style="background-color:#E5E5E5;"></td>\n};
		
	    } elsif ( $score ) { # there IS a value, display it in red.
		print qq{<td class="cn" style="color:red;">};
		print qq{<i>$score</i></td>\n};
		
	    } else { # just print the score
		print qq{<td>$score</td>\n};
	    }

	} # End of test loop
	print qq{</tr>\n};

    }
    # End of printing Student Marks


    # Print the Test Average Row;
    print qq{<tr style="background-color:#CCC;"><td>&nbsp;</td>\n};

    foreach my $test ( @test ) {
	my ($name,$id,$score,$desc,$grp,$sg,$tdate) = split /:/,$test;
	# Get the student's scores
        my $totscore;
        my $scorecount;
        $sth = $dbh->prepare("select id, score from gbscore
 	   where testid = ? and score != '$specchar'");
        $sth->execute( $id );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}
        while (my ($id,$addscore) = $sth->fetchrow){ # just throw away id
            if (not defined $addscore) { next; }
	    $totscore += $addscore;
	    $scorecount++;
	}
        if ( not $scorecount) { 
	    print qq{<td>&nbsp;</td>\n};
	    next; 
	}
	my $avgscore = $totscore / $scorecount;
        my $average = round( ($avgscore / $score * 100), 1);

	if ($avgscore){ # print average only if we have a score...
	    print qq{<td class="cn">$average%</td>\n};
	} else {
	    print qq{<td>&nbsp;</td>\n};
	}
	
    } # End of Tests Loop
    
    print qq{</tr>\n};
    # End of Test Averages Row


    # Print the Test Weighting Row
    print qq{<tr style="background-color: $altcolor;"><td>&nbsp;</td>\n};

    # Note: $totalweight defined at start of script... it is ALL tests.
    #  We are displaying the weight of the test against the total.
    foreach my $test (@test){
	my ($name,$id,$score,$desc,$grp,$sg,$tdate) = split /:/, $test;
	my $wtmult;
	if ($defaultItemWeight) {
	    $wtmult = round( ($weight{$id} / $defaultItemWeight), 1);
	}
	print qq{<td class="cn">$wtmult\X</td>\n};
    }
    #print qq{</tr>};
    # End of Test Weight Row


    # Print Test Header Section - Second time at bottom.
    print qq{<tr style="text-align:center;background-color:$maincolor;">};
    print qq{<td>&nbsp;</td>\n};
    foreach my $test ( @test ) {
	my ( $name, $id, $score, $desc, $grp, $sg, $tdate ) = split /:/, $test;
	$name =~ s/^\s+//g;
	$name =~ s/-|\.//g;	
	if ( length($name) > 6 ){ 
	    $sname = substr($name,0,6);
	} else { 
	    $sname = $name; 
	}

	print qq{<td style="white-space:nowrap"><a href="gbTestEdit.pl?id=$id" };
	print qq{title="$name: $desc ($grp) $tdate" target="_top">$sname</a>};
	print qq{</td>\n};
    }

    
    print qq{</tr>\n};
    # End of Test Header - Second Time

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

    exit;

}
