--- loncom/homework/grades.pm	2012/12/10 01:13:08	1.677
+++ loncom/homework/grades.pm	2013/06/01 00:22:42	1.689
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # The LON-CAPA Grading handler
 #
-# $Id: grades.pm,v 1.677 2012/12/10 01:13:08 raeburn Exp $
+# $Id: grades.pm,v 1.689 2013/06/01 00:22:42 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -3101,7 +3101,7 @@ sub handback_files {
                         &Apache::lonnet::dirlist($portfolio_root.$portfolio_path,
                                                  $domain,$stuname,$getpropath);
 		    my $version = &get_next_version($answer_name,$answer_ext,$dir_list);
-                    # fix file name
+                    # fix filename
                     my ($save_file_name) = (($directory.$answer_name.".$version.".$answer_ext) =~ /^.+\/${stuname}\/(.*)/);
                     my $result=&Apache::lonnet::finishuserfileupload($stuname,$domain,
             	                                $newflg.'_'.$part_resp.'_returndoc'.$counter,
@@ -3120,7 +3120,7 @@ sub handback_files {
                         $$newrecord{"resource.$new_part.$resp_id.handback"} .= $save_file_name;
 			$file_msg.= '<span class="LC_filename"><a href="/uploaded/'."$domain/$stuname/".$save_file_name.'">'.$save_file_name."</a></span> <br />";
                     }
-                    $request->print('<br />'.&mt('[_1] will be the uploaded file name [_2]','<span class="LC_info">'.$fname.'</span>','<span class="LC_filename">'.$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter}.'</span>'));
+                    $request->print('<br />'.&mt('[_1] will be the uploaded filename [_2]','<span class="LC_info">'.$fname.'</span>','<span class="LC_filename">'.$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter}.'</span>'));
                 }
             }
         }
@@ -4650,8 +4650,8 @@ sub displayPage {
 		&Apache::loncommon::start_data_table_row().
 		'<td align="center" valign="top" >'.$prob.
 		(scalar(@{$parts}) == 1 ? '' 
-		                        : '<br />('.&mt('[_1]parts)',
-							scalar(@{$parts}).'&nbsp;')
+		                        : '<br />('.&mt('[_1]parts',
+							scalar(@{$parts}).'&nbsp;').')'
 		 ).
 		 '</td>';
 	    $studentTable.='<td valign="top">';
@@ -6441,7 +6441,7 @@ sub scantron_warning_screen {
 <tr><td><b>'.&mt('Data File that will be used:').'</b></td><td><tt>'.$env{'form.scantron_selectfile'}.'</tt></td></tr>
 '.$CODElist.$lastbubblepoints.'
 </table>
-<p> '.&mt('If this information is correct, please click on \'[_1]\'.',&mt($button_text)).'<br />
+<p> '.&mt("If this information is correct, please click on '[_1]'.",&mt($button_text)).'<br />
 '.&mt('If something is incorrect, please return to [_1]Grade/Manage/Review Bubblesheets[_2] to start over.','<a href="/adm/grades?symb='.$symb.'&command=scantron_selectphase" class="LC_info">','</a>').'</p>
 
 <br />
@@ -7006,7 +7006,7 @@ sub scantron_validate_sequence {
 	    $r->print(
                 '<p class="LC_warning">'
                .&mt('Some resources in the sequence currently are not set to'
-                   .' exam mode. Grading these resources currently may not'
+                   .' bubblesheet exam mode. Grading these resources currently may not'
                    .' work correctly.')
                .'</p>'
             );
@@ -7140,7 +7140,7 @@ sub scantron_get_correction {
 	$r->print(&Apache::loncommon::selectstudent_link('scantronupload',
 				       'scantron_username','scantron_domain'));
 	$r->print(": <input type='text' name='scantron_username' value='' />");
-	$r->print("\n@".
+	$r->print("\n:\n".
 		 &Apache::loncommon::select_dom_form($env{'request.role.domain'},'scantron_domain'));
 
 	$r->print('</li>');
@@ -7400,7 +7400,16 @@ 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).'<br /><br />'.&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.').'<br />'.&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.').'<br />'.&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.").'<br /><br />');
+            $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)
+               .'<br /><br />'
+               .&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.')
+               .'<br />'
+               .&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.')
+               .'<br />'
+               .&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.")
+               .'<br /><br />'
+            );
         } else {
             $r->print(&mt("Select at most one bubble in a single line and select 'No Bubble' in all the other lines. ")."<br />");
         }
@@ -7914,9 +7923,10 @@ sub scantron_process_students {
         return '';
     }  
     my $map=$navmap->getResourceByUrl($sequence);
-    my $randomorder;
+    my ($randomorder,$randompick);
     if (ref($map)) {
         $randomorder = $map->randomorder();
+        $randompick = $map->randompick();
     }
     my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
     my (%grader_partids_by_symb,%grader_randomlists_by_symb,%ordered);
@@ -8025,22 +8035,10 @@ SCANTRONFORM
         }
 
         my @mapresources = @resources;
-        if ($randomorder && $scancode) {
-            unless (ref($ordered{$scancode}) eq 'ARRAY') {
-                $env{'form.CODE'} = $scancode;
-                my $actual_seq =
-                    &Apache::lonprintout::master_seq_to_person_seq($sequence,
-                                                                   \@master_seq,
-                                                                   $user,$scancode);
-                if (ref($actual_seq) eq 'ARRAY') {
-                    @{$ordered{$scancode}} = 
-                        map { $symb_to_resource{$_}; } @{$actual_seq};
-                }
-                delete($env{'form.CODE'});
-            }
-            if (ref($ordered{$scancode}) eq 'ARRAY') {
-                @mapresources = @{$ordered{$scancode}};
-            }
+        if ($randomorder || $randompick) {
+            @mapresources = 
+                &users_order($user,$scancode,$sequence,\@master_seq,\%ordered,
+                             \%symb_to_resource);
         }
         my (%partids_by_symb,$res_error);
         foreach my $resource (@mapresources) {
@@ -8190,6 +8188,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,1);
+        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,undef,1);
+        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') {
@@ -8445,7 +8490,7 @@ sub scantron_download_scantron_data {
     if (! &valid_file($file)) {
 	$r->print('
 	<p>
-	    '.&mt('The requested file name was invalid.').'
+	    '.&mt('The requested filename was invalid.').'
         </p>
 ');
 	return;
@@ -8495,11 +8540,19 @@ sub checkscantron_results {
         return '';
     }
     my $map=$navmap->getResourceByUrl($sequence);
-    my $randomorder;
+    my ($randomorder,$randompick,@master_seq,%symb_to_resource);
     if (ref($map)) { 
         $randomorder=$map->randomorder();
+        $randompick=$map->randompick();
     }
     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);
@@ -8513,7 +8566,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) {
@@ -8555,9 +8608,11 @@ 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,%ordered);
+        my $scancode;
         if ((exists($scan_record->{'scantron.CODE'})) &&
             (&Apache::lonnet::validCODE($scan_record->{'scantron.CODE'}))) {
             $scancode = $scan_record->{'scantron.CODE'};
@@ -8566,18 +8621,10 @@ sub checkscantron_results {
         }
 
         my @mapresources = @resources;
-        if ($randomorder && $scancode) {
-            unless (ref($ordered{$scancode}) eq 'ARRAY') {
-                $env{'form.CODE'} = $scancode;
-                $ordered{$scancode} = 
-                    &Apache::lonprintout::master_seq_to_person_seq($sequence,
-                                                                   \@resources,
-                                                                   $uname,$scancode);
-                delete($env{'form.CODE'});
-            }
-            if (ref($ordered{$scancode}) eq 'ARRAY') {
-                @mapresources = @{$ordered{$scancode}};
-            }
+        if ($randomorder || $randompick) {
+            @mapresources =
+                &users_order($user,$scancode,$sequence,\@master_seq,\%ordered,
+                             \%symb_to_resource);
         }
         my $counter = -1;
         foreach my $resource (@mapresources) {
@@ -8642,7 +8689,12 @@ sub checkscantron_results {
             $env{'form.scantron_maxbubble'})
        .'</p>'
     );
-    $r->print('<p>'.&mt('Exact matches for <b>[quant,_1,student]</b>.',$passed).'<br />'.&mt('Discrepancies detected for <b>[quant,_1,student]</b>.',$failed).'</p>');
+    $r->print('<p>'
+             .&mt('Exact matches for [_1][quant,_2,student][_3].','<b>',$passed,'</b>')
+             .'<br />'
+             .&mt('Discrepancies detected for [_1][quant,_2,student][_3].','<b>',$failed,'</b>')
+             .'</p>'
+    );
     if ($passed) {
         $r->print(&mt('Students with exact correspondence between bubblesheet data and submissions are as follows:').'<br /><br />');
         $r->print(&Apache::loncommon::start_data_table()."\n".
@@ -9707,6 +9759,7 @@ sub handler {
         }
     } elsif (!%perm) {
         $request->internal_redirect('/adm/quickgrades');
+        return OK;
     }
     &Apache::loncommon::content_type($request,'text/html');
     $request->send_http_header;