version 1.797, 2024/12/09 02:29:37
|
version 1.806, 2024/12/14 17:47:39
|
Line 67 my $ssi_retries = 5;
|
Line 67 my $ssi_retries = 5;
|
my $ssi_error; |
my $ssi_error; |
my $ssi_error_resource; |
my $ssi_error_resource; |
my $ssi_error_message; |
my $ssi_error_message; |
|
my $registered_cleanup; |
|
|
sub ssi_with_retries { |
sub ssi_with_retries { |
my ($resource, $retries, %form) = @_; |
my ($resource, $retries, %form) = @_; |
Line 776 sub getclasslist {
|
Line 776 sub getclasslist {
|
if (($udom ne '') && ($uname ne '')) { |
if (($udom ne '') && ($uname ne '')) { |
my %pbinfo = &Apache::lonnet::get('nohist_'.$cdom.'_'.$cnum.'_linkprot_pb',[$filterbypbid],$udom,$uname); |
my %pbinfo = &Apache::lonnet::get('nohist_'.$cdom.'_'.$cnum.'_linkprot_pb',[$filterbypbid],$udom,$uname); |
if (ref($pbinfo{$filterbypbid}) eq 'ARRAY') { |
if (ref($pbinfo{$filterbypbid}) eq 'ARRAY') { |
$passback{$student} = $pbinfo{$filterbypbid} |
$passback{$student} = $pbinfo{$filterbypbid}; |
} else { |
} else { |
delete($classlist->{$student}); |
delete($classlist->{$student}); |
next; |
next; |
Line 1061 sub verifyreceipt {
|
Line 1061 sub verifyreceipt {
|
return $string; |
return $string; |
} |
} |
|
|
|
#------------------------------------------------------------------- |
|
|
|
#------------------------------------------- Grade Passback Routines |
|
# |
|
|
sub initialpassback { |
sub initialpassback { |
my ($request,$symb) = @_; |
my ($request,$symb) = @_; |
my $cdom = $env{"course.$env{'request.course.id'}.domain"}; |
my $cdom = $env{"course.$env{'request.course.id'}.domain"}; |
Line 1258 sub do_passback {
|
Line 1263 sub do_passback {
|
my $cdom = $env{"course.$env{'request.course.id'}.domain"}; |
my $cdom = $env{"course.$env{'request.course.id'}.domain"}; |
my $cnum = $env{"course.$env{'request.course.id'}.num"}; |
my $cnum = $env{"course.$env{'request.course.id'}.num"}; |
my $crstype = &Apache::loncommon::course_type(); |
my $crstype = &Apache::loncommon::course_type(); |
my ($launcher,$appname,$setter,$linkuri,$linkprotector,$scope,$chosen); |
my ($launchsymb,$appname,$setter,$linkuri,$linkprotector,$scope,$chosen); |
if ($env{'form.passback'} ne '') { |
if ($env{'form.passback'} ne '') { |
$chosen = &unescape($env{'form.passback'}); |
$chosen = &unescape($env{'form.passback'}); |
($linkuri,$linkprotector,$scope) = split("\0",$chosen); |
($linkuri,$linkprotector,$scope) = split("\0",$chosen); |
($launcher,$appname,$setter) = &get_passback_launcher($cdom,$cnum,$chosen); |
($launchsymb,$appname,$setter) = &get_passback_launcher($cdom,$cnum,$chosen); |
} |
} |
if ($launcher ne '') { |
if ($launchsymb ne '') { |
$request->print(&launcher_info_box($launcher,$appname,$setter,$linkuri,$scope)); |
$request->print(&launcher_info_box($launchsymb,$appname,$setter,$linkuri,$scope)); |
} |
} |
my $error; |
my $error; |
if ($perm{'mgr'}) { |
if ($perm{'mgr'}) { |
if ($launcher ne '') { |
if ($launchsymb ne '') { |
my @poss_students = &Apache::loncommon::get_env_multiple('form.stuinfo'); |
my @poss_students = &Apache::loncommon::get_env_multiple('form.stuinfo'); |
if (@poss_students) { |
if (@poss_students) { |
my %possibles; |
my %possibles; |
Line 1307 sub do_passback {
|
Line 1312 sub do_passback {
|
if ($lti_in_use->{'scoreformat'} =~ /^(decimal|ratio|percentage)$/) { |
if ($lti_in_use->{'scoreformat'} =~ /^(decimal|ratio|percentage)$/) { |
$scoretype = $1; |
$scoretype = $1; |
} |
} |
my $pbsymb = &Apache::loncommon::symb_from_tinyurl($linkuri,$cnum,$cdom); |
|
my $pbmap; |
my $pbmap; |
if ($pbsymb =~ /\.(page|sequence)$/) { |
if ($launchsymb =~ /\.(page|sequence)$/) { |
$pbmap = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($pbsymb))[2]); |
$pbmap = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($launchsymb))[2]); |
} else { |
} else { |
$pbmap = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($pbsymb))[0]); |
$pbmap = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($launchsymb))[0]); |
} |
} |
$pbmap = &Apache::lonnet::clutter($pbmap); |
$pbmap = &Apache::lonnet::clutter($pbmap); |
my $pbscope; |
my $pbscope; |
Line 1323 sub do_passback {
|
Line 1327 sub do_passback {
|
} elsif ($scope eq 'rec') { |
} elsif ($scope eq 'rec') { |
$pbscope = 'map'; |
$pbscope = 'map'; |
} |
} |
my $sigmethod = 'HMAC-SHA1'; |
my %pb = &common_passback_info(); |
my $type = 'linkprot'; |
|
my $clientip = &Apache::lonnet::get_requestor_ip(); |
|
my $lonhost = $Apache::lonnet::perlvar{'lonHostID'}; |
|
my $ip = &Apache::lonnet::get_host_ip($lonhost); |
|
my $numstudents = scalar(keys(%tosend)); |
my $numstudents = scalar(keys(%tosend)); |
my %prog_state = &Apache::lonhtmlcommon::Create_PrgWin($request,$numstudents); |
my %prog_state = &Apache::lonhtmlcommon::Create_PrgWin($request,$numstudents); |
my $outcome = &Apache::loncommon::start_data_table(). |
my $outcome = &Apache::loncommon::start_data_table(). |
&Apache::loncommon::start_data_table_header_row(); |
&Apache::loncommon::start_data_table_header_row(); |
my $loop = 0; |
my $loop = 0; |
while ($loop < 2) { |
while ($loop < 2) { |
$outcome .= '<th>'.&mt('No.').'</th>'. |
$outcome .= '<th>'.&mt('No.').'</th>'. |
'<th>'.&nameUserString('header').' '.&mt('Section/Group').'</th>'. |
'<th>'.&nameUserString('header').' '.&mt('Section/Group').'</th>'. |
'<th>'.&mt('Score').'</th>'; |
'<th>'.&mt('Score').'</th>'; |
$loop++; |
$loop++; |
} |
} |
$outcome .= &Apache::loncommon::end_data_table_header_row()."\n"; |
$outcome .= &Apache::loncommon::end_data_table_header_row()."\n"; |
my $ctr=0; |
my $ctr=0; |
Line 1364 sub do_passback {
|
Line 1364 sub do_passback {
|
$possible = 0; |
$possible = 0; |
my $navmap = Apache::lonnavmaps::navmap->new($uname,$udom); |
my $navmap = Apache::lonnavmaps::navmap->new($uname,$udom); |
if (ref($navmap)) { |
if (ref($navmap)) { |
my $res = $navmap->getBySymb($pbsymb); |
my $res = $navmap->getBySymb($launchsymb); |
if (ref($res)) { |
if (ref($res)) { |
my $partlist = $res->parts(); |
my $partlist = $res->parts(); |
if (ref($partlist) eq 'ARRAY') { |
if (ref($partlist) eq 'ARRAY') { |
my %record = &Apache::lonnet::restore($pbsymb,$env{'request.course.id'},$udom,$uname); |
my %record = &Apache::lonnet::restore($launchsymb,$env{'request.course.id'},$udom,$uname); |
foreach my $part (@{$partlist}) { |
foreach my $part (@{$partlist}) { |
next if ($record{"resource.$part.solved"} =~/^excused/); |
next if ($record{"resource.$part.solved"} =~/^excused/); |
my $weight = &Apache::lonnet::EXT("resource.$part.weight",$pbsymb,$udom,$uname,$usec); |
my $weight = &Apache::lonnet::EXT("resource.$part.weight",$launchsymb,$udom,$uname,$usec); |
$possible += $weight; |
$possible += $weight; |
if (($record{'version'}) && (exists($record{"resource.$part.awarded"}))) { |
if (($record{'version'}) && (exists($record{"resource.$part.awarded"}))) { |
my $awarded = $record{"resource.$part.awarded"}; |
my $awarded = $record{"resource.$part.awarded"}; |
Line 1385 sub do_passback {
|
Line 1385 sub do_passback {
|
} |
} |
} elsif (($pbscope eq 'map') || ($pbscope eq 'nonrec')) { |
} elsif (($pbscope eq 'map') || ($pbscope eq 'nonrec')) { |
($total,$possible) = |
($total,$possible) = |
&Apache::lonhomework::get_lti_score($uname,$udom,$pbmap,$pbscope); |
&Apache::lonhomework::get_lti_score($uname,$udom,$usec,$pbmap,$pbscope); |
} |
} |
if (($id ne '') && ($url ne '') && ($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, |
&LONCAPA::ltiutils::send_grade($cdom,$cnum,$crsdef,$pb{'type'},$ltinum,$keynum,$id, |
$url,$scoretype,$sigmethod,$msgformat,$total,$possible); |
$url,$scoretype,$pb{'sigmethod'},$msgformat,$total,$possible); |
my $no_passback; |
my $no_passback; |
if ($sent) { |
if ($sent) { |
if ($code == 200) { |
if ($code == 200) { |
Line 1398 sub do_passback {
|
Line 1398 sub do_passback {
|
my $namespace = $cdom.'_'.$cnum.'_lp_passback'; |
my $namespace = $cdom.'_'.$cnum.'_lp_passback'; |
my $store = { |
my $store = { |
'score' => $score, |
'score' => $score, |
'ip' => $ip, |
'ip' => $pb{'ip'}, |
'host' => $lonhost, |
'host' => $pb{'lonhost'}, |
'protector' => $linkprotector, |
'protector' => $linkprotector, |
'deeplink' => $linkuri, |
'deeplink' => $linkuri, |
'scope' => $scope, |
'scope' => $scope, |
'url' => $url, |
'url' => $url, |
'id' => $id, |
'id' => $id, |
'clientip' => $clientip, |
'clientip' => $pb{'clientip'}, |
'whodoneit' => $env{'user.name'}.':'.$env{'user.domain'}, |
'whodoneit' => $env{'user.name'}.':'.$env{'user.domain'}, |
}; |
}; |
my $value=''; |
my $value=''; |
foreach my $key (keys(%{$store})) { |
foreach my $key (keys(%{$store})) { |
$value.=&escape($key).'='.&Apache::lonnet::freeze_escape($store->{$key}).'&'; |
$value.=&escape($key).'='.&Apache::lonnet::freeze_escape($store->{$key}).'&'; |
} |
} |
$value=~s/\&$//; |
$value=~s/\&$//; |
&Apache::lonnet::courselog(&escape($linkuri).':'.$uname.':'.$udom.':EXPORT:'.$value); |
&Apache::lonnet::courselog(&escape($linkuri).':'.$uname.':'.$udom.':EXPORT:'.$value); |
&Apache::lonnet::cstore({'score' => $score},$chosen,$namespace,$udom,$uname,'',$ip,1); |
&Apache::lonnet::cstore({'score' => $score},$chosen,$namespace,$udom,$uname,'',$pb{'ip'},1); |
$ctr++; |
$ctr++; |
if ($ctr%2 ==1) { |
if ($ctr%2 ==1) { |
$outcome .= &Apache::loncommon::start_data_table_row(); |
$outcome .= &Apache::loncommon::start_data_table_row(); |
} |
} |
my $section = $classlist->{$student}->[&Apache::loncoursedata::CL_SECTION()]; |
|
my $group = $classlist->{$student}->[&Apache::loncoursedata::CL_GROUP()]; |
my $group = $classlist->{$student}->[&Apache::loncoursedata::CL_GROUP()]; |
$outcome .= '<td align="right">'.$ctr.' </td>'. |
$outcome .= '<td align="right">'.$ctr.' </td>'. |
'<td>'.&nameUserString(undef,$$fullname{$student},$uname,$udom). |
'<td>'.&nameUserString(undef,$$fullname{$student},$uname,$udom). |
' '.$section.($group ne '' ?'/'.$group:'').'</td>'. |
' '.$usec.($group ne '' ?'/'.$group:'').'</td>'. |
'<td>'.$score.'</td>'."\n"; |
'<td>'.$score.'</td>'."\n"; |
if ($ctr%2 ==0) { |
if ($ctr%2 ==0) { |
$outcome .= &Apache::loncommon::end_data_table_row()."\n"; |
$outcome .= &Apache::loncommon::end_data_table_row()."\n"; |
} |
} |
Line 1440 sub do_passback {
|
Line 1439 sub do_passback {
|
} |
} |
if ($no_passback) { |
if ($no_passback) { |
&Apache::lonnet::log($udom,$uname,$uhome,$no_passback." score: $score; total: $total; possible: $possible"); |
&Apache::lonnet::log($udom,$uname,$uhome,$no_passback." score: $score; total: $total; possible: $possible"); |
|
my $key = &Time::HiRes::time().':'.$uname.':'.$udom.':'. |
|
"$linkuri\0$linkprotector\0$scope"; |
my $ltigrade = { |
my $ltigrade = { |
'ltinum' => $ltinum, |
$key => { |
'lti' => $lti_in_use, |
'ltinum' => $ltinum, |
'crsdef' => $crsdef, |
'lti' => $lti_in_use, |
'cid' => $cdom.'_'.$cnum, |
'crsdef' => $crsdef, |
'uname' => $uname, |
'cid' => $cdom.'_'.$cnum, |
'udom' => $udom, |
'uname' => $uname, |
'uhome' => $uhome, |
'udom' => $udom, |
'pbid' => $id, |
'uhome' => $uhome, |
'pburl' => $url, |
'pbid' => $id, |
'pbtype' => $type, |
'pburl' => $url, |
'pbscope' => $pbscope, |
'pbtype' => $pb{'type'}, |
'pbmap' => $pbmap, |
'pbscope' => $pbscope, |
'pbsymb' => $pbsymb, |
'pbmap' => $pbmap, |
'format' => $scoretype, |
'pbsymb' => $launchsymb, |
'scope' => $scope, |
'format' => $scoretype, |
'clientip' => $clientip, |
'scope' => $scope, |
'linkprot' => $linkprotector, |
'clientip' => $pb{'clientip'}, |
'total' => $total, |
'linkprot' => $linkprotector.':'.$linkuri, |
'possible' => $possible, |
'total' => $total, |
'score' => $score, |
'possible' => $possible, |
|
'score' => $score, |
|
}, |
}; |
}; |
&Apache::lonnet::put('linkprot_passback_pending',$ltigrade,$cdom,$cnum); |
&Apache::lonnet::put('linkprot_passback_pending',$ltigrade,$cdom,$cnum); |
} |
} |
Line 1574 sub get_passback_launcher {
|
Line 1577 sub get_passback_launcher {
|
} |
} |
} |
} |
} |
} |
if ($linkuri =~ m{^\Q/tiny/$cdom/\E(\w+)$}) { |
my $launchsymb = &Apache::loncommon::symb_from_tinyurl($linkuri,$cnum,$cdom); |
my $key = $1; |
if ($launchsymb eq '') { |
my $tinyurl; |
my %passback = &Apache::lonnet::dump('nohist_linkprot_passback',$cdom,$cnum); |
my ($result,$cached)=&Apache::lonnet::is_cached_new('tiny',$cdom."\0".$key); |
foreach my $poss_symb (keys(%passback)) { |
if (defined($cached)) { |
if (ref($passback{$poss_symb}) eq 'HASH') { |
$tinyurl = $result; |
if (exists($passback{$poss_symb}{$chosen})) { |
} else { |
$launchsymb = $poss_symb; |
my $configuname = &Apache::lonnet::get_domainconfiguser($cdom); |
last; |
my %currtiny = &Apache::lonnet::get('tiny',[$key],$cdom,$configuname); |
|
if ($currtiny{$key} ne '') { |
|
$tinyurl = $currtiny{$key}; |
|
&Apache::lonnet::do_cache_new('tiny',$cdom."\0".$key,$currtiny{$key},600); |
|
} |
|
} |
|
if ($tinyurl) { |
|
my ($crsnum,$launchsymb) = split(/\&/,$tinyurl); |
|
if ($crsnum eq $cnum) { |
|
my %passback = &Apache::lonnet::get('nohist_linkprot_passback',[$launchsymb],$cdom,$cnum); |
|
if (ref($passback{$launchsymb}) eq 'HASH') { |
|
if (exists($passback{$launchsymb}{$chosen})) { |
|
return ($launchsymb,$appname,$setter) |
|
} |
|
} |
} |
} |
} |
} |
} |
|
if ($launchsymb ne '') { |
|
return ($launchsymb,$appname,$setter); |
|
} |
|
} else { |
|
my %passback = &Apache::lonnet::get('nohist_linkprot_passback',[$launchsymb],$cdom,$cnum); |
|
if (ref($passback{$launchsymb}) eq 'HASH') { |
|
if (exists($passback{$launchsymb}{$chosen})) { |
|
return ($launchsymb,$appname,$setter); |
|
} |
|
} |
} |
} |
return (); |
return (); |
} |
} |
Line 1666 sub launcher_info_box {
|
Line 1665 sub launcher_info_box {
|
&Apache::lonhtmlcommon::end_pick_box().'</p>'."\n"; |
&Apache::lonhtmlcommon::end_pick_box().'</p>'."\n"; |
} |
} |
|
|
|
sub passbacks_for_symb { |
|
my ($cdom,$cnum,$symb) = @_; |
|
my %passback = &Apache::lonnet::dump('nohist_linkprot_passback',$cdom,$cnum); |
|
my %needpb; |
|
if (keys(%passback)) { |
|
my $checkpb = 1; |
|
if (exists($passback{$symb})) { |
|
if (keys(%passback) == 1) { |
|
undef($checkpb); |
|
} |
|
if (ref($passback{$symb}) eq 'HASH') { |
|
foreach my $launcher (keys(%{$passback{$symb}})) { |
|
$needpb{$launcher} = $symb; |
|
} |
|
} |
|
} |
|
if ($checkpb) { |
|
my ($map,$id,$url) = &Apache::lonnet::decode_symb($symb); |
|
my $navmap = Apache::lonnavmaps::navmap->new(); |
|
if (ref($navmap)) { |
|
my $mapres = $navmap->getResourceByUrl($map); |
|
if (ref($mapres)) { |
|
my $mapsymb = $mapres->symb(); |
|
if (exists($passback{$mapsymb})) { |
|
if (keys(%passback) == 1) { |
|
undef($checkpb); |
|
} |
|
if (ref($passback{$mapsymb}) eq 'HASH') { |
|
foreach my $launcher (keys(%{$passback{$mapsymb}})) { |
|
$needpb{$launcher} = $mapsymb; |
|
} |
|
} |
|
} |
|
my %posspb; |
|
if ($checkpb) { |
|
my @recurseup = $navmap->recurseup_maps($map,1); |
|
if (@recurseup) { |
|
map { $posspb{$_} = 1; } @recurseup; |
|
} |
|
} |
|
foreach my $key (keys(%passback)) { |
|
if (exists($posspb{$key})) { |
|
if (ref($passback{$key}) eq 'HASH') { |
|
foreach my $launcher (keys(%{$passback{$key}})) { |
|
my ($linkuri,$linkprotector,$scope) = split("\0",$launcher); |
|
next unless ($scope eq 'rec'); |
|
$needpb{$launcher} = $key; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
return %needpb; |
|
} |
|
|
|
sub process_passbacks { |
|
my ($context,$symbs,$cdom,$cnum,$udom,$uname,$usec,$weights,$awardeds,$excuseds,$needpb, |
|
$skip_passback,$pbsave,$pbids) = @_; |
|
if ((ref($needpb) eq 'HASH') && (ref($skip_passback) eq 'HASH') && (ref($pbsave) eq 'HASH')) { |
|
my (%weight,%awarded,%excused); |
|
if ((ref($symbs) eq 'ARRAY') && (ref($weights) eq 'HASH') && (ref($awardeds) eq 'HASH') && |
|
(ref($excuseds) eq 'HASH')) { |
|
%weight = %{$weights}; |
|
%awarded = %{$awardeds}; |
|
%excused = %{$excuseds}; |
|
} |
|
my $uhome = &Apache::lonnet::homeserver($uname,$udom); |
|
my @launchers = keys(%{$needpb}); |
|
my %pbinfo; |
|
if (ref($pbids) eq 'HASH') { |
|
%pbinfo = %{$pbids}; |
|
} else { |
|
%pbinfo = &Apache::lonnet::get('nohist_'.$cdom.'_'.$cnum.'_linkprot_pb',\@launchers,$udom,$uname); |
|
} |
|
my %pbc = &common_passback_info(); |
|
foreach my $launcher (@launchers) { |
|
if (ref($pbinfo{$launcher}) eq 'ARRAY') { |
|
my $pbid = $pbinfo{$launcher}[0]; |
|
my $pburl = $pbinfo{$launcher}[1]; |
|
my (%total_by_symb,%possible_by_symb); |
|
if (($pbid ne '') && ($pburl ne '')) { |
|
next if ($skip_passback->{$launcher}); |
|
my %pb = %pbc; |
|
if ((exists($pbsave->{$launcher})) && |
|
(ref($pbsave->{$launcher}) eq 'HASH')) { |
|
foreach my $item ('lti_in_use','crsdef','ltinum','keynum','scoretype','msgformat', |
|
'symb','map','pbscope','linkuri','linkprotector','scope') { |
|
$pb{$item} = $pbsave->{$launcher}{$item}; |
|
} |
|
} else { |
|
my $ltitype; |
|
($pb{'linkuri'},$pb{'linkprotector'},$pb{'scope'}) = split("\0",$launcher); |
|
($pb{'ltinum'},$ltitype) = ($pb{'linkprotector'} =~ /^(\d+)(c|d)$/); |
|
if ($ltitype eq 'c') { |
|
my %crslti = &Apache::lonnet::get_course_lti($cnum,$cdom,'provider'); |
|
$pb{'lti_in_use'} = $crslti{$pb{'ltinum'}}; |
|
$pb{'crsdef'} = 1; |
|
} else { |
|
my %domlti = &Apache::lonnet::get_domain_lti($cdom,'linkprot'); |
|
$pb{'lti_in_use'} = $domlti{$pb{'ltinum'}}; |
|
} |
|
if (ref($pb{'lti_in_use'}) eq 'HASH') { |
|
$pb{'msgformat'} = $pb{'lti_in_use'}->{'passbackformat'}; |
|
$pb{'keynum'} = $pb{'lti_in_use'}->{'cipher'}; |
|
$pb{'scoretype'} = 'decimal'; |
|
if ($pb{'lti_in_use'}->{'scoreformat'} =~ /^(decimal|ratio|percentage)$/) { |
|
$pb{'scoretype'} = $1; |
|
} |
|
$pb{'symb'} = $needpb->{$launcher}; |
|
if ($pb{'symb'} =~ /\.(page|sequence)$/) { |
|
$pb{'map'} = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($pb{'symb'}))[2]); |
|
} else { |
|
$pb{'map'} = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($pb{'symb'}))[0]); |
|
} |
|
$pb{'map'} = &Apache::lonnet::clutter($pb{'map'}); |
|
if ($pb{'scope'} eq 'res') { |
|
$pb{'pbscope'} = 'resource'; |
|
} elsif ($pb{'scope'} eq 'map') { |
|
$pb{'pbscope'} = 'nonrec'; |
|
} elsif ($pb{'scope'} eq 'rec') { |
|
$pb{'pbscope'} = 'map'; |
|
} |
|
foreach my $item ('lti_in_use','crsdef','ltinum','keynum','scoretype','msgformat', |
|
'symb','map','pbscope','linkuri','linkprotector','scope') { |
|
$pbsave->{$launcher}{$item} = $pb{$item}; |
|
} |
|
} else { |
|
$skip_passback->{$launcher} = 1; |
|
} |
|
} |
|
if (ref($symbs) eq 'ARRAY') { |
|
foreach my $symb (@{$symbs}) { |
|
if ((ref($weight{$symb}) eq 'HASH') && (ref($awarded{$symb}) eq 'HASH') && |
|
(ref($excused{$symb}) eq 'HASH')) { |
|
foreach my $part (keys(%{$weight{$symb}})) { |
|
if ($excused{$symb}{$part}) { |
|
next; |
|
} |
|
my $partweight = $weight{$symb}{$part} eq '' ? 1 : |
|
$weight{$symb}{$part}; |
|
if ($awarded{$symb}{$part}) { |
|
$total_by_symb{$symb} += $partweight * $awarded{$symb}{$part}; |
|
} |
|
$possible_by_symb{$symb} += $partweight; |
|
} |
|
} |
|
} |
|
} |
|
if ($context eq 'updatebypage') { |
|
my $ltigrade = { |
|
'ltinum' => $pb{'ltinum'}, |
|
'lti' => $pb{'lti_in_use'}, |
|
'crsdef' => $pb{'crsdef'}, |
|
'cid' => $cdom.'_'.$cnum, |
|
'uname' => $uname, |
|
'udom' => $udom, |
|
'uhome' => $uhome, |
|
'usec' => $usec, |
|
'pbid' => $pbid, |
|
'pburl' => $pburl, |
|
'pbtype' => $pb{'type'}, |
|
'pbscope' => $pb{'pbscope'}, |
|
'pbmap' => $pb{'map'}, |
|
'pbsymb' => $pb{'symb'}, |
|
'format' => $pb{'scoretype'}, |
|
'scope' => $pb{'scope'}, |
|
'clientip' => $pb{'clientip'}, |
|
'linkprot' => $pb{'linkprotector'}.':'.$pb{'linkuri'}, |
|
'total_s' => \%total_by_symb, |
|
'possible_s' => \%possible_by_symb, |
|
}; |
|
push(@Apache::grades::ltipassback,$ltigrade); |
|
next; |
|
} |
|
my ($total,$possible); |
|
if ($pb{'pbscope'} eq 'resource') { |
|
$total = $total_by_symb{$pb{'symb'}}; |
|
$possible = $possible_by_symb{$pb{'symb'}}; |
|
} elsif (($pb{'pbscope'} eq 'map') || ($pb{'pbscope'} eq 'nonrec')) { |
|
($total,$possible) = |
|
&Apache::lonhomework::get_lti_score($uname,$udom,$usec,$pb{'map'},$pb{'pbscope'}, |
|
\%total_by_symb,\%possible_by_symb); |
|
} |
|
if (!$possible) { |
|
$total = 0; |
|
$possible = 1; |
|
} |
|
my ($sent,$score,$code,$result) = |
|
&LONCAPA::ltiutils::send_grade($cdom,$cnum,$pb{'crsdef'},$pb{'type'},$pb{'ltinum'}, |
|
$pb{'keynum'},$pbid,$pburl,$pb{'scoretype'},$pb{'sigmethod'}, |
|
$pb{'msgformat'},$total,$possible); |
|
my $no_passback; |
|
if ($sent) { |
|
if ($code == 200) { |
|
my $namespace = $cdom.'_'.$cnum.'_lp_passback'; |
|
my $store = { |
|
'score' => $score, |
|
'ip' => $pb{'ip'}, |
|
'host' => $pb{'lonhost'}, |
|
'protector' => $pb{'linkprotector'}, |
|
'deeplink' => $pb{'linkuri'}, |
|
'scope' => $pb{'scope'}, |
|
'url' => $pburl, |
|
'id' => $pbid, |
|
'clientip' => $pb{'clientip'}, |
|
'whodoneit' => $env{'user.name'}.':'.$env{'user.domain'}, |
|
}; |
|
my $value=''; |
|
foreach my $key (keys(%{$store})) { |
|
$value.=&escape($key).'='.&Apache::lonnet::freeze_escape($store->{$key}).'&'; |
|
} |
|
$value=~s/\&$//; |
|
&Apache::lonnet::courselog(&escape($pb{'linkuri'}).':'.$uname.':'.$udom.':EXPORT:'.$value); |
|
&Apache::lonnet::cstore({'score' => $score},$launcher,$namespace,$udom,$uname,'',$pb{'ip'},1); |
|
} else { |
|
$no_passback = 1; |
|
} |
|
} else { |
|
$no_passback = 1; |
|
} |
|
if ($no_passback) { |
|
&Apache::lonnet::log($udom,$uname,$uhome,$no_passback." score: $score; total: $total; possible: $possible"); |
|
my $ltigrade = { |
|
'ltinum' => $pb{'ltinum'}, |
|
'lti' => $pb{'lti_in_use'}, |
|
'crsdef' => $pb{'crsdef'}, |
|
'cid' => $cdom.'_'.$cnum, |
|
'uname' => $uname, |
|
'udom' => $udom, |
|
'uhome' => $uhome, |
|
'pbid' => $pbid, |
|
'pburl' => $pburl, |
|
'pbtype' => $pb{'type'}, |
|
'pbscope' => $pb{'pbscope'}, |
|
'pbmap' => $pb{'map'}, |
|
'pbsymb' => $pb{'symb'}, |
|
'format' => $pb{'scoretype'}, |
|
'scope' => $pb{'scope'}, |
|
'clientip' => $pb{'clientip'}, |
|
'linkprot' => $pb{'linkprotector'}.':'.$pb{'linkuri'}, |
|
'total' => $total, |
|
'possible' => $possible, |
|
'score' => $score, |
|
}; |
|
&Apache::lonnet::put('linkprot_passback_pending',$ltigrade,$cdom,$cnum); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
return; |
|
} |
|
|
|
sub common_passback_info { |
|
my %pbc = ( |
|
sigmethod => 'HMAC-SHA1', |
|
type => 'linkprot', |
|
clientip => &Apache::lonnet::get_requestor_ip(), |
|
lonhost => $Apache::lonnet::perlvar{'lonHostID'}, |
|
ip => &Apache::lonnet::get_host_ip($Apache::lonnet::perlvar{'lonHostID'}), |
|
); |
|
return %pbc; |
|
} |
|
|
#--- This is called by a number of programs. |
#--- This is called by a number of programs. |
#--- Called from the Grading Menu - View/Grade an individual student |
#--- Called from the Grading Menu - View/Grade an individual student |
#--- Also called directly when one clicks on the subm button |
#--- Also called directly when one clicks on the subm button |
Line 3914 sub processHandGrade {
|
Line 4180 sub processHandGrade {
|
} |
} |
|
|
if ($button eq 'Save & Next') { |
if ($button eq 'Save & Next') { |
|
my %needpb = &passbacks_for_symb($cdom,$cnum,$symb); |
|
my (%skip_passback,%pbsave,%pbcollab); |
my $ctr = 0; |
my $ctr = 0; |
while ($ctr < $ngrade) { |
while ($ctr < $ngrade) { |
my ($uname,$udom) = split(/:/,$env{'form.unamedom'.$ctr}); |
my ($uname,$udom) = split(/:/,$env{'form.unamedom'.$ctr}); |
my ($errorflag,$pts,$wgt,$numhidden) = |
my ($errorflag,$pts,$wgt,$numhidden) = |
&saveHandGrade($request,$symb,$uname,$udom,$ctr,undef,undef,\%queueable); |
&saveHandGrade($request,$symb,$uname,$udom,$ctr,undef,undef,\%queueable,\%needpb,\%skip_passback,\%pbsave); |
if ($errorflag eq 'no_score') { |
if ($errorflag eq 'no_score') { |
$ctr++; |
$ctr++; |
next; |
next; |
Line 3971 sub processHandGrade {
|
Line 4239 sub processHandGrade {
|
foreach my $collabstr (@collabstrs) { |
foreach my $collabstr (@collabstrs) { |
my ($part,@collaborators) = split(/:/,$collabstr); |
my ($part,@collaborators) = split(/:/,$collabstr); |
foreach my $collaborator (@collaborators) { |
foreach my $collaborator (@collaborators) { |
my ($errorflag,$pts,$wgt) = |
my ($errorflag,$pts,$wgt,$numchg,$numupdate) = |
&saveHandGrade($request,$symb,$collaborator,$udom,$ctr, |
&saveHandGrade($request,$symb,$collaborator,$udom,$ctr, |
$env{'form.unamedom'.$ctr},$part,\%queueable); |
$env{'form.unamedom'.$ctr},$part,\%queueable); |
if ($errorflag eq 'not_allowed') { |
if ($errorflag eq 'not_allowed') { |
$request->print("<span class=\"LC_error\">".&mt('Not allowed to modify grades for [_1]',"$collaborator:$udom")."</span>"); |
$request->print("<span class=\"LC_error\">".&mt('Not allowed to modify grades for [_1]',"$collaborator:$udom")."</span>"); |
next; |
next; |
} elsif ($message ne '') { |
} else { |
my ($baseurl,$showsymb) = |
if ($numchg || $numupdate) { |
&get_feedurl_and_symb($symb,$collaborator, |
$pbcollab{$collaborator}{$part} = [$pts,$wgt]; |
$udom); |
} |
if ($env{'form.withgrades'.$ctr}) { |
if ($message ne '') { |
$messagetail = " for <a href=\"". |
my ($baseurl,$showsymb) = |
$baseurl."?symb=$showsymb\">$restitle</a>"; |
&get_feedurl_and_symb($symb,$collaborator, |
|
$udom); |
|
if ($env{'form.withgrades'.$ctr}) { |
|
$messagetail = " for <a href=\"". |
|
$baseurl."?symb=$showsymb\">$restitle</a>"; |
|
} |
|
$msgstatus = |
|
&Apache::lonmsg::user_normal_msg($collaborator,$udom,$subject,$message.$messagetail,undef,$baseurl,undef,undef,undef,$showsymb,$restitle); |
} |
} |
$msgstatus = |
} |
&Apache::lonmsg::user_normal_msg($collaborator,$udom,$subject,$message.$messagetail,undef,$baseurl,undef,undef,undef,$showsymb,$restitle); |
|
} |
|
} |
} |
} |
} |
} |
} |
$ctr++; |
$ctr++; |
} |
} |
|
if ((keys(%pbcollab)) && (keys(%needpb))) { |
|
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); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
} |
} |
|
|
my %keyhash = (); |
my %keyhash = (); |
Line 4146 sub processHandGrade {
|
Line 4463 sub processHandGrade {
|
|
|
#---- Save the score and award for each student, if changed |
#---- Save the score and award for each student, if changed |
sub saveHandGrade { |
sub saveHandGrade { |
my ($request,$symb,$stuname,$domain,$newflg,$submitter,$part,$queueable) = @_; |
my ($request,$symb,$stuname,$domain,$newflg,$submitter,$part,$queueable,$needpb,$skip_passback,$pbsave) = @_; |
my @version_parts; |
my @version_parts; |
my $usec = &Apache::lonnet::getsection($domain,$stuname, |
my $usec = &Apache::lonnet::getsection($domain,$stuname, |
$env{'request.course.id'}); |
$env{'request.course.id'}); |
Line 4154 sub saveHandGrade {
|
Line 4471 sub saveHandGrade {
|
my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$domain,$stuname); |
my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$domain,$stuname); |
my @parts_graded; |
my @parts_graded; |
my %newrecord = (); |
my %newrecord = (); |
my ($pts,$wgt,$totchg) = ('','',0); |
my ($pts,$wgt,$totchg,$sendupdate) = ('','',0,0); |
my %aggregate = (); |
my %aggregate = (); |
my $aggregateflag = 0; |
my $aggregateflag = 0; |
if ($env{'form.HIDE'.$newflg}) { |
if ($env{'form.HIDE'.$newflg}) { |
Line 4162 sub saveHandGrade {
|
Line 4479 sub saveHandGrade {
|
my $numchgs = &makehidden($version,$parts,\%record,$symb,$domain,$stuname,1); |
my $numchgs = &makehidden($version,$parts,\%record,$symb,$domain,$stuname,1); |
$totchg += $numchgs; |
$totchg += $numchgs; |
} |
} |
|
my (%weights,%awardeds,%excuseds); |
my @parts = split(/:/,$env{'form.partlist'.$newflg}); |
my @parts = split(/:/,$env{'form.partlist'.$newflg}); |
foreach my $new_part (@parts) { |
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; } |
if ($submitter && $new_part ne $part) { next; } |
my $dropMenu = $env{'form.GD_SEL'.$newflg.'_'.$new_part}; |
my $dropMenu = $env{'form.GD_SEL'.$newflg.'_'.$new_part}; |
|
if ($env{'form.WGT'.$newflg.'_'.$new_part} eq '') { |
|
$weights{$symb}{$new_part} = 1; |
|
} else { |
|
$weights{$symb}{$new_part} = $env{'form.WGT'.$newflg.'_'.$new_part}; |
|
} |
if ($dropMenu eq 'excused') { |
if ($dropMenu eq 'excused') { |
|
$excuseds{$symb}{$new_part} = 1; |
|
$awardeds{$symb}{$new_part} = ''; |
if ($record{'resource.'.$new_part.'.solved'} ne 'excused') { |
if ($record{'resource.'.$new_part.'.solved'} ne 'excused') { |
$newrecord{'resource.'.$new_part.'.solved'} = 'excused'; |
$newrecord{'resource.'.$new_part.'.solved'} = 'excused'; |
if (exists($record{'resource.'.$new_part.'.awarded'})) { |
if (exists($record{'resource.'.$new_part.'.awarded'})) { |
$newrecord{'resource.'.$new_part.'.awarded'} = ''; |
$newrecord{'resource.'.$new_part.'.awarded'} = ''; |
} |
} |
$newrecord{'resource.'.$new_part.'.regrader'}="$env{'user.name'}:$env{'user.domain'}"; |
$newrecord{'resource.'.$new_part.'.regrader'}="$env{'user.name'}:$env{'user.domain'}"; |
|
$sendupdate ++; |
} |
} |
} elsif ($dropMenu eq 'reset status' |
} elsif ($dropMenu eq 'reset status' |
&& exists($record{'resource.'.$new_part.'.solved'})) { #don't bother if no old records -> no attempts |
&& exists($record{'resource.'.$new_part.'.solved'})) { #don't bother if no old records -> no attempts |
Line 4197 sub saveHandGrade {
|
Line 4523 sub saveHandGrade {
|
&decrement_aggs($symb,$new_part,\%aggregate,$aggtries,$totaltries,$solvedstatus); |
&decrement_aggs($symb,$new_part,\%aggregate,$aggtries,$totaltries,$solvedstatus); |
$aggregateflag = 1; |
$aggregateflag = 1; |
} |
} |
|
$sendupdate ++; |
|
$excuseds{$symb}{$new_part} = ''; |
|
$awardeds{$symb}{$new_part} = ''; |
} elsif ($dropMenu eq '') { |
} elsif ($dropMenu eq '') { |
$pts = ($env{'form.GD_BOX'.$newflg.'_'.$new_part} ne '' ? |
$pts = ($env{'form.GD_BOX'.$newflg.'_'.$new_part} ne '' ? |
$env{'form.GD_BOX'.$newflg.'_'.$new_part} : |
$env{'form.GD_BOX'.$newflg.'_'.$new_part} : |
Line 4207 sub saveHandGrade {
|
Line 4536 sub saveHandGrade {
|
$wgt = $env{'form.WGT'.$newflg.'_'.$new_part} eq '' ? 1 : |
$wgt = $env{'form.WGT'.$newflg.'_'.$new_part} eq '' ? 1 : |
$env{'form.WGT'.$newflg.'_'.$new_part}; |
$env{'form.WGT'.$newflg.'_'.$new_part}; |
my $partial= $pts/$wgt; |
my $partial= $pts/$wgt; |
|
$awardeds{$symb}{$new_part} = $partial; |
|
$excuseds{$symb}{$new_part} = ''; |
if ($partial eq $record{'resource.'.$new_part.'.awarded'}) { |
if ($partial eq $record{'resource.'.$new_part.'.awarded'}) { |
#do not update score for part if not changed. |
#do not update score for part if not changed. |
&handback_files($request,$symb,$stuname,$domain,$newflg,$new_part,\%newrecord); |
&handback_files($request,$symb,$stuname,$domain,$newflg,$new_part,\%newrecord); |
next; |
next; |
} else { |
} else { |
push(@parts_graded,$new_part); |
push(@parts_graded,$new_part); |
|
$sendupdate ++; |
} |
} |
if ($record{'resource.'.$new_part.'.awarded'} ne $partial) { |
if ($record{'resource.'.$new_part.'.awarded'} ne $partial) { |
$newrecord{'resource.'.$new_part.'.awarded'} = $partial; |
$newrecord{'resource.'.$new_part.'.awarded'} = $partial; |
Line 4264 sub saveHandGrade {
|
Line 4596 sub saveHandGrade {
|
&Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, |
&Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, |
$cdom,$cnum); |
$cdom,$cnum); |
} |
} |
return ('',$pts,$wgt,$totchg); |
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,$sendupdate); |
} |
} |
|
|
sub makehidden { |
sub makehidden { |
Line 5151 sub editgrades {
|
Line 5490 sub editgrades {
|
); |
); |
my ($classlist,undef,$fullname) = &getclasslist($env{'form.section'},'0'); |
my ($classlist,undef,$fullname) = &getclasslist($env{'form.section'},'0'); |
|
|
|
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 (@partid); |
my (@partid); |
my %weight = (); |
my %weight = (); |
my %columns = (); |
my %columns = (); |
Line 5201 sub editgrades {
|
Line 5544 sub editgrades {
|
&Apache::loncommon::end_data_table_header_row(); |
&Apache::loncommon::end_data_table_header_row(); |
my @noupdate; |
my @noupdate; |
my ($updateCtr,$noupdateCtr) = (1,1); |
my ($updateCtr,$noupdateCtr) = (1,1); |
my ($got_types,%queueable); |
my ($got_types,%queueable,%pbsave,%skip_passback); |
for ($i=0; $i<$env{'form.total'}; $i++) { |
for ($i=0; $i<$env{'form.total'}; $i++) { |
my $user = $env{'form.ctr'.$i}; |
my $user = $env{'form.ctr'.$i}; |
my ($uname,$udom)=split(/:/,$user); |
my ($uname,$udom)=split(/:/,$user); |
Line 5220 sub editgrades {
|
Line 5563 sub editgrades {
|
my %aggregate = (); |
my %aggregate = (); |
my $aggregateflag = 0; |
my $aggregateflag = 0; |
$user=~s/:/_/; # colon doen't work in javascript for names |
$user=~s/:/_/; # colon doen't work in javascript for names |
|
my (%weights,%awardeds,%excuseds); |
foreach (@partid) { |
foreach (@partid) { |
my $old_aw = $env{'form.GD_'.$user.'_'.$_.'_awarded_s'}; |
my $old_aw = $env{'form.GD_'.$user.'_'.$_.'_awarded_s'}; |
my $old_part_pcr = $old_aw/($weight{$_} ne '0' ? $weight{$_}:1); |
my $old_part_pcr = $old_aw/($weight{$_} ne '0' ? $weight{$_}:1); |
Line 5228 sub editgrades {
|
Line 5572 sub editgrades {
|
my $awarded = $env{'form.GD_'.$user.'_'.$_.'_awarded'}; |
my $awarded = $env{'form.GD_'.$user.'_'.$_.'_awarded'}; |
my $pcr = $awarded/($weight{$_} ne '0' ? $weight{$_} : 1); |
my $pcr = $awarded/($weight{$_} ne '0' ? $weight{$_} : 1); |
my $partial = $awarded eq '' ? '' : $pcr; |
my $partial = $awarded eq '' ? '' : $pcr; |
|
$awardeds{$symb}{$_} = $partial; |
my $score; |
my $score; |
if ($partial eq '') { |
if ($partial eq '') { |
$score = $scoreptr{$env{'form.GD_'.$user.'_'.$_.'_solved_s'}}; |
$score = $scoreptr{$env{'form.GD_'.$user.'_'.$_.'_solved_s'}}; |
Line 5268 sub editgrades {
|
Line 5613 sub editgrades {
|
|
|
|
|
my $partid=$_; |
my $partid=$_; |
|
if ($score eq 'excused') { |
|
$excuseds{$symb}{$partid} = 1; |
|
} else { |
|
$excuseds{$symb}{$partid} = ''; |
|
} |
foreach my $stores (@parts) { |
foreach my $stores (@parts) { |
my ($part,$type) = &split_part_type($stores); |
my ($part,$type) = &split_part_type($stores); |
if ($part !~ m/^\Q$partid\E/) { next;} |
if ($part !~ m/^\Q$partid\E/) { next;} |
Line 5285 sub editgrades {
|
Line 5635 sub editgrades {
|
} |
} |
$line.="\n"; |
$line.="\n"; |
|
|
my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; |
|
my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; |
|
|
|
if ($updateflag) { |
if ($updateflag) { |
$count++; |
$count++; |
&Apache::lonnet::cstore(\%newrecord,$symb,$env{'request.course.id'}, |
&Apache::lonnet::cstore(\%newrecord,$symb,$env{'request.course.id'}, |
Line 5339 sub editgrades {
|
Line 5686 sub editgrades {
|
'<td align="right"> '.$updateCtr.' </td>'.$line. |
'<td align="right"> '.$updateCtr.' </td>'.$line. |
&Apache::loncommon::end_data_table_row(); |
&Apache::loncommon::end_data_table_row(); |
$updateCtr++; |
$updateCtr++; |
|
if (keys(%needpb)) { |
|
$weights{$symb} = \%weight; |
|
&process_passbacks('editgrades',[$symb],$cdom,$cnum,$udom,$uname,$usec,\%weights, |
|
\%awardeds,\%excuseds,\%needpb,\%skip_passback,\%pbsave); |
|
} |
} else { |
} else { |
push(@noupdate, |
push(@noupdate, |
'<td align="right"> '.$noupdateCtr.' </td>'.$line); |
'<td align="right"> '.$noupdateCtr.' </td>'.$line); |
Line 5704 sub csvuploadassign {
|
Line 6056 sub csvuploadassign {
|
my @gradedata = &Apache::loncommon::upfile_record_sep(); |
my @gradedata = &Apache::loncommon::upfile_record_sep(); |
my %fields=&get_fields(); |
my %fields=&get_fields(); |
my $courseid=$env{'request.course.id'}; |
my $courseid=$env{'request.course.id'}; |
|
my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; |
|
my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; |
my ($classlist) = &getclasslist('all',0); |
my ($classlist) = &getclasslist('all',0); |
my @notallowed; |
my @notallowed; |
my @skipped; |
my @skipped; |
my @warnings; |
my @warnings; |
my $countdone=0; |
my $countdone=0; |
|
my @parts; |
|
my %needpb = &passbacks_for_symb($cdom,$cnum,$symb); |
|
my $passback; |
|
if (keys(%needpb)) { |
|
$passback = 1; |
|
my $navmap = Apache::lonnavmaps::navmap->new(); |
|
if (ref($navmap)) { |
|
my $res = $navmap->getBySymb($symb); |
|
if (ref($res)) { |
|
my $partlist = $res->parts(); |
|
if (ref($partlist) eq 'ARRAY') { |
|
@parts = sort(@{$partlist}); |
|
} |
|
} |
|
} else { |
|
return &navmap_errormsg(); |
|
} |
|
} |
|
my (%skip_passback,%pbsave,%weights,%awardeds,%excuseds); |
|
|
foreach my $grade (@gradedata) { |
foreach my $grade (@gradedata) { |
my %entries=&Apache::loncommon::record_sep($grade); |
my %entries=&Apache::loncommon::record_sep($grade); |
my $domain; |
my $domain; |
Line 5783 sub csvuploadassign {
|
Line 6157 sub csvuploadassign {
|
my $part=$1; |
my $part=$1; |
my $wgt =&Apache::lonnet::EXT('resource.'.$part.'.weight', |
my $wgt =&Apache::lonnet::EXT('resource.'.$part.'.weight', |
$symb,$domain,$username); |
$symb,$domain,$username); |
|
$weights{$symb}{$part} = $wgt; |
if ($wgt) { |
if ($wgt) { |
$entries{$fields{$dest}}=~s/\s//g; |
$entries{$fields{$dest}}=~s/\s//g; |
my $pcr=$entries{$fields{$dest}} / $wgt; |
my $pcr=$entries{$fields{$dest}} / $wgt; |
|
if ($passback) { |
|
$awardeds{$symb}{$part} = $pcr; |
|
$excuseds{$symb}{$part} = ''; |
|
} |
my $award=($pcr == 0) ? 'incorrect_by_override' |
my $award=($pcr == 0) ? 'incorrect_by_override' |
: 'correct_by_override'; |
: 'correct_by_override'; |
if ($pcr>1) { |
if ($pcr>1) { |
Line 5805 sub csvuploadassign {
|
Line 6184 sub csvuploadassign {
|
if ($dest=~/stores_(.*)_awarded/) { if ($points{$1}) {next;} } |
if ($dest=~/stores_(.*)_awarded/) { if ($points{$1}) {next;} } |
if ($dest=~/stores_(.*)_solved/) { if ($points{$1}) {next;} } |
if ($dest=~/stores_(.*)_solved/) { if ($points{$1}) {next;} } |
my $store_key=$dest; |
my $store_key=$dest; |
|
if ($passback) { |
|
if ($store_key=~/stores_(.*)_(awarded|solved)/) { |
|
my ($part,$key) = ($1,$2); |
|
unless ((ref($weights{$symb}) eq 'HASH') && (exists($weights{$symb}{$part}))) { |
|
$weights{$symb}{$part} = &Apache::lonnet::EXT('resource.'.$part.'.weight', |
|
$symb,$domain,$username); |
|
} |
|
if ($key eq 'awarded') { |
|
$awardeds{$symb}{$part} = $entries{$fields{$dest}}; |
|
} elsif ($key eq 'solved') { |
|
if ($entries{$fields{$dest}} =~ /^excused/) { |
|
$excuseds{$symb}{$part} = 1; |
|
} |
|
} |
|
} |
|
} |
$store_key=~s/^stores/resource/; |
$store_key=~s/^stores/resource/; |
$store_key=~s/_/\./g; |
$store_key=~s/_/\./g; |
$grades{$store_key}=$entries{$fields{$dest}}; |
$grades{$store_key}=$entries{$fields{$dest}}; |
Line 5821 sub csvuploadassign {
|
Line 6216 sub csvuploadassign {
|
# Successfully stored |
# Successfully stored |
$request->print('.'); |
$request->print('.'); |
# Remove from grading queue |
# Remove from grading queue |
&Apache::bridgetask::remove_from_queue('gradingqueue',$symb, |
&Apache::bridgetask::remove_from_queue('gradingqueue',$symb,$cdom,$cnum, |
$env{'course.'.$env{'request.course.id'}.'.domain'}, |
$domain,$username); |
$env{'course.'.$env{'request.course.id'}.'.num'}, |
|
$domain,$username); |
|
$countdone++; |
$countdone++; |
|
if ($passback) { |
|
my @parts_in_upload; |
|
if (ref($weights{$symb}) eq 'HASH') { |
|
@parts_in_upload = sort(keys(%{$weights{$symb}})); |
|
} |
|
my @diffs = &Apache::loncommon::compare_arrays(\@parts_in_upload,\@parts); |
|
if (@diffs > 0) { |
|
my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$domain,$username); |
|
foreach my $part (@parts) { |
|
next if (grep(/^\Q$part\E$/,@parts_in_upload)); |
|
$weights{$symb}{$part} = &Apache::lonnet::EXT('resource.'.$part.'.weight', |
|
$symb,$domain,$username); |
|
if ($record{"resource.$part.solved"} =~/^excused/) { |
|
$excuseds{$symb}{$part} = 1; |
|
} else { |
|
$excuseds{$symb}{$part} = ''; |
|
} |
|
$awardeds{$symb}{$part} = $record{"resource.$part.awarded"}; |
|
} |
|
} |
|
&process_passbacks('csvupload',[$symb],$cdom,$cnum,$domain,$username,$usec,\%weights, |
|
\%awardeds,\%excuseds,\%needpb,\%skip_passback,\%pbsave); |
|
} |
} else { |
} else { |
$request->print("<p><span class=\"LC_error\">". |
$request->print("<p><span class=\"LC_error\">". |
&mt("Failed to save data for student [_1]. Message when trying to save was: [_2]", |
&mt("Failed to save data for student [_1]. Message when trying to save was: [_2]", |
Line 6421 sub updateGradeByPage {
|
Line 6837 sub updateGradeByPage {
|
$iterator->next(); # skip the first BEGIN_MAP |
$iterator->next(); # skip the first BEGIN_MAP |
my $curRes = $iterator->next(); # for "current resource" |
my $curRes = $iterator->next(); # for "current resource" |
my ($depth,$question,$prob,$changeflag,$hideflag)= (1,1,1,0,0); |
my ($depth,$question,$prob,$changeflag,$hideflag)= (1,1,1,0,0); |
|
my (@updates,%weights,%excuseds,%awardeds,@symbs_in_map); |
while ($depth > 0) { |
while ($depth > 0) { |
if($curRes == $iterator->BEGIN_MAP) { $depth++; } |
if($curRes == $iterator->BEGIN_MAP) { $depth++; } |
if($curRes == $iterator->END_MAP) { $depth--; } |
if($curRes == $iterator->END_MAP) { $depth--; } |
Line 6429 sub updateGradeByPage {
|
Line 6846 sub updateGradeByPage {
|
my $parts = $curRes->parts(); |
my $parts = $curRes->parts(); |
my $title = $curRes->compTitle(); |
my $title = $curRes->compTitle(); |
my $symbx = $curRes->symb(); |
my $symbx = $curRes->symb(); |
|
push(@symbs_in_map,$symbx); |
$studentTable.= |
$studentTable.= |
&Apache::loncommon::start_data_table_row(). |
&Apache::loncommon::start_data_table_row(). |
'<td align="center" valign="top" >'.$prob. |
'<td align="center" valign="top" >'.$prob. |
Line 6446 sub updateGradeByPage {
|
Line 6864 sub updateGradeByPage {
|
my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname); |
my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname); |
my ($version,$parts) = split(/:/,$env{'form.HIDE'.$prob},2); |
my ($version,$parts) = split(/:/,$env{'form.HIDE'.$prob},2); |
my $numchgs = &makehidden($version,$parts,\%record,$symbx,$udom,$uname,1); |
my $numchgs = &makehidden($version,$parts,\%record,$symbx,$udom,$uname,1); |
|
if ($numchgs) { |
|
push(@updates,$symbx); |
|
} |
$hideflag += $numchgs; |
$hideflag += $numchgs; |
} |
} |
foreach my $partid (@{$parts}) { |
foreach my $partid (@{$parts}) { |
Line 6467 sub updateGradeByPage {
|
Line 6888 sub updateGradeByPage {
|
} |
} |
my $wgt = $env{'form.WGT'.$question.'_'.$partid} != 0 ? |
my $wgt = $env{'form.WGT'.$question.'_'.$partid} != 0 ? |
$env{'form.WGT'.$question.'_'.$partid} : 1; |
$env{'form.WGT'.$question.'_'.$partid} : 1; |
|
$weights{$symbx}{$partid} = $wgt; |
|
$excuseds{$symbx}{$partid} = ''; |
my $partial = $newpts/$wgt; |
my $partial = $newpts/$wgt; |
my $score; |
my $score; |
if ($partial > 0) { |
if ($partial > 0) { |
Line 6478 sub updateGradeByPage {
|
Line 6901 sub updateGradeByPage {
|
if ($dropMenu eq 'excused') { |
if ($dropMenu eq 'excused') { |
$partial = ''; |
$partial = ''; |
$score = 'excused'; |
$score = 'excused'; |
|
$excuseds{$symbx}{$partid} = 1; |
} elsif ($dropMenu eq 'reset status' |
} elsif ($dropMenu eq 'reset status' |
&& $env{'form.solved'.$question.'_'.$partid} ne '') { #update only if previous record exists |
&& $env{'form.solved'.$question.'_'.$partid} ne '') { #update only if previous record exists |
$newrecord{'resource.'.$partid.'.tries'} = 0; |
$newrecord{'resource.'.$partid.'.tries'} = 0; |
Line 6505 sub updateGradeByPage {
|
Line 6929 sub updateGradeByPage {
|
(($score eq 'excused') ? 'excused' : $newpts). |
(($score eq 'excused') ? 'excused' : $newpts). |
' <br />'; |
' <br />'; |
$question++; |
$question++; |
|
if (($newpts eq '') || ($partial eq '')) { |
|
$awardeds{$symbx}{$partid} = 0; |
|
} else { |
|
$awardeds{$symbx}{$partid} = $partial; |
|
} |
next if ($dropMenu eq 'reset status' || ($newpts eq $oldpts && $score ne 'excused')); |
next if ($dropMenu eq 'reset status' || ($newpts eq $oldpts && $score ne 'excused')); |
|
|
$newrecord{'resource.'.$partid.'.awarded'} = $partial if $partial ne ''; |
$newrecord{'resource.'.$partid.'.awarded'} = $partial if $partial ne ''; |
Line 6544 sub updateGradeByPage {
|
Line 6973 sub updateGradeByPage {
|
&Apache::loncommon::end_data_table_row(); |
&Apache::loncommon::end_data_table_row(); |
|
|
$prob++; |
$prob++; |
|
if ($changeflag) { |
|
push(@updates,$symbx); |
|
} |
} |
} |
$curRes = $iterator->next(); |
$curRes = $iterator->next(); |
} |
} |
Line 6557 sub updateGradeByPage {
|
Line 6989 sub updateGradeByPage {
|
$hideflag).'<br />'); |
$hideflag).'<br />'); |
$request->print($hidemsg.$grademsg.$studentTable); |
$request->print($hidemsg.$grademsg.$studentTable); |
|
|
|
if (@updates) { |
|
my (@allsymbs,$mapsymb,@recurseup,%parentmapsymbs,%possmappb,%possrespb); |
|
@allsymbs = @updates; |
|
if (ref($map)) { |
|
$mapsymb = $map->symb(); |
|
push(@allsymbs,$mapsymb); |
|
@recurseup = $navmap->recurseup_maps($map->src,1); |
|
} |
|
if (@recurseup) { |
|
push(@allsymbs,@recurseup); |
|
map { $parentmapsymbs{$_} = 1; } @recurseup; |
|
} |
|
my %passback = &Apache::lonnet::get('nohist_linkprot_passback',\@allsymbs,$cdom,$cnum); |
|
my (%uniqsymbs,$use_symbs_in_map,%launch_to_symb); |
|
if (keys(%passback)) { |
|
foreach my $possible (keys(%passback)) { |
|
if (ref($passback{$possible}) eq 'HASH') { |
|
if ($possible eq $mapsymb) { |
|
foreach my $launcher (keys(%{$passback{$possible}})) { |
|
$possmappb{$launcher} = 1; |
|
$launch_to_symb{$launcher} = $possible; |
|
} |
|
$use_symbs_in_map = 1; |
|
} elsif (exists($parentmapsymbs{$possible})) { |
|
foreach my $launcher (keys(%{$passback{$possible}})) { |
|
my ($linkuri,$linkprotector,$scope) = split(/\0/,$launcher); |
|
if ($scope eq 'rec') { |
|
$possmappb{$launcher} = 1; |
|
$use_symbs_in_map = 1; |
|
$launch_to_symb{$launcher} = $possible; |
|
} |
|
} |
|
} elsif (grep(/^\Q$possible$\E$/,@updates)) { |
|
foreach my $launcher (keys(%{$passback{$possible}})) { |
|
$possrespb{$launcher} = 1; |
|
$launch_to_symb{$launcher} = $possible; |
|
} |
|
$uniqsymbs{$possible} = 1; |
|
} |
|
} |
|
} |
|
} |
|
if ($use_symbs_in_map) { |
|
map { $uniqsymbs{$_} = 1; } @symbs_in_map; |
|
} |
|
my @posslaunchers; |
|
if (keys(%possmappb)) { |
|
push(@posslaunchers,keys(%possmappb)); |
|
} |
|
if (keys(%possrespb)) { |
|
push(@posslaunchers,keys(%possrespb)); |
|
} |
|
if (@posslaunchers) { |
|
my (%pbsave,%skip_passback,%needpb); |
|
my %pbids = &Apache::lonnet::get('nohist_'.$cdom.'_'.$cnum.'_linkprot_pb',\@posslaunchers,$udom,$uname); |
|
foreach my $key (keys(%pbids)) { |
|
if (ref($pbids{$key}) eq 'ARRAY') { |
|
if ($launch_to_symb{$key}) { |
|
$needpb{$key} = $launch_to_symb{$key}; |
|
} |
|
} |
|
} |
|
my @symbs = keys(%uniqsymbs); |
|
&process_passbacks('updatebypage',\@symbs,$cdom,$cnum,$udom,$uname,$usec,\%weights, |
|
\%awardeds,\%excuseds,\%needpb,\%skip_passback,\%pbsave,\%pbids); |
|
if (@Apache::grades::ltipassback) { |
|
unless ($registered_cleanup) { |
|
my $handlers = $request->get_handlers('PerlCleanupHandler'); |
|
$request->set_handlers('PerlCleanupHandler' => |
|
[\&Apache::grades::make_passback,@{$handlers}]); |
|
$registered_cleanup=1; |
|
} |
|
} |
|
} |
|
} |
return ''; |
return ''; |
} |
} |
|
|
|
sub make_passback { |
|
if (@Apache::grades::ltipassback) { |
|
my $lonhost = $Apache::lonnet::perlvar{'lonHostID'}; |
|
my $ip = &Apache::lonnet::get_host_ip($lonhost); |
|
foreach my $item (@Apache::grades::ltipassback) { |
|
&Apache::lonhomework::run_passback($item,$lonhost,$ip); |
|
} |
|
undef(@Apache::grades::ltipassback); |
|
} |
|
} |
|
|
#-------- end of section for handling grading by page/sequence --------- |
#-------- end of section for handling grading by page/sequence --------- |
# |
# |
#------------------------------------------------------------------- |
#------------------------------------------------------------------- |
Line 12076 sub assign_clicker_grades {
|
Line 12594 sub assign_clicker_grades {
|
if ($res_error) { |
if ($res_error) { |
return &navmap_errormsg(); |
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 |
# FIXME: This should probably look for the first handgradeable part |
my $part=$$partlist[0]; |
my $part=$$partlist[0]; |
# Start screen output |
# Start screen output |
Line 12185 sub assign_clicker_grades {
|
Line 12707 sub assign_clicker_grades {
|
$result.="<br /><span class=\"LC_error\">Failed to save student $username:$domain. Message when trying to save was ($returncode)</span>"; |
$result.="<br /><span class=\"LC_error\">Failed to save student $username:$domain. Message when trying to save was ($returncode)</span>"; |
} else { |
} else { |
$storecount++; |
$storecount++; |
|
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); |
|
} |
} |
} |
} |
} |
} |
} |
Line 12343 sub handler {
|
Line 12874 sub handler {
|
&Apache::lonnet::logthis("grades got multiple commands ".join(':',@commands)); |
&Apache::lonnet::logthis("grades got multiple commands ".join(':',@commands)); |
} |
} |
|
|
|
# -------------------------------------- Flag and buffer for registered cleanup |
|
$registered_cleanup=0; |
|
undef(@Apache::grades::ltipassback); |
|
|
# see what the symb is |
# see what the symb is |
|
|
my $symb=$env{'form.symb'}; |
my $symb=$env{'form.symb'}; |