--- loncom/homework/grades.pm 2011/10/23 02:15:25 1.596.2.9 +++ loncom/homework/grades.pm 2012/05/02 14:00:28 1.672 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.596.2.9 2011/10/23 02:15:25 raeburn Exp $ +# $Id: grades.pm,v 1.672 2012/05/02 14:00:28 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -43,6 +43,8 @@ use Apache::lonmsg(); use Apache::Constants qw(:common :http); use Apache::lonlocal; use Apache::lonenc; +use Apache::lonstathelpers; +use Apache::lonquickgrades; use Apache::bridgetask(); use String::Similarity; use LONCAPA; @@ -97,6 +99,9 @@ sub ssi_print_error { # # --- Retrieve the parts from the metadata file.--- +# Returns an array of everything that the resources stores away +# + sub getpartlist { my ($symb,$errorref) = @_; @@ -121,21 +126,6 @@ sub getpartlist { return @stores; } -# --- Get the symbolic name of a problem and the url -sub get_symb { - my ($request,$silent) = @_; - (my $url=$env{'form.url'}) =~ s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--; - my $symb=($env{'form.symb'} ne '' ? $env{'form.symb'} : (&Apache::lonnet::symbread($url))); - if ($symb eq '') { - if (!$silent) { - $request->print(&mt("Unable to handle ambiguous references: [_1].",$url)); - return (); - } - } - &Apache::lonenc::check_decrypt(\$symb); - return ($symb); -} - #--- Format fullname, username:domain if different for display #--- Use anywhere where the student names are listed sub nameUserString { @@ -150,6 +140,7 @@ sub nameUserString { #--- Get the partlist and the response type for a given problem. --- #--- Indicate if a response type is coded handgraded or not. --- +#--- Sets response_error pointer to "1" if navmaps object broken --- sub response_type { my ($symb,$response_error) = @_; @@ -208,55 +199,6 @@ sub get_display_part { return $display; } -#--- Show resource title -#--- and parts and response type -sub showResourceInfo { - my ($symb,$probTitle,$checkboxes,$res_error) = @_; - my $result = '

'.&mt('Current Resource').': '.$probTitle.'

'."\n"; - my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error); - if (ref($res_error)) { - if ($$res_error) { - return; - } - } - $result.=&Apache::loncommon::start_data_table() - .&Apache::loncommon::start_data_table_header_row(); - if ($checkboxes) { - $result.=' '; - } - $result.=''.&mt('Problem Part').'' - .''.&mt('Res. ID').'' - .''.&mt('Type').'' - .&Apache::loncommon::end_data_table_header_row(); - my %resptype = (); - my $hdgrade='no'; - my %partsseen; - foreach my $partID (sort(keys(%$responseType))) { - foreach my $resID (sort(keys(%{ $responseType->{$partID} }))) { - my $handgrade=$$handgrade{$partID.'_'.$resID}; - my $responsetype = $responseType->{$partID}->{$resID}; - $hdgrade = $handgrade if ($handgrade eq 'yes'); - $result.=&Apache::loncommon::start_data_table_row(); - if ($checkboxes) { - if (exists($partsseen{$partID})) { - $result.=" "; - } else { - $result.=""; - } - $partsseen{$partID}=1; - } - my $display_part=&get_display_part($partID,$symb); - $result.=''.$display_part.'' - .''.''.$resID.'' - .''.&mt($responsetype).'' -# .''.&mt('Handgrade: [_1]',$handgrade).'' - .&Apache::loncommon::end_data_table_row(); - } - } - $result.=&Apache::loncommon::end_data_table(); - return $result,$responseType,$hdgrade,$partlist,$handgrade; -} - sub reset_caches { &reset_analyze_cache(); &reset_perm(); @@ -272,7 +214,7 @@ sub reset_caches { } sub get_analyze { - my ($symb,$uname,$udom,$no_increment,$add_to_hash,$type,$trial,$rndseed)=@_; + my ($symb,$uname,$udom,$no_increment,$add_to_hash,$type,$trial,$rndseed,$bubbles_per_row)=@_; my $key = "$symb\0$uname\0$udom"; if ($type eq 'randomizetry') { if ($trial ne '') { @@ -306,6 +248,9 @@ sub reset_caches { 'grade_courseid' => $env{'request.course.id'}, 'grade_username' => $uname, 'grade_noincrement' => $no_increment); + if ($bubbles_per_row ne '') { + $form{'bubbles_per_row'} = $bubbles_per_row; + } if ($type eq 'randomizetry') { $form{'grade_questiontype'} = $type; if ($rndseed ne '') { @@ -346,7 +291,7 @@ sub reset_caches { } sub scantron_partids_tograde { - my ($resource,$cid,$uname,$udom,$check_for_randomlist) = @_; + my ($resource,$cid,$uname,$udom,$check_for_randomlist,$bubbles_per_row) = @_; my (%analysis,@parts); if (ref($resource)) { my $symb = $resource->symb(); @@ -354,7 +299,9 @@ sub reset_caches { if ($check_for_randomlist) { $add_to_form = { 'check_parts_withrandomlist' => 1,}; } - my $analyze = &get_analyze($symb,$uname,$udom,undef,$add_to_form); + my $analyze = + &get_analyze($symb,$uname,$udom,undef,$add_to_form, + undef,undef,undef,$bubbles_per_row); if (ref($analyze) eq 'HASH') { %analysis = %{$analyze}; } @@ -499,8 +446,7 @@ sub cleanRecord { #-- A couple of common js functions sub commonJSfunctions { my $request = shift; - $request->print(< + $request->print(&Apache::lonhtmlcommon::scripttag(< 1) { @@ -528,7 +474,6 @@ sub commonJSfunctions { return selectOne.value; } } - COMMONJSFUNCTIONS } @@ -683,17 +628,15 @@ sub student_gradeStatus { sub jscriptNform { my ($symb) = @_; my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status')); - my $jscript=''."\n"; + "\n"); $jscript.= '
'."\n". ''."\n". - ''."\n". - ''."\n". ''."\n". ''."\n". ''."\n". @@ -783,22 +726,31 @@ sub most_similar { #------------------------------------ Receipt Verification Routines # + +sub initialverifyreceipt { + my ($request,$symb) = @_; + &commonJSfunctions($request); + return ''. + &Apache::lonnet::recprefix($env{'request.course.id'}). + '-'. + ''."\n". + ''. + "
\n"; +} + #--- Check whether a receipt number is valid.--- sub verifyreceipt { - my $request = shift; + my ($request,$symb) = @_; my $courseid = $env{'request.course.id'}; my $receipt = &Apache::lonnet::recprefix($courseid).'-'. $env{'form.receipt'}; $receipt =~ s/[^\-\d]//g; - my ($symb) = &get_symb($request); my $title.= '

'. - &mt('Verifying Receipt No. [_1]',$receipt). - '

'."\n". - '

'.&mt('Resource: [_1]',$env{'form.probTitle'}). - '

'."\n"; + &mt('Verifying Receipt Number [_1]',$receipt). + ''."\n"; my ($string,$contents,$matches) = ('','',0); my (undef,undef,$fullname) = &getclasslist('all','0'); @@ -868,7 +820,7 @@ sub verifyreceipt { $contents. &Apache::loncommon::end_data_table()."\n"; } - return $string.&show_grading_menu_form($symb); + return $string; } #--- This is called by a number of programs. @@ -876,30 +828,25 @@ sub verifyreceipt { #--- Also called directly when one clicks on the subm button # on the problem page. sub listStudents { - my ($request) = shift; + my ($request,$symb,$submitonly) = @_; - my ($symb) = &get_symb($request); 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'}; my $getgroup = $env{'form.group'} eq '' ? 'all' : $env{'form.group'}; - my $submitonly= $env{'form.submitonly'} eq '' ? 'all' : $env{'form.submitonly'}; - my $viewgrade = $env{'form.showgrading'} eq 'yes' ? 'View/Grade/Regrade' : 'View'; - $env{'form.probTitle'} = $env{'form.probTitle'} eq '' ? - &Apache::lonnet::gettitle($symb) : $env{'form.probTitle'}; - - my $result='

 ' - .&mt("$viewgrade Submissions for a Student or a Group of Students") - .'

'; + unless ($submitonly) { + $submitonly= $env{'form.submitonly'} eq '' ? 'all' : $env{'form.submitonly'}; + } - my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($symb,$env{'form.probTitle'},($env{'form.showgrading'} eq 'yes')); + my $result=''; + my $res_error; + my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error); my %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.', ); - $request->print(< + $request->print(&Apache::lonhtmlcommon::scripttag(< LISTJAVASCRIPT &commonJSfunctions($request); $request->print($result); - my $checkhdgrade = ($env{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1 ) ? 'checked="checked"' : ''; - my $checklastsub = $checkhdgrade eq '' ? 'checked="checked"' : ''; my $gradeTable='
'. - "\n".$table; + "\n"; $gradeTable .= &Apache::lonhtmlcommon::start_pick_box(); $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Problem Text')) @@ -952,22 +896,18 @@ LISTJAVASCRIPT .&Apache::lonhtmlcommon::row_closure(); my $submission_options; - if ($env{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1) { - $submission_options.= - ''."\n"; - } my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status')); my $saveStatus = $stu_status eq '' ? 'Active' : $stu_status; $env{'form.Status'} = $saveStatus; $submission_options.= ''. - ''."\n". ''. ''."\n". ''. - ''."\n". ''. '

'; } - $users{$user}=1; + $users{$user}=1; my @answer=split(/\,/,$env{$key}); my $sum=0; my $realnumber=$number; for (my $i=0;$i<$number;$i++) { if ($correct[$i] eq '-') { $realnumber--; - } elsif ($answer[$i]) { + } elsif (($answer[$i]) || ($answer[$i]=~/^[0\.]+$/)) { if ($gradingmechanism eq 'attendance') { $sum+=$pcorrect; } elsif ($correct[$i] eq '*') { @@ -9498,8 +9571,8 @@ sub assign_clicker_grades { $result.='
'.&mt('Successfully stored grades for [quant,_1,student].',$storecount). ''. &Apache::loncommon::end_data_table_row(). - &Apache::loncommon::end_data_table()."

\n"; - return $result.&show_grading_menu_form($symb); + &Apache::loncommon::end_data_table(); + return $result; } sub navmap_errormsg { @@ -9509,6 +9582,29 @@ sub navmap_errormsg { ''; } +sub startpage { + my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$js) = @_; + if ($nomenu) { + $r->print(&Apache::loncommon::start_page("Student's Version",$js,{'only_body' => '1'})); + } else { + unshift(@$crumbs,{href=>&href_symb_cmd($symb,'gradingmenu'),text=>"Grading"}); + $r->print(&Apache::loncommon::start_page('Grading',$js, + {'bread_crumbs' => $crumbs})); + &Apache::lonquickgrades::startGradeScreen($r,($env{'form.symb'}?'probgrading':'grading')); + } + unless ($nodisplayflag) { + $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp)); + } +} + +sub select_problem { + my ($r)=@_; + $r->print('

'.&mt('Select the problem or one of the problems you want to grade').'

'); + $r->print(&Apache::lonstathelpers::problem_selector('.',undef,1)); + $r->print(''); + $r->print('
'); +} + sub handler { my $request=$_[0]; &reset_caches(); @@ -9519,144 +9615,212 @@ sub handler { } &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}); - my $symb=&get_symb($request,1); +# see what command we need to execute + my @commands=&Apache::loncommon::get_env_multiple('form.command'); my $command=$commands[0]; + &init_perm(); + if (!$env{'request.course.id'}) { + unless ((&Apache::lonnet::allowed('usc',$env{'request.role.domain'})) && + ($command =~ /^scantronupload/)) { + # Not in a course. + $env{'user.error.msg'}="/adm/grades::vgr:0:0:Cannot display grades page outside course context"; + return HTTP_NOT_ACCEPTABLE; + } + } elsif (!%perm) { + $request->internal_redirect('/adm/quickgrades'); + } + &Apache::loncommon::content_type($request,'text/html'); + $request->send_http_header; + if ($#commands > 0) { &Apache::lonnet::logthis("grades got multiple commands ".join(':',@commands)); } +# see what the symb is + + my $symb=$env{'form.symb'}; + unless ($symb) { + (my $url=$env{'form.url'}) =~ s-^https*://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--; + $symb=&Apache::lonnet::symbread($url); + } + &Apache::lonenc::check_decrypt(\$symb); + $ssi_error = 0; - my $brcrum = [{href=>"/adm/grades",text=>"Grading"}]; - my $start_page = &Apache::loncommon::start_page('Grading',undef, - {'bread_crumbs' => $brcrum}); - if ($symb eq '' && $command eq '') { - if ($env{'user.adv'}) { - &Apache::loncommon::content_type($request,'text/html'); - $request->send_http_header; - $request->print($start_page); - if (($env{'form.codeone'}) && ($env{'form.codetwo'}) && - ($env{'form.codethree'})) { - my $token=$env{'form.codeone'}.'*'.$env{'form.codetwo'}.'*'. - $env{'form.codethree'}; - my ($tsymb,$tuname,$tudom,$tcrsid)= - &Apache::lonnet::checkin($token); - if ($tsymb) { - my ($map,$id,$url)=&Apache::lonnet::decode_symb($tsymb); - if (&Apache::lonnet::allowed('mgr',$tcrsid)) { - $request->print(&ssi_with_retries('/res/'.$url, $ssi_retries, - ('grade_username' => $tuname, - 'grade_domain' => $tudom, - 'grade_courseid' => $tcrsid, - 'grade_symb' => $tsymb))); - } else { - $request->print('

Not authorized: '.$token.'

'); - } - } else { - $request->print('

Not a valid DocID: '.$token.'

'); - } - } else { - $request->print(&Apache::lonxml::tokeninputfield()); - } - } elsif ($env{'request.course.id'}) { - &init_perm(); - if (!%perm) { - $request->internal_redirect('/adm/quickgrades'); - } else { - &Apache::loncommon::content_type($request,'text/html'); - $request->send_http_header; - $request->print($start_page); - } - } + if (($symb eq '' || $command eq '') && ($env{'request.course.id'})) { +# +# Not called from a resource, but inside a course +# + &startpage($request,undef,[],1,1); + &select_problem($request); } else { - &init_perm(); - if (!$env{'request.course.id'}) { - # Not in a course. - $env{'user.error.msg'}="/adm/grades::vgr:0:0:Cannot display grades page outside course context"; - return HTTP_NOT_ACCEPTABLE; - } elsif (!%perm) { - $request->internal_redirect('/adm/quickgrades'); - } - &Apache::loncommon::content_type($request,'text/html'); - $request->send_http_header; - $request->print($start_page); if ($command eq 'submission' && $perm{'vgr'}) { - ($env{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0)); + my ($stuvcurrent,$stuvdisp,$versionform,$js); + if (($env{'form.student'} ne '') && ($env{'form.userdom'} ne '')) { + ($stuvcurrent,$stuvdisp,$versionform,$js) = + &choose_task_version_form($symb,$env{'form.student'}, + $env{'form.userdom'}); + } + &startpage($request,$symb,[{href=>"", text=>"Student Submissions"}],undef,undef,$stuvcurrent,$stuvdisp,undef,$js); + if ($versionform) { + $request->print($versionform); + } + $request->print('
'); + ($env{'form.student'} eq '' ? &listStudents($request,$symb) : &submission($request,0,0,$symb)); + } elsif ($command eq 'versionsub' && $perm{'vgr'}) { + my ($stuvcurrent,$stuvdisp,$versionform,$js) = + &choose_task_version_form($symb,$env{'form.student'}, + $env{'form.userdom'}, + $env{'form.inhibitmenu'}); + &startpage($request,$symb,[{href=>"", text=>"Previous Student Version"}],undef,undef,$stuvcurrent,$stuvdisp,$env{'form.inhibitmenu'},$js); + if ($versionform) { + $request->print($versionform); + } + $request->print('
'); + $request->print(&show_previous_task_version($request,$symb)); } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) { - &pickStudentPage($request); + &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'}, + {href=>'',text=>'Select student'}],1,1); + &pickStudentPage($request,$symb); } elsif ($command eq 'displayPage' && $perm{'vgr'}) { - &displayPage($request); + &startpage($request,$symb, + [{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'}, + {href=>'',text=>'Select student'}, + {href=>'',text=>'Grade student'}],1,1); + &displayPage($request,$symb); } elsif ($command eq 'gradeByPage' && $perm{'mgr'}) { - &updateGradeByPage($request); + &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'}, + {href=>'',text=>'Select student'}, + {href=>'',text=>'Grade student'}, + {href=>'',text=>'Store grades'}],1,1); + &updateGradeByPage($request,$symb); } elsif ($command eq 'processGroup' && $perm{'vgr'}) { - &processGroup($request); + &startpage($request,$symb,[{href=>'',text=>'...'}, + {href=>'',text=>'Modify grades'}]); + &processGroup($request,$symb); } elsif ($command eq 'gradingmenu' && $perm{'vgr'}) { - $request->print(&grading_menu($request)); - } elsif ($command eq 'submit_options' && $perm{'vgr'}) { - $request->print(&submit_options($request)); + &startpage($request,$symb); + $request->print(&grading_menu($request,$symb)); + } elsif ($command eq 'individual' && $perm{'vgr'}) { + &startpage($request,$symb,[{href=>'',text=>'Select individual students to grade'}]); + $request->print(&submit_options($request,$symb)); + } elsif ($command eq 'ungraded' && $perm{'vgr'}) { + &startpage($request,$symb,[{href=>'',text=>'Grade ungraded submissions'}]); + $request->print(&listStudents($request,$symb,'graded')); + } elsif ($command eq 'table' && $perm{'vgr'}) { + &startpage($request,$symb,[{href=>"", text=>"Grading table"}]); + $request->print(&submit_options_table($request,$symb)); + } elsif ($command eq 'all_for_one' && $perm{'vgr'}) { + &startpage($request,$symb,[{href=>'',text=>'Grade page/folder for one student'}],1,1); + $request->print(&submit_options_sequence($request,$symb)); } elsif ($command eq 'viewgrades' && $perm{'vgr'}) { - $request->print(&viewgrades($request)); + &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},{href=>'', text=>"Modify grades"}]); + $request->print(&viewgrades($request,$symb)); } elsif ($command eq 'handgrade' && $perm{'mgr'}) { - $request->print(&processHandGrade($request)); + &startpage($request,$symb,[{href=>'',text=>'...'}, + {href=>'',text=>'Store grades'}]); + $request->print(&processHandGrade($request,$symb)); } elsif ($command eq 'editgrades' && $perm{'mgr'}) { - $request->print(&editgrades($request)); + &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"}, + {href=>&href_symb_cmd($symb,'viewgrades').'&group=all§ion=all&Status=Active', + text=>"Modify grades"}, + {href=>'', text=>"Store grades"}]); + $request->print(&editgrades($request,$symb)); + } elsif ($command eq 'initialverifyreceipt' && $perm{'vgr'}) { + &startpage($request,$symb,[{href=>'',text=>'Verify Receipt Number'}]); + $request->print(&initialverifyreceipt($request,$symb)); } elsif ($command eq 'verify' && $perm{'vgr'}) { - $request->print(&verifyreceipt($request)); + &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"initialverifyreceipt"),text=>'Verify Receipt Number'}, + {href=>'',text=>'Verification Result'}]); + $request->print(&verifyreceipt($request,$symb)); } elsif ($command eq 'processclicker' && $perm{'mgr'}) { - $request->print(&process_clicker($request)); + &startpage($request,$symb,[{href=>'', text=>'Process clicker'}]); + $request->print(&process_clicker($request,$symb)); } elsif ($command eq 'processclickerfile' && $perm{'mgr'}) { - $request->print(&process_clicker_file($request)); + &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'processclicker'), text=>'Process clicker'}, + {href=>'', text=>'Process clicker file'}]); + $request->print(&process_clicker_file($request,$symb)); } elsif ($command eq 'assignclickergrades' && $perm{'mgr'}) { - $request->print(&assign_clicker_grades($request)); + &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'processclicker'), text=>'Process clicker'}, + {href=>'', text=>'Process clicker file'}, + {href=>'', text=>'Store grades'}]); + $request->print(&assign_clicker_grades($request,$symb)); } elsif ($command eq 'csvform' && $perm{'mgr'}) { - $request->print(&upcsvScores_form($request)); + &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1); + $request->print(&upcsvScores_form($request,$symb)); } elsif ($command eq 'csvupload' && $perm{'mgr'}) { - $request->print(&csvupload($request)); + &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1); + $request->print(&csvupload($request,$symb)); } elsif ($command eq 'csvuploadmap' && $perm{'mgr'} ) { - $request->print(&csvuploadmap($request)); + &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1); + $request->print(&csvuploadmap($request,$symb)); } elsif ($command eq 'csvuploadoptions' && $perm{'mgr'}) { if ($env{'form.associate'} ne 'Reverse Association') { - $request->print(&csvuploadoptions($request)); + &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1); + $request->print(&csvuploadoptions($request,$symb)); } else { if ( $env{'form.upfile_associate'} ne 'reverse' ) { $env{'form.upfile_associate'} = 'reverse'; } else { $env{'form.upfile_associate'} = 'forward'; } - $request->print(&csvuploadmap($request)); + &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1); + $request->print(&csvuploadmap($request,$symb)); } } elsif ($command eq 'csvuploadassign' && $perm{'mgr'} ) { - $request->print(&csvuploadassign($request)); + &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1); + $request->print(&csvuploadassign($request,$symb)); } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) { - $request->print(&scantron_selectphase($request)); + &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1); + $request->print(&scantron_selectphase($request,undef,$symb)); } elsif ($command eq 'scantron_warning' && $perm{'mgr'}) { - $request->print(&scantron_do_warning($request)); + &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1); + $request->print(&scantron_do_warning($request,$symb)); } elsif ($command eq 'scantron_validate' && $perm{'mgr'}) { - $request->print(&scantron_validate_file($request)); + &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1); + $request->print(&scantron_validate_file($request,$symb)); } elsif ($command eq 'scantron_process' && $perm{'mgr'}) { - $request->print(&scantron_process_students($request)); + &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1); + $request->print(&scantron_process_students($request,$symb)); } elsif ($command eq 'scantronupload' && (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})|| &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) { - $request->print(&scantron_upload_scantron_data($request)); + &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1); + $request->print(&scantron_upload_scantron_data($request,$symb)); } elsif ($command eq 'scantronupload_save' && (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})|| &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) { - $request->print(&scantron_upload_scantron_data_save($request)); + &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1); + $request->print(&scantron_upload_scantron_data_save($request,$symb)); } elsif ($command eq 'scantron_download' && &Apache::lonnet::allowed('usc',$env{'request.course.id'})) { - $request->print(&scantron_download_scantron_data($request)); + &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1); + $request->print(&scantron_download_scantron_data($request,$symb)); } elsif ($command eq 'checksubmissions' && $perm{'vgr'}) { - $request->print(&checkscantron_results($request)); + &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1); + $request->print(&checkscantron_results($request,$symb)); + } elsif ($command eq 'downloadfilesselect' && $perm{'vgr'}) { + &startpage($request,$symb,[{href=>'', text=>'Select which submissions to download'}]); + $request->print(&submit_options_download($request,$symb)); + } elsif ($command eq 'downloadfileslink' && $perm{'vgr'}) { + &startpage($request,$symb, + [{href=>&href_symb_cmd($symb,'downloadfilesselect'), text=>'Select which submissions to download'}, + {href=>'', text=>'Download submissions'}]); + &submit_download_link($request,$symb); } elsif ($command) { + &startpage($request,$symb,[{href=>'', text=>'Access denied'}]); $request->print('

'.&mt('Access Denied ([_1])',$command).'

'); } } if ($ssi_error) { &ssi_print_error($request); } - $request->print(&Apache::loncommon::end_page()); + if ($env{'form.inhibitmenu'}) { + $request->print(&Apache::loncommon::end_page()); + } else { + &Apache::lonquickgrades::endGradeScreen($request); + } &reset_caches(); return OK; } @@ -9727,6 +9891,75 @@ ssi_with_retries() =over +=head1 Routines to display previous version of a Task for a specific student + +Tasks are graded pass/fail. Students who have yet to pass a particular Task +can receive another opportunity. Access to tasks is slot-based. If a slot +requires a proctor to check-in the student, a new version of the Task will +be created when the student is checked in to the new opportunity. + +If a particular student has tried two or more versions of a particular task, +the submission screen provides a user with vgr privileges (e.g., a Course +Coordinator) the ability to display a previous version worked on by the +student. By default, the current version is displayed. If a previous version +has been selected for display, submission data are only shown that pertain +to that particular version, and the interface to submit grades is not shown. + +=over 4 + +=item show_previous_task_version() + +Displays a specified version of a student's Task, as the student sees it. + +Inputs: 2 + request - request object + symb - unique symb for current instance of resource + +Output: None. + +Side Effects: calls &show_problem() to print version of Task, with + version contained in form item: $env{'form.previousversion'} + +=item choose_task_version_form() + +Displays a web form used to select which version of a student's view of a +Task should be displayed. Either launches a pop-up window, or replaces +content in existing pop-up, or replaces page in main window. + +Inputs: 4 + symb - unique symb for current instance of resource + uname - username of student + udom - domain of student + nomenu - 1 if display is in a pop-up window, and hence no menu + breadcrumbs etc., are displayed + +Output: 4 + current - student's current version + displayed - student's version being displayed + result - scalar containing HTML for web form used to switch to + a different version (or a link to close window, if pop-up). + js - javascript for processing selection in versions web form + +Side Effects: None. + +=item previous_display_javascript() + +Inputs: 2 + nomenu - 1 if display is in a pop-up window, and hence no menu + breadcrumbs etc., are displayed. + current - student's current version number. + +Output: 1 + js - javascript for processing selection in versions web form. + +Side Effects: None. + +=back + +=head1 Routines to process bubblesheet data. + +=over 4 + =item scantron_get_correction() : Builds the interface screen to interact with the operator to fix a @@ -9762,6 +9995,8 @@ ssi_with_retries() calling routine should trap the error condition and display the warning found in &navmap_errormsg(). + $scantron_config - Reference to bubblesheet format configuration hash. + Returns the maximum number of bubble lines that are expected to occur. Does this by walking the selected sequence rendering the resource and then checking &Apache::lonxml::get_problem_counter() @@ -9830,7 +10065,9 @@ ssi_with_retries() =item navmap_errormsg() : Returns HTML mark-up inside a
with a link to re-initialize the course. - Should be called whenever the request to instantiate a navmap object fails. + Should be called whenever the request to instantiate a navmap object fails. + +=back =back