--- loncom/homework/grades.pm	2024/12/10 04:55:03	1.802
+++ loncom/homework/grades.pm	2024/12/10 18:38:10	1.804
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # The LON-CAPA Grading handler
 #
-# $Id: grades.pm,v 1.802 2024/12/10 04:55:03 raeburn Exp $
+# $Id: grades.pm,v 1.804 2024/12/10 18:38:10 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -4241,14 +4241,16 @@ sub processHandGrade {
 		foreach my $collabstr (@collabstrs) {
 		    my ($part,@collaborators) = split(/:/,$collabstr);
 		    foreach my $collaborator (@collaborators) {
-			my ($errorflag,$pts,$wgt) = 
+			my ($errorflag,$pts,$wgt,$numchg,$numupdate) = 
 			    &saveHandGrade($request,$symb,$collaborator,$udom,$ctr,
-					   $env{'form.unamedom'.$ctr},$part,\%queueable,\%needpb,\%skip_passback,%pbsave);
+					   $env{'form.unamedom'.$ctr},$part,\%queueable);
 			if ($errorflag eq 'not_allowed') {
 			    $request->print("<span class=\"LC_error\">".&mt('Not allowed to modify grades for [_1]',"$collaborator:$udom")."</span>");
 			    next;
 			} else {
-                            $pbcollab{$collaborator}{$part} = [$pts,$wgt];
+                            if ($numchg || $numupdate) { 
+                                $pbcollab{$collaborator}{$part} = [$pts,$wgt];
+                            }
                             if ($message ne '') {
 			        my ($baseurl,$showsymb) = 
 				    &get_feedurl_and_symb($symb,$collaborator,
@@ -4267,7 +4269,48 @@ sub processHandGrade {
 	    $ctr++;
 	}
         if ((keys(%pbcollab)) && (keys(%needpb))) {
-            # FIXME passback scores for collaborators
+            foreach my $user (keys(%pbcollab)) {
+                my ($clbuname,$clbudom) = split(/:/,$user);
+                my $clbusec = &Apache::lonnet::getsection($clbudom,$clbuname,$cdom.'_'.$cnum); 
+                if (ref($pbcollab{$user}) eq 'HASH') {
+                    my @clparts = keys(%{$pbcollab{$user}});
+                    if (@clparts) {
+                        my $navmap = Apache::lonnavmaps::navmap->new($clbuname,$clbudom,$clbusec);
+                        if (ref($navmap)) {
+                            my $res = $navmap->getBySymb($symb);
+                            if (ref($res)) {
+                                my $partlist = $res->parts();
+                                if (ref($partlist) eq 'ARRAY') {
+                                    my (%weights,%awardeds,%excuseds);
+                                    foreach my $part (@{$partlist}) {
+                                        if ($res->status($part) eq $res->EXCUSED) {
+                                            $excuseds{$symb}{$part} = 1;
+                                        } else { 
+                                            $excuseds{$symb}{$part} = '';
+                                        }
+                                        if ((exists($pbcollab{$user}{$part})) && (ref($pbcollab{$user}{$part}) eq 'ARRAY')) {
+                                            my $pts = $pbcollab{$user}{$part}[0];
+                                            my $wt = $pbcollab{$user}{$part}[1];
+                                            if ($wt) {
+                                                $awardeds{$symb}{$part} = $pts/$wt;
+                                                $weights{$symb}{$part} = $wt;
+                                            } else {
+                                                $awardeds{$symb}{$part} = 0;
+                                                $weights{$symb}{$part} = 0;
+                                            }
+                                        } else {
+                                            $awardeds{$symb}{$part} = $res->awarded($part);
+                                            $weights{$symb}{$part} = $res->weight($part);
+                                        }
+                                    }
+                                    &process_passbacks('handgrade',[$symb],$cdom,$cnum,$clbudom,$clbuname,$clbusec,\%weights,
+                                                       \%awardeds,\%excuseds,\%needpb,\%skip_passback,\%pbsave);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
         }
     }
 
@@ -4430,22 +4473,18 @@ sub saveHandGrade {
     my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$domain,$stuname);
     my @parts_graded;
     my %newrecord  = ();
-    my ($pts,$wgt,$totchg) = ('','',0);
+    my ($pts,$wgt,$totchg,$sendupdate) = ('','',0,0);
     my %aggregate = ();
     my $aggregateflag = 0;
-    my $sendupdate;
     if ($env{'form.HIDE'.$newflg}) {
         my ($version,$parts) = split(/:/,$env{'form.HIDE'.$newflg},2);
         my $numchgs = &makehidden($version,$parts,\%record,$symb,$domain,$stuname,1);
         $totchg += $numchgs;
-        if ($numchgs) {
-            $sendupdate = 1;
-        }
     }
     my (%weights,%awardeds,%excuseds);
     my @parts = split(/:/,$env{'form.partlist'.$newflg});
     foreach my $new_part (@parts) {
-	#collaborator ($submi may vary for different parts
+	#collaborator ($submitter may vary for different parts)
 	if ($submitter && $new_part ne $part) { next; }
 	my $dropMenu = $env{'form.GD_SEL'.$newflg.'_'.$new_part};
         if ($env{'form.WGT'.$newflg.'_'.$new_part} eq '') {
@@ -4462,7 +4501,7 @@ sub saveHandGrade {
 		    $newrecord{'resource.'.$new_part.'.awarded'} = '';
 		}
 	        $newrecord{'resource.'.$new_part.'.regrader'}="$env{'user.name'}:$env{'user.domain'}";
-                $sendupdate = 1;
+                $sendupdate ++;
 	    }
 	} elsif ($dropMenu eq 'reset status'
 		 && exists($record{'resource.'.$new_part.'.solved'})) { #don't bother if no old records -> no attempts
@@ -4486,7 +4525,7 @@ sub saveHandGrade {
                 &decrement_aggs($symb,$new_part,\%aggregate,$aggtries,$totaltries,$solvedstatus);
                 $aggregateflag = 1;
             }
-            $sendupdate = 1;
+            $sendupdate ++;
             $excuseds{$symb}{$new_part} = '';
             $awardeds{$symb}{$new_part} = '';
 	} elsif ($dropMenu eq '') {
@@ -4507,7 +4546,7 @@ sub saveHandGrade {
 		next;
 	    } else {
 	        push(@parts_graded,$new_part);
-                $sendupdate = 1;
+                $sendupdate ++;
 	    }
 	    if ($record{'resource.'.$new_part.'.awarded'} ne $partial) {
 		$newrecord{'resource.'.$new_part.'.awarded'}  = $partial;
@@ -4559,14 +4598,14 @@ sub saveHandGrade {
         &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate,
 			      $cdom,$cnum);
     }
-    if (($sendupdate) && (!$submitter)) {
+    if (($sendupdate || $totchg) && (!$submitter)) {
         if ((ref($needpb) eq 'HASH') &&
             (keys(%{$needpb}))) {
             &process_passbacks('handgrade',[$symb],$cdom,$cnum,$domain,$stuname,$usec,\%weights,
                                \%awardeds,\%excuseds,$needpb,$skip_passback,$pbsave);
         }
     }
-    return ('',$pts,$wgt,$totchg);
+    return ('',$pts,$wgt,$totchg,$sendupdate);
 }
 
 sub makehidden {
@@ -12552,6 +12591,10 @@ sub assign_clicker_grades {
     if ($res_error) {
         return &navmap_errormsg();
     }
+    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+    my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+    my %needpb = &passbacks_for_symb($cdom,$cnum,$symb);
+    my (%skip_passback,%pbsave); 
 # FIXME: This should probably look for the first handgradeable part
     my $part=$$partlist[0];
 # Start screen output
@@ -12661,7 +12704,15 @@ sub assign_clicker_grades {
              $result.="<br /><span class=\"LC_error\">Failed to save student $username:$domain. Message when trying to save was ($returncode)</span>";
           } else {
              $storecount++;
-             #FIXME Do passback for $user if required
+             if (keys(%needpb)) {
+                 my (%weights,%awardeds,%excuseds);
+                 my $usec = &Apache::lonnet::getsection($domain,$username,$env{'request.course.id'});
+                 $weights{$symb}{$part} = &Apache::lonnet::EXT("resource.$part.weight",$symb,$domain,$username,$usec);
+                 $awardeds{$symb}{$part} = $ave;
+                 $excuseds{$symb}{$part} = '';
+                 &process_passbacks('clickergrade',[$symb],$cdom,$cnum,$domain,$username,$usec,\%weights,
+                                    \%awardeds,\%excuseds,\%needpb,\%skip_passback,\%pbsave);
+             }
           }
        }
     }