--- loncom/homework/grades.pm 2009/03/09 01:58:48 1.556 +++ loncom/homework/grades.pm 2010/04/13 16:12:54 1.617 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.556 2009/03/09 01:58:48 weissno Exp $ +# $Id: grades.pm,v 1.617 2010/04/13 16:12:54 www Exp $ # # Copyright Michigan State University Board of Trustees # @@ -96,10 +96,19 @@ 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) = @_; + 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(); @@ -114,21 +123,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("Unable to handle ambiguous references:$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 { @@ -144,10 +138,20 @@ 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); + unless (ref($res)) { + $$response_error = 1; + return; + } my $partlist = $res->parts(); my %vPart = map { $_ => 1 } (&Apache::loncommon::get_env_multiple('form.vPart')); @@ -183,50 +187,14 @@ 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; } return $display; } -#--- Show resource title -#--- and parts and response type -sub showResourceInfo { - my ($symb,$probTitle,$checkboxes) = @_; - my $col=3; - if ($checkboxes) { $col=4; } - my $result = '

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

'."\n"; - $result .=''; - my ($partlist,$handgrade,$responseType) = &response_type($symb); - 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.=''; - if ($checkboxes) { - if (exists($partsseen{$partID})) { - $result.=""; - } else { - $result.=""; - } - $partsseen{$partID}=1; - } - my $display_part=&get_display_part($partID,$symb); - $result.=''. - ''; -# ''; - } - } - $result.='
 '.&mt('Part').': '.$display_part. - ' '.$resID.''.&mt('Type').': '.$responsetype.'
'.&mt('Handgrade: [_1]',$handgrade).'
'."\n"; - return $result,$responseType,$hdgrade,$partlist,$handgrade; -} - sub reset_caches { &reset_analyze_cache(); &reset_perm(); @@ -234,28 +202,54 @@ sub reset_caches { { my %analyze_cache; + my %analyze_cache_formkeys; sub reset_analyze_cache { undef(%analyze_cache); + undef(%analyze_cache_formkeys); } sub get_analyze { - my ($symb,$uname,$udom,$no_increment)=@_; + my ($symb,$uname,$udom,$no_increment,$add_to_hash)=@_; my $key = "$symb\0$uname\0$udom"; - return $analyze_cache{$key} if (exists($analyze_cache{$key})); + if (exists($analyze_cache{$key})) { + my $getupdate = 0; + if (ref($add_to_hash) eq 'HASH') { + foreach my $item (keys(%{$add_to_hash})) { + if (ref($analyze_cache_formkeys{$key}) eq 'HASH') { + if (!exists($analyze_cache_formkeys{$key}{$item})) { + $getupdate = 1; + last; + } + } else { + $getupdate = 1; + } + } + } + if (!$getupdate) { + return $analyze_cache{$key}; + } + } my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb); $url=&Apache::lonnet::clutter($url); - my $subresult=&ssi_with_retries($url, $ssi_retries, - ('grade_target' => 'analyze', - 'grade_domain' => $udom, - 'grade_symb' => $symb, - 'grade_courseid' => - $env{'request.course.id'}, - 'grade_username' => $uname, - 'grade_noincrement' => $no_increment)); + my %form = ('grade_target' => 'analyze', + 'grade_domain' => $udom, + 'grade_symb' => $symb, + 'grade_courseid' => $env{'request.course.id'}, + 'grade_username' => $uname, + 'grade_noincrement' => $no_increment); + if (ref($add_to_hash)) { + %form = (%form,%{$add_to_hash}); + } + my $subresult=&ssi_with_retries($url, $ssi_retries,%form); (undef,$subresult)=split(/_HASH_REF__/,$subresult,2); my %analyze=&Apache::lonnet::str2hash($subresult); + if (ref($add_to_hash) eq 'HASH') { + $analyze_cache_formkeys{$key} = $add_to_hash; + } else { + $analyze_cache_formkeys{$key} = {}; + } return $analyze_cache{$key} = \%analyze; } @@ -279,11 +273,15 @@ sub reset_caches { } sub scantron_partids_tograde { - my ($resource,$cid,$uname,$udom) = @_; + my ($resource,$cid,$uname,$udom,$check_for_randomlist) = @_; my (%analysis,@parts); if (ref($resource)) { my $symb = $resource->symb(); - my $analyze = &get_analyze($symb,$uname,$udom); + my $add_to_form; + if ($check_for_randomlist) { + $add_to_form = { 'check_parts_withrandomlist' => 1,}; + } + my $analyze = &get_analyze($symb,$uname,$udom,undef,$add_to_form); if (ref($analyze) eq 'HASH') { %analysis = %{$analyze}; } @@ -366,7 +364,7 @@ sub cleanRecord { return '
'. ''.$toprow.''. ''. - $grayFont.$bottomrow.''.'
'.&mt('Answer').'
'.$grayFont.&mt('Option ID').'
'; + $bottomrow.''.''; } elsif ($response eq 'essay') { if (! exists ($env{'form.'.$symb})) { my (%keyhash) = &Apache::lonnet::dump('nohist_handgrade', @@ -428,8 +426,7 @@ sub cleanRecord { #-- A couple of common js functions sub commonJSfunctions { my $request = shift; - $request->print(< + $request->print(&Apache::lonhtmlcommon::scripttag(< 1) { @@ -457,7 +454,6 @@ sub commonJSfunctions { return selectOne.value; } } - COMMONJSFUNCTIONS } @@ -612,17 +608,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". @@ -675,7 +669,7 @@ sub most_similar { # ignore empty submissions (occuring when only files are sent) - unless ($uessay=~/\w+/) { return ''; } + unless ($uessay=~/\w+/s) { return ''; } # these will be returned. Do not care if not at least 50 percent similar my $limit=0.6; @@ -712,22 +706,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'); @@ -736,7 +739,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(). @@ -778,17 +787,20 @@ sub verifyreceipt { } } if ($matches == 0) { - $string = $title.&mt('No match found for the above receipt.'); + $string = $title + .'

' + .&mt('No match found for the above receipt number.') + .'

'; } else { $string = &jscriptNform($symb).$title. '

'. - &mt('The above receipt matches the following [numerate,_1,student].',$matches). + &mt('The above receipt number matches the following [quant,_1,student].',$matches). '

'. $header. $contents. &Apache::loncommon::end_data_table()."\n"; } - return $string.&show_grading_menu_form($symb); + return $string; } #--- This is called by a number of programs. @@ -796,32 +808,30 @@ 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'}; + unless ($submitonly) { + $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") .'

'; - my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($symb,$env{'form.probTitle'},($env{'form.showgrading'} eq 'yes')); - - my %lt = ( 'multiple' => - &mt("Please select a student or group of students before clicking on the Next button."), - 'single' => - &mt("Please select the student before clicking on the Next button."), - ); - %lt = &Apache::lonlocal::texthash(%lt); - $request->print(< + 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(&Apache::lonhtmlcommon::scripttag(< LISTJAVASCRIPT &commonJSfunctions($request); @@ -859,18 +868,19 @@ LISTJAVASCRIPT my $checkhdgrade = ($env{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1 ) ? 'checked="checked"' : ''; my $checklastsub = $checkhdgrade eq '' ? 'checked="checked"' : ''; my $gradeTable='
'. - "\n".$table; + "\n"; - $gradeTable .= - ' '.&mt('View Problem Text').': '. - ''."\n". - ''."\n". - '
'."\n"; - $gradeTable .= - ' '.&mt('View Answer').': '. - ''."\n". - ''."\n". - '
'."\n"; + $gradeTable .= &Apache::lonhtmlcommon::start_pick_box(); + $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Problem Text')) + .''."\n" + .''."\n" + .'
'."\n" + .&Apache::lonhtmlcommon::row_closure(); + $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Answer')) + .''."\n" + .''."\n" + .'
'."\n" + .&Apache::lonhtmlcommon::row_closure(); my $submission_options; if ($env{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1) { @@ -881,49 +891,64 @@ LISTJAVASCRIPT my $saveStatus = $stu_status eq '' ? 'Active' : $stu_status; $env{'form.Status'} = $saveStatus; $submission_options.= - ''."\n". - ''."\n". - ''."\n". - ''; - $gradeTable .= - ' '.&mt('Submissions').': '.$submission_options.'
'."\n"; + ''. + ''."\n". + ''. + ''."\n". + ''. + ''."\n". + ''. + ''; + $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Submissions')) + .$submission_options + .&Apache::lonhtmlcommon::row_closure(); + + $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Grading Increments')) + .'' + .&Apache::lonhtmlcommon::row_closure(); $gradeTable .= - ' '.&mt('Grading Increments').': '. - ''; - - $gradeTable .= &build_section_inputs(). ''."\n". '
'."\n". '
'."\n". - ''."\n". - ''."\n". ''."\n". ''."\n"; if (exists($env{'form.gradingMenu'}) && exists($env{'form.Status'})) { - $gradeTable.=''."\n"; + $gradeTable .= ''."\n"; } else { - $gradeTable.=&mt('Student Status: [_1]', - &Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,'javascript:reLoadList(this.form);')).'
'; + $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Student Status')) + .&Apache::lonhtmlcommon::StatusOptions( + $saveStatus,undef,1,'javascript:reLoadList(this.form);') + .&Apache::lonhtmlcommon::row_closure(); } - $gradeTable.=&mt('To '.lc($viewgrade)." 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". - ''."\n"; + $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Check For Plagiarism')) + .'' + .&Apache::lonhtmlcommon::row_closure(1) + .&Apache::lonhtmlcommon::end_pick_box(); + + $gradeTable .= '

' + .&mt('To '.lc($viewgrade)." 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" + .'' + .'

'; # checkall buttons $gradeTable.=&check_script('gradesub', 'stuinfo'); $gradeTable.='
'."\n"; + 'onclick="javascript:checkSelect(this.form.stuinfo);" '."\n". + 'value="'.&mt('Next').' →" />
'."\n"; $gradeTable.=&check_buttons(); - $gradeTable.=''; my ($classlist, undef, $fullname) = &getclasslist($getsec,'1',$getgroup); $gradeTable.= &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(); @@ -1006,7 +1031,7 @@ LISTJAVASCRIPT $gradeTable.= &Apache::loncommon::start_data_table_row(); } $gradeTable.=''.$ctr.' '. - '