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

#  This file is part of Open Admin for Schools.

# multiedit.pl - add/edit multiple item scores.

my %lex = ('Multiple Item Score Entry' => 'Multiple Item Score Entry',
	   'GB Main' => 'GB Main',
	   'Main' => 'Main',
	   'Max Score' => 'Max Score',
	   'Save / Update Scores' => 'Save / Update Scores',
	   'Assessment Item' => 'Assessment Item',
	   'Item Date' => 'Item Date',
	   'Continue' => 'Continue',
	   'Error' => 'Error',
	   'Multiple Test Score Entry' => 'Multiple Test Score Entry',
	   'Test' => 'Test',
	   'Select' => 'Select',
	   'Items with no test scores are automatically checked.' => 
	     'Items with no test scores are automatically checked.',
	   'Please Log In' => 'Please Log In',
	   'Student' => 'Student',
	   'Record(s) Updated' => 'Record(s) Updated',

	   );


use DBI;
use CGI;
use CGI::Session;

# Set the current date
my @tim = localtime(time);
my $year = @tim[5] + 1900;
my $month = @tim[4] + 1;
my $day = @tim[3];
my $currdate = "$year-$month-$day"; 

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

my $q = new CGI;

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


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

my $logged_in = $session->param(logged_in);
if (not $logged_in){
    print $q->header( -charset, $charset );
    print qq{<div>$lex{'Please Log In'}</div>>\n};
    exit;
}

my $subjsec = $session->param('subjsec');

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


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


# Now setup page header
my $title = qq{$lex{'Multiple Item Score Entry'}};

print qq{$doctype\n<html><head><title>$title</title>\n};
print qq{<link rel="stylesheet" href="$tchcss" type="text/css">\n};
print qq{$chartype\n</head><body>\n};

print qq{[ <a href="$tchpage">$lex{Main}</a> |\n};
print qq{<a href="gbmain.pl">$lex{'GB Main'}</a> ]\n};
print qq{<h1>$title</h1>\n};


# Select subjects if not already done in last loop.
if ( not $arr{page} ){
    showStartPage($subjsec); # select tests to update
  
} elsif ( $arr{page} == 1 ) {
    delete $arr{page};
    viewMarks();
}

# Update records for changed scores.
if ( $arr{page} == 2 ){
    delete $arr{page};
    updateRecs();
}



#------------
sub viewMarks {
#------------

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

    my $subjsec = $arr{subjsec};
    delete $arr{subjsec};
    
    # Lookup Test records;
    my $sth = $dbh->prepare("select tdate,name,score from gbtest where id = ?");
    foreach $key (keys %arr){
	$sth->execute( $key );
	if ($DBI::errstr){ print $DBI::errstr; die; }
	my ($tdate,$name,$score) = $sth->fetchrow;
	$name =~ s/://g; # strip colons
	$test{"$tdate:$key"} = "$name:$score"; # use this to sort hash
    }
    

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

    print qq{<form action="multiedit.pl" method="post">\n};
    print qq{<input type="hidden" name="page" value="2">\n};
    print qq{<input type="hidden" name="subjsec" value="$subjsec">\n};

    print qq{<div style="margin:0.5em;">};
    print qq{<input type="submit" value="$lex{'Save / Update Scores'}">\n}; 
    print qq{</div>\n};

    print qq{<table cellpadding="3" cellspacing="0" border="1">\n};
    print qq{<tr><th>$lex{'Assessment Item'}</th>\n};

    # Print item Name, Date, Max Score
    foreach my $key (sort keys %test){
	my ($name,$score) = split(':',$test{$key} );
	print qq{<td style="text-align:center;background:#CCC">};
	print qq{<b>$name</b></td>\n};
    }

    print qq{</tr>\n<tr><th>$lex{'Max Score'}</th>};
    foreach my $key (sort keys %test){
	my ($name,$score) = split ':',$test{$key};
	print qq{<td class="bcn">$score</td>};
    }

    print qq{</tr>\n<tr><th>$lex{'Item Date'}</th>};
    foreach my $key (sort keys %test){
	my ($date,$id) = split ':',$key;
	my ($y,$m,$d) = split('-', $date);
	my $newdate = qq{$s_month[$m] $d};

	print qq{<td>$newdate</td>};
    }
    print qq{</tr>\n};

    my $sth = $dbh->prepare("select lastname, firstname from studentall where studnum = ?");

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

    my $sth2 = $dbh->prepare("select id, score from gbscore where studnum = ? and testid = ?");
    
    # Print the students and their marks;
    foreach my $studnum ( @studnum ) {
	
	# Do the name column
	$sth->execute( $studnum );
	if ($DBI::errstr) { print "$DBI::errstr"; die;}
	my ($lastname, $firstname) = $sth->fetchrow;


	# Check for withdrawn
	$sth1->execute( $studnum );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}
	my $wd = $sth1->fetchrow;

	if ( $wd ) {
	    $lastname = qq{<span style="color:red;">WD $lastname</span>};
	}
	
	print qq{<tr><td><b>$lastname</b>, $firstname</td>\n};

	# Do all of the test columns for the student.
	foreach my $key (sort keys %test){
	    
	    my ($tdate,$id) = split ':',$key; # id of the test
	    	    
	    # Now get the score for this student for this testid.
	    $sth2->execute( $studnum, $id );
	    if ($DBI::errstr) { print "GetScore Error: $DBI::errstr"; die;}
	    my $trow = $sth2->rows; 
	    # Trow is passed to the next script for deciding how to update record
	    #  0 means no record and thus add new one; 1 means update record.
	    my ($sid,$score) = $sth2->fetchrow; 

	    print qq{<td class="cn"><input type="text" name="$id:$studnum:$trow" value="$score" };
	    print qq{style="width:4ch;"></td>\n};
	}
	print qq{</tr>\n\n};

    } # End of Student Loop

    print qq{</table>\n};
    print qq{<div style="margin:0.5em;">};
    print qq{<input type="submit" value="$lex{'Save / Update Scores'}">\n}; 
    print qq{</div>\n};
    
    print qq{</form></body></html>\n};

    exit;
    
} # end of viewMarks





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

    my $subjsec = shift;
    my (@eval, @studnum, %remove);

    # 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 (%remove)
    # 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
    $sth = $dbh->prepare("select distinct e.studnum from eval e
			 left outer join studentall s on s.studnum = e.studnum 
			 where 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;
    }
    
    # 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
	$sth = $dbh->prepare("select studnum from gbscore where testid = ? order by score");
	$sth->execute( $sortid );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr;}
	while (my $sn = $sth->fetchrow){
	    push @studnum, $sn;
	    $remove{$sn} = 1;
	}
	
	# Now add on @eval elements who are not in @studnum
	foreach my $en (@eval){
	    if (not $remove{$en}){ push @studnum, $en;}
	}
	return @studnum;

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


#----------------
sub showStartPage { # Test Selection
#----------------

    my $subjsec = shift; # Get passed subjsec

    $sth = $dbh->prepare("select description from subject where subjsec = ?");
    $sth->execute( $subjsec );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    $subject = $sth->fetchrow;

    if ( $view ne 'All' and defined $view){ # a select group is being viewed.
	$grpselect = "and grp = '$view'";
    }

    # Get Tests for this subject
    $sth = $dbh->prepare("select id, name, description from gbtest
      where subjsec = ? and name != 'sortorder' $grpselect
      order by tdate");
    $sth->execute( $subjsec );
    if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
    

    print qq{<h1>$subject</h1>\n};
    print qq{<form action="multiedit.pl" method="post">\n};
    print qq{<input type="hidden" name="page" value="1">\n};
    print qq{<input type="hidden" name="subjsec" value="$subjsec">\n};
    
    print qq{<table cellpadding="3" cellspacing="0" border="1">\n};
    print qq{<tr><th>$lex{Test}</th><th>Scores</th><th>$lex{Select}</th></tr>\n};

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

    while (my ($id,$name,$desc) = $sth->fetchrow){
	my $checked; # initially zilch
	# From the testid, find out if they have any score records.
	# If not, then they get checked.
	$sth1 = $dbh->prepare("select count(*) from gbscore where testid = ?");
	$sth1->execute( $id );
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my $count = $sth1->fetchrow;
	# if ( not $count){ $checked = 'checked';}

	print qq{<tr><td>$desc ($name)</td><td class="cn">$count</td>\n};
	print qq{<td class="cn"><input type="checkbox" name="$id" value="1" $checked>}; 
	print qq{</td></tr>\n};
    }

    print qq{<tr><td colspan="3" class="cn">\n};
    print qq{<input type="submit" value="$lex{'Continue'}">};
    print qq{</td></tr></table></form></body></html>\n};

    exit;

} # end of showStartPage


#-------------
sub updateRecs { # Update scores records
#-------------

    # foreach my $key ( sort keys %arr ) { print qq{K:$key VAL:$arr{$key}<br>\n}; }
    
    my $subjsec = $arr{subjsec};
    delete $arr{subjsec};
    # not needed here, since we already have testid values, etc.
        
    
    my $sth = $dbh->prepare("select count(*) from gbscore where studnum = ? and testid = ?");
    my $sth1 = $dbh->prepare("update gbscore set score = ? where studnum = ? and testid = ?");
    my $sth2 = $dbh->prepare("insert into gbscore values ($sql{default},?,?,?,$sql{default})");    
    
RECORD:
    foreach $key ( keys %arr  ) { # only test marks now
	# if ($key eq 'subjsec' or $key eq 'vw'){ next; } # skip those values

        my ($testid,$studnum,$flag) = split /:/,$key;
	#print qq{T:$testid S:$studnum F:$flag V:$arr{$key}<br>\n};
	
	if ( not defined $flag) {
	    print qq{Error in Entry Value for: $arr{$key} for test: $arr{id}<br>\n};
	    print qq{Contact Programmer!<br>\n};
	    exit;
	}

	# Look for an existing student score record...
	$sth->execute( $studnum, $testid );
	if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;}
	my $count = $sth->fetchrow;

	if ($count != $flag){ 
	    print qq{<div>Count does not match flag value for student number };
	    print qq{$studnum for test $testid. Contact Programmer!</div>\n};
	    exit;
	    
	} elsif ( not $studnum or not $testid ){
	    print qq{<div>Missing value for entry: Student Num: $studnum };
	    print qq{Testid: $testid  Flag: $flag . Write down this message};
	    print qq{ and contact Les Richardson</div>\n};
	    exit;
	}

	if ($count == 1 ){  # we have an existing record to update
	    $sth1->execute( $arr{$key}, $studnum, $testid);

	} elsif ($count == 0) {
	    if (not defined $arr{$key}) { next RECORD;}
	    $sth2->execute( $studnum, $testid, $arr{$key} );

	} else { # we have an $count error condition:
            print qq{$lex{Error}: $lex{Test}:$testid  $lex{Student}:$studnum.};
            print qq{ Count:$count\n};
	    print qq{</body></html>\n};
            exit;
        }

	if ($DBI::errstr){ print $DBI::errstr; exit $DBI::errstr; }
	
    }

    print qq{<div style="padding:0.5em;border:2px dotted red;width:16ch;};
    print qq{background-color:white;font-size:120%;font-weight: bold;">};
    print qq{$lex{'Record(s) Updated'}</div>\n};

    exit;

    
} # End of updateRecs
