--- loncom/homework/grades.pm 2025/01/18 22:07:25 1.596.2.12.2.60.2.10 +++ loncom/homework/grades.pm 2024/12/09 01:24:24 1.596.2.12.2.63 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.596.2.12.2.60.2.10 2025/01/18 22:07:25 raeburn Exp $ +# $Id: grades.pm,v 1.596.2.12.2.63 2024/12/09 01:24:24 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -46,12 +46,10 @@ use Apache::lonenc; use Apache::lonstathelpers; use Apache::bridgetask(); use Apache::lontexconvert(); -use Apache::loncourserespicker; -use String::Similarity; use HTML::Parser(); use File::MMagic; +use String::Similarity; use LONCAPA; -use LONCAPA::ltiutils(); use POSIX qw(floor); @@ -66,7 +64,7 @@ my $ssi_retries = 5; my $ssi_error; my $ssi_error_resource; my $ssi_error_message; -my $registered_cleanup; + sub ssi_with_retries { my ($resource, $retries, %form) = @_; @@ -120,11 +118,7 @@ sub getpartlist { my $res = $navmap->getBySymb($symb); my $partlist = $res->parts(); my $url = $res->src(); - my $toolsymb; - if ($url =~ /ext\.tool$/) { - $toolsymb = $symb; - } - my @metakeys = split(/,/,&Apache::lonnet::metadata($url,'keys',$toolsymb)); + my @metakeys = split(/,/,&Apache::lonnet::metadata($url,'keys')); my @stores; foreach my $part (@{ $partlist }) { @@ -305,7 +299,7 @@ sub showResourceInfo { } else { return '<br clear="all" />'; } - } + } return $result; } @@ -592,7 +586,7 @@ sub cleanRecord { return $result; } } elsif ( $response =~ m/(?:numerical|formula|custom)/) { - # Respect multiple input fields, see Bug #5409 + # Respect multiple input fields, see Bug #5409 $answer = &Apache::loncommon::format_previous_attempt_value('submission', $answer); @@ -638,7 +632,7 @@ COMMONJSFUNCTIONS #--- Dumps the class list with usernames,list of sections, #--- section, ids and fullnames for each user. sub getclasslist { - my ($getsec,$filterbyaccstatus,$getgroup,$symb,$submitonly,$filterbysubmstatus,$filterbypbid,$possibles) = @_; + my ($getsec,$filterbyaccstatus,$getgroup,$symb,$submitonly,$filterbysubmstatus) = @_; my @getsec; my @getgroup; my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status')); @@ -666,16 +660,12 @@ sub getclasslist { # my %sections; my %fullnames; - my %passback; my ($cdom,$cnum,$partlist); if (($filterbysubmstatus) && ($submitonly ne 'all') && ($symb ne '')) { $cdom = $env{"course.$env{'request.course.id'}.domain"}; $cnum = $env{"course.$env{'request.course.id'}.num"}; my $res_error; ($partlist) = &response_type($symb,\$res_error); - } elsif ($filterbypbid) { - $cdom = $env{"course.$env{'request.course.id'}.domain"}; - $cnum = $env{"course.$env{'request.course.id'}.num"}; } foreach my $student (keys(%$classlist)) { my $end = @@ -762,27 +752,6 @@ sub getclasslist { } } } - if ($filterbypbid) { - if (ref($possibles) eq 'HASH') { - unless (exists($possibles->{$student})) { - delete($classlist->{$student}); - next; - } - } - my $udom = - $classlist->{$student}->[&Apache::loncoursedata::CL_SDOM()]; - my $uname = - $classlist->{$student}->[&Apache::loncoursedata::CL_SNAME()]; - if (($udom ne '') && ($uname ne '')) { - my %pbinfo = &Apache::lonnet::get('nohist_'.$cdom.'_'.$cnum.'_linkprot_pb',[$filterbypbid],$udom,$uname); - if (ref($pbinfo{$filterbypbid}) eq 'ARRAY') { - $passback{$student} = $pbinfo{$filterbypbid}; - } else { - delete($classlist->{$student}); - next; - } - } - } $section = ($section ne '' ? $section : 'none'); if (&canview($section)) { if (!@getsec || grep(/^\Q$section\E$/,@getsec)) { @@ -798,7 +767,7 @@ sub getclasslist { } } my @sections = sort(keys(%sections)); - return ($classlist,\@sections,\%fullnames,\%passback); + return ($classlist,\@sections,\%fullnames); } sub canmodify { @@ -1061,877 +1030,6 @@ sub verifyreceipt { return $string; } -#------------------------------------------------------------------- - -#------------------------------------------- Grade Passback Routines -# - -sub initialpassback { - my ($request,$symb) = @_; - my $cdom = $env{"course.$env{'request.course.id'}.domain"}; - my $cnum = $env{"course.$env{'request.course.id'}.num"}; - my $crstype = &Apache::loncommon::course_type(); - my %passback = &Apache::lonnet::dump('nohist_linkprot_passback',$cdom,$cnum); - my $readonly; - unless ($perm{'mgr'}) { - $readonly = 1; - } - my $formname = 'initialpassback'; - my $navmap = Apache::lonnavmaps::navmap->new(); - my $output; - if (!defined($navmap)) { - if ($crstype eq 'Community') { - $output = &mt('Unable to retrieve information about community contents'); - } else { - $output = &mt('Unable to retrieve information about course contents'); - } - return '<p>'.$output.'</p>'; - } - return &Apache::loncourserespicker::create_picker($navmap,'passback',$formname,$crstype,undef, - undef,undef,undef,undef,undef,undef, - \%passback,$readonly); -} - -sub passback_filters { - my ($request,$symb) = @_; - my $cdom = $env{"course.$env{'request.course.id'}.domain"}; - my $cnum = $env{"course.$env{'request.course.id'}.num"}; - my $crstype = &Apache::loncommon::course_type(); - my ($launcher,$appname,$setter,$linkuri,$linkprotector,$scope,$chosen); - if ($env{'form.passback'} ne '') { - $chosen = &unescape($env{'form.passback'}); - ($linkuri,$linkprotector,$scope) = split("\0",$chosen); - ($launcher,$appname,$setter) = &get_passback_launcher($cdom,$cnum,$chosen); - } - my $result; - if ($launcher ne '') { - $result = &launcher_info_box($launcher,$appname,$setter,$linkuri,$scope). - '<p><br />'.&mt('Set criteria to use to list students for possible passback of scores, then push Next [_1]', - '→'). - '</p>'; - } - $result .= '<form action="/adm/grades" method="post" name="gradingMenu">'."\n". - '<input type="hidden" name="passback" value="'.&escape($chosen).'" />'."\n". - '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n"; - my ($submittext,$newcommand); - if ($launcher ne '') { - $submittext = &mt('Next').' →'; - $newcommand = 'passbacknames'; - $result .= &selectfield(0)."\n"; - } else { - $submittext = '← '.&mt('Previous'); - $newcommand = 'initialpassback'; - if ($env{'form.passback'}) { - $result .= '<span class="LC_warning">'.&mt('Invalid launcher').'</span>'."\n"; - } else { - $result .= '<span class="LC_warning">'.&mt('No launcher selected').'</span>'."\n"; - } - } - $result .= '<input type="hidden" name="command" value="'.$newcommand.'" />'."\n". - '<div>'."\n". - '<input type="submit" value="'.$submittext.'" />'."\n". - '</div>'."\n". - '</form>'."\n"; - return $result; -} - -sub names_for_passback { - my ($request,$symb) = @_; - my $cdom = $env{"course.$env{'request.course.id'}.domain"}; - my $cnum = $env{"course.$env{'request.course.id'}.num"}; - my $crstype = &Apache::loncommon::course_type(); - my ($launcher,$appname,$setter,$linkuri,$linkprotector,$scope,$chosen); - if ($env{'form.passback'} ne '') { - $chosen = &unescape($env{'form.passback'}); - ($linkuri,$linkprotector,$scope) = split("\0",$chosen); - ($launcher,$appname,$setter) = &get_passback_launcher($cdom,$cnum,$chosen); - } - my ($result,$ctr,$newcommand,$submittext); - if ($launcher ne '') { - $result = &launcher_info_box($launcher,$appname,$setter,$linkuri,$scope); - } - $ctr = 0; - my @statuses = &Apache::loncommon::get_env_multiple('form.Status'); - my $stu_status = join(':',@statuses); - $result .= '<form action="/adm/grades" method="post" name="passbackusers">'."\n". - '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n"; - if ($launcher ne '') { - $result .= '<input type="hidden" name="passback" value="'.&escape($chosen).'" />'."\n". - '<input type="hidden" name="Status" value="'.$stu_status.'" />'."\n"; - my ($sections,$groups,$group_display,$disabled) = §ions_and_groups(); - my $section_display = join(' ',@{$sections}); - my $status_display; - if ((grep(/^Any$/,@statuses)) || - (@statuses == 3)) { - $status_display = &mt('Any'); - } else { - $status_display = join(' '.&mt('or').' ',map { &mt($_); } @statuses); - } - $result .= '<p>'.&mt('Student(s) with stored passback credentials for [_1], and also satisfy:', - '<span class="LC_cusr_emph">'.$linkuri.'</span>'). - '<ul>'. - '<li>'.&mt('Section(s)').": $section_display</li>\n". - '<li>'.&mt('Group(s)').": $group_display</li>\n". - '<li>'.&mt('Status').": $status_display</li>\n". - '</ul>'; - my ($classlist,undef,$fullname) = &getclasslist($sections,'1',$groups,'','','',$chosen); - if (keys(%$fullname)) { - $newcommand = 'passbackscores'; - $result .= &build_section_inputs(). - &checkselect_js('passbackusers'). - '<p><br />'. - &mt("To send scores, check box(es) next to the student's name(s), then push 'Send Scores'."). - '</p>'. - &check_script('passbackusers', 'stuinfo')."\n". - '<input type="button" '."\n". - 'onclick="javascript:checkSelect(this.form.stuinfo);" '."\n". - 'value="'.&mt('Send Scores').'" /> <br />'."\n". - &check_buttons()."\n". - &Apache::loncommon::start_data_table(). - &Apache::loncommon::start_data_table_header_row(); - my $loop = 0; - while ($loop < 2) { - $result .= '<th>'.&mt('No.').'</th><th>'.&mt('Select').'</th>'. - '<th>'.&nameUserString('header').' '.&mt('Section/Group').'</th>'; - $loop++; - } - $result .= &Apache::loncommon::end_data_table_header_row()."\n"; - foreach my $student (sort - { - if (lc($$fullname{$a}) ne lc($$fullname{$b})) { - return (lc($$fullname{$a}) cmp lc($$fullname{$b})); - } - return $a cmp $b; - } - (keys(%$fullname))) { - $ctr++; - my $section = $classlist->{$student}->[&Apache::loncoursedata::CL_SECTION()]; - my $group = $classlist->{$student}->[&Apache::loncoursedata::CL_GROUP()]; - my $udom = $classlist->{$student}->[&Apache::loncoursedata::CL_SDOM()]; - my $uname = $classlist->{$student}->[&Apache::loncoursedata::CL_SNAME()]; - if ( $perm{'vgr'} eq 'F' ) { - if ($ctr%2 ==1) { - $result.= &Apache::loncommon::start_data_table_row(); - } - $result .= '<td align="right">'.$ctr.' </td>'. - '<td align="center"><label><input type="checkbox" name="stuinfo" value="'. - $student.':'.$$fullname{$student}.':::SECTION'.$section. - ') " /> </label></td>'."\n".'<td>'. - &nameUserString(undef,$$fullname{$student},$uname,$udom). - ' '.$section.($group ne '' ?'/'.$group:'').'</td>'."\n"; - - if ($ctr%2 ==0) { - $result .= &Apache::loncommon::end_data_table_row()."\n"; - } - } - } - if ($ctr%2 ==1) { - $result .= &Apache::loncommon::end_data_table_row(); - } - $result .= &Apache::loncommon::end_data_table()."\n"; - if ($ctr) { - $result .= '<input type="button" '. - 'onclick="javascript:checkSelect(this.form.stuinfo);" '. - 'value="'.&mt('Send Scores').'" />'."\n"; - } - } else { - $submittext = '← '.&mt('Previous'); - $newcommand = 'passback'; - $result .= '<span class="LC_warning">'.&mt('No students match the selection criteria').'</p>'; - } - } else { - $newcommand = 'initialpassback'; - $submittext = &mt('Start over'); - if ($env{'form.passback'}) { - $result .= '<span class="LC_warning">'.&mt('Invalid launcher').'</span>'."\n"; - } else { - $result .= '<span class="LC_warning">'.&mt('No launcher selected').'</span>'."\n"; - } - } - $result .= '<input type="hidden" name="command" value="'.$newcommand.'" />'."\n"; - if (!$ctr) { - $result .= '<div>'."\n". - '<input type="submit" value="'.$submittext.'" />'."\n". - '</div>'."\n"; - } - $result .= '</form>'."\n"; - return $result; -} - -sub do_passback { - my ($request,$symb) = @_; - my $cdom = $env{"course.$env{'request.course.id'}.domain"}; - my $cnum = $env{"course.$env{'request.course.id'}.num"}; - my $crstype = &Apache::loncommon::course_type(); - my ($launchsymb,$appname,$setter,$linkuri,$linkprotector,$scope,$chosen); - if ($env{'form.passback'} ne '') { - $chosen = &unescape($env{'form.passback'}); - ($linkuri,$linkprotector,$scope) = split("\0",$chosen); - ($launchsymb,$appname,$setter) = &get_passback_launcher($cdom,$cnum,$chosen); - } - if ($launchsymb ne '') { - $request->print(&launcher_info_box($launchsymb,$appname,$setter,$linkuri,$scope)); - } - my $error; - if ($perm{'mgr'}) { - if ($launchsymb ne '') { - my @poss_students = &Apache::loncommon::get_env_multiple('form.stuinfo'); - if (@poss_students) { - my %possibles; - foreach my $item (@poss_students) { - my ($stuname,$studom) = split(/:/,$item,3); - $possibles{$stuname.':'.$studom} = 1; - } - my ($sections,$groups,$group_display,$disabled) = §ions_and_groups(); - my ($classlist,undef,$fullname,$pbinfo) = - &getclasslist($sections,'1',$groups,'','','',$chosen,\%possibles); - if ((ref($classlist) eq 'HASH') && (ref($pbinfo) eq 'HASH')) { - my %passback = %{$pbinfo}; - my (%tosend,%remotenotok,%scorenotok,%zeroposs,%nopbinfo); - foreach my $possible (keys(%possibles)) { - if ((exists($classlist->{$possible})) && - (exists($passback{$possible})) && (ref($passback{$possible}) eq 'ARRAY')) { - $tosend{$possible} = 1; - } - } - if (keys(%tosend)) { - my ($lti_in_use,$crsdef); - my ($ltinum,$ltitype) = ($linkprotector =~ /^(\d+)(c|d)$/); - if ($ltitype eq 'c') { - my %crslti = &Apache::lonnet::get_course_lti($cnum,$cdom,'provider'); - $lti_in_use = $crslti{$ltinum}; - $crsdef = 1; - } else { - my %domlti = &Apache::lonnet::get_domain_lti($cdom,'linkprot'); - $lti_in_use = $domlti{$ltinum}; - } - if (ref($lti_in_use) eq 'HASH') { - my $msgformat = $lti_in_use->{'passbackformat'}; - my $keynum = $lti_in_use->{'cipher'}; - my $scoretype = 'decimal'; - if ($lti_in_use->{'scoreformat'} =~ /^(decimal|ratio|percentage)$/) { - $scoretype = $1; - } - my $pbmap; - if ($launchsymb =~ /\.(page|sequence)$/) { - $pbmap = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($launchsymb))[2]); - } else { - $pbmap = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($launchsymb))[0]); - } - $pbmap = &Apache::lonnet::clutter($pbmap); - my $pbscope; - if ($scope eq 'res') { - $pbscope = 'resource'; - } elsif ($scope eq 'map') { - $pbscope = 'nonrec'; - } elsif ($scope eq 'rec') { - $pbscope = 'map'; - } - my %pb = &common_passback_info(); - my $numstudents = scalar(keys(%tosend)); - my %prog_state = &Apache::lonhtmlcommon::Create_PrgWin($request,$numstudents); - my $outcome = &Apache::loncommon::start_data_table(). - &Apache::loncommon::start_data_table_header_row(); - my $loop = 0; - while ($loop < 2) { - $outcome .= '<th>'.&mt('No.').'</th>'. - '<th>'.&nameUserString('header').' '.&mt('Section/Group').'</th>'. - '<th>'.&mt('Score').'</th>'; - $loop++; - } - $outcome .= &Apache::loncommon::end_data_table_header_row()."\n"; - my $ctr=0; - foreach my $student (sort - { - if (lc($$fullname{$a}) ne lc($$fullname{$b})) { - return (lc($$fullname{$a}) cmp lc($$fullname{$b})); - } - return $a cmp $b; - } (keys(%$fullname))) { - next unless ($tosend{$student}); - my ($uname,$udom) = split(/:/,$student); - &Apache::lonhtmlcommon::Increment_PrgWin($request,\%prog_state,'last student'); - my ($uname,$udom) = split(/:/,$student); - my $uhome = &Apache::lonnet::homeserver($uname,$udom), - my $id = $passback{$student}[0], - my $url = $passback{$student}[1], - my ($total,$possible,$usec); - if (ref($classlist->{$student}) eq 'ARRAY') { - $usec = $classlist->{$student}->[&Apache::loncoursedata::CL_SECTION]; - } - if ($pbscope eq 'resource') { - $total = 0; - $possible = 0; - my $navmap = Apache::lonnavmaps::navmap->new($uname,$udom); - if (ref($navmap)) { - my $res = $navmap->getBySymb($launchsymb); - if (ref($res)) { - my $partlist = $res->parts(); - if (ref($partlist) eq 'ARRAY') { - my %record = &Apache::lonnet::restore($launchsymb,$env{'request.course.id'},$udom,$uname); - foreach my $part (@{$partlist}) { - next if ($record{"resource.$part.solved"} =~/^excused/); - my $weight = &Apache::lonnet::EXT("resource.$part.weight",$launchsymb,$udom,$uname,$usec); - $possible += $weight; - if (($record{'version'}) && (exists($record{"resource.$part.awarded"}))) { - my $awarded = $record{"resource.$part.awarded"}; - if ($awarded) { - $total += $weight * $awarded; - } - } - } - } - } - } - } elsif (($pbscope eq 'map') || ($pbscope eq 'nonrec')) { - ($total,$possible) = - &Apache::lonhomework::get_lti_score($uname,$udom,$usec,$pbmap,$pbscope); - } - if (($id ne '') && ($url ne '') && ($possible)) { - my ($sent,$score,$code,$result) = - &LONCAPA::ltiutils::send_grade($cdom,$cnum,$crsdef,$pb{'type'},$ltinum,$keynum,$id, - $url,$scoretype,$pb{'sigmethod'},$msgformat,$total,$possible); - my $no_passback; - if ($sent) { - if ($code == 200) { - delete($tosend{$student}); - my $namespace = $cdom.'_'.$cnum.'_lp_passback'; - my $store = { - 'score' => $score, - 'ip' => $pb{'ip'}, - 'host' => $pb{'lonhost'}, - 'protector' => $linkprotector, - 'deeplink' => $linkuri, - 'scope' => $scope, - 'url' => $url, - 'id' => $id, - '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($linkuri).':'.$uname.':'.$udom.':EXPORT:'.$value); - &Apache::lonnet::store_userdata({'score' => $score},$chosen,$namespace,$udom,$uname,$pb{'ip'}); - $ctr++; - if ($ctr%2 ==1) { - $outcome .= &Apache::loncommon::start_data_table_row(); - } - my $group = $classlist->{$student}->[&Apache::loncoursedata::CL_GROUP()]; - $outcome .= '<td align="right">'.$ctr.' </td>'. - '<td>'.&nameUserString(undef,$$fullname{$student},$uname,$udom). - ' '.$usec.($group ne '' ?'/'.$group:'').'</td>'. - '<td>'.$score.'</td>'."\n"; - if ($ctr%2 ==0) { - $outcome .= &Apache::loncommon::end_data_table_row()."\n"; - } - } else { - $remotenotok{$student} = 1; - $no_passback = "Passback response for ".$linkprotector." was $code ($result)"; - &Apache::lonnet::logthis($no_passback." for $uname:$udom in ${cdom}_${cnum}"); - } - } else { - $scorenotok{$student} = 1; - $no_passback = "Passback of grades not sent for ".$linkprotector; - &Apache::lonnet::logthis($no_passback." for $uname:$udom in ${cdom}_${cnum}"); - } - if ($no_passback) { - &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 = { - $key => { - 'ltinum' => $ltinum, - 'lti' => $lti_in_use, - 'crsdef' => $crsdef, - 'cid' => $cdom.'_'.$cnum, - 'uname' => $uname, - 'udom' => $udom, - 'uhome' => $uhome, - 'pbid' => $id, - 'pburl' => $url, - 'pbtype' => $pb{'type'}, - 'pbscope' => $pbscope, - 'pbmap' => $pbmap, - 'pbsymb' => $launchsymb, - 'format' => $scoretype, - 'scope' => $scope, - 'clientip' => $pb{'clientip'}, - 'linkprot' => $linkprotector.':'.$linkuri, - 'total' => $total, - 'possible' => $possible, - 'score' => $score, - }, - }; - &Apache::lonnet::put('linkprot_passback_pending',$ltigrade,$cdom,$cnum); - } - } else { - if (($id ne '') && ($url ne '')) { - $zeroposs{$student} = 1; - } else { - $nopbinfo{$student} = 1; - } - } - } - &Apache::lonhtmlcommon::Close_PrgWin($request,\%prog_state); - if ($ctr%2 ==1) { - $outcome .= &Apache::loncommon::end_data_table_row(); - } - $outcome .= &Apache::loncommon::end_data_table(); - if ($ctr) { - $request->print('<p><br />'.&mt('Scores sent to launcher CMS').'</p>'. - '<p>'.$outcome.'</p>'); - } else { - $request->print('<p>'.&mt('No scores sent to launcher CMS').'</p>'); - } - if (keys(%tosend)) { - $request->print('<p>'.&mt('No scores sent for following')); - my ($zeros,$nopbcreds,$noconfirm,$noscore); - foreach my $student (sort - { - if (lc($$fullname{$a}) ne lc($$fullname{$b})) { - return (lc($$fullname{$a}) cmp lc($$fullname{$b})); - } - return $a cmp $b; - } (keys(%$fullname))) { - next unless ($tosend{$student}); - my ($uname,$udom) = split(/:/,$student); - my $line = '<li>'.&nameUserString(undef,$$fullname{$student},$uname,$udom).'</li>'."\n"; - if ($zeroposs{$student}) { - $zeros .= $line; - } elsif ($nopbinfo{$student}) { - $nopbcreds .= $line; - } elsif ($remotenotok{$student}) { - $noconfirm .= $line; - } elsif ($scorenotok{$student}) { - $noscore .= $line; - } - } - if ($zeros) { - $request->print('<br />'.&mt('Total points possible was 0').':'. - '<ul>'.$zeros.'</ul><br />'); - } - if ($nopbcreds) { - $request->print('<br />'.&mt('Missing unique identifier and/or passback location').':'. - '<ul>'.$nopbcreds.'</ul><br />'); - } - if ($noconfirm) { - $request->print('<br />'.&mt('Score receipt not confirmed by receiving CMS').':'. - '<ul>'.$noconfirm.'</ul><br />'); - } - if ($noscore) { - $request->print('<br />'.&mt('Score computation or transmission failed').':'. - '<ul>'.$noscore.'</ul><br />'); - } - $request->print('</p>'); - } - } else { - $error = &mt('Settings for deep-link launch target unavailable, so no scores were sent'); - } - } else { - $error = &mt('No available students for whom scores can be sent.'); - } - } else { - $error = &mt('Classlist could not be retrieved so no scores were sent.'); - } - } else { - $error = &mt('No students selected to receive scores so none were sent.'); - } - } else { - if ($env{'form.passback'}) { - $error = &mt('Deep-link launch target was invalid so no scores were sent.'); - } else { - $error = &mt('Deep-link launch target was missing so no scores were sent.'); - } - } - } else { - $error = &mt('You do not have permission to manage grades, so no scores were sent'); - } - if ($error) { - $request->print('<p class="LC_info">'.$error.'</p>'); - } - return; -} - -sub get_passback_launcher { - my ($cdom,$cnum,$chosen) = @_; - my ($linkuri,$linkprotector,$scope) = split("\0",$chosen); - my ($ltinum,$ltitype) = ($linkprotector =~ /^(\d+)(c|d)$/); - my ($appname,$setter); - if ($ltitype eq 'c') { - my %lti = &Apache::lonnet::get_course_lti($cnum,$cdom,'provider'); - if (ref($lti{$ltinum}) eq 'HASH') { - $appname = $lti{$ltinum}{'name'}; - if ($appname) { - $setter = ' (defined in course)'; - } - } - } elsif ($ltitype eq 'd') { - my %lti = &Apache::lonnet::get_domain_lti($cdom,'linkprot'); - if (ref($lti{$ltinum}) eq 'HASH') { - $appname = $lti{$ltinum}{'name'}; - if ($appname) { - $setter = ' (defined in domain)'; - } - } - } - my $launchsymb = &Apache::loncommon::symb_from_tinyurl($linkuri,$cnum,$cdom); - if ($launchsymb eq '') { - my %passback = &Apache::lonnet::dump('nohist_linkprot_passback',$cdom,$cnum); - foreach my $poss_symb (keys(%passback)) { - if (ref($passback{$poss_symb}) eq 'HASH') { - if (exists($passback{$poss_symb}{$chosen})) { - $launchsymb = $poss_symb; - last; - } - } - } - 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 (); -} - -sub sections_and_groups { - my (@sections,@groups,$group_display); - @groups = &Apache::loncommon::get_env_multiple('form.group'); - if (grep(/^all$/,@groups)) { - @groups = ('all'); - $group_display = 'all'; - } elsif (grep(/^none$/,@groups)) { - @groups = ('none'); - $group_display = 'none'; - } elsif (@groups > 0) { - $group_display = join(', ',@groups); - } - if ($env{'request.course.sec'} ne '') { - @sections = ($env{'request.course.sec'}); - } else { - @sections = &Apache::loncommon::get_env_multiple('form.section'); - } - my $disabled = ' disabled="disabled"'; - if ($perm{'mgr'}) { - if (grep(/^all$/,@sections)) { - undef($disabled); - } else { - foreach my $sec (@sections) { - if (&canmodify($sec)) { - undef($disabled); - last; - } - } - } - } - if (grep(/^all$/,@sections)) { - @sections = ('all'); - } - return(\@sections,\@groups,$group_display,$disabled); -} - -sub launcher_info_box { - my ($launcher,$appname,$setter,$linkuri,$scope) = @_; - my $shownscope; - if ($scope eq 'res') { - $shownscope = &mt('Resource'); - } elsif ($scope eq 'map') { - $shownscope = &mt('Folder'); - } elsif ($scope eq 'rec') { - $shownscope = &mt('Folder + sub-folders'); - } - return '<p>'. - &Apache::lonhtmlcommon::start_pick_box(). - &Apache::lonhtmlcommon::row_title(&mt('Launch Item Title')). - &Apache::lonnet::gettitle($launcher). - &Apache::lonhtmlcommon::row_closure(). - &Apache::lonhtmlcommon::row_title(&mt('Deep-link')). - $linkuri. - &Apache::lonhtmlcommon::row_closure(). - &Apache::lonhtmlcommon::row_title(&mt('Launcher')). - $appname.' '.$setter. - &Apache::lonhtmlcommon::row_closure(). - &Apache::lonhtmlcommon::row_title(&mt('Score Type')). - $shownscope. - &Apache::lonhtmlcommon::row_closure(1). - &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::store_userdata({'score' => $score},$launcher,$namespace,$udom,$uname,$pb{'ip'}); - } 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. #--- Called from the Grading Menu - View/Grade an individual student #--- Also called directly when one clicks on the subm button @@ -1939,7 +1037,6 @@ sub common_passback_info { sub listStudents { my ($request,$symb,$submitonly,$divforres) = @_; - my $is_tool = ($symb =~ /ext\.tool$/); my $cdom = $env{"course.$env{'request.course.id'}.domain"}; my $cnum = $env{"course.$env{'request.course.id'}.num"}; my $getsec = $env{'form.section'} eq '' ? 'all' : $env{'form.section'}; @@ -1963,8 +1060,34 @@ sub listStudents { } } - $request->print(&checkselect_js()); + my %js_lt = &Apache::lonlocal::texthash ( + 'multiple' => 'Please select a student or group of students before clicking on the Next button.', + 'single' => 'Please select the student before clicking on the Next button.', + ); + &js_escape(\%js_lt); $request->print(&Apache::lonhtmlcommon::scripttag(<<LISTJAVASCRIPT)); + function checkSelect(checkBox) { + var ctr=0; + var sense=""; + if (checkBox.length > 1) { + for (var i=0; i<checkBox.length; i++) { + if (checkBox[i].checked) { + ctr++; + } + } + sense = '$js_lt{'multiple'}'; + } else { + if (checkBox.checked) { + ctr = 1; + } + sense = '$js_lt{'single'}'; + } + if (ctr == 0) { + alert(sense); + return false; + } + document.gradesub.submit(); + } function reLoadList(formname) { if (formname.saveStatusOld.value == pullDownSelection(formname.Status)) {return;} @@ -1980,38 +1103,26 @@ LISTJAVASCRIPT "\n".$table; $gradeTable .= &Apache::lonhtmlcommon::start_pick_box(); - unless ($is_tool) { - $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Problem Text')) - .'<label><input type="radio" name="vProb" value="no" checked="checked" /> '.&mt('no').' </label>'."\n" - .'<label><input type="radio" name="vProb" value="yes" /> '.&mt('one student').' </label>'."\n" - .'<label><input type="radio" name="vProb" value="all" /> '.&mt('all students').' </label><br />'."\n" - .&Apache::lonhtmlcommon::row_closure(); - $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Answer')) - .'<label><input type="radio" name="vAns" value="no" /> '.&mt('no').' </label>'."\n" - .'<label><input type="radio" name="vAns" value="yes" /> '.&mt('one student').' </label>'."\n" - .'<label><input type="radio" name="vAns" value="all" checked="checked" /> '.&mt('all students').' </label><br />'."\n" - .&Apache::lonhtmlcommon::row_closure(); - } + $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Problem Text')) + .'<label><input type="radio" name="vProb" value="no" checked="checked" /> '.&mt('no').' </label>'."\n" + .'<label><input type="radio" name="vProb" value="yes" /> '.&mt('one student').' </label>'."\n" + .'<label><input type="radio" name="vProb" value="all" /> '.&mt('all students').' </label><br />'."\n" + .&Apache::lonhtmlcommon::row_closure(); + $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Answer')) + .'<label><input type="radio" name="vAns" value="no" /> '.&mt('no').' </label>'."\n" + .'<label><input type="radio" name="vAns" value="yes" /> '.&mt('one student').' </label>'."\n" + .'<label><input type="radio" name="vAns" value="all" checked="checked" /> '.&mt('all students').' </label><br />'."\n" + .&Apache::lonhtmlcommon::row_closure(); my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status')); my $saveStatus = $stu_status eq '' ? 'Active' : $stu_status; $env{'form.Status'} = $saveStatus; - my %optiontext; - if ($is_tool) { - %optiontext = &Apache::lonlocal::texthash ( - lastonly => 'last transaction', - last => 'last transaction with details', - datesub => 'all transactions', - all => 'all transactions with details', - ); - } else { - %optiontext = &Apache::lonlocal::texthash ( + my %optiontext = &Apache::lonlocal::texthash ( lastonly => 'last submission', last => 'last submission with details', datesub => 'all submissions', all => 'all submissions with details', ); - } my $submission_options = '<span class="LC_nobreak">'. '<label><input type="radio" name="lastSub" value="lastonly" /> '. @@ -2025,19 +1136,13 @@ LISTJAVASCRIPT '<span class="LC_nobreak">'. '<label><input type="radio" name="lastSub" value="all" /> '. $optiontext{'all'}.'</label></span>'; - my $viewtitle; - if ($is_tool) { - $viewtitle = &mt('View Transactions'); - } else { - $viewtitle = &mt('View Submissions'); - } my ($compmsg,$nocompmsg); $nocompmsg = ' checked="checked"'; if ($numessay) { $compmsg = $nocompmsg; $nocompmsg = ''; } - $gradeTable .= &Apache::lonhtmlcommon::row_title($viewtitle) + $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Submissions')) .$submission_options; # Check if any gradable my $showmore; @@ -2102,14 +1207,9 @@ LISTJAVASCRIPT } $gradeTable .= &Apache::lonhtmlcommon::row_closure(1) .&Apache::lonhtmlcommon::end_pick_box(); - my $regrademsg; - if ($is_tool) { - $regrademsg =&mt("To view/grade/regrade, click on the check box(es) next to the student's name(s). Then click on the Next button."); - } else { - $regrademsg = &mt("To view/grade/regrade 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."); - } + $gradeTable .= '<p>' - .$regrademsg."\n" + .&mt("To view/grade/regrade 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.")."\n" .'<input type="hidden" name="command" value="processGroup" />' .'</p>'; @@ -2252,55 +1352,7 @@ LISTJAVASCRIPT return ''; } -#---- Called from the listStudents and the names_for_passback routines. - -sub checkselect_js { - my ($formname) = @_; - if ($formname eq '') { - $formname = 'gradesub'; - } - my %js_lt; - if ($formname eq 'passbackusers') { - %js_lt = &Apache::lonlocal::texthash ( - 'multiple' => 'Please select a student or group of students before pushing the Save Scores button.', - 'single' => 'Please select the student before pushing the Save Scores button.', - ); - } else { - %js_lt = &Apache::lonlocal::texthash ( - 'multiple' => 'Please select a student or group of students before clicking on the Next button.', - 'single' => 'Please select the student before clicking on the Next button.', - ); - } - &js_escape(\%js_lt); - return &Apache::lonhtmlcommon::scripttag(<<LISTJAVASCRIPT); - - function checkSelect(checkBox) { - var ctr=0; - var sense=""; - var len = checkBox.length; - if (len == undefined) len = 1; - if (len > 1) { - for (var i=0; i<len; i++) { - if (checkBox[i].checked) { - ctr++; - } - } - sense = '$js_lt{'multiple'}'; - } else { - if (checkBox.checked) { - ctr = 1; - } - sense = '$js_lt{'single'}'; - } - if (ctr == 0) { - alert(sense); - return false; - } - document.$formname.submit(); - } -LISTJAVASCRIPT - -} +#---- Called from the listStudents routine sub check_script { my ($form,$type) = @_; @@ -2592,6 +1644,7 @@ INNERJS my $end_page_msg_central = &Apache::loncommon::end_page({'js_ready' => 1}); + my $docopen=&Apache::lonhtmlcommon::javascript_docopen(); $docopen=~s/^document\.//; @@ -3228,7 +2281,6 @@ sub submission { if ($symb eq '') { $request->print("Unable to handle ambiguous references:."); return ''; } my $probtitle=&Apache::lonnet::gettitle($symb); - my $is_tool = ($symb =~ /ext\.tool$/); my ($essayurl,%coursedesc_by_cid); if (!&canview($usec)) { @@ -3250,10 +2302,8 @@ sub submission { } if (!$env{'form.lastSub'}) { $env{'form.lastSub'} = 'datesub'; } - unless ($is_tool) { - if (!$env{'form.vProb'}) { $env{'form.vProb'} = 'yes'; } - if (!$env{'form.vAns'}) { $env{'form.vAns'} = 'yes'; } - } + if (!$env{'form.vProb'}) { $env{'form.vProb'} = 'yes'; } + if (!$env{'form.vAns'}) { $env{'form.vAns'} = 'yes'; } if (($numessay) && ($calledby eq 'submission') && (!exists($env{'form.compmsg'}))) { $env{'form.compmsg'} = 1; } @@ -3446,15 +2496,11 @@ sub submission { # Display student info $request->print(($counter == 0 ? '' : '<br />')); - my $boxtitle = &mt('Submissions'); - if ($is_tool) { - $boxtitle = &mt('Transactions') - } my $result='<div class="LC_Box">' - .'<h3 class="LC_hcell">'.$boxtitle.'</h3>'; + .'<h3 class="LC_hcell">'.&mt('Submissions').'</h3>'; $result.='<input type="hidden" name="name'.$counter. '" value="'.$env{'form.fullname'}.'" />'."\n"; - if (($numresp > $numessay) && !$is_tool) { + if ($numresp > $numessay) { $result.='<p class="LC_info">' .&mt('Part(s) graded correct by the computer is marked with a [_1] symbol.',$checkIcon) ."</p>\n"; @@ -3477,12 +2523,176 @@ sub submission { # (3) All transactions (by date) # (4) The whole record (with detailed information for all transactions) - my ($lastsubonly,$partinfo) = - &show_last_submission($uname,$udom,$symb,$essayurl,$responseType,$env{'form.lastSub'}, - $is_tool,$fullname,\%record,\%coursedesc_by_cid); - $request->print($partinfo); - $request->print($lastsubonly); + my ($string,$timestamp,$lastgradetime,$lastsubmittime) = + &get_last_submission(\%record); + + my $lastsubonly; + if ($timestamp eq '') { + $lastsubonly.='<div class="LC_grade_submissions_body">'.$string->[0].'</div>'; + } else { + my ($shownsubmdate,$showngradedate); + if ($lastsubmittime && $lastgradetime) { + $shownsubmdate = &Apache::lonlocal::locallocaltime($lastsubmittime); + if ($lastgradetime > $lastsubmittime) { + $showngradedate = &Apache::lonlocal::locallocaltime($lastgradetime); + } + } else { + $shownsubmdate = $timestamp; + } + $lastsubonly = + '<div class="LC_grade_submissions_body">' + .'<b>'.&mt('Date Submitted:').'</b> '.$shownsubmdate."\n"; + if ($showngradedate) { + $lastsubonly .= '<br /><b>'.&mt('Date Graded:').'</b> '.$showngradedate."\n"; + } + + my %seenparts; + my @part_response_id = &flatten_responseType($responseType); + foreach my $part (@part_response_id) { + my ($partid,$respid) = @{ $part }; + my $display_part=&get_display_part($partid,$symb); + if ($env{"form.$uname:$udom:$partid:submitted_by"}) { + if (exists($seenparts{$partid})) { next; } + $seenparts{$partid}=1; + $request->print( + '<b>'.&mt('Part: [_1]',$display_part).'</b>'. + ' <b>'.&mt('Collaborative submission by: [_1]', + '<a href="javascript:viewSubmitter(\''. + $env{"form.$uname:$udom:$partid:submitted_by"}. + '\');" target="_self">'. + $$fullname{$env{"form.$uname:$udom:$partid:submitted_by"}}.'</a>'). + '<br />'); + next; + } + my $responsetype = $responseType->{$partid}->{$respid}; + if (!exists($record{"resource.$partid.$respid.submission"})) { + $lastsubonly.="\n".'<div class="LC_grade_submission_part">'. + '<b>'.&mt('Part: [_1]',$display_part).'</b>'. + ' <span class="LC_internal_info">'. + '('.&mt('Response ID: [_1]',$respid).')'. + '</span> '. + '<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br /><br /></div>'; + next; + } + foreach my $submission (@$string) { + my ($partid,$respid) = ($submission =~ /^resource\.([^\.]*)\.([^\.]*)\.submission/); + if (join('_',@{$part}) ne ($partid.'_'.$respid)) { next; } + my ($ressub,$hide,$draft,$subval) = split(/:/,$submission,4); + # Similarity check + my $similar=''; + my ($type,$trial,$rndseed); + if ($hide eq 'rand') { + $type = 'randomizetry'; + $trial = $record{"resource.$partid.tries"}; + $rndseed = $record{"resource.$partid.rndseed"}; + } + if ($env{'form.checkPlag'}) { + my ($oname,$odom,$ocrsid,$oessay,$osim)= + &most_similar($uname,$udom,$symb,$subval); + if ($osim) { + $osim=int($osim*100.0); + if ($hide eq 'anon') { + $similar='<hr /><span class="LC_warning">'.&mt("Essay was found to be similar to another essay submitted for this assignment.").'<br />'. + &mt('As the current submission is for an anonymous survey, no other details are available.').'</span><hr />'; + } else { + $similar='<hr />'; + if ($essayurl eq 'lib/templates/simpleproblem.problem') { + $similar .= '<h3><span class="LC_warning">'. + &mt('Essay is [_1]% similar to an essay by [_2]', + $osim, + &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')'). + '</span></h3>'; + } elsif ($ocrsid ne '') { + my %old_course_desc; + if (ref($coursedesc_by_cid{$ocrsid}) eq 'HASH') { + %old_course_desc = %{$coursedesc_by_cid{$ocrsid}}; + } else { + my $args; + if ($ocrsid ne $env{'request.course.id'}) { + $args = {'one_time' => 1}; + } + %old_course_desc = + &Apache::lonnet::coursedescription($ocrsid,$args); + $coursedesc_by_cid{$ocrsid} = \%old_course_desc; + } + $similar .= + '<h3><span class="LC_warning">'. + &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])', + $osim, + &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')', + $old_course_desc{'description'}, + $old_course_desc{'num'}, + $old_course_desc{'domain'}). + '</span></h3>'; + } else { + $similar .= + '<h3><span class="LC_warning">'. + &mt('Essay is [_1]% similar to an essay by [_2] in an unknown course', + $osim, + &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')'). + '</span></h3>'; + } + $similar .= '<blockquote><i>'. + &keywords_highlight($oessay). + '</i></blockquote><hr />'; + } + } + } + my $order=&get_order($partid,$respid,$symb,$uname,$udom, + undef,$type,$trial,$rndseed); + if (($env{'form.lastSub'} eq 'lastonly') || + ($env{'form.lastSub'} eq 'datesub') || + ($env{'form.lastSub'} =~ /^(last|all)$/)) { + my $display_part=&get_display_part($partid,$symb); + $lastsubonly.='<div class="LC_grade_submission_part">'. + '<b>'.&mt('Part: [_1]',$display_part).'</b>'. + ' <span class="LC_internal_info">'. + '('.&mt('Response ID: [_1]',$respid).')'. + '</span> '; + my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record); + if (@$files) { + if ($hide eq 'anon') { + $lastsubonly.='<br />'.&mt('[quant,_1,file] uploaded to this anonymous survey',scalar(@{$files})); + } else { + $lastsubonly.='<br /><br />'.'<b>'.&mt('Submitted Files:').'</b>' + .'<br /><span class="LC_warning">'; + if(@$files == 1) { + $lastsubonly .= &mt('Like all files provided by users, this file may contain viruses!'); + } else { + $lastsubonly .= &mt('Like all files provided by users, these files may contain viruses!'); + } + $lastsubonly .= '</span>'; + foreach my $file (@$files) { + &Apache::lonnet::allowuploaded('/adm/grades',$file); + $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0" alt="" /> '.$file.'</a>'; + } + } + $lastsubonly.='<br />'; + } + if ($hide eq 'anon') { + $lastsubonly.='<br /><b>'.&mt('Anonymous Survey').'</b>'; + } else { + $lastsubonly.='<br /><b>'.&mt('Submitted Answer:').' </b>'; + if ($draft) { + $lastsubonly.= ' <span class="LC_warning">'.&mt('Draft Copy').'</span>'; + } + $subval = + &cleanRecord($subval,$responsetype,$symb,$partid, + $respid,\%record,$order,undef,$uname,$udom,$type,$trial,$rndseed); + if ($responsetype eq 'essay') { + $subval =~ s{\n}{<br />}g; + } + $lastsubonly.=$subval."\n"; + } + if ($similar) {$lastsubonly.="<br /><br />$similar\n";} + $lastsubonly.='</div>'; + } + } + } + $lastsubonly.='</div>'."\n"; # End: LC_grade_submissions_body + } + $request->print($lastsubonly); if ($env{'form.lastSub'} eq 'datesub') { my ($parts,$handgrade,$responseType) = &response_type($symb,\$res_error); $request->print(&displaySubByDates($symb,\%record,$parts,$responseType,$checkIcon,$uname,$udom)); @@ -3535,12 +2745,7 @@ sub submission { my %seen = (); my @partlist; my @gradePartRespid; - my @part_response_id; - if ($is_tool) { - @part_response_id = ([0,'']); - } else { - @part_response_id = &flatten_responseType($responseType); - } + my @part_response_id = &flatten_responseType($responseType); $request->print( '<div class="LC_Box">' .'<h3 class="LC_hcell">'.&mt('Assign Grades').'</h3>' @@ -3606,186 +2811,6 @@ sub submission { return ''; } -sub show_last_submission { - my ($uname,$udom,$symb,$essayurl,$responseType,$viewtype,$is_tool,$fullname, - $record,$coursedesc_by_cid) = @_; - my ($string,$timestamp,$lastgradetime,$lastsubmittime) = - &get_last_submission($record,$is_tool); - - my ($lastsubonly,$partinfo); - if ($timestamp eq '') { - $lastsubonly.='<div class="LC_grade_submissions_body">'.$string->[0].'</div>'; - } elsif ($is_tool) { - $lastsubonly = - '<div class="LC_grade_submissions_body">' - .'<b>'.&mt('Date Grade Passed Back:').'</b> '.$timestamp."</div>\n"; - } else { - my ($shownsubmdate,$showngradedate); - if ($lastsubmittime && $lastgradetime) { - $shownsubmdate = &Apache::lonlocal::locallocaltime($lastsubmittime); - if ($lastgradetime > $lastsubmittime) { - $showngradedate = &Apache::lonlocal::locallocaltime($lastgradetime); - } - } else { - $shownsubmdate = $timestamp; - } - $lastsubonly = - '<div class="LC_grade_submissions_body">' - .'<b>'.&mt('Date Submitted:').'</b> '.$shownsubmdate."\n"; - if ($showngradedate) { - $lastsubonly .= '<br /><b>'.&mt('Date Graded:').'</b> '.$showngradedate."\n"; - } - - my %seenparts; - my @part_response_id = &flatten_responseType($responseType); - foreach my $part (@part_response_id) { - my ($partid,$respid) = @{ $part }; - my $display_part=&get_display_part($partid,$symb); - if ($env{"form.$uname:$udom:$partid:submitted_by"}) { - if (exists($seenparts{$partid})) { next; } - $seenparts{$partid}=1; - $partinfo .= - '<b>'.&mt('Part: [_1]',$display_part).'</b>'. - ' <b>'.&mt('Collaborative submission by: [_1]', - '<a href="javascript:viewSubmitter(\''. - $env{"form.$uname:$udom:$partid:submitted_by"}. - '\');" target="_self">'. - $$fullname{$env{"form.$uname:$udom:$partid:submitted_by"}}.'</a>'). - '<br />'; - next; - } - my $responsetype = $responseType->{$partid}->{$respid}; - if (!exists($record->{"resource.$partid.$respid.submission"})) { - $lastsubonly.="\n".'<div class="LC_grade_submission_part">'. - '<b>'.&mt('Part: [_1]',$display_part).'</b>'. - ' <span class="LC_internal_info">'. - '('.&mt('Response ID: [_1]',$respid).')'. - '</span> '. - '<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br /><br /></div>'; - next; - } - foreach my $submission (@$string) { - my ($partid,$respid) = ($submission =~ /^resource\.([^\.]*)\.([^\.]*)\.submission/); - if (join('_',@{$part}) ne ($partid.'_'.$respid)) { next; } - my ($ressub,$hide,$draft,$subval) = split(/:/,$submission,4); - # Similarity check - my $similar=''; - my ($type,$trial,$rndseed); - if ($hide eq 'rand') { - $type = 'randomizetry'; - $trial = $record->{"resource.$partid.tries"}; - $rndseed = $record->{"resource.$partid.rndseed"}; - } - if ($env{'form.checkPlag'}) { - my ($oname,$odom,$ocrsid,$oessay,$osim)= - &most_similar($uname,$udom,$symb,$subval); - if ($osim) { - $osim=int($osim*100.0); - if ($hide eq 'anon') { - $similar='<hr /><span class="LC_warning">'.&mt("Essay was found to be similar to another essay submitted for this assignment.").'<br />'. - &mt('As the current submission is for an anonymous survey, no other details are available.').'</span><hr />'; - } else { - $similar='<hr />'; - if ($essayurl eq 'lib/templates/simpleproblem.problem') { - $similar .= '<h3><span class="LC_warning">'. - &mt('Essay is [_1]% similar to an essay by [_2]', - $osim, - &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')'). - '</span></h3>'; - } else { - my %old_course_desc; - if ($ocrsid ne '') { - if (ref($coursedesc_by_cid->{$ocrsid}) eq 'HASH') { - %old_course_desc = %{$coursedesc_by_cid->{$ocrsid}}; - } else { - my $args; - if ($ocrsid ne $env{'request.course.id'}) { - $args = {'one_time' => 1}; - } - %old_course_desc = - &Apache::lonnet::coursedescription($ocrsid,$args); - $coursedesc_by_cid->{$ocrsid} = \%old_course_desc; - } - $similar .= - '<h3><span class="LC_warning">'. - &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])', - $osim, - &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')', - $old_course_desc{'description'}, - $old_course_desc{'num'}, - $old_course_desc{'domain'}). - '</span></h3>'; - } else { - $similar .= - '<h3><span class="LC_warning">'. - &mt('Essay is [_1]% similar to an essay by [_2] in an unknown course', - $osim, - &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')'). - '</span></h3>'; - } - } - $similar .= '<blockquote><i>'. - &keywords_highlight($oessay). - '</i></blockquote><hr />'; - } - } - } - my $order=&get_order($partid,$respid,$symb,$uname,$udom, - undef,$type,$trial,$rndseed); - if (($viewtype eq 'lastonly') || - ($viewtype eq 'datesub') || - ($viewtype =~ /^(last|all)$/)) { - my $display_part=&get_display_part($partid,$symb); - $lastsubonly.='<div class="LC_grade_submission_part">'. - '<b>'.&mt('Part: [_1]',$display_part).'</b>'. - ' <span class="LC_internal_info">'. - '('.&mt('Response ID: [_1]',$respid).')'. - '</span> '; - my $files=&get_submitted_files($udom,$uname,$partid,$respid,$record); - if (@$files) { - if ($hide eq 'anon') { - $lastsubonly.='<br />'.&mt('[quant,_1,file] uploaded to this anonymous survey',scalar(@{$files})); - } else { - $lastsubonly.='<br /><br />'.'<b>'.&mt('Submitted Files:').'</b>' - .'<br /><span class="LC_warning">'; - if(@$files == 1) { - $lastsubonly .= &mt('Like all files provided by users, this file may contain viruses!'); - } else { - $lastsubonly .= &mt('Like all files provided by users, these files may contain viruses!'); - } - $lastsubonly .= '</span>'; - foreach my $file (@$files) { - &Apache::lonnet::allowuploaded('/adm/grades',$file); - $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0" alt="" /> '.$file.'</a>'; - } - } - $lastsubonly.='<br />'; - } - if ($hide eq 'anon') { - $lastsubonly.='<br /><b>'.&mt('Anonymous Survey').'</b>'; - } else { - $lastsubonly.='<br /><b>'.&mt('Submitted Answer:').' </b>'; - if ($draft) { - $lastsubonly.= ' <span class="LC_warning">'.&mt('Draft Copy').'</span>'; - } - $subval = - &cleanRecord($subval,$responsetype,$symb,$partid, - $respid,$record,$order,undef,$uname,$udom,$type,$trial,$rndseed); - if ($responsetype eq 'essay') { - $subval =~ s{\n}{<br />}g; - } - $lastsubonly.=$subval."\n"; - } - if ($similar) {$lastsubonly.="<br /><br />$similar\n";} - $lastsubonly.='</div>'; - } - } - } - $lastsubonly.='</div>'."\n"; # End: LC_grade_submissions_body - } - return ($lastsubonly,$partinfo); -} - sub check_collaborators { my ($symb,$uname,$udom,$record,$handgrade,$counter) = @_; my ($result,@col_fullnames); @@ -3844,7 +2869,7 @@ sub check_collaborators { #--- Retrieve the last submission for all the parts sub get_last_submission { - my ($returnhash,$is_tool)=@_; + my ($returnhash)=@_; my (@string,$timestamp,$lastgradetime,$lastsubmittime); if ($$returnhash{'version'}) { my %lasthash=(); @@ -3871,7 +2896,7 @@ sub get_last_submission { $prevsolved{$1} = $solved{$1}; $solved{$1} = $lasthash{$key}; } - } + } foreach my $partid (keys(%handgraded)) { if (($prevsolved{$partid} eq 'ungraded_attempted') && (($solved{$partid} eq 'incorrect_by_override') || @@ -3943,14 +2968,8 @@ sub get_last_submission { } } if (!@string) { - my $msg; - if ($is_tool) { - $msg = &mt('No grade passed back.'); - } else { - $msg = &mt('Nothing submitted - no attempts.'); - } $string[0] = - '<span class="LC_warning">'.$msg.'</span>'; + '<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span>'; } return (\@string,$timestamp,$lastgradetime,$lastsubmittime); } @@ -4178,13 +3197,11 @@ sub processHandGrade { } if ($button eq 'Save & Next') { - my %needpb = &passbacks_for_symb($cdom,$cnum,$symb); - my (%skip_passback,%pbsave,%pbcollab); my $ctr = 0; while ($ctr < $ngrade) { my ($uname,$udom) = split(/:/,$env{'form.unamedom'.$ctr}); my ($errorflag,$pts,$wgt,$numhidden) = - &saveHandGrade($request,$symb,$uname,$udom,$ctr,undef,undef,\%queueable,\%needpb,\%skip_passback,\%pbsave); + &saveHandGrade($request,$symb,$uname,$udom,$ctr,undef,undef,\%queueable); if ($errorflag eq 'no_score') { $ctr++; next; @@ -4237,77 +3254,28 @@ sub processHandGrade { foreach my $collabstr (@collabstrs) { my ($part,@collaborators) = split(/:/,$collabstr); foreach my $collaborator (@collaborators) { - my ($errorflag,$pts,$wgt,$numchg,$numupdate) = + my ($errorflag,$pts,$wgt) = &saveHandGrade($request,$symb,$collaborator,$udom,$ctr, $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 { - if ($numchg || $numupdate) { - $pbcollab{$collaborator}{$part} = [$pts,$wgt]; - } - if ($message ne '') { - my ($baseurl,$showsymb) = - &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); - } + } elsif ($message ne '') { + my ($baseurl,$showsymb) = + &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); } } } } $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 = (); @@ -4461,8 +3429,7 @@ sub processHandGrade { #---- Save the score and award for each student, if changed sub saveHandGrade { - my ($request,$symb,$stuname,$domain,$newflg,$submitter, - $part,$queueable,$needpb,$skip_passback,$pbsave) = @_; + my ($request,$symb,$stuname,$domain,$newflg,$submitter,$part,$queueable) = @_; my @version_parts; my $usec = &Apache::lonnet::getsection($domain,$stuname, $env{'request.course.id'}); @@ -4470,7 +3437,7 @@ sub saveHandGrade { my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$domain,$stuname); my @parts_graded; my %newrecord = (); - my ($pts,$wgt,$totchg,$sendupdate,$poss_pb) = ('','',0,0,0); + my ($pts,$wgt,$totchg) = ('','',0); my %aggregate = (); my $aggregateflag = 0; if ($env{'form.HIDE'.$newflg}) { @@ -4478,33 +3445,18 @@ sub saveHandGrade { my $numchgs = &makehidden($version,$parts,\%record,$symb,$domain,$stuname,1); $totchg += $numchgs; } - if ((ref($needpb) eq 'HASH') && (keys(%{$needpb}))) { - $poss_pb = 1; - } - my (%weights,%awardeds,%excuseds); my @parts = split(/:/,$env{'form.partlist'.$newflg}); foreach my $new_part (@parts) { - #collaborator ($submitter may vary for different parts) + #collaborator ($submi may vary for different parts if ($submitter && $new_part ne $part) { next; } my $dropMenu = $env{'form.GD_SEL'.$newflg.'_'.$new_part}; - if ($poss_pb) { - $weights{$symb}{$new_part} = - &Apache::lonnet::EXT('resource.'.$new_part.'.weight',$symb,$domain,$stuname); - } elsif ($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') { - $excuseds{$symb}{$new_part} = 1; - $awardeds{$symb}{$new_part} = ''; if ($record{'resource.'.$new_part.'.solved'} ne 'excused') { $newrecord{'resource.'.$new_part.'.solved'} = 'excused'; if (exists($record{'resource.'.$new_part.'.awarded'})) { $newrecord{'resource.'.$new_part.'.awarded'} = ''; } $newrecord{'resource.'.$new_part.'.regrader'}="$env{'user.name'}:$env{'user.domain'}"; - $sendupdate ++; } } elsif ($dropMenu eq 'reset status' && exists($record{'resource.'.$new_part.'.solved'})) { #don't bother if no old records -> no attempts @@ -4528,9 +3480,6 @@ sub saveHandGrade { &decrement_aggs($symb,$new_part,\%aggregate,$aggtries,$totaltries,$solvedstatus); $aggregateflag = 1; } - $sendupdate ++; - $excuseds{$symb}{$new_part} = ''; - $awardeds{$symb}{$new_part} = ''; } elsif ($dropMenu eq '') { $pts = ($env{'form.GD_BOX'.$newflg.'_'.$new_part} ne '' ? $env{'form.GD_BOX'.$newflg.'_'.$new_part} : @@ -4541,15 +3490,12 @@ sub saveHandGrade { $wgt = $env{'form.WGT'.$newflg.'_'.$new_part} eq '' ? 1 : $env{'form.WGT'.$newflg.'_'.$new_part}; my $partial= $pts/$wgt; - $awardeds{$symb}{$new_part} = $partial; - $excuseds{$symb}{$new_part} = ''; if ($partial eq $record{'resource.'.$new_part.'.awarded'}) { #do not update score for part if not changed. &handback_files($request,$symb,$stuname,$domain,$newflg,$new_part,\%newrecord); next; } else { push(@parts_graded,$new_part); - $sendupdate ++; } if ($record{'resource.'.$new_part.'.awarded'} ne $partial) { $newrecord{'resource.'.$new_part.'.awarded'} = $partial; @@ -4601,11 +3547,7 @@ sub saveHandGrade { &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, $cdom,$cnum); } - if (($sendupdate || $totchg) && (!$submitter) && ($poss_pb)) { - &process_passbacks('handgrade',[$symb],$cdom,$cnum,$domain,$stuname,$usec,\%weights, - \%awardeds,\%excuseds,$needpb,$skip_passback,$pbsave); - } - return ('',$pts,$wgt,$totchg,$sendupdate); + return ('',$pts,$wgt,$totchg); } sub makehidden { @@ -5103,11 +4045,6 @@ VIEWJAVASCRIPT #--- show scores for a section or whole class w/ option to change/update a score sub viewgrades { my ($request,$symb) = @_; - my ($is_tool,$toolsymb); - if ($symb =~ /ext\.tool$/) { - $is_tool = 1; - $toolsymb = $symb; - } &viewgrades_js($request); #need to make sure we have the correct data for later EXT calls, @@ -5207,13 +4144,7 @@ sub viewgrades { if ($env{'form.submitonly'} eq 'all') { $result.= '<h3>'.$common_header.'</h3>'; } else { - my $text; - if ($is_tool) { - $text = &mt('(transaction status: "[_1]")',$submission_status); - } else { - $text = &mt('(submission status: "[_1]")',$submission_status); - } - $result.= '<h3>'.$common_header.' '.$text.'</h3>'; + $result.= '<h3>'.$common_header.' '.&mt('(submission status: "[_1]")',$submission_status).'</h3>'; } $result .= &Apache::loncommon::start_data_table(); #radio buttons/text box for assigning points for a section or class. @@ -5226,12 +4157,7 @@ sub viewgrades { my %weight = (); my $ctsparts = 0; my %seen = (); - my @part_response_id; - if ($is_tool) { - @part_response_id = ([0,'']); - } else { - @part_response_id = &flatten_responseType($responseType); - } + my @part_response_id = &flatten_responseType($responseType); foreach my $part_response_id (@part_response_id) { my ($partid,$respid) = @{ $part_response_id }; my $part_resp = join('_',@{ $part_response_id }); @@ -5282,16 +4208,10 @@ sub viewgrades { #table listing all the students in a section/class #header of table - if ($env{'form.submitonly'} eq 'all') { + if ($env{'form.submitonly'} eq 'all') { $result.= '<h3>'.$specific_header.'</h3>'; } else { - my $text; - if ($is_tool) { - $text = &mt('(transaction status: "[_1]")',$submission_status); - } else { - $text = &mt('(submission status: "[_1]")',$submission_status); - } - $result.= '<h3>'.$specific_header.' '.$text.'</h3>'; + $result.= '<h3>'.$specific_header.' '.&mt('(submission status: "[_1]")',$submission_status).'</h3>'; } $result.= &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(). @@ -5305,10 +4225,10 @@ sub viewgrades { my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb); my @partids = (); foreach my $part (@parts) { - my $display=&Apache::lonnet::metadata($url,$part.'.display',$toolsymb); + my $display=&Apache::lonnet::metadata($url,$part.'.display'); my $narrowtext = &mt('Tries'); $display =~ s|^Number of Attempts|$narrowtext <br />|; # makes the column narrower - if (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name',$toolsymb); } + if (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); } my ($partid) = &split_part_type($part); push(@partids,$partid); # @@ -5349,7 +4269,7 @@ sub viewgrades { return $a cmp $b; } (keys(%$fullname))) { $result.=&viewstudentgrade($symb,$env{'request.course.id'}, - $_,$$fullname{$_},\@parts,\%weight,\$ctr,\%last_resets,$is_tool); + $_,$$fullname{$_},\@parts,\%weight,\$ctr,\%last_resets); } $result.=&Apache::loncommon::end_data_table(); $result.='<input type="hidden" name="total" value="'.$ctr.'" />'."\n"; @@ -5437,7 +4357,7 @@ sub viewgrades { #--- call by previous routine to display each student who satisfies submission filter. sub viewstudentgrade { - my ($symb,$courseid,$student,$fullname,$parts,$weight,$ctr,$last_resets,$is_tool) = @_; + my ($symb,$courseid,$student,$fullname,$parts,$weight,$ctr,$last_resets) = @_; my ($uname,$udom) = split(/:/,$student); my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname); my $submitonly = $env{'form.submitonly'}; @@ -5495,6 +4415,7 @@ sub viewstudentgrade { my ($aggtries,$totaltries); unless (exists($aggregates{$part})) { $totaltries = $record{'resource.'.$part.'.tries'}; + $aggtries = $totaltries; if ($$last_resets{$part}) { $aggtries = &get_num_tries(\%record,$$last_resets{$part}, @@ -5543,10 +4464,6 @@ sub viewstudentgrade { # record does not get update if unchanged sub editgrades { my ($request,$symb) = @_; - my $toolsymb; - if ($symb =~ /ext\.tool$/) { - $toolsymb = $symb; - } my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section')); my $title='<h2>'.&mt('Current Grade Status').'</h2>'; @@ -5566,10 +4483,6 @@ sub editgrades { ); 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 %weight = (); my %columns = (); @@ -5597,7 +4510,7 @@ sub editgrades { my ($part,$type) = &split_part_type($stores); if ($part !~ m/^\Q$partid\E/) { next;} if ($type eq 'awarded' || $type eq 'solved') { next; } - my $display=&Apache::lonnet::metadata($url,$stores.'.display',$toolsymb); + my $display=&Apache::lonnet::metadata($url,$stores.'.display'); $display =~ s/\[Part: \Q$part\E\]//; my $narrowtext = &mt('Tries'); $display =~ s/Number of Attempts/$narrowtext/; @@ -5620,7 +4533,7 @@ sub editgrades { &Apache::loncommon::end_data_table_header_row(); my @noupdate; my ($updateCtr,$noupdateCtr) = (1,1); - my ($got_types,%queueable,%pbsave,%skip_passback); + my ($got_types,%queueable); for ($i=0; $i<$env{'form.total'}; $i++) { my $user = $env{'form.ctr'.$i}; my ($uname,$udom)=split(/:/,$user); @@ -5639,7 +4552,6 @@ sub editgrades { my %aggregate = (); my $aggregateflag = 0; $user=~s/:/_/; # colon doen't work in javascript for names - my (%weights,%awardeds,%excuseds); foreach (@partid) { my $old_aw = $env{'form.GD_'.$user.'_'.$_.'_awarded_s'}; my $old_part_pcr = $old_aw/($weight{$_} ne '0' ? $weight{$_}:1); @@ -5648,7 +4560,6 @@ sub editgrades { my $awarded = $env{'form.GD_'.$user.'_'.$_.'_awarded'}; my $pcr = $awarded/($weight{$_} ne '0' ? $weight{$_} : 1); my $partial = $awarded eq '' ? '' : $pcr; - $awardeds{$symb}{$_} = $partial; my $score; if ($partial eq '') { $score = $scoreptr{$env{'form.GD_'.$user.'_'.$_.'_solved_s'}}; @@ -5689,11 +4600,6 @@ sub editgrades { my $partid=$_; - if ($score eq 'excused') { - $excuseds{$symb}{$partid} = 1; - } else { - $excuseds{$symb}{$partid} = ''; - } foreach my $stores (@parts) { my ($part,$type) = &split_part_type($stores); if ($part !~ m/^\Q$partid\E/) { next;} @@ -5711,6 +4617,9 @@ sub editgrades { } $line.="\n"; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + if ($updateflag) { $count++; &Apache::lonnet::cstore(\%newrecord,$symb,$env{'request.course.id'}, @@ -5763,11 +4672,6 @@ sub editgrades { '<td align="right"> '.$updateCtr.' </td>'.$line. &Apache::loncommon::end_data_table_row(); $updateCtr++; - if (keys(%needpb)) { - $weights{$symb} = \%weight; - &process_passbacks('editgrades',[$symb],$cdom,$cnum,$udom,$uname,$usec,\%weights, - \%awardeds,\%excuseds,\%needpb,\%skip_passback,\%pbsave); - } } else { push(@noupdate, '<td align="right"> '.$noupdateCtr.' </td>'.$line); @@ -5938,10 +4842,6 @@ ENDPICK sub csvupload_fields { my ($symb,$errorref) = @_; - my $toolsymb; - if ($symb =~ /ext\.tool$/) { - $toolsymb = $symb; - } my (@parts) = &getpartlist($symb,$errorref); if (ref($errorref)) { if ($$errorref) { @@ -5955,7 +4855,7 @@ sub csvupload_fields { my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb); foreach my $part (sort(@parts)) { my @datum; - my $display=&Apache::lonnet::metadata($url,$part.'.display',$toolsymb); + my $display=&Apache::lonnet::metadata($url,$part.'.display'); my $name=$part; if (!$display) { $display = $name; } @datum=($name,$display); @@ -6136,33 +5036,11 @@ sub csvuploadassign { if ($env{'form.noFirstLine'}) { shift(@gradedata); } my %fields=&get_fields(); 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 @notallowed; my @skipped; my @warnings; 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) { my %entries=&Apache::loncommon::record_sep($grade); my $domain; @@ -6205,14 +5083,9 @@ sub csvuploadassign { my $part=$1; my $wgt =&Apache::lonnet::EXT('resource.'.$part.'.weight', $symb,$domain,$username); - $weights{$symb}{$part} = $wgt; if ($wgt) { $entries{$fields{$dest}}=~s/\s//g; my $pcr=$entries{$fields{$dest}} / $wgt; - if ($passback) { - $awardeds{$symb}{$part} = $pcr; - $excuseds{$symb}{$part} = ''; - } my $award=($pcr == 0) ? 'incorrect_by_override' : 'correct_by_override'; if ($pcr>1) { @@ -6232,22 +5105,6 @@ sub csvuploadassign { if ($dest=~/stores_(.*)_awarded/) { if ($points{$1}) {next;} } if ($dest=~/stores_(.*)_solved/) { if ($points{$1}) {next;} } 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/_/\./g; $grades{$store_key}=$entries{$fields{$dest}}; @@ -6264,32 +5121,11 @@ sub csvuploadassign { # Successfully stored $request->print('.'); # Remove from grading queue - &Apache::bridgetask::remove_from_queue('gradingqueue',$symb,$cdom,$cnum, - $domain,$username); + &Apache::bridgetask::remove_from_queue('gradingqueue',$symb, + $env{'course.'.$env{'request.course.id'}.'.domain'}, + $env{'course.'.$env{'request.course.id'}.'.num'}, + $domain,$username); $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 { $request->print("<p><span class=\"LC_error\">". &mt("Failed to save data for student [_1]. Message when trying to save was: [_2]", @@ -6485,7 +5321,7 @@ sub getSymbMap { my @sequences = $navmap->retrieveResources(undef, sub { shift->is_map(); }, 1,0,1); for my $sequence ($navmap->getById('0.0'), @sequences) { - if ($navmap->hasResource($sequence, sub { shift->is_gradable(); }, 0) ) { + if ($navmap->hasResource($sequence, sub { shift->is_problem(); }, 0) ) { my $title = $minder.'.'. &HTML::Entities::encode($sequence->compTitle(),'"\'&'); push(@titles, $title); # minder in case two titles are identical @@ -6582,11 +5418,10 @@ sub displayPage { if($curRes == $iterator->BEGIN_MAP) { $depth++; } if($curRes == $iterator->END_MAP) { $depth--; } - if (ref($curRes) && $curRes->is_gradable()) { + if (ref($curRes) && $curRes->is_problem()) { my $parts = $curRes->parts(); my $title = $curRes->compTitle(); my $symbx = $curRes->symb(); - my $is_tool = ($symbx =~ /ext\.tool$/); $studentTable.= &Apache::loncommon::start_data_table_row(). '<td align="center" valign="top" >'.$prob. @@ -6597,34 +5432,26 @@ sub displayPage { '</td>'; $studentTable.='<td valign="top">'; my %form = ('CODE' => $env{'form.CODE'},); - if ($is_tool) { - $studentTable.=' <b>'.$title.'</b><br />'; - } else { - if ($env{'form.vProb'} eq 'yes' ) { - $studentTable.=&show_problem($request,$symbx,$uname,$udom,1, - undef,'both',\%form); - } else { - my $companswer = &Apache::loncommon::get_student_answers($symbx,$uname,$udom,$env{'request.course.id'},%form); - $companswer =~ s|<form(.*?)>||g; - $companswer =~ s|</form>||g; -# while ($companswer =~ /(<a href\=\"javascript:newWindow.*?Script Vars<\/a>)/s) { #<a href="javascript:newWindow</a> -# $companswer =~ s/$1/ /ms; -# $request->print('match='.$1."<br />\n"); -# } -# $companswer =~ s|<table border=\"1\">|<table border=\"0\">|g; - $studentTable.=' <b>'.$title.'</b> <br /> <b>'.&mt('Correct answer').':</b><br />'.$companswer; - } + if ($env{'form.vProb'} eq 'yes' ) { + $studentTable.=&show_problem($request,$symbx,$uname,$udom,1, + undef,'both',\%form); + } else { + my $companswer = &Apache::loncommon::get_student_answers($symbx,$uname,$udom,$env{'request.course.id'},%form); + $companswer =~ s|<form(.*?)>||g; + $companswer =~ s|</form>||g; +# while ($companswer =~ /(<a href\=\"javascript:newWindow.*?Script Vars<\/a>)/s) { #<a href="javascript:newWindow</a> +# $companswer =~ s/$1/ /ms; +# $request->print('match='.$1."<br />\n"); +# } +# $companswer =~ s|<table border=\"1\">|<table border=\"0\">|g; + $studentTable.=' <b>'.$title.'</b> <br /> <b>'.&mt('Correct answer').':</b><br />'.$companswer; } my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname); if ($env{'form.lastSub'} eq 'datesub') { if ($record{'version'} eq '') { - my $msg = &mt('No recorded submission for this problem.'); - if ($is_tool) { - $msg = &mt('No recorded transactions for this external tool'); - } - $studentTable.='<br /> <span class="LC_warning">'.$msg.'</span><br />'; + $studentTable.='<br /> <span class="LC_warning">'.&mt('No recorded submission for this problem.').'</span><br />'; } else { my %responseType = (); foreach my $partid (@{$parts}) { @@ -6682,14 +5509,13 @@ sub displaySubByDates { my ($symb,$record,$parts,$responseType,$checkIcon,$uname,$udom) = @_; my $isCODE=0; my $isTask = ($symb =~/\.task$/); - my $is_tool = ($symb =~/\.tool$/); if (exists($record->{'resource.CODE'})) { $isCODE=1; } my $studentTable=&Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(). '<th>'.&mt('Date/Time').'</th>'. ($isCODE?'<th>'.&mt('CODE').'</th>':''). ($isTask?'<th>'.&mt('Version').'</th>':''). - '<th>'.($is_tool?&mt('Grade'):&mt('Submission')).'</th>'. + '<th>'.&mt('Submission').'</th>'. '<th>'.&mt('Status').'</th>'. &Apache::loncommon::end_data_table_header_row(); my ($version); @@ -6697,11 +5523,7 @@ sub displaySubByDates { my %orders; $mark{'correct_by_student'} = $checkIcon; if (!exists($$record{'1:timestamp'})) { - if ($is_tool) { - return '<br /> <span class="LC_warning">'.&mt('No grade passed back.').'</span><br />'; - } else { - return '<br /> <span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br />'; - } + return '<br /> <span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br />'; } my $interaction; @@ -6737,8 +5559,6 @@ sub displaySubByDates { my @matchKey; if ($isTask) { @matchKey = sort(grep(/^resource\.\d+\.\Q$partid\E\.award$/,@versionKeys)); - } elsif ($is_tool) { - @matchKey = sort(grep(/^resource\.\Q$partid\E\.awarded$/,@versionKeys)); } else { @matchKey = sort(grep(/^resource\.\Q$partid\E\..*?\.submission$/,@versionKeys)); } @@ -6747,51 +5567,48 @@ sub displaySubByDates { foreach my $matchKey (@matchKey) { if (exists($$record{$version.':'.$matchKey}) && $$record{$version.':'.$matchKey} ne '') { - if ($is_tool) { - $displaySub[0].=$$record{"$version:resource.$partid.awarded"}; + + my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/) + : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/)); + $displaySub[0].='<span class="LC_nobreak">'; + $displaySub[0].='<b>'.&mt('Part: [_1]',$display_part).'</b>' + .' <span class="LC_internal_info">' + .'('.&mt('Response ID: [_1]',$responseId).')' + .'</span>' + .' <b>'; + if ($hidden) { + $displaySub[0].= &mt('Anonymous Survey').'</b>'; } else { - my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/) - : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/)); - $displaySub[0].='<span class="LC_nobreak">'; - $displaySub[0].='<b>'.&mt('Part: [_1]',$display_part).'</b>' - .' <span class="LC_internal_info">' - .'('.&mt('Response ID: [_1]',$responseId).')' - .'</span>' - .' <b>'; - if ($hidden) { - $displaySub[0].= &mt('Anonymous Survey').'</b>'; - } else { - my ($trial,$rndseed,$newvariation); - if ($type eq 'randomizetry') { - $trial = $$record{"$where.$partid.tries"}; - $rndseed = $$record{"$where.$partid.rndseed"}; - } - if ($$record{"$where.$partid.tries"} eq '') { - $displaySub[0].=&mt('Trial not counted'); - } else { - $displaySub[0].=&mt('Trial: [_1]', - $$record{"$where.$partid.tries"}); - if (($rndseed ne '') && ($lastrndseed{$partid} ne '')) { - if (($rndseed ne $lastrndseed{$partid}) && - (($type eq 'randomizetry') || ($lasttype{$partid} eq 'randomizetry'))) { - $newvariation = ' ('.&mt('New variation this try').')'; - } - } - $lastrndseed{$partid} = $rndseed; - $lasttype{$partid} = $type; - } - my $responseType=($isTask ? 'Task' - : $responseType->{$partid}->{$responseId}); - if (!exists($orders{$partid})) { $orders{$partid}={}; } - if ((!exists($orders{$partid}->{$responseId})) || ($trial)) { - $orders{$partid}->{$responseId}= - &get_order($partid,$responseId,$symb,$uname,$udom, - $no_increment,$type,$trial,$rndseed); - } - $displaySub[0].='</b>'.$newvariation.'</span>'; # /nobreak - $displaySub[0].=' '. - &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:",$uname,$udom,$type,$trial,$rndseed).'<br />'; + my ($trial,$rndseed,$newvariation); + if ($type eq 'randomizetry') { + $trial = $$record{"$where.$partid.tries"}; + $rndseed = $$record{"$where.$partid.rndseed"}; } + if ($$record{"$where.$partid.tries"} eq '') { + $displaySub[0].=&mt('Trial not counted'); + } else { + $displaySub[0].=&mt('Trial: [_1]', + $$record{"$where.$partid.tries"}); + if (($rndseed ne '') && ($lastrndseed{$partid} ne '')) { + if (($rndseed ne $lastrndseed{$partid}) && + (($type eq 'randomizetry') || ($lasttype{$partid} eq 'randomizetry'))) { + $newvariation = ' ('.&mt('New variation this try').')'; + } + } + $lastrndseed{$partid} = $rndseed; + $lasttype{$partid} = $type; + } + my $responseType=($isTask ? 'Task' + : $responseType->{$partid}->{$responseId}); + if (!exists($orders{$partid})) { $orders{$partid}={}; } + if ((!exists($orders{$partid}->{$responseId})) || ($trial)) { + $orders{$partid}->{$responseId}= + &get_order($partid,$responseId,$symb,$uname,$udom, + $no_increment,$type,$trial,$rndseed); + } + $displaySub[0].='</b>'.$newvariation.'</span>'; # /nobreak + $displaySub[0].=' '. + &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:",$uname,$udom,$type,$trial,$rndseed).'<br />'; } } } @@ -6806,22 +5623,14 @@ sub displaySubByDates { lc($$record{"$where.$partid.award"}).' '. $mark{$$record{"$where.$partid.solved"}}. '<br />'; - } elsif (($is_tool) && (exists($$record{"$version:resource.$partid.solved"}))) { - if ($$record{"$version:resource.$partid.solved"} =~ /^(in|)correct_by_passback$/) { - $displaySub[1].=&mt('Grade passed back by external tool'); - } } if (exists $$record{"$where.$partid.regrader"}) { - $displaySub[2].=$$record{"$where.$partid.regrader"}; - unless ($is_tool) { - $displaySub[2].=' (<b>'.&mt('Part').':</b> '.$display_part.')'; - } + $displaySub[2].=$$record{"$where.$partid.regrader"}. + ' (<b>'.&mt('Part').':</b> '.$display_part.')'; } elsif ($$record{"$version:resource.$partid.regrader"} =~ /\S/) { $displaySub[2].= - $$record{"$version:resource.$partid.regrader"}; - unless ($is_tool) { - $displaySub[2].=' (<b>'.&mt('Part').':</b> '.$display_part.')'; - } + $$record{"$version:resource.$partid.regrader"}. + ' (<b>'.&mt('Part').':</b> '.$display_part.')'; } } # needed because old essay regrader has not parts info @@ -6886,7 +5695,6 @@ sub updateGradeByPage { $iterator->next(); # skip the first BEGIN_MAP my $curRes = $iterator->next(); # for "current resource" my ($depth,$question,$prob,$changeflag,$hideflag)= (1,1,1,0,0); - my (@updates,%weights,%excuseds,%awardeds,@symbs_in_map); while ($depth > 0) { if($curRes == $iterator->BEGIN_MAP) { $depth++; } if($curRes == $iterator->END_MAP) { $depth--; } @@ -6895,7 +5703,6 @@ sub updateGradeByPage { my $parts = $curRes->parts(); my $title = $curRes->compTitle(); my $symbx = $curRes->symb(); - push(@symbs_in_map,$symbx); $studentTable.= &Apache::loncommon::start_data_table_row(). '<td align="center" valign="top" >'.$prob. @@ -6913,9 +5720,6 @@ sub updateGradeByPage { my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname); my ($version,$parts) = split(/:/,$env{'form.HIDE'.$prob},2); my $numchgs = &makehidden($version,$parts,\%record,$symbx,$udom,$uname,1); - if ($numchgs) { - push(@updates,$symbx); - } $hideflag += $numchgs; } foreach my $partid (@{$parts}) { @@ -6937,8 +5741,6 @@ sub updateGradeByPage { } my $wgt = $env{'form.WGT'.$question.'_'.$partid} != 0 ? $env{'form.WGT'.$question.'_'.$partid} : 1; - $weights{$symbx}{$partid} = $wgt; - $excuseds{$symbx}{$partid} = ''; my $partial = $newpts/$wgt; my $score; if ($partial > 0) { @@ -6950,7 +5752,6 @@ sub updateGradeByPage { if ($dropMenu eq 'excused') { $partial = ''; $score = 'excused'; - $excuseds{$symbx}{$partid} = 1; } elsif ($dropMenu eq 'reset status' && $env{'form.solved'.$question.'_'.$partid} ne '') { #update only if previous record exists $newrecord{'resource.'.$partid.'.tries'} = 0; @@ -6978,11 +5779,6 @@ sub updateGradeByPage { (($score eq 'excused') ? 'excused' : $newpts). ' <br />'; $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')); $newrecord{'resource.'.$partid.'.awarded'} = $partial if $partial ne ''; @@ -7022,9 +5818,6 @@ sub updateGradeByPage { &Apache::loncommon::end_data_table_row(); $prob++; - if ($changeflag) { - push(@updates,$symbx); - } } $curRes = $iterator->next(); } @@ -7038,95 +5831,9 @@ sub updateGradeByPage { $hideflag).'<br />'); $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 ''; } -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 --------- # #------------------------------------------------------------------- @@ -11335,8 +10042,7 @@ sub verify_scantron_grading { sub href_symb_cmd { my ($symb,$cmd)=@_; - return '/adm/grades?symb='.&HTML::Entities::encode(&Apache::lonenc::check_encrypt($symb),'<>&"').'&command='. - &HTML::Entities::encode($cmd,'<>&"'); + return '/adm/grades?symb='.&HTML::Entities::encode(&Apache::lonenc::check_encrypt($symb),'<>&"').'&command='.$cmd; } sub grading_menu { @@ -11445,20 +10151,7 @@ sub grading_menu { ] }); - my $cdom = $env{"course.$env{'request.course.id'}.domain"}; - my $cnum = $env{"course.$env{'request.course.id'}.num"}; - my %passback = &Apache::lonnet::dump('nohist_linkprot_passback',$cdom,$cnum); - if (keys(%passback)) { - $fields{'command'} = 'initialpassback'; - my $url6 = &Apache::lonhtmlcommon::build_url('grades/',\%fields); - push (@{$menu[1]{items}}, - { linktext => 'Passback of Scores', - url => $url6, - permission => $permissions{'either'}, - icon => 'passback.png', - linktitle => 'Passback scores to launcher CMS for resources accessed via LTI-mediated deep-linking', - }); - } + # Create the menu my $Str; $Str .= '<form method="post" action="" name="gradingMenu">'; @@ -11496,13 +10189,12 @@ sub submit_options_table { my ($request,$symb) = @_; if (!$symb) {return '';} &commonJSfunctions($request); - my $is_tool = ($symb =~ /ext\.tool$/); my $result; $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n". '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n"; - $result.=&selectfield(1,$is_tool). + $result.=&selectfield(1). '<input type="hidden" name="command" value="viewgrades" /> <div> <input type="submit" value="'.&mt('Next').' →" /> @@ -11534,7 +10226,6 @@ sub submit_options_download { } } - my $is_tool = ($symb =~ /ext\.tool$/); &commonJSfunctions($request); my $result='<form action="/adm/grades" method="post" name="gradingMenu">'."\n". @@ -11543,7 +10234,7 @@ sub submit_options_download { $result.=' <h2> '.&mt('Select Students for whom to Download Submitted Files').' -</h2>'.&selectfield(1,$is_tool).' +</h2>'.&selectfield(1).' <input type="hidden" name="command" value="downloadfileslink" /> <input type="submit" value="'.&mt('Next').' →" /> </div> @@ -11559,13 +10250,12 @@ sub submit_options { my ($request,$symb) = @_; if (!$symb) {return '';} - my $is_tool = ($symb =~ /ext\.tool$/); &commonJSfunctions($request); my $result; $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n". '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n"; - $result.=&selectfield(1,$is_tool).' + $result.=&selectfield(1).' <input type="hidden" name="command" value="submission" /> <input type="submit" value="'.&mt('Next').' →" /> </div> @@ -11575,17 +10265,10 @@ sub submit_options { } sub selectfield { - my ($full,$is_tool)=@_; - my %options; - if ($is_tool) { - %options = - (&transtatus_options, - 'select_form_order' => ['yes','incorrect','all']); - } else { - %options = - (&substatus_options, - 'select_form_order' => ['yes','queued','graded','incorrect','all']); - } + my ($full)=@_; + my %options = + (&substatus_options, + 'select_form_order' => ['yes','queued','graded','incorrect','all']); # # PrepareClasslist() needs to be called to avoid getting a sections list @@ -11617,14 +10300,10 @@ sub selectfield { '.&Apache::lonhtmlcommon::StatusOptions(undef,undef,5,undef,'mult').' </fieldset>'; if ($full) { - my $heading = &mt('Submission Status'); - if ($is_tool) { - $heading = &mt('Transaction Status'); - } $result.=' <fieldset> <legend> - '.$heading.' + '.&mt('Submission Status').' </legend>'. &Apache::loncommon::select_form('all','submitonly',\%options). '</fieldset>'; @@ -12196,10 +10875,6 @@ 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 @@ -12309,15 +10984,6 @@ 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++; - 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); - } } } } @@ -12368,77 +11034,6 @@ sub select_problem { $r->print('<input type="submit" value="'.&mt('Next').' →" /></form>'); } -#----- display problem, answer, and submissions for a single student (no grading) - -sub view_as_user { - my ($symb,$vuname,$vudom,$hasperm) = @_; - my $plainname = &Apache::loncommon::plainname($vuname,$vudom,'lastname'); - my $displayname = &nameUserString('',$plainname,$vuname,$vudom); - my $output = &Apache::loncommon::get_student_view($symb,$vuname,$vudom, - $env{'request.course.id'}, - undef,{'disable_submit' => 1}). - "\n\n". - '<div class="LC_grade_show_user">'. - '<h2>'.$displayname.'</h2>'. - "\n". - &Apache::loncommon::track_student_link('View recent activity', - $vuname,$vudom,'check').' '. - "\n"; - if (&Apache::lonnet::allowed('opa',$env{'request.course.id'}) || - (($env{'request.course.sec'} ne '') && - &Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.$env{'request.course.sec'}))) { - $output .= &Apache::loncommon::pprmlink(&mt('Set/Change parameters'), - $vuname,$vudom,$symb,'check'); - } - $output .= "\n"; - my $companswer = &Apache::loncommon::get_student_answers($symb,$vuname,$vudom, - $env{'request.course.id'}); - $companswer=~s|<form(.*?)>||g; - $companswer=~s|</form>||g; - $companswer=~s|name="submit"|name="would_have_been_submit"|g; - $output .= '<div class="LC_Box">'. - '<h3 class="LC_hcell">'.&mt('Correct answer for[_1]',$displayname).'</h3>'. - $companswer. - '</div>'."\n"; - my $is_tool = ($symb =~ /ext\.tool$/); - my ($essayurl,%coursedesc_by_cid); - (undef,undef,$essayurl) = &Apache::lonnet::decode_symb($symb); - my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$vudom,$vuname); - my $res_error; - my ($partlist,$handgrade,$responseType,$numresp,$numessay) = - &response_type($symb,\$res_error); - my $fullname; - my $collabinfo; - if ($numessay) { - unless ($hasperm) { - &init_perm(); - } - ($collabinfo,$fullname)= - &check_collaborators($symb,$vuname,$vudom,\%record,$handgrade,0); - unless ($hasperm) { - &reset_perm(); - } - } - my $checkIcon = '<img alt="'.&mt('Check Mark'). - '" src="'.$Apache::lonnet::perlvar{'lonIconsURL'}. - '/check.gif" height="16" border="0" />'; - my ($lastsubonly,$partinfo) = - &show_last_submission($vuname,$vudom,$symb,$essayurl,$responseType,'datesub', - '',$fullname,\%record,\%coursedesc_by_cid); - $output .= '<div class="LC_Box">'. - '<h3 class="LC_hcell">'.&mt('Submissions').'</h3>'."\n".$collabinfo."\n"; - if (($numresp > $numessay) & !$is_tool) { - $output .='<p class="LC_info">'. - &mt('Part(s) graded correct by the computer is marked with a [_1] symbol.',$checkIcon). - "</p>\n"; - } - $output .= $partinfo; - $output .= $lastsubonly; - $output .= &displaySubByDates($symb,\%record,$partlist,$responseType,$checkIcon,$vuname,$vudom); - $output .= '</div></div>'."\n"; - return $output; -} - sub handler { my $request=$_[0]; &reset_caches(); @@ -12473,10 +11068,6 @@ sub handler { &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 my $symb=$env{'form.symb'}; @@ -12690,44 +11281,6 @@ sub handler { undef,undef,undef,undef,undef,undef,undef,1); $request->print('<div style="padding:0;clear:both;margin:0;border:0"></div>'); &submit_download_link($request,$symb); - } elsif ($command eq 'initialpassback') { - &startpage($request,$symb,[{href=>'', text=>'Choose Launcher'}],undef,1); - $request->print(&initialpassback($request,$symb)); - } elsif ($command eq 'passback') { - &startpage($request,$symb, - [{href=>&href_symb_cmd($symb,'initialpassback'), text=>'Choose Launcher'}, - {href=>'', text=>'Types of User'}],undef,1); - $request->print(&passback_filters($request,$symb)); - } elsif ($command eq 'passbacknames') { - my $chosen; - if ($env{'form.passback'} ne '') { - if ($env{'form.passback'} eq &unescape($env{'form.passback'})) { - $env{'form.passback'} = &escape($env{'form.passback'} ); - } - $chosen = &HTML::Entities::encode($env{'form.passback'},'<>"&'); - } - &startpage($request,$symb, - [{href=>&href_symb_cmd($symb,'initialpassback'), text=>'Choose Launcher'}, - {href=>&href_symb_cmd($symb,'passback').'&passback='.$chosen, text=>'Types of User'}, - {href=>'', text=>'Select Users'}],undef,1); - $request->print(&names_for_passback($request,$symb)); - } elsif ($command eq 'passbackscores') { - my ($chosen,$stu_status); - if ($env{'form.passback'} ne '') { - if ($env{'form.passback'} eq &unescape($env{'form.passback'})) { - $env{'form.passback'} = &escape($env{'form.passback'} ); - } - $chosen = &HTML::Entities::encode($env{'form.passback'},'<>"&'); - } - if ($env{'form.Status'}) { - $stu_status = &HTML::Entities::encode($env{'form.Status'}); - } - &startpage($request,$symb, - [{href=>&href_symb_cmd($symb,'initialpassback'), text=>'Choose Launcher'}, - {href=>&href_symb_cmd($symb,'passback').'&passback='.$chosen, text=>'Types of User'}, - {href=>&href_symb_cmd($symb,'passbacknames').'&Status='.$stu_status.'&passback='.$chosen, text=>'Select Users'}, - {href=>'', text=>'Execute Passback'}],undef,1); - $request->print(&do_passback($request,$symb)); } elsif ($command) { &startpage($request,$symb,[{href=>'', text=>'Access denied'}]); $request->print('<p class="LC_error">'.&mt('Access Denied ([_1])',$command).'</p>');