--- loncom/homework/grades.pm	2005/02/12 15:18:41	1.246
+++ loncom/homework/grades.pm	2005/04/02 18:44:39	1.254
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # The LON-CAPA Grading handler
 #
-# $Id: grades.pm,v 1.246 2005/02/12 15:18:41 albertel Exp $
+# $Id: grades.pm,v 1.254 2005/04/02 18:44:39 banghart Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -96,7 +96,7 @@ sub get_symb_and_url {
 sub nameUserString {
     my ($type,$fullname,$uname,$udom) = @_;
     if ($type eq 'header') {
-	return '<b>&nbsp;Fullname&nbsp;</b><font color="#999999">(Username)</font>&nbsp;';
+	return '<b>&nbsp;Fullname&nbsp;</b><font color="#999999">(Username)</font>';
     } else {
 	return '&nbsp;'.$fullname.'<font color="#999999">&nbsp;('.$uname.
 	    ($ENV{'user.domain'} eq $udom ? '' : ' ('.$udom.')').')</font>';
@@ -664,17 +664,21 @@ LISTJAVASCRIPT
     $gradeTable.='To '.lc($viewgrade).' a submission or a group of submissions, click on the check box(es) '.
 	'next to the student\'s name(s). Then click on the Next button.<br />'."\n".
 	'<input type="hidden" name="command" value="processGroup" />'."\n";
+
+# checkall buttons
+    $gradeTable.=&check_script('gradesub', 'stuinfo');
     $gradeTable.='<input type="button" '."\n".
 	'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n".
-	'value="Next->" />'."\n";
+	'value="Next->" /> <br />'."\n";
+    $gradeTable.=&check_buttons();
     $gradeTable.='<input type="checkbox" name="checkPlag" checked="on">Check For Plagiarism</input>';
-    my (undef, undef, $fullname) = &getclasslist($getsec,'1');  
+    my ($classlist, undef, $fullname) = &getclasslist($getsec,'1');
     $gradeTable.='<table border="0"><tr><td bgcolor="#777777">'.
 	'<table border="0"><tr bgcolor="#e6ffff">';
     my $loop = 0;
     while ($loop < 2) {
 	$gradeTable.='<td><b>&nbsp;No.</b>&nbsp;</td><td><b>&nbsp;Select&nbsp;</b></td>'.
-	    '<td>'.&nameUserString('header').'</td>';
+	    '<td>'.&nameUserString('header').'&nbsp;Section/Group</td>';
 	if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
 	    foreach (sort(@$partlist)) {
 		my $display_part=&get_display_part((split(/_/))[0],$url,$symb);
@@ -695,10 +699,12 @@ LISTJAVASCRIPT
 	    (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist);
 	    my $submitted = 0;
 	    my $graded = 0;
+	    my $incorrect = 0;
 	    foreach (keys(%status)) {
 		$submitted = 1 if ($status{$_} ne 'nothing');
-		$graded = 1 if ($status{$_} !~ /^correct/);
-
+		$graded = 1 if ($status{$_} =~ /^ungraded/);
+		$incorrect = 1 if ($status{$_} =~ /^incorrect/);
+		
 		my ($foo,$partid,$foo1) = split(/\./,$_);
 		if ($status{'resource.'.$partid.'.submitted_by'} ne '') {
 		    $submitted = 0;
@@ -708,20 +714,25 @@ LISTJAVASCRIPT
 			$status{'resource.'.$partid.'.submitted_by'}.'" />';
 		}
 	    }
+	    
 	    next if (!$submitted && ($submitonly eq 'yes' ||
 				     $submitonly eq 'incorrect' ||
 				     $submitonly eq 'graded'));
-	    next if (!$graded && ($submitonly eq 'graded' ||
-				  $submitonly eq 'incorrect'));
+	    next if (!$graded && ($submitonly eq 'graded'));
+	    next if (!$incorrect && $submitonly eq 'incorrect');
 	}
 
 	$ctr++;
+	my $section = $classlist->{$student}->[&Apache::loncoursedata::CL_SECTION()];
+
 	if ( $perm{'vgr'} eq 'F' ) {
 	    $gradeTable.='<tr bgcolor="#ffffe6">' if ($ctr%2 ==1);
 	    $gradeTable.='<td align="right">'.$ctr.'&nbsp;</td>'.
-		'<td align="center"><input type=checkbox name="stuinfo" value="'.
-		$student.':'.$$fullname{$student}.'&nbsp;"></td>'."\n".
-		'<td>'.&nameUserString(undef,$$fullname{$student},$uname,$udom).'</td>'."\n";
+               '<td align="center"><label><input type=checkbox name="stuinfo" value="'.
+               $student.':'.$$fullname{$student}.':::SECTION'.$section.
+	       ')&nbsp;" />&nbsp;&nbsp;</label></td>'."\n".'<td>'.
+	       &nameUserString(undef,$$fullname{$student},$uname,$udom).
+	       '&nbsp;'.$section.'</td>'."\n";
 
 	    if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
 		foreach (sort keys(%status)) {
@@ -743,7 +754,7 @@ LISTJAVASCRIPT
 	$gradeTable.='</tr>';
     }
 
-    $gradeTable.='</table></td></tr></table>'.
+    $gradeTable.='</table></td></tr></table>'."\n".
 	'<input type="button" '.
 	'onClick="javascript:checkSelect(this.form.stuinfo);" '.
 	'value="Next->" /></form>'."\n";
@@ -768,6 +779,52 @@ LISTJAVASCRIPT
 }
 
 #---- Called from the listStudents routine
+
+sub check_script {
+    my ($form, $type)=@_;
+    my $chkallscript='<script type="text/javascript">
+    function checkall() {
+        for (i=0; i<document.forms.'.$form.'.elements.length; i++) {
+            ele = document.forms.'.$form.'.elements[i];
+            if (ele.name == "'.$type.'") {
+            document.forms.'.$form.'.elements[i].checked=true;
+                                       }
+        }
+    }
+
+    function checksec() {
+        for (i=0; i<document.forms.'.$form.'.elements.length; i++) {
+            ele = document.forms.'.$form.'.elements[i];
+           string = document.forms.'.$form.'.chksec.value;
+           if
+          (ele.value.indexOf(":::SECTION"+string)>0) {
+              document.forms.'.$form.'.elements[i].checked=true;
+            }
+        }
+    }
+
+
+    function uncheckall() {
+        for (i=0; i<document.forms.'.$form.'.elements.length; i++) {
+            ele = document.forms.'.$form.'.elements[i];
+            if (ele.name == "'.$type.'") {
+            document.forms.'.$form.'.elements[i].checked=false;
+                                       }
+        }
+    }
+
+</script>'."\n";
+    return $chkallscript;
+}
+
+sub check_buttons {
+    my $buttons.='<input type="button" onclick="checkall()" value="Check All" />';
+    $buttons.='<input type="button" onclick="uncheckall()" value="Uncheck All" />&nbsp;';
+    $buttons.='<input type="button" onclick="checksec()" value="Check Section/Group" />';
+    $buttons.='<input type="text" size="5" name="chksec" />&nbsp;';
+    return $buttons;
+}
+
 #     Displays the submissions for one student or a group of students
 sub processGroup {
     my ($request)  = shift;
@@ -2006,10 +2063,12 @@ sub processHandGrade {
 #	    my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);
 	    my %status=&student_gradeStatus($url,$symb,$udom,$uname,$partlist);
 	    my $submitted = 0;
-	    my $graded = 1;
+	    my $ungraded = 0;
+	    my $incorrect = 0;
 	    foreach (keys(%status)) {
 		$submitted = 1 if ($status{$_} ne 'nothing');
-		$graded = 0 if ($status{$_} =~ /^correct/);
+		$ungraded = 1 if ($status{$_} =~ /^ungraded/);
+		$incorrect = 1 if ($status{$_} =~ /^incorrect/);
 		my ($foo,$partid,$foo1) = split(/\./,$_);
 		if ($status{'resource.'.$partid.'.submitted_by'} ne '') {
 		    $submitted = 0;
@@ -2018,8 +2077,8 @@ sub processHandGrade {
 	    next if (!$submitted && ($submitonly eq 'yes' ||
 				     $submitonly eq 'incorrect' ||
 				     $submitonly eq 'graded'));
-	    next if (!$graded && ($submitonly eq 'graded' ||
-				  $submitonly eq 'incorrect'));
+	    next if (!$ungraded && ($submitonly eq 'graded'));
+	    next if (!$incorrect && $submitonly eq 'incorrect');
 	}
 	push @nextlist,$student if ($ctr < $ntstu);
 	last if ($ctr == $ntstu);
@@ -2054,6 +2113,7 @@ sub saveHandGrade {
 					   $ENV{'request.course.id'});
     if (!&canmodify($usec)) { return('not_allowed'); }
     my %record     = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$domain,$stuname);
+    my @parts_graded;
     my %newrecord  = ();
     my ($pts,$wgt) = ('','');
     foreach (split(/:/,$ENV{'form.partlist'.$newflg})) {
@@ -2088,6 +2148,8 @@ sub saveHandGrade {
 	    if ($partial eq $record{'resource.'.$_.'.awarded'}) {
 		#do not update score for part if not changed.
 		next;
+	    } else {
+	        push @parts_graded, $_;
 	    }
 	    if ($record{'resource.'.$_.'.awarded'} ne $partial) {
 		$newrecord{'resource.'.$_.'.awarded'}  = $partial;
@@ -2111,12 +2173,56 @@ sub saveHandGrade {
 	}
     }
     if (scalar(keys(%newrecord)) > 0) {
+        &version_portfiles(\%record, \@parts_graded, $ENV{'request.course.id'}, $symb, $domain, $stuname);
 	&Apache::lonnet::cstore(\%newrecord,$symb,
 				$ENV{'request.course.id'},$domain,$stuname);
     }
     return '',$pts,$wgt;
 }
 
+# ----------- Handles creating versions for portfolio files as answers
+sub version_portfiles {
+    my ($record, $parts_graded, $courseid, $symb, $domain, $stuname) = @_;
+    my $parts = join '|', @$parts_graded;
+    my $portfolio_root = &Apache::loncommon::propath($domain,
+						 $stuname).
+						'/userfiles/portfolio';
+    foreach my $key (keys %$record) {
+        if ($key =~ /^resource\.($parts)\./ && $key =~ /\.portfiles$/) {
+            my @portfiles = split /,/,$$record{$key};
+            foreach my $file (@portfiles) {
+                my ($directory,$answer_file) =( $file =~ /^(.*?)([^\/]*$)/);
+                my $version = 0;
+                my @answer_file_parts = split /\./, $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])) {
+                        # 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]};
+                        }
+                    }
+                }
+                $version += 1;
+                &Apache::lonnet::logthis('answer file is '.$answer_file.
+                        ' becomes '.$answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[(scalar @answer_file_parts)-1]);
+                &Apache::lonnet::logthis('from dir list is '.$file_names[0].' has '.@file_name_parts.' parts');
+            }
+            &Apache::lonnet::logthis('found key portfiles '.$key);
+            &Apache::lonnet::logthis('found value portfiles '.$$record{$key});
+        }
+    } 
+    
+    
+}
+
 #--------------------------------------------------------------------------------------
 #
 #-------------------------- Next few routines handles grading by section or whole class
@@ -2971,11 +3077,18 @@ sub csvuploadassign {
 	$username=~s/\s//g;
 	if (!$username) {
 	    my $id=$entries{$fields{'ID'}};
+	    $id=~s/\s//g;
 	    my %ids=&Apache::lonnet::idget($domain,$id);
 	    $username=$ids{$id};
 	}
 	if (!exists($$classlist{"$username:$domain"})) {
-	    push(@skipped,"$username:$domain");
+	    my $id=$entries{$fields{'ID'}};
+	    $id=~s/\s//g;
+	    if ($id) {
+		push(@skipped,"$id:$domain");
+	    } else {
+		push(@skipped,"$username:$domain");
+	    }
 	    next;
 	}
 	my $usec=$classlist->{"$username:$domain"}[5];
@@ -2993,6 +3106,7 @@ sub csvuploadassign {
 		my $part=$1;
 		my $wgt =&Apache::lonnet::EXT('resource.'.$part.'.weight',
 					      $symb,$domain,$username);
+		$entries{$fields{$dest}}=~s/\s//g;
 		my $pcr=$entries{$fields{$dest}} / $wgt;
 		my $award='correct_by_override';
 		$grades{"resource.$part.awarded"}=$pcr;