--- loncom/homework/grades.pm	2006/02/14 15:11:09	1.313
+++ loncom/homework/grades.pm	2006/02/27 02:06:52	1.319
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # The LON-CAPA Grading handler
 #
-# $Id: grades.pm,v 1.313 2006/02/14 15:11:09 banghart Exp $
+# $Id: grades.pm,v 1.319 2006/02/27 02:06:52 bowersj2 Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -40,6 +40,7 @@ use Apache::lonmsg qw(:user_normal_msg);
 use Apache::Constants qw(:common);
 use Apache::lonlocal;
 use String::Similarity;
+use POSIX qw(floor);
 
 my %oldessays=();
 my %perm=();
@@ -467,6 +468,33 @@ sub jscriptNform {
     return $jscript;
 }
 
+# Given the score (as a number [0-1] and the weight) what is the final
+# point value? This function will round to the nearest tenth, third,
+# or quarter if one of those is within the tolerance of .00001.
+sub compute_points {
+    my ($score, $weight) = @_;
+    
+    my $tolerance = .00001;
+    my $points = $score * $weight;
+
+    # Check for nearness to 1/x.
+    my $check_for_nearness = sub {
+        my ($factor) = @_;
+        my $num = ($points * $factor) + $tolerance;
+        my $floored_num = floor($num);
+        if ($num - $floored_num < 2 * $tolerance * $factor) {
+            return $floored_num / $factor;
+        }
+        return $points;
+    };
+
+    $points = $check_for_nearness->(10);
+    $points = $check_for_nearness->(3);
+    $points = $check_for_nearness->(4);
+    
+    return $points;
+}
+
 #------------------ End of general use routines --------------------
 
 #
@@ -1385,7 +1413,7 @@ SUBJAVASCRIPT
 
 #--- displays the grading box, used in essay type problem and grading by page/sequence
 sub gradeBox {
-    my ($request,$symb,$uname,$udom,$counter,$partid,$record) = @_;
+    my ($request,$symb,$uname,$udom,$counter,$partid,$record,$respid) = @_;
     my $checkIcon = '<img src="'.$request->dir_config('lonIconsURL').
 	'/check.gif" height="16" border="0" />';
     my $wgt    = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb,$udom,$uname);
@@ -1393,8 +1421,9 @@ sub gradeBox {
 		  '<font color="red">problem weight assigned by computer</font>');
     $wgt       = ($wgt > 0 ? $wgt : '1');
     my $score  = ($$record{'resource.'.$partid.'.awarded'} eq '' ?
-		  '' : $$record{'resource.'.$partid.'.awarded'}*$wgt);
+		  '' : compute_points($$record{'resource.'.$partid.'.awarded'},$wgt));
     my $result='<input type="hidden" name="WGT'.$counter.'_'.$partid.'" value="'.$wgt.'" />'."\n";
+    $result.='<br />'.$partid.' - '.$respid.'<br />';
     my $display_part=&get_display_part($partid,undef,$symb);
     my %last_resets = &get_last_resets($symb,$env{'request.course.id'},
 				       [$partid]);
@@ -1443,19 +1472,23 @@ sub gradeBox {
         '<input type="hidden" name="aggtries'.$counter.'_'.$partid.'" value="'.
         $aggtries.'" />'."\n";
     $result.='</td></tr></table>'."\n";
-    my $files=&get_submitted_files($udom,$uname,$partid,$counter,$record);
+    $result.=&handbackBox($uname,$udom,$counter,$partid,$record,$respid);
+    return $result;
+}
+sub handbackBox {
+    my ($uname,$udom,$counter,$partid,$record,$respid) = @_;
+    my $files=&get_submitted_files($udom,$uname,$partid,$respid,$record);
+    my $result;
     if (@$files) {
         my $file_counter = 0;
 	foreach my $file (@$files) {
             $result.=' Return commented document to student. <input type="file" name="part'.$partid.'_returndoc';
             $result.=$file_counter.'" />'."\n";
-            $result.='<input type="hidden" name="respid" value="'.$counter.'" />';
-            $result.='<input type="hidden" name="returndocorig'.$file_counter.'" value="'.$file.'" />';
+            $result.='<input type="hidden" name="respid" value="'.$respid.'" />';
+            $result.='<input type="hidden" name="returndocorig'.$file_counter.'" value="'.$file.'" /><br />';
         }
     }
-
-    
-    return $result;
+    return $result;    
 }
 
 sub show_problem {
@@ -1797,22 +1830,13 @@ KEYWORDS
 			    $display_part.' <font color="#999999">( ID '.$respid.
 			    ' )</font>&nbsp; &nbsp;';
 			my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record);
-#			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);
-#			    }
-#			}
-#			if ($record{"resource.$partid.$respid.uploadedurl"}) {
-#			    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 />';
 			    my $file_counter = 0;
 			    foreach my $file (@$files) {
 			        $file_counter ++;
 				&Apache::lonnet::allowuploaded('/adm/grades',$file);
-				$lastsubonly.='<br /><a href="'.$file.'" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border=0"> '.$file.'</a>';
+				$lastsubonly.='<br /><a href="'.$file.'" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0"> '.$file.'</a>';
 			    }
 			    $lastsubonly.='<br />';
 			}
@@ -1890,15 +1914,18 @@ KEYWORDS
     my %seen = ();
     my @partlist;
     my @gradePartRespid;
-    for (sort keys(%$handgrade)) {
-	my ($partid,$respid) = split(/_/);
-	next if ($seen{$partid} > 0);
+    for my $part_resp(sort keys(%$handgrade)) {
+	my ($partid,$respid) = split(/_/, $part_resp);
+	#next if ($seen{$partid} > 0);
+	if ($seen{$partid} > 0) {
+	    $request->print(&handbackBox($uname,$udom,$counter,$partid,\%record,$respid));
+	    next;
+	}
 	$seen{$partid}++;
-	next if ($$handgrade{$_} =~ /:no$/ && $env{'form.lastSub'} =~ /^(hdgrade)$/);
+	next if ($$handgrade{$part_resp} =~ /:no$/ && $env{'form.lastSub'} =~ /^(hdgrade)$/);
 	push @partlist,$partid;
 	push @gradePartRespid,$partid.'.'.$respid;
-
-	$request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record));
+	$request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record,$respid));
     }
     $result='<input type="hidden" name="partlist'.$counter.
 	'" value="'.(join ":",@partlist).'" />'."\n";
@@ -2866,7 +2893,7 @@ sub viewstudentgrade {
             $aggregates{$part} = 1;
         }
 	if ($type eq 'awarded') {
-	    my $pts = $score eq '' ? '' : $score*$$weight{$part};
+	    my $pts = $score eq '' ? '' : compute_points($score,$$weight{$part});
 	    $result.='<input type="hidden" name="'.
 		'GD_'.$student.'_'.$part.'_awarded_s" value="'.$pts.'" />'."\n";
 	    $result.='<input type="text" name="'.