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

#  This file is part of Open Admin for Schools.
# Based on gbmail.pl from gradebook.


# 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',
	   'Main' => 'Main',
	   'NA' => 'NA',
	   'No Tests Found' => 'No Tests Found',	   
	   'Report Card' => 'Report Card',
	   'Continue' => 'Continue',
	   'Error' => 'Error',
	   
	);

my $self = 'gradebookView.pl';


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);
use Cwd;

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

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


# 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.
}


eval require "$configpath/etc/admin.conf";

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

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

# calcAverage and mkstudnum
eval require "$configpath/lib/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 "$configpath/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);

# Header
print $q->header(-charset, $charset);

# Userid
my $userid = $ENV{'REMOTE_USER'};


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

if ( $teachermode ) { # change css and homepage
    $homepage = $tchpage;
    $css = $tchcss;
}

# Print HTML Page Header
my $title = qq{Gradebook Viewer};

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 style="padding:1em 2em;">\n};
print qq{[ <a href="$homepage">$lex{Main}</a> };
if ( not $teachermode ) {
    print qq{| <a href="$reppage">$lex{'Report Card'}</a> };
}
print qq{]\n};

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



if ( not $arr{page} ) {
    showStartPage();
    
} elsif ( $arr{page} == 1 ) {
    delete $arr{page};
    showCourses();

} elsif ( $arr{page} == 2 ) {
    delete $arr{page};
    showReport();
}
    

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

    # Load all course teachers and their course count, and gradebook entries (if any).
    
    print qq{<h3>Select Teachers - Page 1</h3>\n};


    # Check for department head. If not, exit.
    my %depthead; # depthead{faculty}{staff in faculty};

    my $sth = $dbh->prepare("select field_value from staff_multi
       where userid = ? and field_name = 'depthead'");
    $sth->execute($userid);
    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my $faculty = $sth->fetchrow ) {
	$depthead{$faculty} = 1;
    }

    
    if ( not %depthead and $teachermode ) { # in teacher site but not a department head
	print qq{<h3>Not Department Head. Access not allowed</h3>\n};
	print qq{</body></html>\n};
	exit;
	
    } elsif ($teachermode )  { # otherwise this is at least one dept head.

	my $sth = $dbh->prepare("select userid from staff_multi
    	   where field_value = ? and field_name = 'dept'");
	
	foreach my $faculty ( sort keys %depthead ) { # get folks in this dept.
	    $sth->execute($faculty);
	    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	    while ( my $userid = $sth->fetchrow ) {
		$depthead{$faculty}{$userid} = 1;
	    }
	}
	#%depthead should be fully populated now
    }

=head
    foreach my $faculty ( keys %depthead ) {
	print qq{F:$faculty<br>\n};
	foreach my $userid ( sort keys %{ $depthead{$faculty}} ) {
	    print "User:$userid<br>\n";
	}
    }
    exit;
=cut
    
    
    if ( not $teachermode ) { # depthead populate with normal staff with gradebook data

	# Get the teachers from subject table (course master)
	my $sth = $dbh->prepare("select distinct teacher, grade, subjsec from subject 
      	   where teacher is not NULL and teacher != ''");
	$sth->execute;
	if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	while ( my ($tch,$gr, $subjsec) = $sth->fetchrow ) {
	    $depthead{'Main'}{$tch} = 1;
	}

    }


    print qq{<form action="$self" method="post">\n};
    print qq{<input type="hidden" name="page" value="1">\n};

    print qq{<table cellpadding="3" cellspacing="0" border="0" };
    print qq{style="border:1px solid gray;padding:0.4em;">\n};

    
    foreach my $faculty ( sort keys %depthead ) {

	if ( $teachermode ) {
	    print qq{<tr><td colspan="4" style="font-size:120%;font-weight:bold;">Faculty $faculty</td></tr>\n};
	}

	print qq{<tr><th>Sel</th><th>Teacher</th><th>Courses</th><th>Assignments</th></tr>\n};
	
	
	# now get sorted list of teachers;
	my (%sort, %names);
	my $sth = $dbh->prepare("select lastname, firstname from staff where userid = ?");
	foreach my $userid ( keys %{ $depthead{$faculty}} ) {
	    $sth->execute( $userid );
	    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	    my ($ln,$fn) = $sth->fetchrow;
	    $sort{"$ln$fn$userid"} = $userid;
	    $names{$userid} = qq{<b>$ln</b>, $fn};
	}

	my @sort = sort keys %sort;
    
	my $first = 1;
	foreach my $key ( @sort ) {
	    my $userid = $sort{$key};

	    # get the teacher's courses (either all for admin site or faculty based for teacher site
	    my %courses;
	    my $sth = $dbh->prepare("select * from subject where teacher = ?");
	    $sth->execute( $userid );
	    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	    while ( my $ref = $sth->fetchrow_hashref ) {
		my %r = %$ref;
		my $subjsec = $r{subjsec};
		$courses{$subjsec} = 1;
	    }

	    # Get the gradebook counts
	    my $sth = $dbh->prepare("select count(*) from gbtest where subjsec = ?");
	    my $gbcount;
	    foreach my $subjsec ( sort keys %courses ) {
		$sth->execute($subjsec);
		if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
		my $count = $sth->fetchrow;
		$gbcount += $count;
	    }

#	    print qq{$userid - $gbcount<br>\n};
	    
	    
	 

	    print qq{<tr><td>};
	    if ( $gbcount ) { # ie we have gradebook data
		print qq{<input type="checkbox" name="$userid:$faculty" value="1">};
	    }
	    print qq{</td><td>$names{$userid}</td><td>};
	    
	    
	    foreach my $crs ( sort keys %courses ) {
		print qq{$crs };
	    }
	    print qq{</td>};
	    print qq{<td class="cn">$gbcount</td></tr>\n};
	} # end of teacher loop

#	if ( not $first ) {
#	    print qq{</table>\n};
#	}

    } # end of faculty loop
	
    # Continue
    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;

}


#--------------
sub showCourses {
#--------------    

    # foreach my $key ( sort keys %arr ) { print qq{K:$key VAL:$arr{$key}<br>\n}; }
    # Passed: "userid:faculty" for teachers selected in first page 

    my %alldept; # alldept{dept}{userid}
     
    foreach my $key ( keys %arr ) {
	my ($userid, $faculty) = split(':', $key);
	$alldept{$faculty}{$userid} = 1;
    }
    # %alldept now fully populated.

    print qq{<h3>Select Courses - Page 2</h3>\n};
     
    # Form start
    print qq{<form action="$self" method="post">\n};
    print qq{<input type="hidden" name="page" value="2">\n};


    # Table
    print qq{<table cellpadding="3" cellspacing="0" border="0" };
    print qq{style="border:1px solid gray;padding:0.4em;">\n};

    
    foreach my $dept ( sort keys %alldept ) {

	if ( $teachermode ) {
	    print qq{<tr style="font-weight:bold;font-size:120%;"><td colspan="4">Department $dept</td></tr>\n};
	}
	
	foreach my $userid ( keys %{ $alldept{$dept}} ) {

	    my $sth = $dbh->prepare("select lastname, firstname from staff where userid = ?");
	    $sth->execute( $userid );
	    if ( DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
	    my ($ln,$fn) = $sth->fetchrow;

	    print qq{<tr style="background-color:#DDD;"><td style="font-weight:bold;" colspan="4">};
	    print qq{$fn $ln ($userid)</td></tr>\n};

	    my $sth1 = $dbh->prepare("select count(*) from gbtest where subjsec = ?");
	
	    # Get courses.
	    my $sth = $dbh->prepare("select * from subject where teacher = ? order by description");
	    $sth->execute( $userid );
	    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;}

	    my $first = 1;
	    while ( my $ref = $sth->fetchrow_hashref ) {
		my %c = %$ref;
		my $subjsec = $c{subjsec};

		if ( $teachermode ) {
#		    print "Dept:$dept / Faculty: $c{faculty} / $c{description} / $subjsec<br>\n";
		    if ( $c{faculty} ne $dept ) { # skip this course, not in faculty
			next;
		    }
		}

		
		# skip if member of %r_SupressSubject or %r_AdditionalComments
		my ($tsubjcode, $dud) = split('-', $subjsec ); 
		if ( $r_SupressSubject{$tsubjcode} or $r_SupressSubject{$subjsec} or
		     $r_AdditionalComments{$tsubjcode} or $r_AdditionalComments{$subjsec} ) {
		    next; 
		}

	    
		# Gradebook Assignments (gbtest)?
		$sth1->execute( $subjsec );
		if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;}
		my $gbcount = $sth1->fetchrow;

		if ( $first ) {
		    print qq{<tr><th>Sel</th><th>Teacher</th><th>Courses</th><th>Assignments</th></tr>\n};
		    $first = 0;
		}
		
		
		print qq{<tr><td>};
		if ( $gbcount ) {
		    print qq{<input type="checkbox" name="$userid:$subjsec" value="1">};
		}
		print qq{</td>};
		print qq{<td>$c{description} ($subjsec)</td><td>$c{startrptperiod}-$c{endrptperiod}</td>};
		print qq{<td class="cn">$gbcount</td></tr>\n};
	    }

	    if ( $first ) { # no courses
		print qq{<tr><td colspan="4">No Courses</td></tr>\n};
	    } else {
		# Continue
		print qq{<tr><td></td><td class="la">\n};
		print qq{<input type="submit" value="$lex{Continue}"></td></tr>\n};
	    }
	
	} # end of teacher loop

    } # end of dept loop

    print qq{</table>\n};
    print qq{</form>\n};
    print qq{</body></html>\n};
    
    exit;
    
} # end of showCourses




#-------------
sub showReport {
#-------------

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

    # split and join into separate teacher course lists
    my %data;
    foreach my $key ( keys %arr ) {
	my ($uid,$crs) = split(':', $key);
	$data{$uid}{$crs} = 1;
    }


    foreach my $userid ( sort keys %data ) {
	foreach my $subjsec ( sort keys %{ $data{$userid}} ) {
	    mkIframe($subjsec);
	}
    }

    exit;

}


#-----------
sub mkIframe { # main report stuff for a teacher and a course.
#-----------

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

    # load course info
    my $sth = $dbh->prepare("select * from subject where subjsec = ?");
    $sth->execute( $subjsec );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    my $cref = $sth->fetchrow_hashref;
    my %crs = %$cref;

    # Get Staff Name
    my $sth = $dbh->prepare("select firstname, lastname from staff where userid = ?");
    $sth->execute( $crs{teacher} );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    my ($fn, $ln) = $sth->fetchrow;
    my $staffname = qq{$fn $ln};

    
    # get students in the course sorted by name;
    my (@studnum, %studname);
    my $sth = $dbh->prepare("select distinct e.studnum, s.lastname, s.firstname from eval e, studentall s
       where subjcode = ? and e.studnum = s.studnum order by s.lastname,s.firstname");
    $sth->execute( $subjsec );
    if ( $DBI::errstr ) { print $DBI::errstr; die $DBI::errstr; }
    while ( my ( $studnum,$ln,$fn ) = $sth->fetchrow ) {
	push @studnum, $studnum;
	$studname{$studnum} = qq{<b>$ln</b>, $fn};
    }

    # Test
    #foreach my $studnum ( @studnum ) {
    # print qq{Name:$studname{$studnum}<br>\n};
    #}
    

    # get tests for this course from gradebook
    my @test;
    my (%weight,%maxscore,%groupweight);
    $sth = $dbh->prepare("select name, id, score, weight, description, grp, tdate
    	 from gbtest where subjsec = ? order by tdate");
    $sth->execute( $subjsec );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}

    my $first = 1;
    while (my ($name,$id,$score,$weight,$desc,$grp,$tdate) = $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:$tdate";
	
	$weight{$id} = $weight; # used for calculating averages.
	$maxscore{$id} = $score;
	$first = 0;
    }
    if ( $first ) { # no tests.
	print qq{<h3>$lex{'No Tests Found'}</h3>\n};
	print qq{</body></html>\n};
	exit;
    }
    # 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;
	}
    }


    
    my $cellview = 'p'; # print test average rather than raw score


    # 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[$_];
	}
    }

    print qq{<h3>$crs{description} ($subjsec) - $staffname</h3>\n};

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


    # print the weighing groups for tests.
    my $tempcols = scalar @test + 2;
    print qq{<tr valign="middle" style="background-color:$altcolor;">};
    print qq{<td colspan="$tempcols" class="la">};
    foreach my $grp (sort keys %groupweight ) {
	if ( not $g_color[$grpcolor{$grp}] ) {
	    print qq{<span style = "background-color:red;">$grp $groupweight{$grp}%</span> / \n};
	} else {
	    print qq{<span style="background-color:$g_color[$grpcolor{$grp}];">$grp $groupweight{$grp}%</span> / \n};
	}
    }
    print qq{</td></tr>\n};
    

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

	print qq{<td style="text-align:center;background-color:$g_color[$grpcolor{$grp}];color:black;" };
	print qq{title="$desc ($grp) $tdate (x/$score)">$sname</td>\n};

	
	#print qq{<td style="color:black;" };
	#print qq{title="$name - $desc ($grp) $tdate">$sname};
	#print qq{</td>\n};
    }
    print qq{</tr>\n};
    # End of Test Header


    # 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>$studname{$studnum}</td>};

	my $avg = calcAverage($studnum, $subjsec, \%weight, \%groupweight, \%maxscore, $dbh);
	print qq{<td>$avg</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 class="ra" colspan="2">Test Average</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 class="ra" colspan="2">Test Weight</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};
    }
    # End of Test Weight Row

    
    print qq{</table>\n};
    

    return;

}
