--- loncom/homework/lonhomework.pm 2024/11/21 07:26:01 1.384 +++ loncom/homework/lonhomework.pm 2024/12/09 02:46:01 1.386 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Homework handler # -# $Id: lonhomework.pm,v 1.384 2024/11/21 07:26:01 raeburn Exp $ +# $Id: lonhomework.pm,v 1.386 2024/12/09 02:46:01 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -2001,21 +2001,45 @@ sub do_ltipassback { my $scoretype = $item->{'format'}; my $scope = $item->{'scope'}; my $clientip = $item->{'clientip'}; - my ($total,$possible); - if ($pbscope eq 'resource') { + my ($total,$possible,%total_by_symb,%possible_by_symb); + if ((exists($item->{'total_s'})) && (ref($item->{'total_s'}) eq 'HASH')) { + %total_by_symb = %{$item->{'total_s'}}; + if ($pbscope eq 'resource') { + if (exists($total_by_symb{$symb})) { + $total = $total_by_symb{$symb}; + } else { + $total = $item->{'total'}; + } + } + } elsif ($pbscope eq 'resource') { $total = $item->{'total'}; + } + if ((exists($item->{'possible_s'})) && (ref($item->{'possible_s'}) eq 'HASH')) { + %possible_by_symb = %{$item->{'possible_s'}}; + if ($pbscope eq 'resource') { + if (exists($possible_by_symb{$symb})) { + $possible = $possible_by_symb{$symb}; + } else { + $possible = $item->{'possible'}; + } + } + } elsif ($pbscope eq 'resource') { $possible = $item->{'possible'}; - } else { - if (($pbscope eq 'map') || ($pbscope eq 'nonrec')) { + } + if (($pbscope eq 'map') || ($pbscope eq 'nonrec')) { + if ((keys(%total_by_symb)) && (keys(%possible_by_symb))) { + ($total,$possible) = + &get_lti_score($uname,$udom,$map,$pbscope,\%total_by_symb,\%possible_by_symb); + } else { ($total,$possible) = &get_lti_score($uname,$udom,$map,$pbscope); - } elsif ($pbscope eq 'course') { - ($total,$possible) = &get_lti_score($uname,$udom); } - $item->{'total'} = $total; - $item->{'possible'} = $possible; + } elsif ($pbscope eq 'course') { + ($total,$possible) = &get_lti_score($uname,$udom); } + $item->{'total'} = $total; + $item->{'possible'} = $possible; if (($id ne '') && ($url ne '') && ($possible)) { - my ($sent,$score,$code,$result) = + my ($sent,$score,$code,$result) = &LONCAPA::ltiutils::send_grade($cdom,$cnum,$crsdef,$type,$ltinum,$keynum,$id, $url,$scoretype,$sigmethod,$msgformat,$total,$possible); $item->{'score'} = $score; @@ -2026,7 +2050,7 @@ sub do_ltipassback { if ($sent) { if ($code == 200) { if ($item->{'linkprot'}) { - my $key = join("\0",($linkuri,$linkprotector,$scope)); + my $skey = join("\0",($linkuri,$linkprotector,$scope)); my $namespace = $cdom.'_'.$cnum.'_lp_passback'; my $store = { 'score' => $score, @@ -2046,7 +2070,7 @@ sub do_ltipassback { } $value=~s/\&$//; &Apache::lonnet::courselog(&escape($linkuri).':'.$uname.':'.$udom.':EXPORT:'.$value); - &Apache::lonnet::cstore({'score' => $score},$key,$namespace,$udom,$uname,'',$ip,1); + &Apache::lonnet::cstore({'score' => $score},$skey,$namespace,$udom,$uname,'',$ip,1); } } else { if ($item->{'linkprot'}) { @@ -2087,7 +2111,7 @@ sub do_ltipassback { } sub get_lti_score { - my ($uname,$udom,$mapurl,$pbscope) = @_; + my ($uname,$udom,$mapurl,$pbscope,$totals,$possibles) = @_; my $navmap = Apache::lonnavmaps::navmap->new($uname,$udom); if (ref($navmap)) { my $iterator; @@ -2107,17 +2131,31 @@ sub get_lti_score { my $depth = 1; my $total = 0; my $possible = 0; + my (%totals_by_symb,%possibles_by_symb); + if (ref($totals) eq 'HASH') { + %totals_by_symb = %{$totals}; + } + if (ref($possibles) eq 'HASH') { + %possibles_by_symb = %{$possibles}; + } $iterator->next(); # ignore first BEGIN_MAP my $curRes = $iterator->next(); while ( $depth > 0 ) { if ($curRes == $iterator->BEGIN_MAP()) {$depth++;} if ($curRes == $iterator->END_MAP()) { $depth--; } if (ref($curRes) && $curRes->is_gradable() && !$curRes->randomout) { - my $parts = $curRes->parts(); - foreach my $part (@{$parts}) { - next if ($curRes->solved($part) eq 'excused'); - $total += $curRes->weight($part) * $curRes->awarded($part); - $possible += $curRes->weight($part); + my $currsymb = $curRes->symb(); + if (($currsymb) && (exists($totals_by_symb{$currsymb})) && + (exists($possibles_by_symb{$currsymb}))) { + $total += $totals_by_symb{$currsymb}; + $possible += $possibles_by_symb{$currsymb}; + } else { + my $parts = $curRes->parts(); + foreach my $part (@{$parts}) { + next if ($curRes->solved($part) eq 'excused'); + $total += $curRes->weight($part) * $curRes->awarded($part); + $possible += $curRes->weight($part); + } } } $curRes = $iterator->next();