--- loncom/homework/grades.pm	2004/03/19 03:47:09	1.181
+++ loncom/homework/grades.pm	2004/04/20 06:11:49	1.186
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # The LON-CAPA Grading handler
 #
-# $Id: grades.pm,v 1.181 2004/03/19 03:47:09 albertel Exp $
+# $Id: grades.pm,v 1.186 2004/04/20 06:11:49 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -511,7 +511,7 @@ sub verifyreceipt {
     my $request  = shift;
 
     my $courseid = $ENV{'request.course.id'};
-    my $receipt  = unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}).'-'.
+    my $receipt  = &Apache::lonnet::recprefix($courseid).'-'.
 	$ENV{'form.receipt'};
     $receipt     =~ s/[^\-\d]//g;
     my $url      = $ENV{'form.url'};
@@ -3445,6 +3445,30 @@ sub scantron_scantab {
     return $result;
 }
 
+sub scantron_CODElist {
+    my $cdom = $ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
+    my $cnum = $ENV{'course.'.$ENV{'request.course.id'}.'.num'};
+    my @names=&Apache::lonnet::getkeys('CODEs',$cdom,$cnum);
+    my $namechoice='<option></option>';
+    foreach my $name (@names) {
+	$namechoice.='<option value="'.$name.'">'.$name.'</option>';
+    }
+    $namechoice='<select name="scantron_CODElist">'.$namechoice.'</select>';
+    return $namechoice;
+}
+
+sub scantron_CODEunique {
+    my $result='<nobr>
+                 <input type="radio" name="scantron_CODEunique"
+                        value="Yes" checked="on" /> Yes
+                </nobr>
+                <nobr>
+                 <input type="radio" name="scantron_CODEunique"
+                        value="No" /> No
+                </nobr>';
+    return $result;
+}
+
 sub scantron_selectphase {
     my ($r) = @_;
     my ($symb,$url)=&get_symb_and_url($r);
@@ -3454,6 +3478,8 @@ sub scantron_selectphase {
     my $grading_menu_button=&show_grading_menu_form($symb,$url);
     my $file_selector=&scantron_uploads();
     my $format_selector=&scantron_scantab();
+    my $CODE_selector=&scantron_CODElist();
+    my $CODE_unique=&scantron_CODEunique();
     my $result;
     #FIXME allow instructor to be able to download the scantron file
     # and to upload it,
@@ -3480,6 +3506,12 @@ sub scantron_selectphase {
             <td> Format of data file: </td><td> $format_selector </td>
           </tr>
           <tr bgcolor="#ffffe6">
+            <td> Saved CODEs to validate against: </td><td> $CODE_selector</td>
+          </tr>
+          <tr bgcolor="#ffffe6">
+            <td> Each CODE is only to be used once:</td><td> $CODE_unique </td>
+          </tr>
+          <tr bgcolor="#ffffe6">
             <td>
 <!-- FIXME this is lazy, a single parse of the set should let me know what this is -->
               Last line to expect an answer on: </td><td>
@@ -3603,7 +3635,7 @@ sub scantron_fixup_scanline {
     my ($scantron_config,$scan_data,$line,$whichline,$field,$args)=@_;
     if ($field eq 'ID') {
 	if (length($args->{'newid'}) > $$scantron_config{'IDlength'}) {
-	    return ($line,1,'New value to large');
+	    return ($line,1,'New value too large');
 	}
 	if (length($args->{'newid'}) < $$scantron_config{'IDlength'}) {
 	    $args->{'newid'}=sprintf('%-'.$$scantron_config{'IDlength'}.'s',
@@ -3615,6 +3647,19 @@ sub scantron_fixup_scanline {
 	    &scan_data($scan_data,"$whichline.user",
 		       $args->{'username'}.':'.$args->{'domain'});
 	}
+    } elsif ($field eq 'CODE') {
+	if (length($args->{'CODE'}) > $$scantron_config{'CODElength'}) {
+	    return ($line,1,'New CODE value too large');
+	}
+	if (length($args->{'CODE'}) < $$scantron_config{'CODElength'}) {
+	    $args->{'CODE'}=sprintf('%-'.$$scantron_config{'CODElength'}.'s',
+				       $args->{'CODE'});
+	}
+	substr($line,$$scantron_config{'CODEstart'}-1,
+	       $$scantron_config{'CODElength'})=$args->{'CODE'};
+	if ($args->{'CODE'}=~/^\s*$/) {
+	    &scan_data($scan_data,"$whichline.CODE",$args->{'CODE'});
+	}
     } elsif ($field eq 'answer') {
 	my $length=$scantron_config->{'Qlength'};
 	my $off=$scantron_config->{'Qoff'};
@@ -3748,6 +3793,11 @@ sub scantron_process_corrections {
 				     'ID',{'newid'=>$newid,
 				    'username'=>$ENV{'form.scantron_username'},
 				    'domain'=>$ENV{'form.scantron_domain'}});
+    } elsif ($ENV{'form.scantron_corrections'} =~ /^(duplicate|incorrect)CODE$/) {
+	my $newCODE=$ENV{'form.scantron_CODE'};
+	($line,$err,$errmsg)=
+	    &scantron_fixup_scanline(\%scantron_config,$scan_data,$line,$which,
+				     'CODE',{'CODE'=>$newCODE});
     } elsif ($ENV{'form.scantron_corrections'} =~ /^(missing|double)bubble$/) {
 	foreach my $question (split(',',$ENV{'form.scantron_questions'})) {
 	    ($line,$err,$errmsg)=
@@ -3941,7 +3991,7 @@ sub scantron_validate_ID {
 					 $line,'duplicateID',$username);
 		return(1);
 	    }
-	    #FIXME store away line we prviously saw the ID on to use above
+	    #FIXME store away line we previously saw the ID on to use above
 	    $found{'ids'}{$found}++;
 	    $found{'usernames'}{$username}++;
 	} else {
@@ -3988,7 +4038,7 @@ sub scantron_get_correction {
     $r->print('<input type="hidden" name="scantron_corrections" value="'.$error.'" />'."\n");
     $r->print('<input type="hidden" name="scantron_line" value="'.$i.'" />'."\n");
     if ($error =~ /ID$/) {
-	if ($error eq 'unknownID') {
+	if ($error eq 'incorrectID') {
 	    $r->print("The encoded ID is not in the classlist</p>\n");
 	} elsif ($error eq 'duplicateID') {
 	    $r->print("The encoded ID has also been used by a previous paper $arg</p>\n");
@@ -4006,9 +4056,23 @@ sub scantron_get_correction {
 				       'scantron_username','scantron_domain'));
 	$r->print(": <input type='text' name='scantron_username' value='' />");
 	$r->print("\n@".
-		 &Apache::loncommon::select_dom_form($ENV{'request.role..domain'},'scantron_domain'));
+		 &Apache::loncommon::select_dom_form($ENV{'request.role.domain'},'scantron_domain'));
 
 	$r->print('</li>');
+    } elsif ($error =~ /CODE$/) {
+	if ($error eq 'incorrectCODE') {
+	    $r->print("The encoded CODE is not in the list of possible CODEs</p>\n");
+	} elsif ($error eq 'duplicateCODE') {
+	    $r->print("The encoded CODE has also been used by a previous paper $arg, and CODEs were supposed to be unique</p>\n");
+	}
+	$r->print("<p>The ID on the form is  <tt>".
+		  $$scan_record{'scantron.ID'}."</tt><br />\n");
+	$r->print("The name on the paper is ".
+		  $$scan_record{'scantron.LastName'}.",".
+		  $$scan_record{'scantron.FirstName'}."</p>");
+	$r->print("<p>How should I handle this? <br /> \n");
+	$r->print("\n<ul><li> ");
+	$r->print('</li>');
     } elsif ($error eq 'doublebubble') {
 #FIXME Need to print out who this is along with the paper info
 	$r->print("<p>There have been multiple bubbles scanned for a some question(s)</p>\n");
@@ -4060,6 +4124,48 @@ sub scantron_bubble_selector {
 sub scantron_validate_CODE {
     my ($r,$currentphase) = @_;
     #FIXME doesn't do anything yet
+    my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'});
+    if ($scantron_config{'CODElocation'} &&
+	$scantron_config{'CODEstart'} &&
+	$scantron_config{'CODElength'}) {
+	if (!$ENV{'form.scantron_CODElist'}) {
+	    &FIXME_blow_up()
+	}
+    } else {
+	&Apache::lonnet::logthis(" CODE stuf $scantron_config{'CODElocation'}:$scantron_config{'CODEstart'}:$scantron_config{'CODElength'}");
+	return (0,$currentphase+1);
+    }
+    
+    my %usedCODEs;
+
+    my $old_name=$ENV{'form.scantron_CODElist'};
+    my $cdom =$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
+    my $cnum =$ENV{'course.'.$ENV{'request.course.id'}.'.num'};
+    my %result=&Apache::lonnet::get('CODEs',[$old_name],$cdom,$cnum);
+    my %allcodes=map {($_,1)} split(',',$result{$old_name});
+
+    my ($scanlines,$scan_data)=&scantron_getfile();
+    for (my $i=0;$i<=$scanlines->{'count'};$i++) {
+	my $line=&scantron_get_line($scanlines,$i);
+	if ($line=~/^[\s\cz]*$/) { next; }
+	my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,
+						 $scan_data);
+	my $CODE=$$scan_record{'scantron.CODE'};
+	my $error=0;
+	if (!exists($allcodes{$CODE})) {
+	    &scantron_get_correction($r,$i,$scan_record,
+				     \%scantron_config,
+				     $line,'incorrectCODE',$CODE);
+	    return(1);
+	}
+	if (exists($usedCODEs{$CODE}) && $ENV{'form.scantron_CODEunique'}) {
+	    &scantron_get_correction($r,$i,$scan_record,
+				     \%scantron_config,
+				     $line,'duplicateCODE',$CODE);
+	    return(1);
+	}
+	$usedCODEs{$CODE}++;
+    }
     return (0,$currentphase+1);
 }
 
@@ -4238,11 +4344,21 @@ UPLOAD
 
 sub scantron_upload_scantron_data_save {
     my($r)=@_;
+    my ($symb,$url)=&get_symb_and_url($r,1);
+    my $doanotherupload=
+	'<br /><form action="/adm/grades" method="post">'."\n".
+	'<input type="hidden" name="command" value="scantronupload" />'."\n".
+	'<input type="submit" name="submit" value="Do Another Upload" />'."\n".
+	'</form>'."\n";
     if (!&Apache::lonnet::allowed('usc',$ENV{'form.domainid'}) &&
 	!&Apache::lonnet::allowed('usc',
 			    $ENV{'form.domainid'}.'_'.$ENV{'form.courseid'})) {
 	$r->print("You are not allowed to upload Scantron data to the requested course.<br />");
-	$r->print(&show_grading_menu_form(&get_symb_and_url($r)));
+	if ($symb) {
+	    $r->print(&show_grading_menu_form($symb,$url));
+	} else {
+	    $r->print($doanotherupload);
+	}
 	return '';
     }
     $r->print("Doing upload to ".$ENV{'form.courseid'}." <br />");
@@ -4263,17 +4379,20 @@ sub scantron_upload_scantron_data_save {
     # See if there is anything left
     unless ($fname) { return 'error: no uploaded file'; }
     $fname='scantron_orig_'.$fname;
-    $r->print(&Apache::lonnet::finishuserfileupload($ENV{'form.courseid'},
-						    $ENV{'form.domainid'},
-						    $home,'upfile',$fname));
-    my ($symb,$url)=&get_symb_and_url($r);
+    if (length($ENV{'form.upfile'}) < 2) {
+	$r->print("<font color='red'>Error:</font> The file you attempted to upload, <tt>".&HTML::Entities::encode($ENV{'form.upfile.filename'},'<>&"')."</tt>, contained no information. Please check that you entered the correct filename.");
+    } else {
+	my $result=&Apache::lonnet::finishuserfileupload($ENV{'form.courseid'},$ENV{'form.domainid'},$home,'upfile',$fname);
+	if ($result =~ m|^/uploaded/|) {
+	    $r->print("<font color='green'>Success:</font> Successfully uploaded ".(length($ENV{'form.upfile'})-1)." bytes of data into location <tt>".$result."</tt>");
+	} else {
+	    $r->print("<font color='red'>Error:</font> An error (".$result.") occured when attempting to upload the file, <tt>".&HTML::Entities::encode($ENV{'form.upfile.filename'},'<>&"')."</tt>");
+	}
+    }
     if ($symb) {
-	$r->print(&show_grading_menu_form(&get_symb_and_url($r)));
+	$r->print(&show_grading_menu_form($symb,$url));
     } else {
-	$r->print('<br /><form action="/adm/grades" method="post">'."\n".
-		  '<input type="hidden" name="command" value="scantronupload" />'."\n".
-		  '<input type="submit" name="submit" value="Do Another Upload" />'."\n".
-		  '</form>'."\n");
+	$r->print($doanotherupload);
     }
     return '';
 }
@@ -4428,17 +4547,18 @@ GRADINGMENUJS
 
     $result.='<table width="100%" border=0>';
     $result.='<tr bgcolor="#ffffe6"><td>'.
-	'<input type="button" onClick="javascript:checkChoice(this.form,\'3\',\'csvform\');" value="Upload" />'.
-	' scores from file </td></tr>'."\n";
+	'<input type="button" onClick="javascript:checkChoice(this.form,\'3\',\'csvform\');" value="'.&mt('Upload').'" />'.
+	' '.&mt('scores from file').' </td></tr>'."\n";
 
     $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'.
 	'<input type="button" onClick="javascript:checkChoice(this.form,\'4\',\'scantron_selectphase\');'.
-	'" value="Grade" /> scantron forms</td></tr>'."\n";
+	'" value="'.&mt('Grade').'" /> scantron forms</td></tr>'."\n";
 
     if ((&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'})) && ($symb)) {
 	$result.='<tr bgcolor="#ffffe6"valign="top"><td>'.
-	    '<input type="button" onClick="javascript:checkChoice(this.form,\'5\',\'verify\');" value="Verify" />'.
-	    ' submission Receipt no: '.unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}).
+	    '<input type="button" onClick="javascript:checkChoice(this.form,\'5\',\'verify\');" value="'.&mt('Verify').'" />'.
+	    ' '.&mt('receipt').': '.
+	    &Apache::lonnet::recprefix($ENV{'request.course.id'}).
 	    '-<input type="text" name="receipt" size="4" onChange="javascript:checkReceiptNo(this.form,\'OK\')">'.
 	    '</td></tr>'."\n";
     }