--- loncom/homework/grades.pm	2005/12/02 19:40:47	1.300
+++ loncom/homework/grades.pm	2006/03/03 21:52:01	1.302.2.5
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # The LON-CAPA Grading handler
 #
-# $Id: grades.pm,v 1.300 2005/12/02 19:40:47 albertel Exp $
+# $Id: grades.pm,v 1.302.2.5 2006/03/03 21:52:01 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -704,12 +704,16 @@ LISTJAVASCRIPT
     while ($loop < 2) {
 	$gradeTable.='<td><b>&nbsp;No.</b>&nbsp;</td><td><b>&nbsp;Select&nbsp;</b></td>'.
 	    '<td>'.&nameUserString('header').'&nbsp;Section/Group</td>';
-	if ($env{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
+	if ($env{'form.showgrading'} eq 'yes' 
+	    && $submitonly ne 'queued'
+	    && $submitonly ne 'all') {
 	    foreach (sort(@$partlist)) {
 		my $display_part=&get_display_part((split(/_/))[0],$url,$symb);
 		$gradeTable.='<td><b>&nbsp;Part: '.$display_part.
 		    ' Status&nbsp;</b></td>';
 	    }
+	} elsif ($submitonly eq 'queued') {
+	    $gradeTable.='<td><b>&nbsp;'.&mt('Queue Status').'&nbsp;</b></td>';
 	}
 	$loop++;
 #	$gradeTable.='<td></td>' if ($loop%2 ==1);
@@ -726,8 +730,20 @@ LISTJAVASCRIPT
 			 }
 			 (keys(%$fullname))) {
 	my ($uname,$udom) = split(/:/,$student);
+
 	my %status = ();
-	if ($env{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
+
+	if ($submitonly eq 'queued') {
+	    my %queue_status = 
+		&Apache::bridgetask::get_student_status($symb,$cdom,$cnum,
+							$udom,$uname);
+	    next if (!defined($queue_status{'gradingqueue'}));
+	    $status{'gradingqueue'} = $queue_status{'gradingqueue'};
+	}
+
+	if ($env{'form.showgrading'} eq 'yes' 
+	    && $submitonly ne 'queued'
+	    && $submitonly ne 'all') {
 	    (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist);
 	    my $submitted = 0;
 	    my $graded = 0;
@@ -778,10 +794,14 @@ LISTJAVASCRIPT
     }
     if ($ctr%2 ==1) {
 	$gradeTable.='<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>';
-	    if ($env{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
+	    if ($env{'form.showgrading'} eq 'yes' 
+		&& $submitonly ne 'queued'
+		&& $submitonly ne 'all') {
 		foreach (@$partlist) {
 		    $gradeTable.='<td>&nbsp;</td>';
 		}
+	    } elsif ($submitonly eq 'queued') {
+		$gradeTable.='<td>&nbsp;</td>';
 	    }
 	$gradeTable.='</tr>';
     }
@@ -798,6 +818,7 @@ LISTJAVASCRIPT
 	    my $submissions='submissions';
 	    if ($submitonly eq 'incorrect') { $submissions = 'incorrect submissions'; }
 	    if ($submitonly eq 'graded'   ) { $submissions = 'ungraded submissions'; }
+	    if ($submitonly eq 'queued'   ) { $submissions = 'queued submissions'; }
 	    $gradeTable='<br />&nbsp;<font color="red">'.
 		'No '.$submissions.' found for this resource for any students. ('.$num_students.
 		' students checked for '.$submissions.')</font><br />';
@@ -1960,6 +1981,9 @@ sub processHandGrade {
     my $button = $env{'form.gradeOpt'};
     my $ngrade = $env{'form.NCT'};
     my $ntstu  = $env{'form.NTSTU'};
+    my $cdom   = $env{'course.'.$env{'request.course.id'}.'.domain'};
+    my $cnum   = $env{'course.'.$env{'request.course.id'}.'.num'};
+
     if ($button eq 'Save & Next') {
 	my $ctr = 0;
 	while ($ctr < $ngrade) {
@@ -2057,9 +2081,7 @@ sub processHandGrade {
 	$env{'form.savemsgN'} = --$idx;
 	$keyhash{$symb.'_savemsgN'} = $env{'form.savemsgN'};
 	my $putresult = &Apache::lonnet::put
-	    ('nohist_handgrade',\%keyhash,
-	     $env{'course.'.$env{'request.course.id'}.'.domain'},
-	     $env{'course.'.$env{'request.course.id'}.'.num'});
+	    ('nohist_handgrade',\%keyhash,$cdom,$cnum);
     }
     # Called by Save & Refresh from Highlight Attribute Window
     my (undef,undef,$fullname) = &getclasslist($env{'form.section'},'1');
@@ -2125,6 +2147,14 @@ sub processHandGrade {
     foreach my $student (@parsedlist) {
 	my $submitonly=$env{'form.submitonly'};
 	my ($uname,$udom) = split(/:/,$student);
+	
+	if ($submitonly eq 'queued') {
+	    my %queue_status = 
+		&Apache::bridgetask::get_student_status($symb,$cdom,$cnum,
+							$udom,$uname);
+	    next if (!defined($queue_status{'gradingqueue'}));
+	}
+
 	if ($submitonly =~ /^(yes|graded|incorrect)$/) {
 #	    my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname);
 	    my %status=&student_gradeStatus($url,$symb,$udom,$uname,$partlist);
@@ -2166,7 +2196,7 @@ sub processHandGrade {
 	my $the_end = '<h3><font color="red">LON-CAPA User Message</font></h3><br />'."\n";
 	$the_end.='<b>Message: </b> No more students for this section or class.<br /><br />'."\n";
 	$the_end.='Click on the button below to return to the grading menu.<br /><br />'."\n";
-	$the_end.=&show_grading_menu_form ($symb,$url);
+	$the_end.=&show_grading_menu_form($symb,$url);
 	$request->print($the_end);
     }
     return '';
@@ -2185,7 +2215,9 @@ sub saveHandGrade {
     my ($pts,$wgt) = ('','');
     my %aggregate = ();
     my $aggregateflag = 0;
-    foreach my $new_part (split(/:/,$env{'form.partlist'.$newflg})) {
+
+    my @parts = split(/:/,$env{'form.partlist'.$newflg});
+    foreach my $new_part (@parts) {
 	#collaborator may vary for different parts
 	if ($submitter && $new_part ne $part) { next; }
 	my $dropMenu = $env{'form.GD_SEL'.$newflg.'_'.$new_part};
@@ -2216,7 +2248,7 @@ sub saveHandGrade {
 
             my $solvedstatus = $record{'resource.'.$new_part.'.solved'};
             if ($aggtries > 0) {
-                &decrement($symb,$new_part,\%aggregate,$aggtries,$totaltries,$solvedstatus);
+                &decrement_aggs($symb,$new_part,\%aggregate,$aggtries,$totaltries,$solvedstatus);
                 $aggregateflag = 1;
             }
 	} elsif ($dropMenu eq '') {
@@ -2260,19 +2292,33 @@ sub saveHandGrade {
 	    push (@v_flag,$new_part);
 	}
     }
+    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+    my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+
     if (scalar(keys(%newrecord)) > 0) {
         if (scalar(@v_flag)) {
             &version_portfiles(\%record, \@parts_graded, $env{'request.course.id'}, $symb, $domain, $stuname, \@v_flag);
         }
 	&Apache::lonnet::cstore(\%newrecord,$symb,
 				$env{'request.course.id'},$domain,$stuname);
+	
+	my @ungraded_parts;
+	foreach my $part (@parts) {
+	    if ( !defined($record{'resource.'.$part.'.awarded'})
+		 && !defined($newrecord{'resource.'.$part.'.awarded'}) ) {
+		push(@ungraded_parts, $part);
+	    }
+	}
+	if ( !@ungraded_parts ) {
+	    &Apache::bridgetask::remove_from_queue('gradingqueue',$symb,$cdom,
+						   $cnum,$domain,$stuname);
+	}
     }
     if ($aggregateflag) {
         &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate,
-                  $env{'course.'.$env{'request.course.id'}.'.domain'},
-                  $env{'course.'.$env{'request.course.id'}.'.num'});
+			      $cdom,$cnum);
     }
-    return '',$pts,$wgt;
+    return ('',$pts,$wgt);
 }
 
 # ----------- Provides number of tries since last reset.
@@ -2351,22 +2397,23 @@ sub version_portfiles {
             &Apache::lonnet::logthis("should be unmarking and remarking $key",@portfiles);
             foreach my $file (@portfiles) {
                 &Apache::lonnet::unmark_as_readonly($domain,$stuname,[$symb,$env{'request.course.id'}],$file);
-                my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*$)/);
+                my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*)$/);
                 my $version = 0;
-                my @answer_file_parts = split(/\./, $answer_file);
+		my ($answer_name,$answer_ver,$answer_ext) =
+		    &file_name_version_ext($answer_file);
                 my @dir_list = &Apache::lonnet::dirlist($directory,$domain,$stuname,$portfolio_root);
-                my @file_names;
-                my @file_name_parts;
                 foreach my $row (@dir_list) {
-                    @file_names = split(/\&/,$row,2);
-                    @file_name_parts = split(/\./, $file_names[0]);
-                    # ($file_name_parts[scalar @file_name_parts] eq $answer_file_parts[scalar @answer_file_parts])
-                    if (($file_name_parts[0] eq $answer_file_parts[0]) && 
-                        ($file_name_parts[-1] eq $answer_file_parts[-1])) {
+                    my ($file) = split(/\&/,$row,2);
+		    my ($file_name,$file_version,$file_ext) =
+			&file_name_version_ext($file);
+                    if (($file_name eq $answer_name) && 
+			($file_ext eq $answer_ext)) {
                         # gets here if filename and extension match, regardless of version
-                        if (scalar @file_name_parts == 3) { # a versioned file is found
-                            # so save it for later
-                            if ($file_name_parts[1] > $version) {$version = $file_name_parts[1]};
+                        if ($file_version ne '') {
+                            # a versioned file is found  so save it for later
+                            if ($file_version > $version) {
+				$version = $file_version;
+			    }
                         }
                     }
                 }
@@ -2375,11 +2422,13 @@ sub version_portfiles {
                 if($env{'form.copy'} eq '-1') {
                     &Apache::lonnet::logthis('problem getting file '.$directory.$answer_file);
                 } else {
-                   my $copy_result = &Apache::lonnet::finishuserfileupload($stuname,$domain,'copy',
-                                    '/portfolio'.$directory.$answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]);
-                    push(@v_portfiles, $directory.$answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]);
+		    my $new_answer = $answer_name.'.'.$version.'.'.$answer_ext;
+		    my $copy_result = &Apache::lonnet::finishuserfileupload(
+                                        $stuname,$domain,'copy',
+				        '/portfolio'.$directory.$new_answer);
+                    push(@v_portfiles, $directory.$new_answer);
                     &Apache::lonnet::mark_as_readonly($domain,$stuname,
-                                ['/portfolio'.$directory.$answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]],
+                                ['/portfolio'.$directory.$new_answer],
                                 [$symb,$env{'request.course.id'},'graded']);
                 }
             }
@@ -2390,6 +2439,22 @@ sub version_portfiles {
     
 }
 
+sub file_name_version_ext {
+    my ($file)=@_;
+    my @file_parts = split(/\./, $file);
+    my ($name,$version,$ext);
+    if (@file_parts > 1) {
+	$ext=pop(@file_parts);
+	if (@file_parts > 1 && $file_parts[-1] =~ /^\d+$/) {
+	    $version=pop(@file_parts);
+	}
+	$name=join('.',@file_parts);
+    } else {
+	$name=join('.',@file_parts);
+    }
+    return($name,$version,$ext);
+}
+
 #--------------------------------------------------------------------------------------
 #
 #-------------------------- Next few routines handles grading by section or whole class
@@ -2922,10 +2987,38 @@ sub editgrades {
 	    }
 	}
 	$line.='</tr>'."\n";
+
+	my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+	my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+
 	if ($updateflag) {
 	    $count++;
 	    &Apache::lonnet::cstore(\%newrecord,$symb,$env{'request.course.id'},
 				    $udom,$uname);
+
+	    if (&Apache::bridgetask::in_queue('gradingqueue',$symb,$cdom,
+					      $cnum,$udom,$uname)) {
+		# need to figure out if should be in queue.
+		my %record =  
+		    &Apache::lonnet::restore($symb,$env{'request.course.id'},
+					     $udom,$uname);
+		my $all_graded = 1;
+		my $none_graded = 1;
+		foreach my $part (@parts) {
+		    if ( $record{'resource.'.$part.'.awarded'} eq '' ) {
+			$all_graded = 0;
+		    } else {
+			$none_graded = 0;
+		    }
+		}
+
+		if ($all_graded || $none_graded) {
+		    &Apache::bridgetask::remove_from_queue('gradingqueue',
+							   $symb,$cdom,$cnum,
+							   $udom,$uname);
+		}
+	    }
+
 	    $result.='<tr bgcolor="#ffffde"><td align="right">&nbsp;'.$updateCtr.'&nbsp;</td>'.$line;
 	    $updateCtr++;
 	} else {
@@ -2934,8 +3027,7 @@ sub editgrades {
 	}
         if ($aggregateflag) {
             &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate,
-                      $env{'course.'.$env{'request.course.id'}.'.domain'},
-                      $env{'course.'.$env{'request.course.id'}.'.num'});
+				  $cdom,$cnum);
         }
     }
     if ($noupdate) {
@@ -3199,8 +3291,13 @@ sub csvuploadmap {
 	    unshift(@fields,['none','']);
 	    $i=&Apache::loncommon::csv_samples_select_table($request,\@records,
 							    \@fields);
-	    my %sone=&Apache::loncommon::record_sep($records[0]);
-	    $keyfields=join(',',sort(keys(%sone)));
+	    foreach my $rec (@records) {
+		my %temp = &Apache::loncommon::record_sep($rec);
+		if (%temp) {
+		    $keyfields=join(',',sort(keys(%temp)));
+		    last;
+		}
+	    }
 	}
     }
     &csvuploadmap_footer($request,$i,$keyfields);
@@ -3218,12 +3315,14 @@ sub csvuploadoptions {
 <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
 <h3><font color="#339933">Uploading Class Grade Options</font></h3>
 <input type="hidden" name="command"    value="csvuploadassign" />
+<!--
 <p>
 <label>
    <input type="checkbox" name="show_full_results" />
    Show a table of all changes
 </label>
 </p>
+-->
 <p>
 <label>
    <input type="checkbox" name="overwite_scores" checked="checked" />
@@ -3342,15 +3441,25 @@ sub csvuploadassign {
 	if (! %grades) { push(@skipped,"$username:$domain no data to store"); }
 	$grades{"resource.regrader"}="$env{'user.name'}:$env{'user.domain'}";
 #	&Apache::lonnet::logthis(" storing ".(join('-',%grades)));
-	&Apache::lonnet::cstore(\%grades,$symb,$env{'request.course.id'},
-				$domain,$username);
-	$request->print('.');
+	my $result=&Apache::lonnet::cstore(\%grades,$symb,
+					   $env{'request.course.id'},
+					   $domain,$username);
+	if ($result eq 'ok') {
+	    $request->print('.');
+	} else {
+	    $request->print("<p>
+                              <font color='red'>
+                                 Failed to store student $username\@$domain.
+                                 Message when trying to store was ($result)
+                              </font>
+                             </p>" );
+	}
 	$request->rflush();
 	$countdone++;
     }
     $request->print("<br />Stored $countdone students\n");
     if (@skipped) {
-	$request->print('<p<font size="+1"><b>Skipped Students</b></font></p>');
+	$request->print('<p><font size="+1"><b>Skipped Students</b></font></p>');
 	foreach my $student (@skipped) { $request->print("$student<br />\n"); }
     }
     if (@notallowed) {
@@ -3954,11 +4063,11 @@ sub scantron_CODElist {
 sub scantron_CODEunique {
     my $result='<nobr>
                  <label><input type="radio" name="scantron_CODEunique"
-                        value="Yes" checked="on" /> Yes </label>
+                        value="yes" checked="checked" /> Yes </label>
                 </nobr>
                 <nobr>
                  <label><input type="radio" name="scantron_CODEunique"
-                        value="No" /> No </label>
+                        value="no" /> No </label>
                 </nobr>';
     return $result;
 }
@@ -5466,13 +5575,15 @@ GRADINGMENUJS
 	($saveCmd eq 'submission' ? 'checked' : '').'> '.'<b>'.&mt('Current Resource').':</b> '.&mt('For one or more students').
 	'</label> <select name="submitonly">'.
 	'<option value="yes" '.
-	($saveSub eq 'yes' ? 'selected="on"' : '').'>with submissions</option>'.
+	($saveSub eq 'yes' ? 'selected="on"' : '').'>'.&mt('with submissions').'</option>'.
+	'<option value="queued" '.
+	($saveSub eq 'queued' ? 'selected="on"' : '').'>'.&mt('in grading queue').'</option>'.
 	'<option value="graded" '.
-	($saveSub eq 'graded' ? 'selected="on"' : '').'>with ungraded submissions</option>'.
+	($saveSub eq 'graded' ? 'selected="on"' : '').'>'.&mt('with ungraded submissions').'</option>'.
 	'<option value="incorrect" '.
-	($saveSub eq 'incorrect' ? 'selected="on"' : '').'>with incorrect submissions</option>'.
+	($saveSub eq 'incorrect' ? 'selected="on"' : '').'>'.&mt('with incorrect submissions').'</option>'.
 	'<option value="all" '.
-	($saveSub eq 'all' ? 'selected="on"' : '').'>with any status</option></select></td></tr>'."\n";
+	($saveSub eq 'all' ? 'selected="on"' : '').'>'.&mt('with any status').'</option></select></td></tr>'."\n";
 
     $result.='<tr bgcolor="#ffffe6"valign="top"><td>'.
 	'<label><input type="radio" name="radioChoice" value="viewgrades" '.