#!/usr/local/bin/perl

## $Id$

####################################################################
# Copyright @ 1995-1998 University of Rochester
# All Rights Reserved
####################################################################


###############################################################################
############          PRELIMINARY SETUP                 #######################
###############################################################################

use lib '/ww/webwork/gage_system/webwork/system/lib/'; # mainWeBWorKDirectory

use Global;
use CGI qw(:standard);
use Auth;
use TimeLocal; # the module Time::Local.pm has a bug which interacts
			   # with DProf.  (They call a subroutine assuming @_ doesn't change.

use strict;

# begin Timing code
use Benchmark;
my $beginTime = new Benchmark;
# end Timing code


&CGI::ReadParse(*main::inputs);
my %inputs=%main::inputs;

# get primary data from CGI form
my $User       = $inputs{'user'};
my $Course     = $inputs{'course'};
my $Key        = $inputs{'key'};
my $psvn       = $inputs{'probSetKey'};

# set course environment
&Global::getCourseEnvironment($Course);

my	$scriptDirectory   = getWebworkScriptDirectory($Course);
my	$databaseDirectory = getCourseDatabaseDirectory($Course);
my 	$cgiURL   		   = getWebworkCgiURL($Course);
my	$htmlURL       	   = getCourseHtmlURL($Course);
my  $logsDirectory     = getCourseLogsDirectory($Course);

require "${scriptDirectory}$Global::DBglue_pl";
require "${scriptDirectory}$Global::classlist_DBglue_pl";
require "${scriptDirectory}$Global::FILE_pl";
require "${scriptDirectory}HTMLglue.pl";

my $keyFile 			= getCourseKeyFile($Course);
&verify_key($inputs{'user'}, $inputs{'key'}, "$keyFile", $inputs{'course'});

my $permissionsFile = &Global::getCoursePermissionsFile($inputs{'course'});
my $permissions = &get_permissions($inputs{'user'}, $permissionsFile);

if ($permissions != $Global::instructor_permissions ) {
	print "permissions = $permissions instructor_permissions = $Global::instructor_permissions\n";
	print &html_NO_PERMISSION;
	exit(0);
	}

# get additional data from calling CGI form
my ( $Mode, $studentLogin, $setNumber);

$Mode        = "HTML";   #default viewing mode
$Mode = $inputs{'Mode'} if defined($inputs{'Mode'});
$studentLogin	= $inputs{'studentLogin'};
$setNumber       = $inputs{'setNo'};

# if the psvn is not given we need to derive it from the set number and
# the student login ID
if (!defined($psvn) ) {
	unless ( defined($studentLogin) && defined($setNumber) ) {
		Global::error("DataMunger: Need psvn, or studentLogin and setNumber");
		}
	my %loginList = &getAllSetNumbersForStudentLoginHash($studentLogin);
	$psvn =$loginList{$setNumber};
	}


# define data to be displayed in the form
# the data for this will be loaded by the subroutine load
# my (@row1, @row2, @row3, @row4);
# my ($StudentLastName, $StudentFirstName, $StudentID);
#     @row1 = qw(StudentLastName StudentFirstName StudentID);
#
# my ($StudentStatus, $StudentGrade, $SetNumber);
#     @row2 = qw(StudentStatus StudentGrade SetNumber);
#
# my ($OpenDate, $DueDate, $AnswerDate );
#     @row3 = qw(OpenDate DueDate AnswerDate );
#
# my	($StudentLogin, $ClassSection );
#     @row4 = qw(StudentLogin ClassSection  );
# my	($SetHeaderFileName, $ProbHeaderFileName );
#     @row5 = qw(SetHeaderFileName, ProbHeaderFileName );


###############################################################################
############       MODIFY SET DATA IN THE DATABASE      #######################
###############################################################################


	# First make sure that the psvn is properly defined
	# then save the information from the CGI form to the database
	# Whether or not information is saved, at the end of this block
	# the most current information has been placed in %probSetRecord
	# using &fetchProbSetRecord.
if (not &fetchProbSetRecord($psvn)) {
	Global::error("in dataMunger.pl:","Can't  find record with psvn = $psvn
					in the database");
}
$studentLogin = getStudentLogin($psvn);
attachCLRecord($studentLogin);

if (defined( $inputs{'save'} ) && $inputs{'save'} eq "ON" ) {
	# in this case we obtain the data from the CGI from and store it in the database

	# update the database from the CGI script:
	&updateDatabase($psvn);
						# loads the information into %probSetRecord,
						# modifies the data and saves it back to the database
						# This effectively executes fetchProbSetRecord
						# so that the contents of %probSetRecord is now current

	#log the changes:  -- the format for loggin the changes needs improvement
	&logChanges( &getProbSetRecord()  );
	&print_modification_form;

}	elsif (defined($inputs{'save'}) && $inputs{'save'} eq "OFF" ){
	# No new information in the calling CGI form
	# and the information has already been loaded into %probSetRecord using &fetchProbSetRecord($psvn);
	# Nothing needs to be done in this case except print the form
	&print_modification_form;
}	elsif ( defined($inputs{'deleteMode'}) && $inputs{'deleteMode'} eq 'delete') {
	# In this case the problem is deleted
	my $psvnSetNumber = getSetNumber($psvn);
	&deleteProbSetRecord($psvn);
	# remove .sco file if it exists
	system ("rm ${databaseDirectory}S${psvnSetNumber}-${psvn}.sco") if (-e "${databaseDirectory}S${psvnSetNumber}-${psvn}.sco");
	# remove any l2h files
	my $l2hDir = getCoursel2hDirectory();
	my $tempDir = convertPath("${l2hDir}set${psvnSetNumber}/*-$psvn");
	system ("rm -rf $tempDir");
	&record_successfully_deleted_message;  #reload empty record
}	else {

#   The calling CGI script must define the 'save' variable or the 'deleteMode' variable
	Global::error( "<P><B>in dataMunger.pl:<BR>",  "No value for 'save' mode in the calling CGI form.</B><P>");
	}

# begin Timing code
my $endTime = new Benchmark;
&Global::logTimingInfo($beginTime,$endTime,"dataMunger.pl",$Course,$User);
# end Timing code
exit;

#### END of main program

###############################################################################
############################  SUBROUTINES          ############################
###############################################################################


###############################################################################
##########################       PRINT FORM      ##############################
###############################################################################
sub print_modification_form {
	print &htmlTOP("data for the problem set version number $psvn");
	print <<END_OF_HTML;

	<A HREF="${cgiURL}profLogin.pl?user=$inputs{'user'}&key=$inputs{'key'}&course=$inputs{'course'}">
	<IMG SRC="${Global::upImgUrl}" align="right" BORDER=1 ALT="[Up]"></A><p>
	<H3 ALIGN ="CENTER">Class Identification: $inputs{'course'}</H3>
	<H3 ALIGN ="CENTER">Data for problem set version number: <FONT COLOR="#AA4400">$psvn</FONT></H3>
	<HR SIZE =2>
	<FORM ACTION="${cgiURL}dataMunger.pl" METHOD=POST>

	Changes can be saved only if the Read/Write Mode button is selected: <BR>

	<INPUT TYPE="radio" CHECKED NAME="save" VALUE="OFF" > Read Only Mode <BR>
	<INPUT TYPE="radio" NAME="save" VALUE="ON"> Read/Write Mode  <B>Make a backup copy of your database first.</B><BR>
	<INPUT TYPE="hidden" NAME="firsttime" VALUE=0>
END_OF_HTML


	######################################################
	# return messages
	#print message about saving to the database and current mode of CGI form
	if (defined( $inputs{'firsttime'} ) && $inputs{'firsttime'} == 0 ) {
		if (defined( $inputs{'save'} ) && $inputs{'save'} eq "ON" ) {
			print "<P><FONT COLOR='#ff00aa'><B>DATABASE MODIFIED</B></font> <P>";
		}	elsif (defined($inputs{'save'}) && $inputs{'save'} eq "OFF" ){

			print "<P><FONT COLOR='#ff00aa'><B>READ ONLY MODE:  DATABASE UNCHANGED</B></font> <P>";

		} else {
	#   When initially entering this CGI the 'save' mode is undefined.
			wwerror( $0,  "No value for 'save' mode.</B><P>");
		}
	}
	# submit button

	print qq!<INPUT TYPE="SUBMIT" VALUE="SAVE CHANGES"><INPUT TYPE = "RESET" VALUE= "RESET FORM"> <BR>!;


	# Get set data
	my $StudentLastName 	= CL_getStudentLastName($studentLogin);
	my $StudentFirstName 	= CL_getStudentFirstName($studentLogin);
	my $StudentID			= CL_getStudentID($studentLogin);
	my $StudentStatus		= CL_getStudentStatus($studentLogin);
	my $SetNumber			= &getSetNumber($psvn);
	my $OpenDate			= &getOpenDate($psvn);
	my $DueDate				= &getDueDate($psvn);
	my $AnswerDate			= &getAnswerDate($psvn);
	my $ClassSection		= CL_getClassSection($psvn);
	my $ClassRecitation		= CL_getClassRecitation($psvn);
	my $SetHeaderFileName	= &getSetHeaderFileName($psvn);
	my $ProbHeaderFileName	= &getProbHeaderFileName($psvn);
	my $StudentLogin		= $studentLogin;
	
	# replace empty strings by a non breaking space
	$ClassSection = '&nbsp;' unless ($ClassSection =~ /\S/);
	$ClassRecitation = '&nbsp;' unless ($ClassRecitation =~ /\S/);
	$SetHeaderFileName = '&nbsp;' unless ($SetHeaderFileName =~ /\S/);
	$ProbHeaderFileName = '&nbsp;' unless ($ProbHeaderFileName =~ /\S/);
	

	# format the dates properly

	$OpenDate       = &formatDateAndTime($OpenDate);
	$DueDate        = &formatDateAndTime($DueDate);
	$AnswerDate     = &formatDateAndTime($AnswerDate);

	# continue printing form ######################################################
	print &sessionKeyInputs(\%inputs);
	print qq!<INPUT TYPE="HIDDEN" NAME="probSetKey" VALUE="$psvn">!;
	print qq! <TABLE BORDER="1" CELLPADDING="1" CELLSPACING="2" > <FONT SIZE=-2>!;

	print "<TR>\n";
		print &formatHeaderCell("Last Name");
		print &formatHeaderCell("First Name");
		print &formatHeaderCell("Student ID" );
	print "</TR>\n";
	print "<TR>\n";
		print &formatFixedDataCell("StudentLastName",$StudentLastName, "20");
		print &formatFixedDataCell("StudentFirstName", $StudentFirstName, "20");
		print &formatFixedDataCell("StudentID", $StudentID, "20");
	print "</TR>\n";

	print "<TR>\n";
		print &formatHeaderCell("Student login name");
		print &formatHeaderCell("Enrollment Status");
		print &formatHeaderCell("Set Number" );
	print "</TR>\n";
	print "<TR>\n";
		print &formatFixedDataCell("StudentLogin",$StudentLogin, "20");
		print &formatFixedDataCell("StudentStatus",$StudentStatus, "20");
		print &formatFixedDataCell("SetNumber", $SetNumber, "20");
	print "</TR>\n";

	print "<TR>\n";
		print &formatHeaderCell("Class Section");
		print &formatHeaderCell("Class Recitation");
	print "</TR>\n";

	print "<TR>\n";
		print &formatFixedDataCell("ClassSection", $ClassSection, "20");
		print &formatFixedDataCell("ClassRecitation", $ClassRecitation, "20");
	print "</TR>\n";

	print "<TR>\n";
		print &formatHeaderCell("Open Date");
		print &formatHeaderCell("Due Date");
		print &formatHeaderCell("Answer Date" );
	print "</TR>\n";

	print "<TR>\n";
		print &formatDataCell("OpenDate",$OpenDate, "20");
		print &formatDataCell("DueDate", $DueDate, "20");
		print &formatDataCell("AnswerDate", $AnswerDate, "20");
	print "</TR>\n";



	print "<TR>\n";
		print &formatHeaderCell("Paper Header File Name" );
		print &formatHeaderCell("Screen Header File Name" );
	print "</TR>\n";

	print "<TR>\n";
		print &formatFixedDataCell("SetHeaderFileName", $SetHeaderFileName, "20");
		print &formatFixedDataCell("ProbHeaderFileName", $ProbHeaderFileName, "20");
	print "</TR>\n";

	print "</TR>\n";
	print " </FONT></TABLE>";

	print qq! <TABLE BORDER="1" CELLPADDING="1" CELLSPACING="2" >!;
	my $i;
	my @row5;
	my @problems = sort {$a <=> $b} &getAllProblemsForProbSetRecord($psvn);
	foreach $i (@problems)  {
		@row5 = ("ProblemFileName$i", "ProblemStatus$i","ProblemSeed$i", "ProblemValue$i", "ProblemMaxNumOfIncorrectAttemps$i");
		print "<TR>";
		print &formatHeaderCell( qq!
		<A HREF="${Global::processProblem_CGI}?probSetKey=$psvn&probNum=$i&Mode=$Mode&course=$Course&user=$User&key=$Key" TARGET="ViewProblem">
			Problem $i</A>!);

		print &formatHeaderCell( "Attempted");
		print &formatHeaderCell( "Status");
		print &formatHeaderCell( "Correct");
		print &formatHeaderCell( "Wrong");
		print &formatHeaderCell( "Seed");
		print &formatHeaderCell( "Value");
		print &formatHeaderCell( "MaxAttmp");
		print "</TR>";

		print "<TR>";

		print &formatFixedDataCell( "ProblemFileName$i"  , &getProblemFileName($i,$psvn) ,"30" );
		print &formatDataCell( "ProblemAttempted$i"    , &getProblemAttempted($i,$psvn)   ,"1");
		print &formatDataCell( "ProblemStatus$i"    , &getProblemStatus($i,$psvn)   ,"5");
		my $correctAns 		= 	&getProblemNumOfCorrectAns($i,$psvn);
		my $incorrectAns 	=	&getProblemNumOfIncorrectAns($i,$psvn);
		$correctAns 		= 	"0" unless $correctAns;  # Force 0 to print instead of a space
		$incorrectAns		=	"0" unless $incorrectAns; #  ditto
		print &formatDataCell( "ProblemNumOfCorrectAns$i"    , $correctAns  ,"2");
		print &formatDataCell( "ProblemNumOfIncorrectAns$i"    , $incorrectAns   ,"2");
		print &formatDataCell( "ProblemSeed$i"      , &getProblemSeed($i,$psvn)     ,"7");
		print &formatFixedDataCell( "ProblemValue$i"     , &getProblemValue($i,$psvn)    ,"4");
		print &formatDataCell( "ProblemMaxNumOfIncorrectAttemps$i"     , &getProblemMaxNumOfIncorrectAttemps($i,$psvn)    ,"4");
		print "</TR>";

		}


	print <<END_HTML;
	</TABLE >

	</FORM>
END_HTML


	# FORM for downloading postscript versions
	print qq!
		<FORM action="${Global::cgiWebworkURL}welcomeAction.pl">
		<HR NOSHADE><H4>Download the postscript version of this problem set:</H4>\n
		Problem Set Number $SetNumber -- psvn: $psvn -- for $StudentLastName, $StudentFirstName<BR>
		<INPUT TYPE='HIDDEN' NAME='local_psvns'  VALUE="$psvn">
		<INPUT TYPE='HIDDEN' NAME='action' VALUE='Get_hard_copy'>
		<B>Download Type:</B> <INPUT TYPE=RADIO NAME=\"downloadType\" VALUE=\"ps\" CHECKED><B>postscript</B> format
		<INPUT TYPE=RADIO NAME=\"downloadType\" VALUE=\"pdf\"><B>pdf</B> format
		<INPUT TYPE=RADIO NAME=\"downloadType\" VALUE=\"TeX\"><B>TeX</B> format
		<INPUT TYPE=RADIO NAME=\"downloadType\" VALUE=\"dvi\"><B>DVI</B> format<BR>
		<INPUT TYPE=CHECKBOX NAME=\"ShowAns\" VALUE=\"1\"> Show answers in hard copy.<BR>

	!;

	print &sessionKeyInputs(\%inputs);

	print qq!
		<br><input type="submit" value="Download  File">
		</FORM>
	!;

	# form for viewing student summary
	print qq!
	<FORM ACTION="studentSummary.pl" METHOD=POST>\n
	<HR NOSHADE><H4>Form for viewing student summary of homework</H4>\n
	<INPUT TYPE="HIDDEN" NAME="studentLogin" VALUE = "$StudentLogin">
		!;

	print &sessionKeyInputs(\%inputs);

	print qq!
		 <input type="submit" value="Get homework summary">\n
		 </FORM>
	!;

	# form for deleting problem set
	print qq!
		<HR NOSHADE><H3>Delete this problem set:</H3>\n
		Problem Set Number $SetNumber -- psvn: $psvn -- for $StudentLastName, $StudentFirstName<BR>
		<B>This action cannot be undone\!</B>
		<FORM ACTION="${cgiURL}dataMunger.pl" METHOD=POST>\n
		<INPUT TYPE="HIDDEN" NAME="probSetKey"  VALUE="$psvn">\n
		<INPUT TYPE="RADIO" NAME="deleteMode"  VALUE="save" CHECKED> Off<BR>\n
		<INPUT TYPE="RADIO" NAME="deleteMode"  VALUE="delete"> Delete this record
	!;

	print &sessionKeyInputs(\%inputs);

	print qq!
		 <br><input type="submit" value="Delete this person's problem set">\n
		 </FORM>
	!;


	print &htmlBOTTOM("dataMunger.pl", \%inputs);

}  # end of print_modification_form


sub updateDatabase {
	my $psvn = shift @_;
	&fetchProbSetRecord($psvn);

	my $time1 = &unformatDateAndTime($inputs{'OpenDate'});
	my $time2 = &unformatDateAndTime($inputs{'DueDate'});
	my $time3 = &unformatDateAndTime($inputs{'AnswerDate'});
	if ($time2 < $time1 or $time3 < $time2) {
		&Global::error('Dates not in chronological order', "The open date: $inputs{'OpenDate'},
		due date: $inputs{'DueDate'}, and answer date: $inputs{'AnswerDate'} must be in chronologicasl order.");
	}
	&putOpenDate   ($time1,$psvn);
	&putDueDate    ($time2,$psvn);
	&putAnswerDate ($time3,$psvn);


	# now update the problem information
	# @problems was defined "globally" within this file
	my @problems = sort {$a <=> $b} &getAllProblemsForProbSetRecord($psvn);
	my ($i,$old_seed, $new_seed);
	my $l2hDir = getCoursel2hDirectory();
	foreach $i (@problems)   {
		$old_seed = getProblemSeed($i,$psvn); 	
		$new_seed =	stripWhiteSpace($inputs{"ProblemSeed$i"});			
#		&putProblemFileName(            stripWhiteSpace($inputs{"ProblemFileName$i"}),   $i,$psvn);
		&putProblemAttempted(           stripWhiteSpace($inputs{"ProblemAttempted$i"}),     $i,$psvn);
		&putProblemStatus(              stripWhiteSpace($inputs{"ProblemStatus$i"}),     $i,$psvn);
		&putProblemNumOfCorrectAns(     stripWhiteSpace($inputs{"ProblemNumOfCorrectAns$i"}),     $i,$psvn);
		&putProblemNumOfIncorrectAns(   stripWhiteSpace($inputs{"ProblemNumOfIncorrectAns$i"}),     $i,$psvn);
#		&putProblemValue(               stripWhiteSpace($inputs{"ProblemValue$i"}),  $i,$psvn);
		&putProblemMaxNumOfIncorrectAttemps( stripWhiteSpace($inputs{"ProblemMaxNumOfIncorrectAttemps$i"}),  $i,$psvn);
		&putProblemSeed(     			$new_seed,$i,$psvn);
		
		if ($old_seed != $new_seed) {  ## remove latex2html cached images
			my $psvnSetNumber = getSetNumber($psvn);
			my $tempDir = convertPath("${l2hDir}set${psvnSetNumber}/${i}-$psvn");
			system ("rm -rf $tempDir");
			}	
		}
	# save the updated information to the database
	&saveProbSetRecord($psvn);
	}
# logs the incremental changes made by dataMunger to a log file
sub	logChanges {
		my @dataArray = @_;
		my $fullLogFileName ="${logsDirectory}dataMunger.log";
		open(LOGFILE,">>$fullLogFileName")  ||  &Global::error( "Can't open $fullLogFileName");

		my $timeNow = formatDateAndTime(time);
		print LOGFILE "\n$Course, psvn is $psvn, user is $User, time is $timeNow, data is: ";
		my $dataString = join( ' ',@dataArray);
		print  LOGFILE "@dataArray\n" ;
		close(LOGFILE);
		}

sub formatDataCell {
	my ($name,$value,$size) = @_;
		# if the data hasn't been entered it appears as a blank:
	$value = '' unless defined($value);

	my $out = qq!
	<TD ALIGN=CENTER VALIGN=MIDDLE >
	<INPUT TYPE="TEXT" NAME="$name" VALUE="$value", SIZE="$size">
	</TD>
	!;
	$out;
	}
sub formatFixedDataCell {
	my ($name,$value,$size) = @_;
		# if the data hasn't been entered it appears as a blank:
	$value = '' unless defined($value);

	my $out = qq!
	<TD ALIGN=CENTER VALIGN=MIDDLE >
	<INPUT TYPE="HIDDEN" NAME="$name" VALUE="$value">
	$value
	</TD>
	!;
	$out;
	}
sub formatHeaderCell {
	my ($item,$options) = @_;
	$options = '' unless defined($options);
	my $out = qq!
	<TH ALIGN=CENTER VALIGN=MIDDLE $options>
	$item
	</TH>
	!;
	$out;
	}



sub record_successfully_deleted_message{

	print &htmlTOP("data for the problem set version number $psvn");
	print <<END_OF_HTML;
	<A HREF="${cgiURL}profLogin.pl?user=$inputs{'user'}&key=$inputs{'key'}&course=$inputs{'course'}">
	<IMG SRC="${Global::upImgUrl}" align="right" BORDER=1 ALT="[Up]"></A>
END_OF_HTML
	
	my $setNumber = getSetNumber($psvn);
	my $studentName = CL_getStudentName($studentLogin);
	print qq!<P><B> Problem set version $psvn for set number !,
				$setNumber, " for ",
			   $studentName,
			   " deleted.</B><P>";
	print &htmlBOTTOM("dataMunger.pl", \%inputs);

}
