--- loncom/homework/grades.pm 2009/12/27 02:05:40 1.574.2.6 +++ loncom/homework/grades.pm 2009/12/09 17:53:55 1.582 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.574.2.6 2009/12/27 02:05:40 raeburn Exp $ +# $Id: grades.pm,v 1.582 2009/12/09 17:53:55 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -97,9 +97,15 @@ sub ssi_print_error { # # --- Retrieve the parts from the metadata file.--- sub getpartlist { - my ($symb) = @_; + my ($symb,$errorref) = @_; my $navmap = Apache::lonnavmaps::navmap->new(); + unless (ref($navmap)) { + if (ref($errorref)) { + $$errorref = 'navmap'; + return; + } + } my $res = $navmap->getBySymb($symb); my $partlist = $res->parts(); my $url = $res->src(); @@ -144,9 +150,15 @@ sub nameUserString { #--- Get the partlist and the response type for a given problem. --- #--- Indicate if a response type is coded handgraded or not. --- sub response_type { - my ($symb) = shift; + my ($symb,$response_error) = @_; my $navmap = Apache::lonnavmaps::navmap->new(); + unless (ref($navmap)) { + if (ref($response_error)) { + $$response_error = 1; + } + return; + } my $res = $navmap->getBySymb($symb); my $partlist = $res->parts(); my %vPart = @@ -183,7 +195,8 @@ sub get_display_part { my ($partID,$symb)=@_; my $display=&Apache::lonnet::EXT('resource.'.$partID.'.display',$symb); if (defined($display) and $display ne '') { - $display.= " (id $partID)"; + $display.= ' (' + .&mt('Part ID: [_1]',$partID).')'; } else { $display=$partID; } @@ -193,12 +206,17 @@ sub get_display_part { #--- Show resource title #--- and parts and response type sub showResourceInfo { - my ($symb,$probTitle,$checkboxes) = @_; + my ($symb,$probTitle,$checkboxes,$res_error) = @_; my $col=3; if ($checkboxes) { $col=4; } 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 .=''; - my ($partlist,$handgrade,$responseType) = &response_type($symb); my %resptype = (); my $hdgrade='no'; my %partsseen; @@ -217,9 +235,9 @@ sub showResourceInfo { $partsseen{$partID}=1; } my $display_part=&get_display_part($partID,$symb); - $result.=''. - ''; + ''; # ''; } } @@ -766,7 +784,13 @@ sub verifyreceipt { if ($env{"course.$courseid.receiptalg"} eq 'receipt2' || $env{"course.$courseid.receiptalg"} eq 'receipt3') { $receiptparts=1; } my $parts=['0']; - if ($receiptparts) { ($parts)=&response_type($symb); } + if ($receiptparts) { + my $res_error; + ($parts)=&response_type($symb,\$res_error); + if ($res_error) { + return &navmap_errormsg(); + } + } my $header = &Apache::loncommon::start_data_table(). @@ -1734,7 +1758,7 @@ sub gradeBox { #&mt('',$display_part,$radio,$line); $result .= - ''; + ''; $result.='
'.&mt('Part').': '.$display_part. + $result.=''.&mt('Part: [_1]',$display_part).''. ' '.$resID.''.&mt('Type').': '.$responsetype.'
'.&mt('Type: [_1]',$responsetype).'
'.&mt('Handgrade: [_1]',$handgrade).'
Part:[_1]Points:[_2]or[_3]'.&mt('Part').':'.$display_part.''.&mt('Points').':'.$radio.''.&mt('or').''.$line.''.&mt('Part:').''.$display_part.''.&mt('Points:').''.$radio.''.&mt('or').''.$line.'
'."\n"; $result.=''."\n". ''."\n". @@ -1744,13 +1768,17 @@ sub gradeBox { $$record{'resource.'.$partid.'.tries'}.'" />'."\n". ''."\n"; - $result.=&handback_box($symb,$uname,$udom,$counter,$partid,$record); + my $res_error; + $result.=&handback_box($symb,$uname,$udom,$counter,$partid,$record,\$res_error); + if ($res_error) { + return &navmap_errormsg(); + } return $result; } sub handback_box { - my ($symb,$uname,$udom,$counter,$partid,$record) = @_; - my ($partlist,$handgrade,$responseType) = &response_type($symb); + my ($symb,$uname,$udom,$counter,$partid,$record,$res_error) = @_; + my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error); my (@respids); my @part_response_id = &flatten_responseType($responseType); foreach my $part_response_id (@part_response_id) { @@ -2045,7 +2073,12 @@ KEYWORDS } my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname); - my ($partlist,$handgrade,$responseType) = &response_type($symb); + my $res_error; + my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error); + if ($res_error) { + $request->print(&navmap_errormsg()); + return; + } # Display student info $request->print(($counter == 0 ? '' : '
')); @@ -2112,9 +2145,11 @@ KEYWORDS } my $responsetype = $responseType->{$partid}->{$respid}; if (!exists($record{"resource.$partid.$respid.submission"})) { - $lastsubonly.="\n".'
Part: '. - $display_part.' ( ID '.$respid. - ' )   '. + $lastsubonly.="\n".'
'. + ''.&mt('Part: [_1]',$display_part).''. + ' '. + '('.&mt('Part ID: [_1]',$respid).')'. + '   '. ''.&mt('Nothing submitted - no attempts.').'

'; next; } @@ -2150,9 +2185,11 @@ KEYWORDS ($env{'form.lastSub'} eq 'hdgrade' && $$handgrade{$$part[0].'_'.$$part[1]} eq 'yes')) { my $display_part=&get_display_part($partid,$symb); - $lastsubonly.='
Part: '. - $display_part.' ( ID '.$respid. - ' )   '; + $lastsubonly.='
'. + ''.&mt('Part: [_1]',$display_part).''. + ' '. + '('.&mt('Part ID: [_1]',$respid).')'. + '   '; my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record); if (@$files) { $lastsubonly.='
'.&mt('Like all files provided by users, this file may contain viruses').'
'; @@ -2592,7 +2629,12 @@ sub processHandGrade { } $ctr = 0; @parsedlist = reverse @parsedlist if ($button eq 'Previous'); - my ($partlist) = &response_type($symb); + my $res_error; + my ($partlist) = &response_type($symb,\$res_error); + if ($res_error) { + $request->print(&navmap_errormsg()); + return; + } foreach my $student (@parsedlist) { my $submitonly=$env{'form.submitonly'}; my ($uname,$udom) = split(/:/,$student); @@ -2790,8 +2832,12 @@ sub check_and_remove_from_queue { sub handback_files { my ($request,$symb,$stuname,$domain,$newflg,$new_part,$newrecord) = @_; my $portfolio_root = '/userfiles/portfolio'; - my ($partlist,$handgrade,$responseType) = &response_type($symb); - + my $res_error; + my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error); + if ($res_error) { + $request->print('
'.&navmap_errormsg().'
'); + return; + } my @part_response_id = &flatten_responseType($responseType); foreach my $part_response_id (@part_response_id) { my ($part_id,$resp_id) = @{ $part_response_id }; @@ -3249,7 +3295,11 @@ sub viewgrades { $result.= '

'.$common_header.'

'.&Apache::loncommon::start_data_table(); #radio buttons/text box for assigning points for a section or class. #handles different parts of a problem - my ($partlist,$handgrade,$responseType) = &response_type($symb); + my $res_error; + my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error); + if ($res_error) { + return &navmap_errormsg(); + } my %weight = (); my $ctsparts = 0; my %seen = (); @@ -3293,7 +3343,7 @@ sub viewgrades { $result.= &Apache::loncommon::start_data_table_row()."\n". - ''.&mt('Part').':'.$display_part.''.&mt('Points').':'.$radio.''.&mt('or').''.$line.''. + ''.&mt('Part:').''.$display_part.''.&mt('Points:').''.$radio.''.&mt('or').''.$line.''. &Apache::loncommon::end_data_table_row()."\n"; $ctsparts++; } @@ -3309,7 +3359,11 @@ sub viewgrades { &Apache::loncommon::start_data_table_header_row(). ''.&mt('No.').''. ''.&nameUserString('header')."\n"; - my (@parts) = sort(&getpartlist($symb)); + my $partserror; + my (@parts) = sort(&getpartlist($symb,\$partserror)); + if ($partserror) { + return &navmap_errormsg(); + } my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb); my @partids = (); foreach my $part (@parts) { @@ -3468,7 +3522,11 @@ sub editgrades { my %columns = (); my ($i,$ctr,$count,$rec_update) = (0,0,0,0); - my (@parts) = sort(&getpartlist($symb)); + my $partserror; + my (@parts) = sort(&getpartlist($symb,\$partserror)); + if ($partserror) { + return &navmap_errormsg(); + } my $header; while ($ctr < $env{'form.totalparts'}) { my $partid = $env{'form.partid_'.$ctr}; @@ -3800,8 +3858,14 @@ ENDPICK } sub csvupload_fields { - my ($symb) = @_; - my (@parts) = &getpartlist($symb); + my ($symb,$errorref) = @_; + my (@parts) = &getpartlist($symb,$errorref); + if (ref($errorref)) { + if ($$errorref) { + return; + } + } + my @fields=(['ID','Student/Employee ID'], ['username','Student Username'], ['domain','Student Domain']); @@ -3901,8 +3965,12 @@ sub csvuploadmap { &csvuploadmap_header($request,$symb,$datatoken,$#records+1); my ($i,$keyfields); if (@records) { - my @fields=&csvupload_fields($symb); - + my $fieldserror; + my @fields=&csvupload_fields($symb,\$fieldserror); + if ($fieldserror) { + $request->print(&navmap_errormsg()); + return; + } if ($env{'form.upfile_associate'} eq 'reverse') { &Apache::loncommon::csv_print_samples($request,\@records); $i=&Apache::loncommon::csv_print_select_table($request,\@records, @@ -4138,7 +4206,12 @@ LISTJAVASCRIPT &mt('Manual Grading by Page or Sequence').''; $result.='
'."\n"; - my ($titles,$symbx) = &getSymbMap(); + my $map_error; + my ($titles,$symbx) = &getSymbMap($map_error); + if ($map_error) { + $request->print(&navmap_errormsg()); + return; + } my ($curpage) =&Apache::lonnet::decode_symb($symb); # my ($curpage,$mapId) =&Apache::lonnet::decode_symb($symb); # my $type=($curpage =~ /\.(page|sequence)/); @@ -4233,8 +4306,14 @@ LISTJAVASCRIPT } sub getSymbMap { + my ($map_error) = @_; my $navmap = Apache::lonnavmaps::navmap->new(); - + unless (ref($navmap)) { + if (ref($map_error)) { + $$map_error = 'navmap'; + } + return; + } my %symbx = (); my @titles = (); my $minder = 0; @@ -4293,6 +4372,11 @@ sub displayPage { $request->print($result); my $navmap = Apache::lonnavmaps::navmap->new(); + unless (ref($navmap)) { + $request->print(&navmap_errormsg()); + $request->print(&show_grading_menu_form($symb)); + return; + } my ($mapUrl, $id, $resUrl)=&Apache::lonnet::decode_symb($env{'form.page'}); my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps if (!$map) { @@ -4465,13 +4549,16 @@ sub displaySubByDates { my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/) : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/)); - $displaySub[0].=''.&mt('Part:').' '.$display_part.' '; - $displaySub[0].='('.&mt('ID').' '. - $responseId.') '; + $displaySub[0].='' + .' ' + .'('.&mt('Part ID: [_1]',$responseId).')' + .'' + .' '; if ($$record{"$where.$partid.tries"} eq '') { - $displaySub[0].=&mt('Trial not counted'); + $displaySub[0].=&mt('Trial not counted'); } else { - $displaySub[0].=&mt('Trial [_1]', + $displaySub[0].=&mt('Trial: [_1]', $$record{"$where.$partid.tries"}); } my $responseType=($isTask ? 'Task' @@ -4482,7 +4569,8 @@ sub displaySubByDates { &get_order($partid,$responseId,$symb,$uname,$udom, $no_increment); } - $displaySub[0].='  '. + $displaySub[0].=''; # /nobreak + $displaySub[0].='  '. &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:",$uname,$udom).'
'; } } @@ -4543,7 +4631,12 @@ sub updateGradeByPage { $request->print($result); + my $navmap = Apache::lonnavmaps::navmap->new(); + unless (ref($navmap)) { + $request->print(&navmap_errormsg()); + return; + } my ($mapUrl, $id, $resUrl) = &Apache::lonnet::decode_symb( $env{'form.page'}); my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps if (!$map) { @@ -4688,7 +4781,7 @@ sub updateGradeByPage { # #------------------------------------------------------------------- -#--------------------Bubblesheet (Scantron) Grading----------------------------------- +#-------------------- Bubblesheet (Scantron) Grading ------------------- # #------ start of section for handling grading by page/sequence --------- @@ -4766,14 +4859,19 @@ sub defaultFormData { Return html dropdown of possible sequences to grade Arguments: - $symb - $symb of the current resource + $symb - $symb of the current resource + $map_error - ref to scalar which will container error if + $navmap object is unavailable in &getSymbMap(). =cut sub getSequenceDropDown { - my ($symb)=@_; + my ($symb,$map_error)=@_; my $result=''."\n". ''."\n". ''."\n"; - foreach my $menudata (@menu) { - if ($menudata->{'name'} ne &mt('Verify Receipt')) { - $Str .='

{'jscript'}. - ' href="'. - $menudata->{'url'}.'" >'. - $menudata->{'name'}."

\n"; - } else { - $Str .='
{'jscript'}. - ' onClick="javascript:checkChoice(document.forms.gradingMenu,\'5\',\'verify\')" '. - ' /> '. - &Apache::lonnet::recprefix($env{'request.course.id'}). - '-'; - } - $Str .= ' '.(' 'x8).$menudata->{'short_description'}. - "\n"; - } + + $Str .= Apache::lonhtmlcommon::generate_menu(@menu); + #$menudata->{'jscript'} + $Str .='
'. + &Apache::lonnet::recprefix($env{'request.course.id'}). + '-'; + $Str .="
\n"; my $receiptalert = &mt("Please enter a receipt number given by a student in the receipt box."); $request->print(<'."\n"; $result.=' -
-
-

- '.&mt('Grade Current Resource').' -

-
-
- '.$table.' -
-
-
- '.&mt('Sections').' -
-
- '."\n"; + $result.= $selsec; $result.= '   '; $result.=' -
-
-
-
- '.&mt('Groups').' -
-
- '.&Apache::lonstatistics::GroupSelect('group','multiple',5).' -
-
-
-
- '.&mt('Access Status').' -
-
- '.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,5,undef,'mult').' -
-
-
-
- '.&mt('Submission Status').' -
-
- + + + + - -
-
-
-
+ + + +
+ +
+
+
+
-
-
-
-
+ +

'.&mt('Grade Complete Folder for One Student').'

-
-
-
+
+
-
- +
+
-
-
-
'; $result .= &show_grading_menu_form($symb); return $result; @@ -8986,7 +9132,11 @@ sub assign_clicker_grades { my ($symb)=&get_symb($r); if (!$symb) {return '';} # See which part we are saving to - my ($partlist,$handgrade,$responseType) = &response_type($symb); + my $res_error; + my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error); + if ($res_error) { + return &navmap_errormsg(); + } # FIXME: This should probably look for the first handgradeable part my $part=$$partlist[0]; # Start screen output @@ -9090,6 +9240,13 @@ ENDHEADER return $result.&show_grading_menu_form($symb); } +sub navmap_errormsg { + return '
'. + &mt('An error occurred retrieving information about resources in the course.').'
'. + &mt('It is recommended that you [_1]re-initialize the course[_2] and then return to this grading page..','',''). + '
'; +} + sub handler { my $request=$_[0]; &reset_caches(); @@ -9315,6 +9472,13 @@ ssi_with_retries() =item scantron_get_maxbubble() : + Arguments: + $nav_error - Reference to scalar which is a flag to indicate a + failure to retrieve a navmap object. + if $nav_error is set to 1 by scantron_get_maxbubble(), the + calling routine should trap the error condition and display the warning + found in &navmap_errormsg(). + 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() @@ -9380,6 +9544,11 @@ ssi_with_retries() Validates all scanlines in the selected file to not have any invalid or underspecified student/employee IDs +=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. + =back =cut