';
@@ -6611,8 +6611,8 @@ sub scantron_warning_screen {
'.$CODElist.$lastbubblepoints.'
-
'.&mt('If this information is correct, please click on \'[_1]\'.',&mt($button_text)).'
-
'.&mt('If something is incorrect, please click the \'Grading Menu\' button to start over.').'
+
'.&mt("If this information is correct, please click on '[_1]'.",&mt($button_text)).'
+
'.&mt("If something is incorrect, please click the 'Grading Menu' button to start over.").'
');
@@ -7175,7 +7175,12 @@ sub scantron_validate_sequence {
my @resources=
$navmap->retrieveResources($map,\&scantron_filter_not_exam,1,0);
if (@resources) {
- $r->print("
".&mt('Some resources in the sequence currently are not set to exam mode. Grading these resources currently may not work correctly.')."
");
+ $r->print('
'
+ .&mt('Some resources in the sequence currently are not set to'
+ .' exam mode. Grading these resources currently may not'
+ .' work correctly.')
+ .'
'
+ );
return (1,$currentphase);
}
}
@@ -7306,7 +7311,7 @@ sub scantron_get_correction {
$r->print(&Apache::loncommon::selectstudent_link('scantronupload',
'scantron_username','scantron_domain'));
$r->print(": ");
- $r->print("\n@".
+ $r->print("\n:\n".
&Apache::loncommon::select_dom_form($env{'request.role.domain'},'scantron_domain'));
$r->print('');
@@ -7570,7 +7575,7 @@ sub prompt_for_corrections {
($responsetype_per_response{$question-1} eq 'imageresponse') ||
($responsetype_per_response{$question-1} eq 'reactionresponse') ||
($responsetype_per_response{$question-1} eq 'organicresponse')) {
- $r->print(&mt("Although this particular question type requires handgrading, the instructions for this question in the exam directed students to leave [quant,_1,line] blank on their bubblesheets.",$lines).'
'.&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.').' '.&mt('The score for this question will be a sum of the numeric values for the selected bubbles from each line, where A=1 point, B=2 points etc.').' '.&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.").'
');
+ $r->print(&mt("Although this particular question type requires handgrading, the instructions for this question in the bubblesheet exam directed students to leave [quant,_1,line] blank on their bubblesheets.",$lines).'
'.&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.').' '.&mt('The score for this question will be a sum of the numeric values for the selected bubbles from each line, where A=1 point, B=2 points etc.').' '.&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.").'
');
} else {
$r->print(&mt("Select at most one bubble in a single line and select 'No Bubble' in all the other lines. ")." ");
}
@@ -8085,15 +8090,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;
@@ -8180,10 +8191,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();
@@ -8215,16 +8242,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("");
@@ -8242,7 +8261,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'},
@@ -8253,7 +8272,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("");
@@ -8265,7 +8284,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'},
@@ -8341,6 +8360,53 @@ 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) = @_;
if (ref($resources) eq 'ARRAY') {
@@ -8602,7 +8668,7 @@ sub scantron_download_scantron_data {
if (! &valid_file($file)) {
$r->print('
- '.&mt('The requested file name was invalid.').'
+ '.&mt('The requested filename was invalid.').'
');
$r->print(&show_grading_menu_form($symb));
@@ -8656,11 +8722,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('
@@ -8671,7 +8747,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) {
@@ -8715,9 +8791,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})) ||
@@ -8778,7 +8871,11 @@ 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:').'