--- loncom/homework/grades.pm 2012/11/09 15:31:42 1.676 +++ loncom/homework/grades.pm 2012/12/18 18:03:40 1.682 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.676 2012/11/09 15:31:42 goltermann Exp $ +# $Id: grades.pm,v 1.682 2012/12/18 18:03:40 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -4650,8 +4650,8 @@ sub displayPage { &Apache::loncommon::start_data_table_row(). ''.$prob. (scalar(@{$parts}) == 1 ? '' - : '
('.&mt('[_1]parts)', - scalar(@{$parts}).' ') + : '
('.&mt('[_1]parts', + scalar(@{$parts}).' ').')' ). ''; $studentTable.=''; @@ -6441,7 +6441,7 @@ sub scantron_warning_screen { '.&mt('Data File that will be used:').''.$env{'form.scantron_selectfile'}.' '.$CODElist.$lastbubblepoints.' -

'.&mt('If this information is correct, please click on \'[_1]\'.',&mt($button_text)).'
+

'.&mt("If this information is correct, please click on '[_1]'.",&mt($button_text)).'
'.&mt('If something is incorrect, please return to [_1]Grade/Manage/Review Bubblesheets[_2] to start over.','','').'


@@ -7914,15 +7914,21 @@ sub scantron_process_students { return ''; } my $map=$navmap->getResourceByUrl($sequence); + my $randomorder; + if (ref($map)) { + $randomorder = $map->randomorder(); + } my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); - my (%grader_partids_by_symb,%grader_randomlists_by_symb); + my (%grader_partids_by_symb,%grader_randomlists_by_symb,%ordered); &graders_resources_pass(\@resources,\%grader_partids_by_symb, \%grader_randomlists_by_symb,$bubbles_per_row); - my $resource_error; + my ($resource_error,%symb_to_resource,@master_seq); foreach my $resource (@resources) { my $ressymb; if (ref($resource)) { $ressymb = $resource->symb(); + push(@master_seq,$ressymb); + $symb_to_resource{$ressymb} = $resource; } else { $resource_error = 1; last; @@ -8006,10 +8012,26 @@ SCANTRONFORM 'Student '.$uname.' has multiple sheets',2); next; } + my $usec = $classlist->{$uname}->[&Apache::loncoursedata::CL_SECTION]; + my $user = $uname.':'.$usec; ($uname,$udom)=split(/:/,$uname); + my $scancode; + if ((exists($scan_record->{'scantron.CODE'})) && + (&Apache::lonnet::validCODE($scan_record->{'scantron.CODE'}))) { + $scancode = $scan_record->{'scantron.CODE'}; + } else { + $scancode = ''; + } + + my @mapresources = @resources; + if ($randomorder) { + @mapresources = + &users_order($user,$scancode,$sequence,\@master_seq,\%ordered, + \%symb_to_resource); + } my (%partids_by_symb,$res_error); - foreach my $resource (@resources) { + foreach my $resource (@mapresources) { my $ressymb; if (ref($resource)) { $ressymb = $resource->symb(); @@ -8041,16 +8063,8 @@ SCANTRONFORM &scantron_putfile($scanlines,$scan_data); } - my $scancode; - if ((exists($scan_record->{'scantron.CODE'})) && - (&Apache::lonnet::validCODE($scan_record->{'scantron.CODE'}))) { - $scancode = $scan_record->{'scantron.CODE'}; - } else { - $scancode = ''; - } - if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode, - \@resources,\%partids_by_symb, + \@mapresources,\%partids_by_symb, $bubbles_per_row) eq 'ssi_error') { $ssi_error = 0; # So end of handler error message does not trigger. $r->print(""); @@ -8067,7 +8081,7 @@ SCANTRONFORM $studentdata =~ s/\r$//; my $studentrecord = ''; my $counter = -1; - foreach my $resource (@resources) { + foreach my $resource (@mapresources) { my $ressymb = $resource->symb(); ($counter,my $recording) = &verify_scantron_grading($resource,$udom,$uname,$env{'request.course.id'}, @@ -8078,7 +8092,7 @@ SCANTRONFORM if ($studentrecord ne $studentdata) { &Apache::lonxml::clear_problem_counter(); if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode, - \@resources,\%partids_by_symb, + \@mapresources,\%partids_by_symb, $bubbles_per_row) eq 'ssi_error') { $ssi_error = 0; # So end of handler error message does not trigger. $r->print(""); @@ -8089,7 +8103,7 @@ SCANTRONFORM } $counter = -1; $studentrecord = ''; - foreach my $resource (@resources) { + foreach my $resource (@mapresources) { my $ressymb = $resource->symb(); ($counter,my $recording) = &verify_scantron_grading($resource,$udom,$uname,$env{'request.course.id'}, @@ -8164,9 +8178,55 @@ sub graders_resources_pass { return; } +=pod + +=item users_order + + Returns array of resources in current map, ordered based on either CODE, + if this is a CODEd exam, or based on student's identity if this is a + "NAMEd" exam. + + Should be used when randomorder applied when the corresponding exam was + printed, prior to students completing bubblesheets for the version of the + exam the student received. + +=cut + +sub users_order { + my ($user,$scancode,$mapurl,$master_seq,$ordered,$symb_to_resource) = @_; + my @mapresources; + unless ((ref($ordered) eq 'HASH') && (ref($symb_to_resource) eq 'HASH')) { + return @mapresources; + } + if (($scancode) && (ref($ordered->{$scancode}) eq 'ARRAY')) { + @mapresources = @{$ordered->{$scancode}}; + } elsif ($scancode) { + $env{'form.CODE'} = $scancode; + my $actual_seq = + &Apache::lonprintout::master_seq_to_person_seq($mapurl, + $master_seq, + $user,$scancode); + if (ref($actual_seq) eq 'ARRAY') { + @{$ordered->{$scancode}} = + map { $symb_to_resource->{$_}; } @{$actual_seq}; + @mapresources = @{$ordered->{$scancode}}; + } + delete($env{'form.CODE'}); + } else { + my $actual_seq = + &Apache::lonprintout::master_seq_to_person_seq($mapurl, + $master_seq, + $user); + if (ref($actual_seq) eq 'ARRAY') { + @mapresources = + map { $symb_to_resource->{$_}; } @{$actual_seq}; + } + } + return @mapresources; +} + sub grade_student_bubbles { - my ($r,$uname,$udom,$scan_record,$scancode,$resources,$parts,$bubbles_per_row) = @_; -# Walk folder as student here to get resources in order student sees. + my ($r,$uname,$udom,$scan_record,$scancode,$resources,$parts,$bubbles_per_row) = @_; if (ref($resources) eq 'ARRAY') { my $count = 0; foreach my $resource (@{$resources}) { @@ -8470,11 +8530,21 @@ sub checkscantron_results { return ''; } my $map=$navmap->getResourceByUrl($sequence); + my ($randomorder,@master_seq,%symb_to_resource); + if (ref($map)) { + $randomorder=$map->randomorder(); + } my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); + foreach my $resource (@resources) { + if (ref($resource)) { + my $ressymb = $resource->symb(); + push(@master_seq,$ressymb); + $symb_to_resource{$ressymb} = $resource; + } + } my (%grader_partids_by_symb,%grader_randomlists_by_symb); &graders_resources_pass(\@resources,\%grader_partids_by_symb, \%grader_randomlists_by_symb,$bubbles_per_row); - my ($uname,$udom); my (%scandata,%lastname,%bylast); $r->print(' @@ -8485,7 +8555,7 @@ sub checkscantron_results { my $count=&Apache::grades::get_todo_count($scanlines,$scan_data); my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,$count); - my ($username,$domain,$started); + my ($username,$domain,$started,%ordered); my $nav_error; &scantron_get_maxbubble(\$nav_error,\%scantron_config); # Need the bubble lines array to parse. if ($nav_error) { @@ -8527,9 +8597,26 @@ sub checkscantron_results { $scandata{$pid} = substr($line,$scantron_config{'Qstart'}-1,$lastpos); chomp($scandata{$pid}); $scandata{$pid} =~ s/\r$//; + my $usec = $classlist->{$uname}->[&Apache::loncoursedata::CL_SECTION]; + my $user = $uname.':'.$usec; ($username,$domain)=split(/:/,$uname); + + my $scancode; + if ((exists($scan_record->{'scantron.CODE'})) && + (&Apache::lonnet::validCODE($scan_record->{'scantron.CODE'}))) { + $scancode = $scan_record->{'scantron.CODE'}; + } else { + $scancode = ''; + } + + my @mapresources = @resources; + if ($randomorder) { + @mapresources = + &users_order($user,$scancode,$sequence,\@master_seq,\%ordered, + \%symb_to_resource); + } my $counter = -1; - foreach my $resource (@resources) { + foreach my $resource (@mapresources) { my $parts; my $ressymb = $resource->symb(); if ((exists($grader_randomlists_by_symb{$ressymb})) || @@ -8591,7 +8678,12 @@ sub checkscantron_results { $env{'form.scantron_maxbubble'}) .'

' ); - $r->print('

'.&mt('Exact matches for [quant,_1,student].',$passed).'
'.&mt('Discrepancies detected for [quant,_1,student].',$failed).'

'); + $r->print('

' + .&mt('Exact matches for [_1][quant,_2,student][_3].','',$passed,''). + .'
' + .&mt('Discrepancies detected for [_1][quant,_2,student][_3].','',$failed,'') + .'

' + ); if ($passed) { $r->print(&mt('Students with exact correspondence between bubblesheet data and submissions are as follows:').'

'); $r->print(&Apache::loncommon::start_data_table()."\n".