
#------------
sub mkStudNum {
#------------

    my ($subjsec, $showwithdrawn, $dbh) = @_;
    my (@eval, %eval, @studnum, %studnum);

    # Create the studnum array that controls the order that students are
    # displayed in. Load the eval records first into an array, sorted by
    # lastname and firstname. (@eval) Load the sort order records in order
    # into an array and also into a hash (%studnum)
    # Any remaining array elements in eval are added to the end of
    # the studnum array once done. If there _are_ no sortorder recs, then
    # the final array becomes the eval records only. This has the desired
    # behavior.

    # Find the enrollments for this class and read them into @eval array
    my $studtable = 'student';
    if ( $showwithdrawn ) {
	$studtable = 'studentall';
    }
    
#    my $sth = $dbh->prepare("select distinct e.studnum from eval e
#     left outer join $studtable s on s.studnum = e.studnum 
#     where e.subjcode = ? order by s.lastname, s.firstname");

    my $sth = $dbh->prepare("select distinct e.studnum from eval e, $studtable s
      where s.studnum = e.studnum and e.subjcode = ? order by s.lastname, s.firstname");

    $sth->execute( $subjsec );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    while (my $studnum = $sth->fetchrow){
	push @eval,$studnum;
	$eval{$studnum} = 1;
    }

    
    # Load 'sortorder' test if it exists.
    $sth = $dbh->prepare("select id from gbtest where
     subjsec = ? and name = 'sortorder'");
    $sth->execute($subjsec);
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    my $sortid = $sth->fetchrow;

    if ($sortid){ # We have a sortorder 'test'.
	my $sth = $dbh->prepare("select id, studnum from gbscore where
          testid = ? order by score");
	$sth->execute($sortid);
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }

	my $sth1 = $dbh->prepare("delete from gbscore where id = ?");

	while (my ($id, $sn) = $sth->fetchrow){
	    # Check that student is still enrolled...
	    if (not $eval{$sn}) { # student is withdrawn...
		$sth1->execute($id); # remove his/her record from gbscore; # sortorder
		next; 
	    }

	    push @studnum, $sn;
	    $studnum{$sn} = 1;
	}

	# Now add on @eval elements who are not in @studnum
	foreach my $sn (@eval){
	    if ( not $studnum{$sn} ){ push @studnum, $sn; }
	}

	return @studnum;

    } else { # no sortorder
	return @eval;
    }
}


#--------------
sub calcAverage { # This is the new one...
#--------------

    require strict;

    my $specchar = '*';  # causes this test to be skipped in calculating avg.
    
    my ($studnum, $subjsec, $weightref, $grpweightref, $maxscoreref, $dbh) = @_;

    # needed: $maxscore{$id}, $weight{$id}, $groupweight{$grp}
    my %weight = %$weightref;
    my %groupweight = %$grpweightref;
    my %maxscore = %$maxscoreref;

    # Get test info and test score ( of that item ) at same time.
    my $sth = $dbh->prepare("select s.id, s.testid, s.score, t.grp from gbscore as s, gbtest as t 
      where s.testid = t.id and t.name != 'sortorder' and 
      s.studnum = ? and t.subjsec = ? order by t.grp");
    $sth->execute( $studnum, $subjsec );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }

    my $currgrp = -1;
    my $oldgrp;
    my $first = 1;
    my ($totalweight, $totalscore);
    # running total for score; zeroed for each new group.
    # running total for weight; zeroed for each new group.
    my %groupscore;

    while ( my ( $id, $testid, $score, $grp) = $sth->fetchrow ) {
	$score =~ s/\s//g; # strip any spaces in score;
	if ($score eq $specchar or $score eq '' or not defined $score ) { next; } # skip

	$oldgrp = $currgrp;
	$currgrp = $grp;
	if ($currgrp ne $oldgrp and not $first) {
	    # setup group values for the current group
	    if ($totalweight) {
		$groupscore{$oldgrp} = $totalscore / $totalweight;
	    } else {
		$groupscore{$oldgrp} = 0;
	    }
	    $totalscore = 0;
	    $totalweight = 0;
	}
	if ( $first ) { $first = 0; }

	
	if ($score =~ m/\d/) { # if score is a digit... do it.
	    $totalscore += $score / $maxscore{$testid} * $weight{$testid};
	    $totalweight += $weight{$testid};
	} else {
	    # some sort of text score...count as zero... update total weight.
	    $totalweight += $weight{$testid};
	}	    

	#print qq{TS: $totalscore TW:$totalweight GP:$grp<br>\n};

    } # End of Scores Loop


    # Get Last group, if any;
    if ($totalweight) { 
	$groupscore{$currgrp} = $totalscore / $totalweight;
    }
    $totalscore = 0; # necessary?
    $totalweight = 0; # necessary?

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

    # Add up the group scores and weight them for overall average
    foreach my $grp (keys %groupscore) {
	$totalscore += $groupscore{$grp} * $groupweight{$grp};
	#print qq{GRP: $grp GS: $groupscore{$grp} GW:$groupweight{$grp}<br>\n};
	$totalweight += $groupweight{$grp};
    }

    #print qq{TS:$totalscore TW:$totalweight<br><br>\n};
    if ($totalweight) { 
	return round( 100 * $totalscore / $totalweight, 2). '%';
    } else {
	return 0;
    }

} # End of CalcAverage (new version)


return 1;
