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

#  This file is part of Open Admin for Schools.

#  scoreAdd.pl
#  Passed id for the gbtest record that we want to add/edit scores for.

#  Flag - does update  Comment - comment entry mode.

my $self = 'scoreAdd.pl';
my %lex = ('Add/Edit Test Scores' => 'Add/Edit Test Scores',
	   'Name' => 'Name',
	   'Score' => 'Score',
	   'Comment' => 'Comment',
	   'GB Main' => 'GB Main',
	   'Fill Blanks' => 'Fill Blanks',
	   'Max Score' => 'Max Score',
	   'Test' => 'Test',
	   'Error' => 'Error',
	   'Save' => 'Save',
	   'Main' => 'Main',
	   'Update' => 'Update',

	   );

use DBI;
use CGI;

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

eval require "../../etc/gbook.conf";
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";
}


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


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

# Test passed as id; just id field for test record.
# my $comment = $arr{comment};
# delete $arr{comment};

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


# Now HTML header
my $title = $lex{'Add/Edit Test Scores'};
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 onload="setfocus()" style="padding:1em;">\n};
print qq{[ <a href="$tchpage">$lex{Main}</a> | };
print qq{<a href="gbmain.pl">$lex{'GB Main'}</a> ]\n};

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


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


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

    # Fill Blanks
    print qq{<form action="$self" method="post" style="display:inline;">\n};
    print qq{<input type="hidden" name="id" value="$arr{id}">\n};
    print qq{<input type="submit" value="$lex{'Fill Blanks'}">\n};
    print qq{Score <input type="text" name="filler" style="width:5ch;">\n};
    print qq{Comment <input type="text" name="commentfill" style="width:16ch;" maxlength="255">\n};
    print qq{</form>\n};
    
    
    # Load Test record
    my $sth = $dbh->prepare("select * from gbtest where id = ?");
    $sth->execute ( $arr{id} );
    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr;; }
    my $ref = $sth->fetchrow_hashref;
    my %test = %$ref;
    my $subjsec = $test{subjsec};


    # Set Focus on first entry with javascript.
    my $elementnumber = 3; # first score entry
    print qq{<script type="text/javascript">};

    print qq{function setfocus() { 
    document.forms[1].elements[$elementnumber].focus();
	     }\n\n};

    print "function movefocus(currid, e) { 
    var currval = currid * 1; // make it a number
    var startid = 100;
    var endid = 100;
    var nodes = document.getElementsByTagName('input');
    for (var i=0;i<nodes.length;i++) {
    tempid = nodes[i].getAttribute('id');
    if (tempid > endid) { endid = tempid; }
    }

    var unicode=e.charCode? e.charCode : e.keyCode;

    if (unicode == 40) { // arrow down
      if (currval == endid) {
        targetid = startid;
      } else {
        targetid = currid + 1;
      }
      oElement = document.getElementById(targetid);
      oElement.focus();
      return;
    } 

    if (unicode == 38) { // arrow up
      if (currval == startid) {
        targetid = endid;
      } else {
        targetid = currid - 1;
      }
      oElement = document.getElementById(targetid);
      oElement.focus();
      return;
    } 

    } \n";

    print qq{</script>\n\n};


    # show entry hands
    print qq{<img src="/images/hands.gif" width="300" };
    print qq{style="border:2px solid black;position:absolute;top:1em;right:1em;">\n};
    

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

    
    # Heading
    print qq{<h3>$test{name}: $test{description}<br>};
    print qq{$lex{'Max Score'}: $test{score}</h3>\n};

    # Form
    print qq{<form action="$self" method="post" name="scoreAdd">\n};
    print qq{<input type="hidden" name="testid" value="$arr{id}">\n};
    print qq{<input type="hidden" name="subjsec" value="$subjsec">\n};
    print qq{<input type="hidden" name="page" value="1">\n};
    print qq{<input type="submit" value="$lex{Save}/$lex{Update}">\n};


    # Table and Heading
    print qq{<table cellpadding="3" cellspacing="0" border="1">\n};
    print qq{<caption>Use Up/Down arrow keys to enter scores (like picture)/Tab key for Comments};
    print qq{</caption>\n};
    print qq{<tr><th>$lex{Name}</th><th>Raw<br>$lex{Score}</th><th>$lex{Comment}</th></tr>\n};

    my $sth = $dbh->prepare("select lastname, firstname from studentall where studnum = ?");
    
    my $idcount = 100; # for javascript moves.

    my $sth1 = $dbh->prepare("select id, score, comment from gbscore 
			     where studnum = ? and testid = ?");

    
    # Print the students and their scores;
    foreach my $studnum ( @studnum ) { # has the ordering 
    
	# Get student name
	$sth->execute($studnum);
	if ($DBI::errstr) { print $DBI::errstr; die $DBI::errstr; }
	my ($lastname, $firstname) = $sth->fetchrow;

	# Now get the score and comment for this student for this testid, if it exists
	$sth1->execute( $studnum, $arr{id} );
	if ($DBI::errstr) { print qq{GetScore Error: $DBI::errstr}; die $DBI::errstr; }
	my ($sid,$score,$comment) = $sth1->fetchrow;

	if ( not defined $score ){ $score = $arr{filler}; }
	if ( not defined $comment ){ $comment = $arr{commentfill}; }
    
	print qq{<tr><td><b>$lastname</b>, $firstname ($studnum)</td>\n};
	
	print qq{<td><input type="text" name="$studnum:$sid:S" style="width:5ch;"};
	print qq{value="$score" id="$idcount" onkeyup="movefocus($idcount, event)"></td>\n};

	print qq{<td><input type="text" name="$studnum:$sid:C" style="width:50ch;"};
	print qq{value="$comment"></td></tr>\n};
	$idcount++;
    }

    print qq{</table><input id="$idcount" onkeyup="movefocus($idcount, event)" };
    print qq{type="submit" value="$lex{Save}/$lex{Update}">};
    print qq{</form></body></html>\n};
							
    exit;
							

} # End of showStartPage
    

# No longer used, but version from libgbook library
=head
#------------
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
    my $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 qq{$DBI::errstr}; die $DBI::errstr;}
    while ( my $studnum = $sth->fetchrow ){
	push @eval,$studnum;
    }
    
    # Load 'SortOrder' test if it exists...
    my $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
	my $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 (enrolled but not in sortorder yet)
	foreach my $en (@eval){
	    if ( not $remove{$en} ){ push @studnum, $en;}
	}
	return @studnum;

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


#----------------
sub updateRecords { # Update scores records
#----------------

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

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

    # remainder of %arr values are studnum:recid:type key (type is C comment or S score)
    # value of the hash element is the score value. recid is blank if no record yet.
    
       
    my $sth = $dbh->prepare("select count(*) from gbscore where studnum = ? and testid = ?");

    # Update existing record.
    my $sth1 = $dbh->prepare("update gbscore set score = ?, comment = ? 
			     where studnum = ? and testid = ?");

    # Delete existing Record
    my $sth2 = $dbh->prepare("delete from gbscore where studnum = ? and testid = ?");

    # Add a new Record (both score and comment)
    my $sth3 = $dbh->prepare("insert into gbscore (score, comment,studnum, testid)
			     values (?,?,?,?)");

    my $sth4 = $dbh->prepare("select lastname, firstname from studentall where studnum = ?");
    
    my $sth5 = $dbh->prepare("select score, comment from gbscore where studnum = ? and testid = ?");

    
    # The hash %sortkey will give us a sorted list by student name.
    my (%sortkey, %studname);
    foreach my $key ( keys %arr ) {
	my ( $studnum,$scoreid,$type ) = split ':',$key;
	if ( $type eq 'S' ) { # only want the score key; we create comment key;
	    
	    $sth4->execute( $studnum ); # get student name
	    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
	    my ($lastname, $firstname) = $sth4->fetchrow;
	    
	    $sortkey{"$lastname$firstname$studnum"} = $key;
	    $studname{$studnum} = qq{<b>$lastname</b>, $firstname};
	}
    }

#    foreach my $studnum ( sort keys %studname ) {
#	print qq{<div>$studnum - $studname{$studnum}</div>\n};
#    }

    

    # loop through all passed records by student name
    foreach my $sortkey ( sort keys %sortkey ) {
	my $key = $sortkey{$sortkey}; # $key is key of the %arr hash with values (or not)
	
	my ( $studnum,$scoreid,$type ) = split ':',$key;
	if ( $type eq 'C' ) { next; } # only do scores. 
	#Type:(S)core/(C)omment

	my $commentKey = qq{$studnum:$scoreid:C};
	my $comment = $arr{$commentKey};
	my $score = $arr{$key};

	if ( not $studnum or not $type ) { # scoreid may be undefined if adding.
	    print qq{$lex{Error} $arr{$key} $lex{Test}: $testid<br>\n};
	    print qq{</body></html>\n};
	    exit;
	}

	# Look for an existing student score record for this student, this test;
	$sth->execute( $studnum, $testid );
        my $count = $sth->fetchrow;
	
#	print qq{<div>SN:$studnum ID:$testid Count:$count</div>\n};
	
	if ( $count > 1) { # We have more than 1 record for score for this student/test.
	    
	    $sth4->execute( $studnum ); # get student name
	    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
	    my ($lastname, $firstname) = $sth4->fetchrow;
	    
	    print qq{<h3>Duplicate Records found for the testid: $testid<br>\n};
	    print qq{for student: $studname{$studnum} ($studnum)</h3>\n};
	    print qq{</body></html>\n};
	    exit;
	}

	if ($count == 1){  #if non zero, we have an existing record to update
	    if ( not $score and not $comment and $score ne '0') { # Delete if no values.

		$sth2->execute( $studnum, $testid );
		if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
		print qq{<div>Delete Record for $studname{$studnum} ($studnum)</div>\n};
		
	    } else { # update values

		# Check for changes.
		$sth5->execute( $studnum, $testid ); # get student score,comment
		if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
		my ($origScore, $origComment) = $sth5->fetchrow;
#		print "ID:$testid OSCore:$origScore OComm:$origComment NewS:$score NewC:$comment<br>\n";
		
		if ( $score != $origScore or $comment ne $origComment
		     or not $score or not $origScore ) { # then update
		
		    $sth4->execute( $studnum ); # get student name
		    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
		    my ($lastname, $firstname) = $sth4->fetchrow;
		    
		    $score =~ s/^\s+//;
		    $score =~ s/\s+$//;
		    $comment =~ s/^\s+//;
		    $comment =~ s/\s+$//;
		    
		    $sth1->execute( $score, $comment, $studnum, $testid );
		    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
		    print qq{<div>Update Record <b>$score / $comment</b> for $studname{$studnum} };
		    print qq{($studnum)</div>\n};
		}
	    }

	} elsif ($count == 0) { # count is zero; we must add a new record.
	    # Skip if no values.
	    # print qq{<div>Skip for student $studnum, testid $testid</div>\n};
	    if ( not $score and not $comment and $score ne '0') {
#		print qq{Skipping Score:$score Comment:$comment<br>\n};
		next; } # skip if empty

	    # Add a record
	    $sth4->execute( $studnum ); # get student name
	    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
	    my ($lastname, $firstname) = $sth4->fetchrow;

	    $score =~ s/^\s+//;
	    $score =~ s/\s+$//;
	    $comment =~ s/^\s+//;
	    $comment =~ s/\s+$//;

	    print qq{<div>Add Score $score / $comment for $studname{$studnum} ($studnum)</div>\n};
	    $sth3->execute( $score, $comment, $studnum, $testid );
	    if ($DBI::errstr){ print $DBI::errstr; die $DBI::errstr; }
	}

    } # End of foreach

    # Display links.
    print qq{<div style="margin-top:1em;">};
    print qq{[ <a href="$self?id=$testid">More</a> | <a href="$tchpage">$lex{Main}</a> | };
    print qq{<a href="gbmain.pl">$lex{'GB Main'}</a> ]</div>\n};

    print qq{</body></html>\n};
    exit;
    
} # End of updateRecords
