--- loncom/homework/grades.pm	2004/08/06 22:06:14	1.207
+++ loncom/homework/grades.pm	2004/12/03 22:44:36	1.233
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # The LON-CAPA Grading handler
 #
-# $Id: grades.pm,v 1.207 2004/08/06 22:06:14 albertel Exp $
+# $Id: grades.pm,v 1.233 2004/12/03 22:44:36 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -25,16 +25,6 @@
 #
 # http://www.lon-capa.org/
 #
-# 2/9,2/13 Guy Albertelli
-# 6/8 Gerd Kortemeyer
-# 7/26 H.K. Ng
-# 8/20 Gerd Kortemeyer
-# Year 2002
-# June-August H.K. Ng
-# Year 2003
-# February, March H.K. Ng
-# July, H. K. Ng
-#
 
 package Apache::grades;
 use strict;
@@ -101,25 +91,6 @@ sub get_symb_and_url {
     return ($symb,$url);
 }
 
-# --- Retrieve the fullname for a user. Return lastname, first middle ---
-# --- Generation is attached next to the lastname if it exists. ---
-sub get_fullname {
-    my ($uname,$udom) = @_;
-    my %name=&Apache::lonnet::get('environment', ['lastname','generation',
-						  'firstname','middlename'],
-                                  $udom,$uname);
-    my $fullname;
-    my ($tmp) = keys(%name);
-    if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
-        $fullname = &Apache::loncoursedata::ProcessFullName
-            (@name{qw/lastname generation firstname middlename/});
-    } else {
-        &Apache::lonnet::logthis('grades.pm: no name data for '.$uname.
-                                 '@'.$udom.':'.$tmp);
-    }
-    return $fullname;
-}
-
 #--- Format fullname, username:domain if different for display
 #--- Use anywhere where the student names are listed
 sub nameUserString {
@@ -174,7 +145,6 @@ sub get_display_part {
 	if ($symb eq '') { $symb=&Apache::lonnet::symbread($url) }
     }
     my $display=&Apache::lonnet::EXT('resource.'.$partID.'.display',$symb);
-    &Apache::lonnet::logthis("\nsymb $symb\n url  $url\npartID $partID\ndisplay $display \n");
     if (defined($display) and $display ne '') {
 	$display.= " (<font color=\"#999900\">id $partID</font>)";
     } else {
@@ -1002,6 +972,7 @@ sub sub_page_kw_js {
     my $request = shift;
     my $iconpath = $request->dir_config('lonIconsURL');
     &commonJSfunctions($request);
+    my $docopen=&Apache::lonhtmlcommon::javascript_docopen();
     $request->print(<<SUBJAVASCRIPT);
 <script type="text/javascript" language="javascript">
 
@@ -1114,7 +1085,7 @@ sub sub_page_kw_js {
     pWin = window.open('', 'MessageCenter', 'resizable=yes,toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=600,height='+height);
     pWin.focus();
     pDoc = pWin.document;
-    pDoc.open('text/html','replace');
+    pDoc.$docopen;
     pDoc.write("<html><head>");
     pDoc.write("<title>Message Central</title>");
 
@@ -1245,7 +1216,7 @@ sub sub_page_kw_js {
     hwdWin = window.open('', 'KeywordHighlightCentral', 'resizeable=yes,toolbar=no,location=no,scrollbars=no,width=400,height=300,screenx='+xpos+',screeny='+ypos);
     hwdWin.focus();
     var hDoc = hwdWin.document;
-    hDoc.open('text/html','replace');
+    hDoc.$docopen;
     hDoc.write("<html><head>");
     hDoc.write("<title>Highlight Central</title>");
 
@@ -1414,14 +1385,15 @@ sub submission {
     my ($uname,$udom)     = ($ENV{'form.student'},$ENV{'form.userdom'});
     $udom = ($udom eq '' ? $ENV{'user.domain'} : $udom); #has form.userdom changed for a student?
     my $usec = &Apache::lonnet::getsection($udom,$uname,$ENV{'request.course.id'});
-    $ENV{'form.fullname'} = &get_fullname ($uname,$udom) if $ENV{'form.fullname'} eq '';
+    $ENV{'form.fullname'} = &Apache::loncommon::plainname($uname,$udom,'lastname') if $ENV{'form.fullname'} eq '';
 
     my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));
     if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }
 
     if (!&canview($usec)) {
 	$request->print('<font color="red">Unable to view requested student.('.
-			$uname.$udom.$usec.$ENV{'request.course.id'}.')</font>');
+			$uname.'@'.$udom.' in section '.$usec.' in course id '.
+			$ENV{'request.course.id'}.')</font>');
 	$request->print(&show_grading_menu_form($symb,$url));
 	return;
     }
@@ -1698,10 +1670,25 @@ KEYWORDS
 			$lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part:</b> '.
 			    $display_part.' <font color="#999999">( ID '.$respid.
 			    ' )</font>&nbsp; &nbsp;';
+			my @files;
+			if ($record{"resource.$partid.$respid.portfiles"}) {
+			    my $file_url = '/uploaded/'.$udom.'/'.$uname.'/portfolio';
+			    foreach my $file (split(',',$record{"resource.$partid.$respid.portfiles"})) {
+				push(@files,$file_url.$file);
+			    
+				&Apache::lonnet::logthis("found a portfolio file".$record{"resource.$partid.$respid.portfiles"});
+				&Apache::lonnet::logthis("uploaded URL file".$record{"resource.$partid.$respid.uploadedurl"});
+			    }
+			}
 			if ($record{"resource.$partid.$respid.uploadedurl"}) {
-			    &Apache::lonnet::allowuploaded('/adm/grades',
-			      $record{"resource.$partid.$respid.uploadedurl"});
-			    $lastsubonly.='<a href="'.$record{"resource.$partid.$respid.uploadedurl"}.'" target="lonGRDs"><img src="/adm/lonIcons/unknown.gif" border=0"> File uploaded by student</a> <font color="red" size="1">Like all files provided by users, this file may contain virusses</font><br />';
+			    push(@files,$record{"resource.$partid.$respid.uploadedurl"});
+			}
+			if (@files) {
+			    $lastsubonly.='<br /><font color="red" size="1">Like all files provided by users, this file may contain virusses</font><br />';
+			    foreach my $file (@files) {
+				&Apache::lonnet::allowuploaded('/adm/grades',$file);
+				$lastsubonly.='<br /><a href="'.$file.'" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border=0"> '.$file.'</a>';
+			    }
 			}
 			$lastsubonly.='<b>Submitted Answer: </b>'.
 			    &cleanRecord($subval,$responsetype,$symb,$partid,
@@ -2415,9 +2402,6 @@ sub viewgrades {
     my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'1');
     my $ctr = 0;
     foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {
-	my $uname = $_;
-	$uname=~s/:/_/;
-	$result.='<input type="hidden" name="ctr'.$ctr.'" value="'.$uname.'" />'."\n";
 	$ctr++;
 	$result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},
 				   $_,$$fullname{$_},\@parts,\%weight,$ctr);
@@ -2441,18 +2425,21 @@ sub viewstudentgrade {
     my ($uname,$udom) = split(/:/,$student);
     $student=~s/:/_/;
     my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname);
-    my $result='<tr bgcolor="#ffffdd"><td align="right">'.$ctr.'&nbsp;</td><td>&nbsp;'.
+    my $result='<tr bgcolor="#ffffdd"><td align="right">'.
+	'<input type="hidden" name="ctr'.($ctr-1).'" value="'.$student.'" />'.
+	"\n".$ctr.'&nbsp;</td><td>&nbsp;'.
 	'<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.
 	'\')"; TARGET=_self>'.$fullname.'</a> '.
 	'<font color="#999999">('.$uname.($ENV{'user.domain'} eq $udom ? '' : ':'.$udom).')</font></td>'."\n";
     foreach my $apart (@$parts) {
 	my ($part,$type) = &split_part_type($apart);
 	my $score=$record{"resource.$part.$type"};
+	$result.='<td align="middle">';
 	if ($type eq 'awarded') {
 	    my $pts = $score eq '' ? '' : $score*$$weight{$part};
 	    $result.='<input type="hidden" name="'.
 		'GD_'.$student.'_'.$part.'_awarded_s" value="'.$pts.'" />'."\n";
-	    $result.='<td align="middle"><input type="text" name="'.
+	    $result.='<input type="text" name="'.
 		'GD_'.$student.'_'.$part.'_awarded" '.
 		'onChange="javascript:changeSelect(\''.$part.'\',\''.$student.
 		'\')" value="'.$pts.'" size="4" /></td>'."\n";
@@ -2461,7 +2448,7 @@ sub viewstudentgrade {
 	    $status = 'nothing' if ($status eq '');
 	    $result.='<input type="hidden" name="'.'GD_'.$student.'_'.
 		$part.'_solved_s" value="'.$status.'" />'."\n";
-	    $result.='<td align="middle">&nbsp;<select name="'.
+	    $result.='&nbsp;<select name="'.
 		'GD_'.$student.'_'.$part.'_solved" '.
 		'onChange="javascript:changeOneScore(\''.$part.'\',\''.$student.'\')" >'."\n";
 	    $result.= (($status eq 'excused') ? '<option> </option><option selected="on">excused</option>' 
@@ -2472,7 +2459,7 @@ sub viewstudentgrade {
 	    $result.='<input type="hidden" name="'.
 		'GD_'.$student.'_'.$part.'_'.$type.'_s" value="'.$score.'" />'.
 		    "\n";
-	    $result.='<td align="middle"><input type="text" name="'.
+	    $result.='<input type="text" name="'.
 		'GD_'.$student.'_'.$part.'_'.$type.'" '.
 		'value="'.$score.'" size="4" /></td>'."\n";
 	}
@@ -3080,8 +3067,6 @@ sub getSymbMap {
 	    $minder++;
 	}
     }
-
-    $navmap->untieHashes();
     return \@titles,\%symbx;
 }
 
@@ -3214,8 +3199,6 @@ sub displayPage {
         $curRes = $iterator->next();
     }
 
-    $navmap->untieHashes();
-
     $studentTable.='</td></tr></table></td></tr></table>'."\n".
 	'<input type="button" value="Save" '.
 	'onClick="javascript:checkSubmitPage(this.form,'.$question.');" TARGET=_self />'.
@@ -3228,9 +3211,12 @@ sub displayPage {
 
 sub displaySubByDates {
     my ($symb,$record,$parts,$responseType,$checkIcon,$uname,$udom) = @_;
+    my $isCODE=0;
+    if (exists($record->{'resource.CODE'})) { $isCODE=1; }
     my $studentTable='<table border="0" width="100%"><tr><td bgcolor="#777777">'.
 	'<table border="0" width="100%"><tr bgcolor="#e6ffff">'.
 	'<td><b>Date/Time</b></td>'.
+	($isCODE?'<td><b>CODE</b></td>':'').
 	'<td><b>Submission</b></td>'.
 	'<td><b>Status&nbsp;</b></td></tr>';
     my ($version);
@@ -3243,6 +3229,9 @@ sub displaySubByDates {
     for ($version=1;$version<=$$record{'version'};$version++) {
 	my $timestamp = scalar(localtime($$record{$version.':timestamp'}));
 	$studentTable.='<tr bgcolor="#ffffff" valign="top"><td>'.$timestamp.'</td>';
+	if ($isCODE) {
+	    $studentTable.='<td>'.$record->{$version.':resource.CODE'}.'</td>';
+	}
 	my @versionKeys = split(/\:/,$$record{$version.':keys'});
 	my @displaySub = ();
 	foreach my $partid (@{$parts}) {
@@ -3411,8 +3400,6 @@ sub updateGradeByPage {
         $curRes = $iterator->next();
     }
 
-    $navmap->untieHashes();
-
     $studentTable.='</td></tr></table></td></tr></table>';
     $studentTable.=&show_grading_menu_form($ENV{'form.symb'},$ENV{'form.url'});
     my $grademsg=($changeflag == 0 ? 'No score was changed or updated.' :
@@ -3473,10 +3460,11 @@ sub scantron_filenames {
 }
 
 sub scantron_uploads {
+    my ($file2grade) = @_;
     my $result=	'<select name="scantron_selectfile">';
     $result.="<option></option>";
     foreach my $filename (sort(&scantron_filenames())) {
-	$result.="<option>$filename</option>\n";
+	$result.="<option".($filename eq $file2grade ? ' selected="on"':'').">$filename</option>\n";
     }
     $result.="</select>";
     return $result;
@@ -3501,7 +3489,7 @@ sub scantron_CODElist {
     my $cnum = $ENV{'course.'.$ENV{'request.course.id'}.'.num'};
     my @names=&Apache::lonnet::getkeys('CODEs',$cdom,$cnum);
     my $namechoice='<option></option>';
-    foreach my $name (sort(@names)) {
+    foreach my $name (sort {uc($a) cmp uc($b)} @names) {
 	if ($name =~ /^error: 2 /) { next; }
 	$namechoice.='<option value="'.$name.'">'.$name.'</option>';
     }
@@ -3522,13 +3510,13 @@ sub scantron_CODEunique {
 }
 
 sub scantron_selectphase {
-    my ($r) = @_;
+    my ($r,$file2grade) = @_;
     my ($symb,$url)=&get_symb_and_url($r);
     if (!$symb) {return '';}
     my $sequence_selector=&getSequenceDropDown($r,$symb);
     my $default_form_data=&defaultFormData($symb,$url);
     my $grading_menu_button=&show_grading_menu_form($symb,$url);
-    my $file_selector=&scantron_uploads();
+    my $file_selector=&scantron_uploads($file2grade);
     my $format_selector=&scantron_scantab();
     my $CODE_selector=&scantron_CODElist();
     my $CODE_unique=&scantron_CODEunique();
@@ -3538,8 +3526,8 @@ sub scantron_selectphase {
     $result.= <<SCANTRONFORM;
     <table width="100%" border="0">
     <tr>
+     <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantron_process">
       <td bgcolor="#777777">
-       <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantron_process">
        <input type="hidden" name="command" value="scantron_warning" />
         $default_form_data
         <table width="100%" border="0">
@@ -3576,8 +3564,8 @@ sub scantron_selectphase {
             </td>
           </tr>
         </table>
-       </form>
-      </td>
+       </td>
+     </form>
     </tr>
 SCANTRONFORM
    
@@ -3633,8 +3621,8 @@ SCANTRONFORM
     }
     $r->print(<<SCANTRONFORM);
     <tr>
-      <td bgcolor="#777777">
-        <form action='/adm/grades' name='scantron_download'>
+      <form action='/adm/grades' name='scantron_download'>
+        <td bgcolor="#777777">
           <input type="hidden" name="command" value="scantron_download" />
           <table width="100%" border="0">
             <tr bgcolor="#e6ffff">
@@ -3651,14 +3639,13 @@ SCANTRONFORM
               </td>
             </tr>
           </table>
-        </form>
-      </td>
+        </td>
+      </form>
     </tr>
 SCANTRONFORM
 
     $r->print(<<SCANTRONFORM);
   </table>
-</form>
 $grading_menu_button
 SCANTRONFORM
 
@@ -3855,7 +3842,8 @@ sub scantron_find_student {
 
 sub scantron_filter {
     my ($curres)=@_;
-    if (ref($curres) && $curres->is_problem() && !$curres->randomout) {
+                        # randomout is dysfunctional at best for this purpose
+    if (ref($curres) && $curres->is_problem()) { #&& !$curres->randomout) {
 	return 1;
     }
     return 0;
@@ -4007,7 +3995,7 @@ sub scantron_form_start {
   <input type="hidden" name="selectpage" value="$ENV{'form.selectpage'}" />
   <input type="hidden" name="scantron_format" value="$ENV{'form.scantron_format'}" />
   <input type="hidden" name="scantron_selectfile" value="$ENV{'form.scantron_selectfile'}" />
-  <input type="hidden" name="scantron_maxbubble" value="$max_bubble'" />
+  <input type="hidden" name="scantron_maxbubble" value="$max_bubble" />
   <input type="hidden" name="scantron_CODElist" value="$ENV{'form.scantron_CODElist'}" />
   <input type="hidden" name="scantron_CODEunique" value="$ENV{'form.scantron_CODEunique'}" />
   <input type="hidden" name="scantron_options_redo" value="$ENV{'form.scantron_options_redo'}" />
@@ -4327,8 +4315,8 @@ sub scantron_get_correction {
 	} elsif ($error eq 'duplicateCODE') {
 	    $r->print("</p><p>The encoded CODE has also been used by a previous paper ".join(', ',@{$arg}).", and CODEs are supposed to be unique</p>\n");
 	}
-	$r->print("<p>The CODE on the form is  <tt>".
-		  $$scan_record{'scantron.CODE'}."</tt><br />\n");
+	$r->print("<p>The CODE on the form is  <tt>'".
+		  $$scan_record{'scantron.CODE'}."'</tt><br />\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 ".
@@ -4474,13 +4462,21 @@ sub scantron_validate_CODE {
 						 $scan_data);
 	my $CODE=$$scan_record{'scantron.CODE'};
 	my $error=0;
-	if (!exists($allcodes{$CODE}) && !$$scan_record{'scantron.useCODE'}) {
+	if (!&Apache::lonnet::validCODE($CODE)) {
 	    &scantron_get_correction($r,$i,$scan_record,
 				     \%scantron_config,
 				     $line,'incorrectCODE',\%allcodes);
 	    return(1,$currentphase);
 	}
-	if (exists($usedCODEs{$CODE}) && $ENV{'form.scantron_CODEunique'}
+	if (%allcodes && !exists($allcodes{$CODE}) 
+	    && !$$scan_record{'scantron.useCODE'}) {
+	    &scantron_get_correction($r,$i,$scan_record,
+				     \%scantron_config,
+				     $line,'incorrectCODE',\%allcodes);
+	    return(1,$currentphase);
+	}
+	if (exists($usedCODEs{$CODE}) 
+	    && $ENV{'form.scantron_CODEunique'} eq 'yes'
 	    && !$$scan_record{'scantron.CODE_ignore_dup'}) {
 	    &scantron_get_correction($r,$i,$scan_record,
 				     \%scantron_config,
@@ -4645,11 +4641,18 @@ SCANTRONFORM
 	    if (exists($scan_record->{'scantron.CODE'}) &&
 		$scan_record->{'scantron.CODE'}) {
 		$form{'CODE'}=$scan_record->{'scantron.CODE'};
+	    } else {
+		$form{'CODE'}='';
 	    }
 	    my $result=&Apache::lonnet::ssi($resource->src(),%form);
-
+	    if ($result ne '') {
+		&Apache::lonnet::logthis("scantron grading error -> $result");
+		&Apache::lonnet::logthis("scantron grading error info name $uname domain $udom course $ENV{'request.course.id'} url ".$resource->src());
+	    }
+	    if (&Apache::loncommon::connection_aborted($r)) { last; }
 	}
 	$completedstudents{$uname}={'line'=>$line};
+	if (&Apache::loncommon::connection_aborted($r)) { last; }
     } continue {
 	&Apache::lonnet::delenv('form.counter');
 	&Apache::lonnet::delenv('scantron\.');
@@ -4658,7 +4661,6 @@ SCANTRONFORM
 #    my $lasttime = &Time::HiRes::time()-$start;
 #    $r->print("<p>took $lasttime</p>");
 
-    $navmap->untieHashes();
     $r->print("</form>");
     $r->print(&show_grading_menu_form($symb,$url));
     return '';
@@ -4719,7 +4721,8 @@ sub scantron_upload_scantron_data_save {
 	}
 	return '';
     }
-    $r->print("Doing upload to ".$ENV{'form.courseid'}." <br />");
+    my %coursedata=&Apache::lonnet::coursedescription($ENV{'form.domainid'}.'_'.$ENV{'form.courseid'});
+    $r->print("Doing upload to ".$coursedata{'description'}." <br />");
     my $home=&Apache::lonnet::homeserver($ENV{'form.courseid'},
 					 $ENV{'form.domainid'});
     my $fname=$ENV{'form.upfile.filename'};
@@ -4736,6 +4739,7 @@ sub scantron_upload_scantron_data_save {
     $fname=~s/[^\w\.\-]//g;
     # See if there is anything left
     unless ($fname) { return 'error: no uploaded file'; }
+    my $uploadedfile=$fname;
     $fname='scantron_orig_'.$fname;
     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.");
@@ -4744,11 +4748,11 @@ sub scantron_upload_scantron_data_save {
 	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>");
+	    $r->print("<font color='red'>Error:</font> An error (".$result.") occurred when attempting to upload the file, <tt>".&HTML::Entities::encode($ENV{'form.upfile.filename'},'<>&"')."</tt>");
 	}
     }
     if ($symb) {
-	$r->print(&show_grading_menu_form($symb,$url));
+	$r->print(&scantron_selectphase($r,$uploadedfile));
     } else {
 	$r->print($doanotherupload);
     }
@@ -5112,8 +5116,7 @@ sub send_header {
 
 sub send_footer {
     my ($request)= @_;
-    $request->print('</body>');
-    $request->print(&Apache::lontexconvert::footer());
+    $request->print('</body></html>');
 }
 
 1;