#!/usr/bin/perl
#  Copyright 2001-2022 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 ($view,$subview) = split /:/,$arr{vw};

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


# 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 $lex{'Please Log In'}. "<br>\n";
    exit;
}

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

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


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


# Update records for changed scores.
if ( $arr{flag} == 3 ){
    updateRecs();
    print qq{<div style="padding:0.5em; border:2px dotted red;};
    print qq{background-color: white; font-size: 150%; font-weight: bold;">};
    print qq{$lex{'Record(s) Updated'}</div><p><hr></p>\n};
}

# Select subjects if not already done in last loop.
if ( not $arr{flag} ){ # no flag, then print entry screen.
    prEntryPage($subjsec);
    exit;
}

# Lookup Test records; Only subjsec=subjsec, id = 1, flag=2
foreach $key (keys %arr){
    if ($arr{$key} == 1){ # loop through the tests: $key is id of test.
	$sth = $dbh->prepare("select tdate,name,score from gbtest where id = ?");
	$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($arr{subjsec});

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

print qq{<div style="padding:0.4em 0 0 4em;">\n};
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="cn">$score</td>};
}

print qq{</tr>\n<tr><th>$lex{'Item Date'}</th>};
foreach my $key (sort keys %test){
    my ($date,$id) = split ':',$key;
    print qq{<td>$date</td>};
}
print qq{</tr>\n};


# Print the students and their marks;
foreach my $studnum (@studnum) {
    # Do the name column
    $sth = $dbh->prepare("select lastname, firstname from studentall where studnum = ?");
    $sth->execute( $studnum );
    if ($DBI::errstr) { print "$DBI::errstr"; die;}
    my ($lastname, $firstname) = $sth->fetchrow;
    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;

	# Now get the score for this student for this testid.
	$sth = $dbh->prepare("select id, score from gbscore where studnum = ? and testid = ?");
	$sth->execute( $studnum, $id );
	if ($DBI::errstr) { print "GetScore Error: $DBI::errstr"; die;}
	my $trow = $sth->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) = $sth->fetchrow; 

	print qq{<td><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><div style="padding-left:4em;">\n};
print qq{<input type="submit" value="$lex{'Save / Update Scores'}">\n};
print qq{</div></form></body></html>\n};



#------------
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 prEntryPage { # Entry Values for 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>$lex{'Multiple Test Score Entry'} - $subject</h1>\n};
    print qq{<form action="multiedit.pl" method="post">\n};
    print qq{<input type="hidden" name="flag" value="2">\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;

}


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

    delete $arr{flag}; # not needed here...force back to entry page

    #foreach $key (keys(%arr)) { # Read all passed values...
    #print qq{K: $key VAL: $arr{$key}<br>\n};
    #}

RECORD:
    foreach $key (keys(%arr)) { # Read all passed values...
	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};
	    die;
	}

	# Look for an existing student score record...
	my $sth = $dbh->prepare("select count(*) from gbscore where studnum = ? and testid = ?");
	$sth->execute( $studnum, $testid );
	if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;}
	my $count = $sth->fetchrow;

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

	if ($count == 1 ){  # we have an existing record to update
	    $sth = $dbh->prepare("update gbscore set score = ? where studnum = ? and testid = ?");
	    $sth->execute( $arr{$key}, $studnum, $testid);

	} elsif ($count == 0) {
	    if (not defined $arr{$key}) { next RECORD;}
	    $sth = $dbh->prepare("insert into gbscore values (
             $sql{default},?,?,?,$sql{default})");
	    $sth->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; die $DBI::errstr; }
    }

} # End of updateRecs
