Diff for /loncom/homework/grades.pm between versions 1.596.2.12.2.56 and 1.768

version 1.596.2.12.2.56, 2021/01/05 22:01:28 version 1.768, 2020/05/08 14:56:53
Line 44  use Apache::Constants qw(:common :http); Line 44  use Apache::Constants qw(:common :http);
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonenc;  use Apache::lonenc;
 use Apache::lonstathelpers;  use Apache::lonstathelpers;
   use Apache::lonquickgrades;
 use Apache::bridgetask();  use Apache::bridgetask();
 use Apache::lontexconvert();  use Apache::lontexconvert();
   use String::Similarity;
 use HTML::Parser();  use HTML::Parser();
 use File::MMagic;  use File::MMagic;
 use String::Similarity;  
 use LONCAPA;  use LONCAPA;
   
 use POSIX qw(floor);  use POSIX qw(floor);
Line 118  sub getpartlist { Line 119  sub getpartlist {
     my $res      = $navmap->getBySymb($symb);      my $res      = $navmap->getBySymb($symb);
     my $partlist = $res->parts();      my $partlist = $res->parts();
     my $url      = $res->src();      my $url      = $res->src();
     my @metakeys = split(/,/,&Apache::lonnet::metadata($url,'keys'));      my $toolsymb;
       if ($url =~ /ext\.tool$/) {
           $toolsymb = $symb;
       }
       my @metakeys = split(/,/,&Apache::lonnet::metadata($url,'keys',$toolsymb));
   
     my @stores;      my @stores;
     foreach my $part (@{ $partlist }) {      foreach my $part (@{ $partlist }) {
Line 143  sub nameUserString { Line 148  sub nameUserString {
   
 #--- Get the partlist and the response type for a given problem. ---  #--- Get the partlist and the response type for a given problem. ---
 #--- Indicate if a response type is coded handgraded or not. ---  #--- Indicate if a response type is coded handgraded or not. ---
 #--- Count responseIDs, essayresponse items, and dropbox items ---  
 #--- Sets response_error pointer to "1" if navmaps object broken ---  #--- Sets response_error pointer to "1" if navmaps object broken ---
 sub response_type {  sub response_type {
     my ($symb,$response_error) = @_;      my ($symb,$response_error) = @_;
Line 161  sub response_type { Line 165  sub response_type {
         return;          return;
     }      }
     my $partlist = $res->parts();      my $partlist = $res->parts();
     my ($numresp,$numessay,$numdropbox) = (0,0,0);  
     my %vPart =       my %vPart = 
  map { $_ => 1 } (&Apache::loncommon::get_env_multiple('form.vPart'));   map { $_ => 1 } (&Apache::loncommon::get_env_multiple('form.vPart'));
     my (%response_types,%handgrade);      my (%response_types,%handgrade);
Line 171  sub response_type { Line 174  sub response_type {
  my @types = $res->responseType($part);   my @types = $res->responseType($part);
  my @ids = $res->responseIds($part);   my @ids = $res->responseIds($part);
  for (my $i=0; $i < scalar(@ids); $i++) {   for (my $i=0; $i < scalar(@ids); $i++) {
             $numresp ++;  
     $response_types{$part}{$ids[$i]} = $types[$i];      $response_types{$part}{$ids[$i]} = $types[$i];
             if ($types[$i] eq 'essay') {  
                 $numessay ++;  
                 if (&Apache::lonnet::EXT("resource.$part".'_'.$ids[$i].".uploadedfiletypes",$symb)) {  
                     $numdropbox ++;  
                 }  
             }  
     $handgrade{$part.'_'.$ids[$i]} =       $handgrade{$part.'_'.$ids[$i]} = 
  &Apache::lonnet::EXT('resource.'.$part.'_'.$ids[$i].   &Apache::lonnet::EXT('resource.'.$part.'_'.$ids[$i].
      '.handgrade',$symb);       '.handgrade',$symb);
  }   }
     }      }
     return ($partlist,\%handgrade,\%response_types,$numresp,$numessay,$numdropbox);      return ($partlist,\%handgrade,\%response_types);
 }  }
   
 sub flatten_responseType {  sub flatten_responseType {
Line 211  sub get_display_part { Line 207  sub get_display_part {
     return $display;      return $display;
 }  }
   
 #--- Show parts and response type  
 sub showResourceInfo {  
     my ($symb,$partlist,$responseType,$formname,$checkboxes,$uploads) = @_;  
     unless ((ref($partlist) eq 'ARRAY') && (ref($responseType) eq 'HASH')) {  
         return '<br clear="all">';  
     }  
     my $coltitle = &mt('Problem Part Shown');  
     if ($checkboxes) {  
         $coltitle = &mt('Problem Part');  
     } else {  
         my $checkedparts = 0;  
         foreach my $partid (&Apache::loncommon::get_env_multiple('form.vPart')) {  
             if (grep(/^\Q$partid\E$/,@{$partlist})) {  
                 $checkedparts ++;  
             }  
         }  
         if ($checkedparts == scalar(@{$partlist})) {  
             return '<br clear="all">';  
         }  
         if ($uploads) {  
             $coltitle = &mt('Problem Part Selected');  
         }  
     }  
     my $result = '<div class="LC_left_float" style="display:inline-block;">';  
     if ($checkboxes) {  
         my $legend = &mt('Parts to display');  
         if ($uploads) {  
             $legend = &mt('Part(s) with dropbox');  
         }  
         $result .= '<fieldset style="display:inline-block;"><legend>'.$legend.'</legend>'.  
                    '<span class="LC_nobreak">'.  
                    '<label><input type="radio" name="chooseparts" value="0" onclick="toggleParts('."'$formname'".');" checked="checked" />'.  
                    &mt('All parts').'</label>'.('&nbsp;'x2).  
                    '<label><input type="radio" name="chooseparts" value="1" onclick="toggleParts('."'$formname'".');" />'.  
                    &mt('Selected parts').'</label></span>'.  
                    '<div id="LC_partselector" style="display:none">';  
     }  
     $result .= &Apache::loncommon::start_data_table()  
               .&Apache::loncommon::start_data_table_header_row();  
     if ($checkboxes) {  
         $result .= '<th>'.&mt('Display?').'</th>';  
     }  
     $result .= '<th>'.$coltitle.'</th>'  
               .'<th>'.&mt('Res. ID').'</th>'  
               .'<th>'.&mt('Type').'</th>'  
               .&Apache::loncommon::end_data_table_header_row();  
     my %partsseen;  
     foreach my $partID (sort(keys(%$responseType))) {  
         foreach my $resID (sort(keys(%{ $responseType->{$partID} }))) {  
             my $responsetype = $responseType->{$partID}->{$resID};  
             if ($uploads) {  
                 next unless ($responsetype eq 'essay');  
                 next unless (&Apache::lonnet::EXT("resource.$partID".'_'."$resID.uploadedfiletypes",$symb));  
             }  
             my $display_part=&get_display_part($partID,$symb);  
             if (exists($partsseen{$partID})) {  
                 $result.=&Apache::loncommon::continue_data_table_row();  
             } else {  
                 $partsseen{$partID}=scalar(keys(%{$responseType->{$partID}}));  
                 $result.=&Apache::loncommon::start_data_table_row().  
                          '<td rowspan="'.$partsseen{$partID}.'" style="vertical-align:middle">';  
                 if ($checkboxes) {  
                     $result.='<input type="checkbox" name="vPart" checked="checked" value="'.$partID.'" /></td>'.  
                              '<td rowspan="'.$partsseen{$partID}.'" style="vertical-align:middle">'.$display_part.'</td>';  
                 } else {  
                     $result.=$display_part.'</td>';  
                 }  
             }  
             $result.='<td>'.'<span class="LC_internal_info">'.$resID.'</span></td>'  
                     .'<td>'.&mt($responsetype).'</td>'  
                     .&Apache::loncommon::end_data_table_row();  
         }  
     }  
     $result.=&Apache::loncommon::end_data_table();  
     if ($checkboxes) {  
         $result .= '</div></fieldset>';  
     }  
     $result .= '</div><div style="padding:0;clear:both;margin:0;border:0"></div>';  
     if (!keys(%partsseen)) {  
         $result = '';  
         if ($uploads) {  
             return '<div style="padding:0;clear:both;margin:0;border:0"></div>'.  
                    '<p class="LC_info">'.  
                     &mt('No dropbox items or essayresponse items with uploadedfiletypes set.').  
                    '</p>';  
         } else {  
             return '<br clear="all" />';  
         }  
     }    
     return $result;  
 }  
   
 sub part_selector_js {  
     my $js = <<"END";  
 function toggleParts(formname) {  
     if (document.getElementById('LC_partselector')) {  
         var index = '';  
         if (document.forms.length) {  
             for (var i=0; i<document.forms.length; i++) {  
                 if (document.forms[i].name == formname) {  
                     index = i;  
                     break;  
                 }  
             }  
         }  
         if ((index != '') && (document.forms[index].elements['chooseparts'].length > 1)) {  
             for (var i=0; i<document.forms[index].elements['chooseparts'].length; i++) {  
                 if (document.forms[index].elements['chooseparts'][i].checked) {  
                    var val = document.forms[index].elements['chooseparts'][i].value;  
                     if (document.forms[index].elements['chooseparts'][i].value == 1) {  
                         document.getElementById('LC_partselector').style.display = 'block';  
                     } else {  
                         document.getElementById('LC_partselector').style.display = 'none';  
                     }  
                 }  
             }  
         }  
     }  
 }  
 END  
     return &Apache::lonhtmlcommon::scripttag($js);  
 }  
   
 sub reset_caches {  sub reset_caches {
     &reset_analyze_cache();      &reset_analyze_cache();
     &reset_perm();      &reset_perm();
Line 586  sub cleanRecord { Line 459  sub cleanRecord {
     return $result;      return $result;
  }   }
     } elsif ( $response =~ m/(?:numerical|formula|custom)/) {      } elsif ( $response =~ m/(?:numerical|formula|custom)/) {
         # Respect multiple input fields, see Bug #5409           # Respect multiple input fields, see Bug #5409
  $answer =    $answer = 
     &Apache::loncommon::format_previous_attempt_value('submission',      &Apache::loncommon::format_previous_attempt_value('submission',
       $answer);        $answer);
Line 665  sub getclasslist { Line 538  sub getclasslist {
         $cdom = $env{"course.$env{'request.course.id'}.domain"};          $cdom = $env{"course.$env{'request.course.id'}.domain"};
         $cnum = $env{"course.$env{'request.course.id'}.num"};          $cnum = $env{"course.$env{'request.course.id'}.num"};
         my $res_error;          my $res_error;
         ($partlist) = &response_type($symb,\$res_error);          ($partlist,my $handgrade,my $responseType) = &response_type($symb,\$res_error);
     }      }
     foreach my $student (keys(%$classlist)) {      foreach my $student (keys(%$classlist)) {
         my $end      =           my $end      = 
Line 1035  sub verifyreceipt { Line 908  sub verifyreceipt {
 #--- Also called directly when one clicks on the subm button   #--- Also called directly when one clicks on the subm button 
 #    on the problem page.  #    on the problem page.
 sub listStudents {  sub listStudents {
     my ($request,$symb,$submitonly,$divforres) = @_;      my ($request,$symb,$submitonly) = @_;
   
       my $is_tool   = ($symb =~ /ext\.tool$/);
     my $cdom      = $env{"course.$env{'request.course.id'}.domain"};      my $cdom      = $env{"course.$env{'request.course.id'}.domain"};
     my $cnum      = $env{"course.$env{'request.course.id'}.num"};      my $cnum      = $env{"course.$env{'request.course.id'}.num"};
     my $getsec    = $env{'form.section'} eq '' ? 'all' : $env{'form.section'};      my $getsec    = $env{'form.section'} eq '' ? 'all' : $env{'form.section'};
Line 1047  sub listStudents { Line 921  sub listStudents {
   
     my $result='';      my $result='';
     my $res_error;      my $res_error;
     my ($partlist,$handgrade,$responseType,$numresp,$numessay) = &response_type($symb,\$res_error);      my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error);
   
     my $table;  
     if (ref($partlist) eq 'ARRAY') {  
         if (scalar(@$partlist) > 1 ) {  
             $table = &showResourceInfo($symb,$partlist,$responseType,'gradesub',1);  
         } elsif ($divforres) {  
             $table = '<div style="padding:0;clear:both;margin:0;border:0"></div>';  
         } else {  
             $table = '<br clear="all" />';  
         }  
     }  
   
     my %js_lt = &Apache::lonlocal::texthash (      my %js_lt = &Apache::lonlocal::texthash (
  'multiple' => 'Please select a student or group of students before clicking on the Next button.',   'multiple' => 'Please select a student or group of students before clicking on the Next button.',
Line 1100  LISTJAVASCRIPT Line 963  LISTJAVASCRIPT
     $request->print($result);      $request->print($result);
   
     my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'.      my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'.
  "\n".$table;   "\n";
   
     $gradeTable .= &Apache::lonhtmlcommon::start_pick_box();      $gradeTable .= &Apache::lonhtmlcommon::start_pick_box();
     $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Problem Text'))      unless ($is_tool) {
                   .'<label><input type="radio" name="vProb" value="no" checked="checked" /> '.&mt('no').' </label>'."\n"          $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Problem Text'))
                   .'<label><input type="radio" name="vProb" value="yes" /> '.&mt('one student').' </label>'."\n"                        .'<label><input type="radio" name="vProb" value="no" checked="checked" /> '.&mt('no').' </label>'."\n"
                   .'<label><input type="radio" name="vProb" value="all" /> '.&mt('all students').' </label><br />'."\n"                        .'<label><input type="radio" name="vProb" value="yes" /> '.&mt('one student').' </label>'."\n"
                   .&Apache::lonhtmlcommon::row_closure();                        .'<label><input type="radio" name="vProb" value="all" /> '.&mt('all students').' </label><br />'."\n"
     $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Answer'))                        .&Apache::lonhtmlcommon::row_closure();
                   .'<label><input type="radio" name="vAns" value="no"  /> '.&mt('no').' </label>'."\n"          $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Answer'))
                   .'<label><input type="radio" name="vAns" value="yes" /> '.&mt('one student').' </label>'."\n"                        .'<label><input type="radio" name="vAns" value="no"  /> '.&mt('no').' </label>'."\n"
                   .'<label><input type="radio" name="vAns" value="all" checked="checked" /> '.&mt('all students').' </label><br />'."\n"                        .'<label><input type="radio" name="vAns" value="yes" /> '.&mt('one student').' </label>'."\n"
                   .&Apache::lonhtmlcommon::row_closure();                        .'<label><input type="radio" name="vAns" value="all" checked="checked" /> '.&mt('all students').' </label><br />'."\n"
                         .&Apache::lonhtmlcommon::row_closure();
       }
   
       my $submission_options;
     my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));      my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));
     my $saveStatus = $stu_status eq '' ? 'Active' : $stu_status;      my $saveStatus = $stu_status eq '' ? 'Active' : $stu_status;
     $env{'form.Status'} = $saveStatus;      $env{'form.Status'} = $saveStatus;
     my %optiontext = &Apache::lonlocal::texthash (      my %optiontext;
       if ($is_tool) {
           %optiontext = &Apache::lonlocal::texthash (
                             lastonly => 'last transaction',
                             last     => 'last transaction with details',
                             datesub  => 'all transactions',
                             all      => 'all transactions with details',
                         );
       } else {
           %optiontext = &Apache::lonlocal::texthash (
                           lastonly => 'last submission',                            lastonly => 'last submission',
                           last     => 'last submission with details',                            last     => 'last submission with details',
                           datesub  => 'all submissions',                            datesub  => 'all submissions',
                           all      => 'all submissions with details',                            all      => 'all submissions with details',
                       );                        );
     my $submission_options =      }
       $submission_options.=
         '<span class="LC_nobreak">'.          '<span class="LC_nobreak">'.
         '<label><input type="radio" name="lastSub" value="lastonly" /> '.          '<label><input type="radio" name="lastSub" value="lastonly" /> '.
         $optiontext{'lastonly'}.' </label></span>'."\n".          $optiontext{'lastonly'}.' </label></span>'."\n".
Line 1136  LISTJAVASCRIPT Line 1012  LISTJAVASCRIPT
         '<span class="LC_nobreak">'.          '<span class="LC_nobreak">'.
         '<label><input type="radio" name="lastSub" value="all" /> '.          '<label><input type="radio" name="lastSub" value="all" /> '.
         $optiontext{'all'}.'</label></span>';          $optiontext{'all'}.'</label></span>';
     my ($compmsg,$nocompmsg);      my $viewtitle;
     $nocompmsg = ' checked="checked"';      if ($is_tool) {
     if ($numessay) {          $viewtitle = &mt('View Transactions');
         $compmsg = $nocompmsg;      } else {
         $nocompmsg = '';          $viewtitle = &mt('View Submissions');
     }  
     $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Submissions'))  
                   .$submission_options;  
 # Check if any gradable  
     my $showmore;  
     if ($perm{'mgr'}) {  
         my @sections;  
         if ($env{'request.course.sec'} ne '') {  
             @sections = ($env{'request.course.sec'});  
         } else {  
             @sections = &Apache::loncommon::get_env_multiple('form.section');  
         }  
         if (grep(/^all$/,@sections)) {  
             $showmore = 1;  
         } else {  
             foreach my $sec (@sections) {  
                 if (&canmodify($sec)) {  
                     $showmore = 1;  
                     last;  
                 }  
             }  
         }  
     }      }
       $gradeTable .= &Apache::lonhtmlcommon::row_title($viewtitle)
     if ($showmore) {                    .$submission_options
         $gradeTable .=  
                    &Apache::lonhtmlcommon::row_closure()  
                   .&Apache::lonhtmlcommon::row_title(&mt('Send Messages'))  
                   .'<span class="LC_nobreak">'  
                   .'<label><input type="radio" name="compmsg" value="0"'.$nocompmsg.' />'  
                   .&mt('No').('&nbsp;'x2).'</label>'  
                   .'<label><input type="radio" name="compmsg" value="1"'.$compmsg.' />'  
                   .&mt('Yes').('&nbsp;'x2).'</label>'  
                   .&Apache::lonhtmlcommon::row_closure();                    .&Apache::lonhtmlcommon::row_closure();
   
         $gradeTable .=       my $closure;
                    &Apache::lonhtmlcommon::row_title(&mt('Grading Increments'))      if (($is_tool) && (exists($env{'form.Status'}))) {
           $closure = 1;
       }
       $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Grading Increments'))
                   .'<select name="increment">'                    .'<select name="increment">'
                   .'<option value="1">'.&mt('Whole Points').'</option>'                    .'<option value="1">'.&mt('Whole Points').'</option>'
                   .'<option value=".5">'.&mt('Half Points').'</option>'                    .'<option value=".5">'.&mt('Half Points').'</option>'
                   .'<option value=".25">'.&mt('Quarter Points').'</option>'                    .'<option value=".25">'.&mt('Quarter Points').'</option>'
                   .'<option value=".1">'.&mt('Tenths of a Point').'</option>'                    .'<option value=".1">'.&mt('Tenths of a Point').'</option>'
                   .'</select>';                    .'</select>'
     }                    .&Apache::lonhtmlcommon::row_closure($closure);
   
     $gradeTable .=       $gradeTable .= 
         &build_section_inputs().          &build_section_inputs().
  '<input type="hidden" name="submitonly"  value="'.$submitonly.'" />'."\n".   '<input type="hidden" name="submitonly"  value="'.$submitonly.'" />'."\n".
  '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n".   '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n".
  '<input type="hidden" name="saveStatusOld" value="'.$saveStatus.'" />'."\n";   '<input type="hidden" name="saveStatusOld" value="'.$saveStatus.'" />'."\n";
   
     if (exists($env{'form.Status'})) {      if (exists($env{'form.Status'})) {
  $gradeTable .= '<input type="hidden" name="Status" value="'.$stu_status.'" />'."\n";   $gradeTable .= '<input type="hidden" name="Status" value="'.$stu_status.'" />'."\n";
     } else {      } else {
         $gradeTable .= &Apache::lonhtmlcommon::row_closure()          if ($is_tool) {
                       .&Apache::lonhtmlcommon::row_title(&mt('Student Status'))              $closure = 1;
           }
           $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Student Status'))
                       .&Apache::lonhtmlcommon::StatusOptions(                        .&Apache::lonhtmlcommon::StatusOptions(
                            $saveStatus,undef,1,'javascript:reLoadList(this.form);');                             $saveStatus,undef,1,'javascript:reLoadList(this.form);')
                         .&Apache::lonhtmlcommon::row_closure($closure);
     }      }
     if ($numessay) {  
         $gradeTable .= &Apache::lonhtmlcommon::row_closure()  
                       .&Apache::lonhtmlcommon::row_title(&mt('Check For Plagiarism'))  
                       .'<input type="checkbox" name="checkPlag" checked="checked" />';  
     }  
     $gradeTable .= &Apache::lonhtmlcommon::row_closure(1)  
                   .&Apache::lonhtmlcommon::end_pick_box();  
   
       unless ($is_tool) {
           $closure = 1;
           $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Check For Plagiarism'))
                         .'<input type="checkbox" name="checkPlag" checked="checked" />'
                         .&Apache::lonhtmlcommon::row_closure($closure);
       }
       $gradeTable .= &Apache::lonhtmlcommon::end_pick_box();
       my $regrademsg;
       if ($is_tool) {
           $regrademsg =&mt("To view/grade/regrade, click on the check box(es) next to the student's name(s). Then click on the Next button.");
       } else {
           $regrademsg = &mt("To view/grade/regrade 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.");
       }
     $gradeTable .= '<p>'      $gradeTable .= '<p>'
                   .&mt("To view/grade/regrade 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"                    .$regrademsg."\n"
                   .'<input type="hidden" name="command" value="processGroup" />'                    .'<input type="hidden" name="command" value="processGroup" />'
                   .'</p>';                    .'</p>';
   
Line 1587  sub sub_page_js { Line 1447  sub sub_page_js {
 SUBJAVASCRIPT  SUBJAVASCRIPT
 }  }
   
 #--- javascript for grading message center  #--- javascript for essay type problem --
 sub sub_grademessage_js {  sub sub_page_kw_js {
     my $request = shift;      my $request = shift;
     my $iconpath = $request->dir_config('lonIconsURL');      my $iconpath = $request->dir_config('lonIconsURL');
     &commonJSfunctions($request);      &commonJSfunctions($request);
Line 1634  sub sub_grademessage_js { Line 1494  sub sub_grademessage_js {
 </script>  </script>
 INNERJS  INNERJS
   
     my $start_page_msg_central =      my $inner_js_highlight_central= (<<INNERJS);
   <script type="text/javascript">
       function updateChoice(flag) {
         opener.document.SCORE.kwclr.value = opener.radioSelection(document.hlCenter.kwdclr);
         opener.document.SCORE.kwsize.value = opener.radioSelection(document.hlCenter.kwdsize);
         opener.document.SCORE.kwstyle.value = opener.radioSelection(document.hlCenter.kwdstyle);
         opener.document.SCORE.refresh.value = "on";
         if (opener.document.SCORE.keywords.value!=""){
            opener.document.SCORE.submit();
         }
         self.close()
       }
   </script>
   INNERJS
   
       my $start_page_msg_central = 
         &Apache::loncommon::start_page('Message Central',$inner_js_msg_central,          &Apache::loncommon::start_page('Message Central',$inner_js_msg_central,
        {'js_ready'  => 1,         {'js_ready'  => 1,
  'only_body' => 1,   'only_body' => 1,
  'bgcolor'   =>'#FFFFFF',});   'bgcolor'   =>'#FFFFFF',});
     my $end_page_msg_central =      my $end_page_msg_central = 
  &Apache::loncommon::end_page({'js_ready' => 1});   &Apache::loncommon::end_page({'js_ready' => 1});
   
   
       my $start_page_highlight_central = 
           &Apache::loncommon::start_page('Highlight Central',
          $inner_js_highlight_central,
          {'js_ready'  => 1,
    'only_body' => 1,
    'bgcolor'   =>'#FFFFFF',});
       my $end_page_highlight_central = 
    &Apache::loncommon::end_page({'js_ready' => 1});
   
     my $docopen=&Apache::lonhtmlcommon::javascript_docopen();      my $docopen=&Apache::lonhtmlcommon::javascript_docopen();
     $docopen=~s/^document\.//;      $docopen=~s/^document\.//;
       my %js_lt = &Apache::lonlocal::texthash(
                   keyw => 'Keywords list, separated by a space. Add/delete to list if desired.',
                   plse => 'Please select a word or group of words from document and then click this link.',
                   adds => 'Add selection to keyword list? Edit if desired.',
                   col1 => 'red',
                   col2 => 'green',
                   col3 => 'blue',
                   siz1 => 'normal',
                   siz2 => '+1',
                   siz3 => '+2',
                   sty1 => 'normal',
                   sty2 => 'italic',
                   sty3 => 'bold',
                );
     my %html_js_lt = &Apache::lonlocal::texthash(      my %html_js_lt = &Apache::lonlocal::texthash(
                 comp => 'Compose Message for: ',                  comp => 'Compose Message for: ',
                 incl => 'Include',                  incl => 'Include',
Line 1655  INNERJS Line 1552  INNERJS
                 new  => 'New',                  new  => 'New',
                 save => 'Save',                  save => 'Save',
                 canc => 'Cancel',                  canc => 'Cancel',
                   kehi => 'Keyword Highlight Options',
                   txtc => 'Text Color',
                   font => 'Font Size',
                   fnst => 'Font Style',
              );               );
       &js_escape(\%js_lt);
     &html_escape(\%html_js_lt);      &html_escape(\%html_js_lt);
     &js_escape(\%html_js_lt);      &js_escape(\%html_js_lt);
     $request->print(&Apache::lonhtmlcommon::scripttag(<<SUBJAVASCRIPT));      $request->print(&Apache::lonhtmlcommon::scripttag(<<SUBJAVASCRIPT));
   
   //===================== Show list of keywords ====================
     function keywords(formname) {
       var nret = prompt("$js_lt{'keyw'}",formname.keywords.value);
       if (nret==null) return;
       formname.keywords.value = nret;
   
       if (formname.keywords.value != "") {
    formname.refresh.value = "on";
    formname.submit();
       }
       return;
     }
   
 //===================== Script to view submitted by ==================  //===================== Script to view submitted by ==================
   function viewSubmitter(submitter) {    function viewSubmitter(submitter) {
     document.SCORE.refresh.value = "on";      document.SCORE.refresh.value = "on";
Line 1669  INNERJS Line 1584  INNERJS
     return;      return;
   }    }
   
   //===================== Script to add keyword(s) ==================
     function getSel() {
       if (document.getSelection) txt = document.getSelection();
       else if (document.selection) txt = document.selection.createRange().text;
       else return;
       var cleantxt = txt.replace(new RegExp('([\\f\\n\\r\\t\\v ])+', 'g')," ");
       if (cleantxt=="") {
    alert("$js_lt{'plse'}");
    return;
       }
       var nret = prompt("$js_lt{'adds'}",cleantxt);
       if (nret==null) return;
       document.SCORE.keywords.value = document.SCORE.keywords.value+" "+nret;
       if (document.SCORE.keywords.value != "") {
    document.SCORE.refresh.value = "on";
    document.SCORE.submit();
       }
       return;
     }
   
 //====================== Script for composing message ==============  //====================== Script for composing message ==============
    // preload images     // preload images
    img1 = new Image();     img1 = new Image();
Line 1770  INNERJS Line 1705  INNERJS
   
   function msgTail() {    function msgTail() {
     pDoc = pWin.document;      pDoc = pWin.document;
       //pDoc.write("<\\/table>");
     pDoc.write("<\\/td><\\/tr><\\/table>&nbsp;");      pDoc.write("<\\/td><\\/tr><\\/table>&nbsp;");
     pDoc.write("<input type=\\"button\\" value=\\"$html_js_lt{'save'}\\" onclick=\\"javascript:checkInput()\\">&nbsp;&nbsp;");      pDoc.write("<input type=\\"button\\" value=\\"$html_js_lt{'save'}\\" onclick=\\"javascript:checkInput()\\">&nbsp;&nbsp;");
     pDoc.write("<input type=\\"button\\" value=\\"$html_js_lt{'canc'}\\" onclick=\\"self.close()\\"><br /><br />");      pDoc.write("<input type=\\"button\\" value=\\"$html_js_lt{'canc'}\\" onclick=\\"self.close()\\"><br /><br />");
Line 1778  INNERJS Line 1714  INNERJS
     pDoc.close();      pDoc.close();
 }  }
   
 SUBJAVASCRIPT  
 }  
   
 #--- javascript for essay type problem --  
 sub sub_page_kw_js {  
     my $request = shift;  
   
     unless ($env{'form.compmsg'}) {  
         &commonJSfunctions($request);  
     }  
   
     my $inner_js_highlight_central= (<<INNERJS);  
 <script type="text/javascript">  
     function updateChoice(flag) {  
       opener.document.SCORE.kwclr.value = opener.radioSelection(document.hlCenter.kwdclr);  
       opener.document.SCORE.kwsize.value = opener.radioSelection(document.hlCenter.kwdsize);  
       opener.document.SCORE.kwstyle.value = opener.radioSelection(document.hlCenter.kwdstyle);  
       opener.document.SCORE.refresh.value = "on";  
       if (opener.document.SCORE.keywords.value!=""){  
          opener.document.SCORE.submit();  
       }  
       self.close()  
     }  
 </script>  
 INNERJS  
   
     my $start_page_highlight_central =  
         &Apache::loncommon::start_page('Highlight Central',  
                                        $inner_js_highlight_central,  
                                        {'js_ready'  => 1,  
                                         'only_body' => 1,  
                                         'bgcolor'   =>'#FFFFFF',});  
     my $end_page_highlight_central =  
         &Apache::loncommon::end_page({'js_ready' => 1});  
   
     my $docopen=&Apache::lonhtmlcommon::javascript_docopen();  
     $docopen=~s/^document\.//;  
   
     my %js_lt = &Apache::lonlocal::texthash(  
                 keyw => 'Keywords list, separated by a space. Add/delete to list if desired.',  
                 plse => 'Please select a word or group of words from document and then click this link.',  
                 adds => 'Add selection to keyword list? Edit if desired.',  
                 col1 => 'red',  
                 col2 => 'green',  
                 col3 => 'blue',  
                 siz1 => 'normal',  
                 siz2 => '+1',  
                 siz3 => '+2',  
                 sty1 => 'normal',  
                 sty2 => 'italic',  
                 sty3 => 'bold',  
              );  
     my %html_js_lt = &Apache::lonlocal::texthash(  
                 save => 'Save',  
                 canc => 'Cancel',  
                 kehi => 'Keyword Highlight Options',  
                 txtc => 'Text Color',  
                 font => 'Font Size',  
                 fnst => 'Font Style',  
              );  
     &js_escape(\%js_lt);  
     &html_escape(\%html_js_lt);  
     &js_escape(\%html_js_lt);  
     $request->print(&Apache::lonhtmlcommon::scripttag(<<SUBJAVASCRIPT));  
   
 //===================== Show list of keywords ====================  
   function keywords(formname) {  
     var nret = prompt("$js_lt{'keyw'}",formname.keywords.value);  
     if (nret==null) return;  
     formname.keywords.value = nret;  
   
     if (formname.keywords.value != "") {  
         formname.refresh.value = "on";  
         formname.submit();  
     }  
     return;  
   }  
   
 //===================== Script to add keyword(s) ==================  
   function getSel() {  
     if (document.getSelection) txt = document.getSelection();  
     else if (document.selection) txt = document.selection.createRange().text;  
     else return;  
     if (typeof(txt) != 'string') {  
         txt = String(txt);  
     }  
     var cleantxt = txt.replace(new RegExp('([\\f\\n\\r\\t\\v ])+', 'g')," ");  
     if (cleantxt=="") {  
         alert("$js_lt{'plse'}");  
         return;  
     }  
     var nret = prompt("$js_lt{'adds'}",cleantxt);  
     if (nret==null) return;  
     document.SCORE.keywords.value = document.SCORE.keywords.value+" "+nret;  
     if (document.SCORE.keywords.value != "") {  
         document.SCORE.refresh.value = "on";  
         document.SCORE.submit();  
     }  
     return;  
   }  
   
 //====================== Script for keyword highlight options ==============  //====================== Script for keyword highlight options ==============
   function kwhighlight() {    function kwhighlight() {
     var kwclr    = document.SCORE.kwclr.value;      var kwclr    = document.SCORE.kwclr.value;
Line 2069  sub gradeBox { Line 1904  sub gradeBox {
   
 sub handback_box {  sub handback_box {
     my ($symb,$uname,$udom,$counter,$partid,$record,$res_error_pointer) = @_;      my ($symb,$uname,$udom,$counter,$partid,$record,$res_error_pointer) = @_;
     my ($partlist,$handgrade,$responseType,$numresp,$numessay) = &response_type($symb,$res_error_pointer);      my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error_pointer);
     return unless ($numessay);  
     my (@respids);      my (@respids);
     my @part_response_id = &flatten_responseType($responseType);      my @part_response_id = &flatten_responseType($responseType);
     foreach my $part_response_id (@part_response_id) {      foreach my $part_response_id (@part_response_id) {
Line 2089  sub handback_box { Line 1923  sub handback_box {
     if ($file =~ /\/portfolio\//) {      if ($file =~ /\/portfolio\//) {
                 $file_counter++;                  $file_counter++;
            my ($file_path, $file_disp) = ($file =~ m|(.+/)(.+)$|);             my ($file_path, $file_disp) = ($file =~ m|(.+/)(.+)$|);
            my ($name,$version,$ext) = &file_name_version_ext($file_disp);             my ($name,$version,$ext) = &Apache::lonnet::file_name_version_ext($file_disp);
            $file_disp = "$name.$ext";             $file_disp = "$name.$ext";
            $file = $file_path.$file_disp;             $file = $file_path.$file_disp;
            $result.=&mt('Return commented version of [_1] to student.',             $result.=&mt('Return commented version of [_1] to student.',
Line 2212  sub download_all_link { Line 2046  sub download_all_link {
 sub submit_download_link {  sub submit_download_link {
     my ($request,$symb) = @_;      my ($request,$symb) = @_;
     if (!$symb) { return ''; }      if (!$symb) { return ''; }
   #FIXME: Figure out which type of problem this is and provide appropriate download
     my $res_error;      my $res_error;
     my ($partlist,$handgrade,$responseType,$numresp,$numessay,$numdropbox) =      my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error);
         &response_type($symb,\$res_error);      if (ref($res_error)) {
     if ($res_error) {          if ($$res_error) {
         $request->print(&mt('An error occurred retrieving response types'));              $request->print(&mt('An error occurred retrieving response types'));
         return;              return;
     }          }
     unless ($numessay) {  
         $request->print(&mt('No essayresponse items found'));  
         return;  
     }      }
     my @chosenparts = &Apache::loncommon::get_env_multiple('form.vPart');      my ($numupload,$numessay) = (0,0);
     if (@chosenparts) {      if (ref($responseType) eq 'HASH') {
         $request->print(&showResourceInfo($symb,$partlist,$responseType,          foreach my $part (sort(keys(%$responseType))) {
                                           undef,undef,1));              foreach my $id (sort(keys(%{ $responseType->{$part} }))) {
                   my $responsetype = $responseType->{$part}->{$id};
                   if ($responsetype eq 'essay') {
                       my $uploadedfiletypes =
                           &Apache::lonnet::EXT("resource.$part".'_'."$id.uploadedfiletypes",$symb);
                       if ($uploadedfiletypes) {
                           $numupload++;
                       } else {
                           $numessay++;
                       }
                   }
               }
           }
     }      }
     if ($numessay) {      if (($numupload) || ($numessay)) {
         my $submitonly= $env{'form.submitonly'} eq '' ? 'all' : $env{'form.submitonly'};          my $submitonly= $env{'form.submitonly'} eq '' ? 'all' : $env{'form.submitonly'};
         my $getsec    = $env{'form.section'} eq '' ? 'all' : $env{'form.section'};          my $getsec    = $env{'form.section'} eq '' ? 'all' : $env{'form.section'};
         my $getgroup  = $env{'form.group'} eq '' ? 'all' : $env{'form.group'};          my $getgroup  = $env{'form.group'} eq '' ? 'all' : $env{'form.group'};
Line 2237  sub submit_download_link { Line 2081  sub submit_download_link {
             my @students = map { $_.':'.$fullname->{$_} } (keys(%{$fullname}));              my @students = map { $_.':'.$fullname->{$_} } (keys(%{$fullname}));
             if (@students) {              if (@students) {
                 @{$env{'form.stuinfo'}} = @students;                  @{$env{'form.stuinfo'}} = @students;
                 if ($numdropbox) {                  if ($numupload) {
                     &download_all_link($request,$symb);                      &download_all_link($request,$symb);
                 } else {  
                     $request->print(&mt('No essayrespose items with dropbox found'));  
                 }                  }
 # FIXME Need a mechanism to download essays, i.e., if $numessay > $numdropbox  # FIXME Need to provide a mechanism to download essays, i.e., if $numessay > 0
 # Needs to omit user's identity if resource instance is for an anonymous survey.  # Needs to omit user's identity if resource instance is for an anonymous survey.
             } else {              } else {
                 $request->print(&mt('No students match the criteria you selected'));                  $request->print(&mt('No students match the criteria you selected'));
Line 2271  sub build_section_inputs { Line 2113  sub build_section_inputs {
   
 # --------------------------- show submissions of a student, option to grade   # --------------------------- show submissions of a student, option to grade 
 sub submission {  sub submission {
     my ($request,$counter,$total,$symb,$divforres,$calledby) = @_;      my ($request,$counter,$total,$symb) = @_;
     my ($uname,$udom)     = ($env{'form.student'},$env{'form.userdom'});      my ($uname,$udom)     = ($env{'form.student'},$env{'form.userdom'});
     $udom = ($udom eq '' ? $env{'user.domain'} : $udom); #has form.userdom changed for a student?      $udom = ($udom eq '' ? $env{'user.domain'} : $udom); #has form.userdom changed for a student?
     my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'});      my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'});
     $env{'form.fullname'} = &Apache::loncommon::plainname($uname,$udom,'lastname') if $env{'form.fullname'} eq '';      $env{'form.fullname'} = &Apache::loncommon::plainname($uname,$udom,'lastname') if $env{'form.fullname'} eq '';
   
       my $probtitle=&Apache::lonnet::gettitle($symb); 
     if ($symb eq '') { $request->print("Unable to handle ambiguous references:."); return ''; }      if ($symb eq '') { $request->print("Unable to handle ambiguous references:."); return ''; }
     my $probtitle=&Apache::lonnet::gettitle($symb);      my $is_tool = ($symb =~ /ext\.tool$/);
     my ($essayurl,%coursedesc_by_cid);      my ($essayurl,%coursedesc_by_cid);
   
     if (!&canview($usec)) {      if (!&canview($usec)) {
Line 2291  sub submission { Line 2134  sub submission {
  return;   return;
     }      }
   
     my $res_error;  
     my ($partlist,$handgrade,$responseType,$numresp,$numessay) =  
         &response_type($symb,\$res_error);  
     if ($res_error) {  
         $request->print(&navmap_errormsg());  
         return;  
     }  
   
     if (!$env{'form.lastSub'}) { $env{'form.lastSub'} = 'datesub'; }      if (!$env{'form.lastSub'}) { $env{'form.lastSub'} = 'datesub'; }
     if (!$env{'form.vProb'}) { $env{'form.vProb'} = 'yes'; }      unless ($is_tool) { 
     if (!$env{'form.vAns'}) { $env{'form.vAns'} = 'yes'; }          if (!$env{'form.vProb'}) { $env{'form.vProb'} = 'yes'; }
     if (($numessay) && ($calledby eq 'submission') && (!exists($env{'form.compmsg'}))) {          if (!$env{'form.vAns'}) { $env{'form.vAns'} = 'yes'; }
         $env{'form.compmsg'} = 1;  
     }      }
     my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : '');      my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : '');
     my $checkIcon = '<img alt="'.&mt('Check Mark').      my $checkIcon = '<img alt="'.&mt('Check Mark').
Line 2312  sub submission { Line 2146  sub submission {
   
     # header info      # header info
     if ($counter == 0) {      if ($counter == 0) {
         my @chosenparts = &Apache::loncommon::get_env_multiple('form.vPart');  
         if (@chosenparts) {  
             $request->print(&showResourceInfo($symb,$partlist,$responseType,'gradesub'));  
         } elsif ($divforres) {  
             $request->print('<div style="padding:0;clear:both;margin:0;border:0"></div>');  
         } else {  
             $request->print('<br clear="all" />');  
         }  
  &sub_page_js($request);   &sub_page_js($request);
         &sub_grademessage_js($request) if ($env{'form.compmsg'});   &sub_page_kw_js($request);
  &sub_page_kw_js($request) if ($numessay);  
   
  # option to display problem, only once else it cause problems    # option to display problem, only once else it cause problems 
         # with the form later since the problem has a form.          # with the form later since the problem has a form.
Line 2339  sub submission { Line 2164  sub submission {
     $request->print(&show_problem($request,$symb,$uname,$udom,0,1,$mode));      $request->print(&show_problem($request,$symb,$uname,$udom,0,1,$mode));
  }   }
   
    # kwclr is the only variable that is guaranteed not to be blank 
           # if this subroutine has been called once.
  my %keyhash = ();   my %keyhash = ();
  if (($env{'form.kwclr'} eq '' && $numessay) || ($env{'form.compmsg'})) {  # if ($env{'form.kwclr'} eq '' && $env{'form.handgrade'} eq 'yes') {
           if (1) {
     %keyhash = &Apache::lonnet::dump('nohist_handgrade',      %keyhash = &Apache::lonnet::dump('nohist_handgrade',
      $env{'course.'.$env{'request.course.id'}.'.domain'},       $env{'course.'.$env{'request.course.id'}.'.domain'},
      $env{'course.'.$env{'request.course.id'}.'.num'});       $env{'course.'.$env{'request.course.id'}.'.num'});
  }  
  # kwclr is the only variable that is guaranteed not to be blank  
  # if this subroutine has been called once.  
  if ($env{'form.kwclr'} eq '' && $numessay) {  
     my $loginuser = $env{'user.name'}.':'.$env{'user.domain'};      my $loginuser = $env{'user.name'}.':'.$env{'user.domain'};
     $env{'form.keywords'} = $keyhash{$symb.'_keywords'} ne '' ? $keyhash{$symb.'_keywords'} : '';      $env{'form.keywords'} = $keyhash{$symb.'_keywords'} ne '' ? $keyhash{$symb.'_keywords'} : '';
     $env{'form.kwclr'}    = $keyhash{$loginuser.'_kwclr'} ne '' ? $keyhash{$loginuser.'_kwclr'} : 'red';      $env{'form.kwclr'}    = $keyhash{$loginuser.'_kwclr'} ne '' ? $keyhash{$loginuser.'_kwclr'} : 'red';
     $env{'form.kwsize'}   = $keyhash{$loginuser.'_kwsize'} ne '' ? $keyhash{$loginuser.'_kwsize'} : '0';      $env{'form.kwsize'}   = $keyhash{$loginuser.'_kwsize'} ne '' ? $keyhash{$loginuser.'_kwsize'} : '0';
     $env{'form.kwstyle'}  = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : '';      $env{'form.kwstyle'}  = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : '';
  }      $env{'form.msgsub'}   = $keyhash{$symb.'_subject'} ne '' ? 
  if ($env{'form.compmsg'}) {  
     $env{'form.msgsub'}   = $keyhash{$symb.'_subject'} ne '' ?  
  $keyhash{$symb.'_subject'} : $probtitle;   $keyhash{$symb.'_subject'} : $probtitle;
     $env{'form.savemsgN'} = $keyhash{$symb.'_savemsgN'} ne '' ? $keyhash{$symb.'_savemsgN'} : '0';      $env{'form.savemsgN'} = $keyhash{$symb.'_savemsgN'} ne '' ? $keyhash{$symb.'_savemsgN'} : '0';
  }   }
   
  my $overRideScore = $env{'form.overRideScore'} eq '' ? 'no' : $env{'form.overRideScore'};   my $overRideScore = $env{'form.overRideScore'} eq '' ? 'no' : $env{'form.overRideScore'};
  my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));   my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));
  $request->print('<form action="/adm/grades" method="post" name="SCORE" enctype="multipart/form-data">'."\n".   $request->print('<form action="/adm/grades" method="post" name="SCORE" enctype="multipart/form-data">'."\n".
Line 2373  sub submission { Line 2195  sub submission {
  '<input type="hidden" name="vProb"      value="'.$env{'form.vProb'}.'" />'."\n".   '<input type="hidden" name="vProb"      value="'.$env{'form.vProb'}.'" />'."\n".
  '<input type="hidden" name="vAns"       value="'.$env{'form.vAns'}.'" />'."\n".   '<input type="hidden" name="vAns"       value="'.$env{'form.vAns'}.'" />'."\n".
  '<input type="hidden" name="lastSub"    value="'.$env{'form.lastSub'}.'" />'."\n".   '<input type="hidden" name="lastSub"    value="'.$env{'form.lastSub'}.'" />'."\n".
  '<input type="hidden" name="compmsg"    value="'.$env{'form.compmsg'}.'" />'."\n".  
  &build_section_inputs().   &build_section_inputs().
  '<input type="hidden" name="submitonly" value="'.$env{'form.submitonly'}.'" />'."\n".   '<input type="hidden" name="submitonly" value="'.$env{'form.submitonly'}.'" />'."\n".
  '<input type="hidden" name="NCT"'.   '<input type="hidden" name="NCT"'.
  ' value="'.($env{'form.NTSTU'} ne '' ? $env{'form.NTSTU'} : $total+1).'" />'."\n");   ' value="'.($env{'form.NTSTU'} ne '' ? $env{'form.NTSTU'} : $total+1).'" />'."\n");
  if ($env{'form.compmsg'}) {  # if ($env{'form.handgrade'} eq 'yes') {
     $request->print('<input type="hidden" name="msgsub"   value="'.$env{'form.msgsub'}.'" />'."\n".          if (1) {
     '<input type="hidden" name="shownSub" value="0" />'."\n".  
     '<input type="hidden" name="savemsgN" value="'.$env{'form.savemsgN'}.'" />'."\n");  
  }  
  if ($numessay) {  
     $request->print('<input type="hidden" name="keywords" value="'.$env{'form.keywords'}.'" />'."\n".      $request->print('<input type="hidden" name="keywords" value="'.$env{'form.keywords'}.'" />'."\n".
     '<input type="hidden" name="kwclr"    value="'.$env{'form.kwclr'}.'" />'."\n".      '<input type="hidden" name="kwclr"    value="'.$env{'form.kwclr'}.'" />'."\n".
     '<input type="hidden" name="kwsize"   value="'.$env{'form.kwsize'}.'" />'."\n".      '<input type="hidden" name="kwsize"   value="'.$env{'form.kwsize'}.'" />'."\n".
     '<input type="hidden" name="kwstyle"  value="'.$env{'form.kwstyle'}.'" />'."\n");      '<input type="hidden" name="kwstyle"  value="'.$env{'form.kwstyle'}.'" />'."\n".
       '<input type="hidden" name="msgsub"   value="'.$env{'form.msgsub'}.'" />'."\n".
       '<input type="hidden" name="shownSub" value="0" />'."\n".
       '<input type="hidden" name="savemsgN" value="'.$env{'form.savemsgN'}.'" />'."\n");
       foreach my $partid (&Apache::loncommon::get_env_multiple('form.vPart')) {
    $request->print('<input type="hidden" name="vPart" value="'.$partid.'" />'."\n");
       }
  }   }
   
  my ($cts,$prnmsg) = (1,'');   my ($cts,$prnmsg) = (1,'');
  while ($cts <= $env{'form.savemsgN'}) {   while ($cts <= $env{'form.savemsgN'}) {
     $prnmsg.='<input type="hidden" name="savemsg'.$cts.'" value="'.      $prnmsg.='<input type="hidden" name="savemsg'.$cts.'" value="'.
Line 2402  sub submission { Line 2225  sub submission {
  }   }
  $request->print($prnmsg);   $request->print($prnmsg);
   
  if ($numessay) {  # if ($env{'form.handgrade'} eq 'yes') {
           unless ($is_tool) {
   
             my %lt = &Apache::lonlocal::texthash(              my %lt = &Apache::lonlocal::texthash(
                           keyh => 'Keyword Highlighting for Essays',                            keyh => 'Keyword Highlighting for Essays',
Line 2410  sub submission { Line 2234  sub submission {
                           list => 'List',                            list => 'List',
                           past => 'Paste Selection to List',                            past => 'Paste Selection to List',
                           high => 'Highlight Attribute',                            high => 'Highlight Attribute',
                      );                       );    
 #  #
 # Print out the keyword options line  # Print out the keyword options line
 #  #
Line 2490  sub submission { Line 2314  sub submission {
     }      }
   
     my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname);      my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname);
       my $res_error;
       my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error);
       if ($res_error) {
           $request->print(&navmap_errormsg());
           return;
       }
   
     # Display student info      # Display student info
     $request->print(($counter == 0 ? '' : '<br />'));      $request->print(($counter == 0 ? '' : '<br />'));
   
       my $boxtitle = &mt('Submissions');
       if ($is_tool) {
           $boxtitle = &mt('Transactions')
       }
     my $result='<div class="LC_Box">'      my $result='<div class="LC_Box">'
               .'<h3 class="LC_hcell">'.&mt('Submissions').'</h3>';                .'<h3 class="LC_hcell">'.$boxtitle.'</h3>';
     $result.='<input type="hidden" name="name'.$counter.      $result.='<input type="hidden" name="name'.$counter.
              '" value="'.$env{'form.fullname'}.'" />'."\n";               '" value="'.$env{'form.fullname'}.'" />'."\n";
     if ($numresp > $numessay) {  #    if ($env{'form.handgrade'} eq 'no') {
       unless ($is_tool) {
         $result.='<p class="LC_info">'          $result.='<p class="LC_info">'
                 .&mt('Part(s) graded correct by the computer is marked with a [_1] symbol.',$checkIcon)                  .&mt('Part(s) graded correct by the computer is marked with a [_1] symbol.',$checkIcon)
                 ."</p>\n";                  ."</p>\n";
     }      }
   
     # If any part of the problem is an essayresponse, then check for collaborators      # If any part of the problem is an essay-response (handgraded), then check for collaborators
     my $fullname;      my $fullname;
     my $col_fullnames = [];      my $col_fullnames = [];
     if ($numessay) {  #    if ($env{'form.handgrade'} eq 'yes') {
       unless ($is_tool) {
  (my $sub_result,$fullname,$col_fullnames)=   (my $sub_result,$fullname,$col_fullnames)=
     &check_collaborators($symb,$uname,$udom,\%record,$handgrade,      &check_collaborators($symb,$uname,$udom,\%record,$handgrade,
  $counter);   $counter);
  $result.=$sub_result;   $result.=$sub_result;
     }      }
     $request->print($result."\n");      $request->print($result."\n");
       
     # print student answer/submission      # print student answer/submission
     # Options are (1) Last submission only      # Options are (1) Handgraded submission only
     #             (2) Last submission (with detailed information for that submission)      #             (2) Last submission, includes submission that is not handgraded 
     #             (3) All transactions (by date)      #                  (for multi-response type part)
     #             (4) The whole record (with detailed information for all transactions)      #             (3) Last submission plus the parts info
       #             (4) The whole record for this student
     my ($string,$timestamp)= &get_last_submission(\%record);      
       my ($string,$timestamp)= &get_last_submission(\%record,$is_tool);
   
     my $lastsubonly;      my $lastsubonly;
   
     if ($$timestamp eq '') {      if ($$timestamp eq '') {
         $lastsubonly.='<div class="LC_grade_submissions_body">'.$$string[0].'</div>';           $lastsubonly.='<div class="LC_grade_submissions_body">'.$$string[0].'</div>'; 
       } elsif ($is_tool) {
           $lastsubonly =
               '<div class="LC_grade_submissions_body">'
              .'<b>'.&mt('Date Grade Passed Back:').'</b> '.$$timestamp."</div>\n";
     } else {      } else {
         $lastsubonly =          $lastsubonly =
             '<div class="LC_grade_submissions_body">'              '<div class="LC_grade_submissions_body">'
Line 2535  sub submission { Line 2376  sub submission {
  my %seenparts;   my %seenparts;
  my @part_response_id = &flatten_responseType($responseType);   my @part_response_id = &flatten_responseType($responseType);
  foreach my $part (@part_response_id) {   foreach my $part (@part_response_id) {
       next if ($env{'form.lastSub'} eq 'hdgrade' 
    && $$handgrade{$$part[0].'_'.$$part[1]} ne 'yes');
   
     my ($partid,$respid) = @{ $part };      my ($partid,$respid) = @{ $part };
     my $display_part=&get_display_part($partid,$symb);      my $display_part=&get_display_part($partid,$symb);
     if ($env{"form.$uname:$udom:$partid:submitted_by"}) {      if ($env{"form.$uname:$udom:$partid:submitted_by"}) {
Line 2549  sub submission { Line 2393  sub submission {
                                $$fullname{$env{"form.$uname:$udom:$partid:submitted_by"}}.'</a>').                                 $$fullname{$env{"form.$uname:$udom:$partid:submitted_by"}}.'</a>').
                     '<br />');                      '<br />');
  next;   next;
     }   }
     my $responsetype = $responseType->{$partid}->{$respid};      my $responsetype = $responseType->{$partid}->{$respid};
     if (!exists($record{"resource.$partid.$respid.submission"})) {      if (!exists($record{"resource.$partid.$respid.submission"})) {
                 $lastsubonly.="\n".'<div class="LC_grade_submission_part">'.                  $lastsubonly.="\n".'<div class="LC_grade_submission_part">'.
Line 2557  sub submission { Line 2401  sub submission {
                     ' <span class="LC_internal_info">'.                      ' <span class="LC_internal_info">'.
                     '('.&mt('Response ID: [_1]',$respid).')'.                      '('.&mt('Response ID: [_1]',$respid).')'.
                     '</span>&nbsp; &nbsp;'.                      '</span>&nbsp; &nbsp;'.
             '<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br /><br /></div>';            '<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br /><br /></div>';
  next;   next;
     }      }
     foreach my $submission (@$string) {      foreach my $submission (@$string) {
Line 2572  sub submission { Line 2416  sub submission {
                     $trial = $record{"resource.$partid.tries"};                      $trial = $record{"resource.$partid.tries"};
                     $rndseed = $record{"resource.$partid.rndseed"};                      $rndseed = $record{"resource.$partid.rndseed"};
                 }                  }
  if ($env{'form.checkPlag'}) {          if ($env{'form.checkPlag'}) {
     my ($oname,$odom,$ocrsid,$oessay,$osim)=         my ($oname,$odom,$ocrsid,$oessay,$osim)=
         &most_similar($uname,$udom,$symb,$subval);          &most_similar($uname,$udom,$symb,$subval);
     if ($osim) {      if ($osim) {
         $osim=int($osim*100.0);   $osim=int($osim*100.0);
                         if ($hide eq 'anon') {                          if ($hide eq 'anon') {
                             $similar='<hr /><span class="LC_warning">'.&mt("Essay was found to be similar to another essay submitted for this assignment.").'<br />'.                              $similar='<hr /><span class="LC_warning">'.&mt("Essay was found to be similar to another essay submitted for this assignment.").'<br />'.
                                      &mt('As the current submission is for an anonymous survey, no other details are available.').'</span><hr />';                                       &mt('As the current submission is for an anonymous survey, no other details are available.').'</span><hr />';
Line 2588  sub submission { Line 2432  sub submission {
                                                 $osim,                                                  $osim,
                                                 &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').                                                  &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').
                                             '</span></h3>';                                              '</span></h3>';
                             } elsif ($ocrsid ne '') {                              } else {
                                 my %old_course_desc;                                  my %old_course_desc;
                                 if (ref($coursedesc_by_cid{$ocrsid}) eq 'HASH') {                                  if ($ocrsid ne '') {
                                     %old_course_desc = %{$coursedesc_by_cid{$ocrsid}};                                      if (ref($coursedesc_by_cid{$ocrsid}) eq 'HASH') {
                                 } else {                                          %old_course_desc = %{$coursedesc_by_cid{$ocrsid}};
                                     my $args;                                      } else {
                                     if ($ocrsid ne $env{'request.course.id'}) {                                          my $args;
                                         $args = {'one_time' => 1};                                          if ($ocrsid ne $env{'request.course.id'}) {
                                               $args = {'one_time' => 1};
                                           }
                                           %old_course_desc =
                                               &Apache::lonnet::coursedescription($ocrsid,$args);
                                           $coursedesc_by_cid{$ocrsid} = \%old_course_desc;
                                     }                                      }
                                     %old_course_desc =                                      $similar .=
                                         &Apache::lonnet::coursedescription($ocrsid,$args);                                          '<h3><span class="LC_warning">'.
                                     $coursedesc_by_cid{$ocrsid} = \%old_course_desc;                                          &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',
                                               $osim,
                                               &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',
                                               $old_course_desc{'description'},
                                               $old_course_desc{'num'},
                                               $old_course_desc{'domain'}).
                                           '</span></h3>';
                                   } else {
                                       $similar .=
                                           '<h3><span class="LC_warning">'.
                                           &mt('Essay is [_1]% similar to an essay by [_2] in an unknown course',
                                               $osim,
                                               &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').
                                           '</span></h3>';
                                 }                                  }
                                 $similar .=  
                                     '<h3><span class="LC_warning">'.  
     &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',  
         $osim,  
         &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',  
         $old_course_desc{'description'},  
         $old_course_desc{'num'},  
         $old_course_desc{'domain'}).  
     '</span></h3>';  
                             } else {  
                                 $similar .=  
                                     '<h3><span class="LC_warning">'.  
                                     &mt('Essay is [_1]% similar to an essay by [_2] in an unknown course',  
                                         $osim,  
                                         &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').  
                                     '</span></h3>';  
                             }                              }
                             $similar .= '<blockquote><i>'.                              $similar .= '<blockquote><i>'.
                                         &keywords_highlight($oessay).                                          &keywords_highlight($oessay).
                                         '</i></blockquote><hr />';                                          '</i></blockquote><hr />';
         }                          }
                     }              }
                 }   }
  my $order=&get_order($partid,$respid,$symb,$uname,$udom,   my $order=&get_order($partid,$respid,$symb,$uname,$udom,
                                      undef,$type,$trial,$rndseed);                                       undef,$type,$trial,$rndseed);
                 if (($env{'form.lastSub'} eq 'lastonly') ||                  if ($env{'form.lastSub'} eq 'lastonly' || $env{'form.lastSub'} eq 'datesub' || $env{'form.lastSub'} =~ /^(last|all)$/ || ($env{'form.lastSub'} eq 'hdgrade' && 
                     ($env{'form.lastSub'} eq 'datesub')  ||   $$handgrade{$$part[0].'_'.$$part[1]} eq 'yes')) {
                     ($env{'form.lastSub'} =~ /^(last|all)$/)) {  
     my $display_part=&get_display_part($partid,$symb);      my $display_part=&get_display_part($partid,$symb);
                     $lastsubonly.='<div class="LC_grade_submission_part">'.                      $lastsubonly.='<div class="LC_grade_submission_part">'.
                         '<b>'.&mt('Part: [_1]',$display_part).'</b>'.                          '<b>'.&mt('Part: [_1]',$display_part).'</b>'.
Line 2636  sub submission { Line 2481  sub submission {
                         '('.&mt('Response ID: [_1]',$respid).')'.                          '('.&mt('Response ID: [_1]',$respid).')'.
                         '</span>&nbsp; &nbsp;';                          '</span>&nbsp; &nbsp;';
     my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record);      my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record);
                           
     if (@$files) {      if (@$files) {
                         if ($hide eq 'anon') {                          if ($hide eq 'anon') {
                             $lastsubonly.='<br />'.&mt('[quant,_1,file] uploaded to this anonymous survey',scalar(@{$files}));                              $lastsubonly.='<br />'.&mt('[quant,_1,file] uploaded to this anonymous survey',scalar(@{$files}));
                         } else {                          } else {
                             $lastsubonly.='<br /><br />'.'<b>'.&mt('Submitted Files:').'</b>'                              $lastsubonly.='<br /><br />'.'<b>'.&mt('Submitted Files:').'</b>'
                                          .'<br /><span class="LC_warning">';                                          .'<br /><span class="LC_warning">';
                             if(@$files == 1) {                              if(@$files == 1) {
                                 $lastsubonly .= &mt('Like all files provided by users, this file may contain viruses!');                                  $lastsubonly .= &mt('Like all files provided by users, this file may contain viruses!');
                             } else {                              } else {
                                 $lastsubonly .= &mt('Like all files provided by users, these files may contain viruses!');                                  $lastsubonly .= &mt('Like all files provided by users, these files may contain viruses!');
                             }                              }
                             $lastsubonly .= '</span>';                              $lastsubonly .= '</span>';                         
                             foreach my $file (@$files) {                              foreach my $file (@$files) {
                                 &Apache::lonnet::allowuploaded('/adm/grades',$file);                                  &Apache::lonnet::allowuploaded('/adm/grades',$file);
                                 $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0" alt="" /> '.$file.'</a>';                                  $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0" alt="" /> '.$file.'</a>';
                             }                              }
                         }                          }
  $lastsubonly.='<br />';   $lastsubonly.='<br />';
     }                      }
                     if ($hide eq 'anon') {                      if ($hide eq 'anon') {
                         $lastsubonly.='<br /><b>'.&mt('Anonymous Survey').'</b>';                           $lastsubonly.='<br /><b>'.&mt('Anonymous Survey').'</b>'; 
                     } else {                      } else {
                         $lastsubonly.='<br /><b>'.&mt('Submitted Answer:').' </b>';                       $lastsubonly.='<br /><b>'.&mt('Submitted Answer:').' </b>';
                         if ($draft) {                          if ($draft) {
                             $lastsubonly.= ' <span class="LC_warning">'.&mt('Draft Copy').'</span>';                              $lastsubonly.= ' <span class="LC_warning">'.&mt('Draft Copy').'</span>';
                         }                          }
Line 2670  sub submission { Line 2516  sub submission {
                         }                          }
                         $lastsubonly.=$subval."\n";                          $lastsubonly.=$subval."\n";
                     }                      }
                     if ($similar) {$lastsubonly.="<br /><br />$similar\n";}              if ($similar) {$lastsubonly.="<br /><br />$similar\n";}
     $lastsubonly.='</div>';      $lastsubonly.='</div>';
  }   }
     }              }
  }   }
  $lastsubonly.='</div>'."\n"; # End: LC_grade_submissions_body   $lastsubonly.='</div>'."\n"; # End: LC_grade_submissions_body
     }      }
Line 2681  sub submission { Line 2527  sub submission {
     if ($env{'form.lastSub'} eq 'datesub') {      if ($env{'form.lastSub'} eq 'datesub') {
         my ($parts,$handgrade,$responseType) = &response_type($symb,\$res_error);          my ($parts,$handgrade,$responseType) = &response_type($symb,\$res_error);
  $request->print(&displaySubByDates($symb,\%record,$parts,$responseType,$checkIcon,$uname,$udom));   $request->print(&displaySubByDates($symb,\%record,$parts,$responseType,$checkIcon,$uname,$udom));
     }    
       } 
     if ($env{'form.lastSub'} =~ /^(last|all)$/) {      if ($env{'form.lastSub'} =~ /^(last|all)$/) {
         my $identifier = (&canmodify($usec)? $counter : '');          my $identifier = (&canmodify($usec)? $counter : '');
  $request->print(&Apache::loncommon::get_previous_attempt($symb,$uname,$udom,          $request->print(&Apache::loncommon::get_previous_attempt($symb,$uname,$udom,
  $env{'request.course.id'},   $env{'request.course.id'},
  $last,'.submission',   $last,'.submission',
  'Apache::grades::keywords_highlight',   'Apache::grades::keywords_highlight',
Line 2694  sub submission { Line 2541  sub submission {
  .$udom.'" />'."\n");   .$udom.'" />'."\n");
     # return if view submission with no grading option      # return if view submission with no grading option
     if (!&canmodify($usec)) {      if (!&canmodify($usec)) {
         $request->print('<p><span class="LC_warning">'.&mt('No grading privileges').'</span></p></div>');   $request->print('<p><span class="LC_warning">'.&mt('No grading privileges').'</span></p></div>');
         return;   return;
     } else {      } else {
  $request->print('</div>'."\n");   $request->print('</div>'."\n");
     }      }
   
     # grading message center      # essay grading message center
   #    if ($env{'form.handgrade'} eq 'yes') {
     if ($env{'form.compmsg'}) {      if (1) {
         my $result='<div class="LC_Box">'.   my $result='<div class="LC_grade_message_center">';
                    '<h3 class="LC_hcell">'.&mt('Send Message').'</h3>'.      
                    '<div class="LC_grade_message_center_body">';   $result.='<div class="LC_grade_message_center_header">'.
         my ($lastname,$givenn) = split(/,/,$env{'form.fullname'});      &mt('Send Message').'</div><div class="LC_grade_message_center_body">';
         my $msgfor = $givenn.' '.$lastname;   my ($lastname,$givenn) = split(/,/,$env{'form.fullname'});
         if (scalar(@$col_fullnames) > 0) {   my $msgfor = $givenn.' '.$lastname;
             my $lastone = pop(@$col_fullnames);   if (scalar(@$col_fullnames) > 0) {
             $msgfor .= ', '.(join ', ',@$col_fullnames).' and '.$lastone.'.';      my $lastone = pop(@$col_fullnames);
         }      $msgfor .= ', '.(join ', ',@$col_fullnames).' and '.$lastone.'.';
         $msgfor =~ s/\'/\\'/g; #' stupid emacs - no! javascript   }
         $result.='<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n".   $msgfor =~ s/\'/\\'/g; #' stupid emacs - no! javascript
                  '<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n".   $result.='<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n".
          '&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.      '<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n";
                  ',\''.$msgfor.'\');" target="_self">'.   $result.='&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.
                  &mt('Compose message to student'.(scalar(@$col_fullnames) >= 1 ? 's' : '')).'</a><label> ('.      ',\''.$msgfor.'\');" target="_self">'.
                  &mt('incl. grades').' <input type="checkbox" name="withgrades'.$counter.'" /></label>)'.      &mt('Compose message to student'.(scalar(@$col_fullnames) >= 1 ? 's' : '')).'</a><label> ('.
                  ' <img src="'.$request->dir_config('lonIconsURL').      &mt('incl. grades').' <input type="checkbox" name="withgrades'.$counter.'" /></label>)'.
                  '/mailbkgrd.gif" width="14" height="10" alt="" name="mailicon'.$counter.'" />'."\n".      ' <img src="'.$request->dir_config('lonIconsURL').
                  '<br />&nbsp;('.      '/mailbkgrd.gif" width="14" height="10" alt="" name="mailicon'.$counter.'" />'."\n".
                  &mt('Message will be sent when you click on Save &amp; Next below.').")\n".      '<br />&nbsp;('.
          '</div></div>';      &mt('Message will be sent when you click on Save &amp; Next below.').")\n";
         $request->print($result);   $result.='</div></div>';
    $request->print($result);
     }      }
   
     my %seen = ();      my %seen = ();
     my @partlist;      my @partlist;
     my @gradePartRespid;      my @gradePartRespid;
     my @part_response_id = &flatten_responseType($responseType);      my @part_response_id;
       if ($is_tool) {
           @part_response_id = ([0,'']);
       } else {
           @part_response_id = &flatten_responseType($responseType);
       }
     $request->print(      $request->print(
         '<div class="LC_Box">'          '<div class="LC_Box">'
        .'<h3 class="LC_hcell">'.&mt('Assign Grades').'</h3>'         .'<h3 class="LC_hcell">'.&mt('Assign Grades').'</h3>'
Line 2741  sub submission { Line 2594  sub submission {
  my $part_resp = join('_',@{ $part_response_id });   my $part_resp = join('_',@{ $part_response_id });
  next if ($seen{$partid} > 0);   next if ($seen{$partid} > 0);
  $seen{$partid}++;   $seen{$partid}++;
    next if ($$handgrade{$part_resp} ne 'yes' 
    && $env{'form.lastSub'} eq 'hdgrade');
  push(@partlist,$partid);   push(@partlist,$partid);
  push(@gradePartRespid,$partid.'.'.$respid);   push(@gradePartRespid,$partid.'.'.$respid);
  $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record));   $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record));
Line 2854  sub check_collaborators { Line 2709  sub check_collaborators {
   
 #--- Retrieve the last submission for all the parts  #--- Retrieve the last submission for all the parts
 sub get_last_submission {  sub get_last_submission {
     my ($returnhash)=@_;      my ($returnhash,$is_tool)=@_;
     my (@string,$timestamp,%lasthidden);      my (@string,$timestamp,%lasthidden);
     if ($$returnhash{'version'}) {      if ($$returnhash{'version'}) {
  my %lasthash=();   my %lasthash=();
Line 2920  sub get_last_submission { Line 2775  sub get_last_submission {
  }   }
     }      }
     if (!@string) {      if (!@string) {
           my $msg;
           if ($is_tool) {
               $msg = &mt('No grade passed back.');
           } else {
               $msg = &mt('Nothing submitted - no attempts.');
           }
  $string[0] =   $string[0] =
     '<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span>';      '<span class="LC_warning">'.$msg.'</span>';
     }      }
     return (\@string,\$timestamp);      return (\@string,\$timestamp);
 }  }
Line 2953  sub show_previous_task_version { Line 2814  sub show_previous_task_version {
     my ($uname,$udom) = ($env{'form.student'},$env{'form.userdom'});      my ($uname,$udom) = ($env{'form.student'},$env{'form.userdom'});
     my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'});      my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'});
     if (!&canview($usec)) {      if (!&canview($usec)) {
         $request->print('<span class="LC_warning">'.          $request->print(
                         &mt('Unable to view previous version for requested student.').              '<span class="LC_warning">'.
                         ' '.&mt('([_1] in section [_2] in course id [_3])',              &mt('Unable to view previous version for requested student.').
                                 $uname.':'.$udom,$usec,$env{'request.course.id'}).              ' '.&mt('([_1] in section [_2] in course id [_3])',
                         '</span>');                      $uname.':'.$udom,$usec,$env{'request.course.id'}).
               '</span>');
         return;          return;
     }      }
     my $mode = 'both';      my $mode = 'both';
Line 3141  sub processHandGrade { Line 3003  sub processHandGrade {
  next;   next;
     }      }
     if ($errorflag eq 'not_allowed') {      if ($errorflag eq 'not_allowed') {
                 $request->print(   $request->print(
                     '<span class="LC_error">'                      '<span class="LC_error">'
                    .&mt('Not allowed to modify grades for [_1]',"$uname:$udom")                     .&mt('Not allowed to modify grades for [_1]',"$uname:$udom")
                    .'</span>');                     .'</span>');
Line 3212  sub processHandGrade { Line 3074  sub processHandGrade {
  }   }
     }      }
   
     my $res_error;  #    if ($env{'form.handgrade'} eq 'yes') {
     my ($partlist,$handgrade,$responseType,$numresp,$numessay) = &response_type($symb,\$res_error);      if (1) {
     if ($res_error) {  
         $request->print(&navmap_errormsg());  
         return;  
     }  
   
     my %keyhash = ();  
     if ($numessay) {  
  # Keywords sorted in alphabatical order   # Keywords sorted in alphabatical order
  my $loginuser = $env{'user.name'}.':'.$env{'user.domain'};   my $loginuser = $env{'user.name'}.':'.$env{'user.domain'};
    my %keyhash = ();
  $env{'form.keywords'}           =~ s/,\s{0,}|\s+/ /g;   $env{'form.keywords'}           =~ s/,\s{0,}|\s+/ /g;
  $env{'form.keywords'}           =~ s/^\s+|\s+$//g;   $env{'form.keywords'}           =~ s/^\s+|\s+$//;
  my (@keywords) = sort(split(/\s+/,$env{'form.keywords'}));   my (@keywords) = sort(split(/\s+/,$env{'form.keywords'}));
  $env{'form.keywords'} = join(' ',@keywords);   $env{'form.keywords'} = join(' ',@keywords);
  $keyhash{$symb.'_keywords'}     = $env{'form.keywords'};   $keyhash{$symb.'_keywords'}     = $env{'form.keywords'};
Line 3232  sub processHandGrade { Line 3088  sub processHandGrade {
  $keyhash{$loginuser.'_kwclr'}   = $env{'form.kwclr'};   $keyhash{$loginuser.'_kwclr'}   = $env{'form.kwclr'};
  $keyhash{$loginuser.'_kwsize'}  = $env{'form.kwsize'};   $keyhash{$loginuser.'_kwsize'}  = $env{'form.kwsize'};
  $keyhash{$loginuser.'_kwstyle'} = $env{'form.kwstyle'};   $keyhash{$loginuser.'_kwstyle'} = $env{'form.kwstyle'};
     }  
   
     if ($env{'form.compmsg'}) {  
  # message center - Order of message gets changed. Blank line is eliminated.   # message center - Order of message gets changed. Blank line is eliminated.
  # New messages are saved in env for the next student.   # New messages are saved in env for the next student.
  # All messages are saved in nohist_handgrade.db   # All messages are saved in nohist_handgrade.db
Line 3257  sub processHandGrade { Line 3111  sub processHandGrade {
  }   }
  $env{'form.savemsgN'} = --$idx;   $env{'form.savemsgN'} = --$idx;
  $keyhash{$symb.'_savemsgN'} = $env{'form.savemsgN'};   $keyhash{$symb.'_savemsgN'} = $env{'form.savemsgN'};
     }  
     if (($numessay) || ($env{'form.compmsg'})) {  
  my $putresult = &Apache::lonnet::put   my $putresult = &Apache::lonnet::put
     ('nohist_handgrade',\%keyhash,$cdom,$cnum);      ('nohist_handgrade',\%keyhash,$cdom,$cnum);
     }      }
   
     # Called by Save & Refresh from Highlight Attribute Window      # Called by Save & Refresh from Highlight Attribute Window
     my (undef,undef,$fullname) = &getclasslist($env{'form.section'},'1');      my (undef,undef,$fullname) = &getclasslist($env{'form.section'},'1');
     if ($env{'form.refresh'} eq 'on') {      if ($env{'form.refresh'} eq 'on') {
Line 3302  sub processHandGrade { Line 3153  sub processHandGrade {
  }   }
  return $a cmp $b;   return $a cmp $b;
      } (keys(%$fullname))) {       } (keys(%$fullname))) {
   # FIXME: this is fishy, looks like the button label
  if ($nextflg == 1 && $button =~ /Next$/) {   if ($nextflg == 1 && $button =~ /Next$/) {
     push(@parsedlist,$item);      push(@parsedlist,$item);
  }   }
Line 3312  sub processHandGrade { Line 3164  sub processHandGrade {
  }   }
     }      }
     $ctr = 0;      $ctr = 0;
   # FIXME: this is fishy, looks like the button label
     @parsedlist = reverse @parsedlist if ($button eq 'Previous');      @parsedlist = reverse @parsedlist if ($button eq 'Previous');
       my $res_error;
       my ($partlist) = &response_type($symb,\$res_error);
       if ($res_error) {
           $request->print(&navmap_errormsg());
           return;
       }
     foreach my $student (@parsedlist) {      foreach my $student (@parsedlist) {
  my $submitonly=$env{'form.submitonly'};   my $submitonly=$env{'form.submitonly'};
  my ($uname,$udom) = split(/:/,$student);   my ($uname,$udom) = split(/:/,$student);
Line 3362  sub processHandGrade { Line 3221  sub processHandGrade {
  $ctr++;   $ctr++;
     }      }
     if ($total < 0) {      if ($total < 0) {
         my $the_end.='<p>'.&mt('[_1]Message:[_2] No more students for this section or class.','<b>','</b>').'</p>'."\n";   my $the_end.='<p>'.&mt('[_1]Message:[_2] No more students for this section or class.','<b>','</b>').'</p>'."\n";
  $request->print($the_end);   $request->print($the_end);
     }      }
     return '';      return '';
Line 3556  sub handback_files { Line 3415  sub handback_files {
  my $part_resp = join('_',@{ $part_response_id });   my $part_resp = join('_',@{ $part_response_id });
         if (($env{'form.'.$newflg.'_'.$part_resp.'_countreturndoc'} =~ /^\d+$/) & ($new_part eq $part_id)) {          if (($env{'form.'.$newflg.'_'.$part_resp.'_countreturndoc'} =~ /^\d+$/) & ($new_part eq $part_id)) {
             for (my $counter=1; $counter<=$env{'form.'.$newflg.'_'.$part_resp.'_countreturndoc'}; $counter++) {              for (my $counter=1; $counter<=$env{'form.'.$newflg.'_'.$part_resp.'_countreturndoc'}; $counter++) {
                 # if multiple files are uploaded names will be 'returndoc2','returndoc3'                  # if multiple files are uploaded names will be 'returndoc2','returndoc3' 
  if ($env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter}) {                  if ($env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter}) {
                     my $fname=$env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter.'.filename'};                      my $fname=$env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter.'.filename'};
                     my ($directory,$answer_file) =                       my ($directory,$answer_file) = 
                         ($env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter} =~ /^(.*?)([^\/]*)$/);                          ($env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter} =~ /^(.*?)([^\/]*)$/);
                     my ($answer_name,$answer_ver,$answer_ext) =                      my ($answer_name,$answer_ver,$answer_ext) =
         &file_name_version_ext($answer_file);          &Apache::lonnet::file_name_version_ext($answer_file);
     my ($portfolio_path) = ($directory =~ /^.+$stuname\/portfolio(.*)/);      my ($portfolio_path) = ($directory =~ /^.+$stuname\/portfolio(.*)/);
                     my $getpropath = 1;                      my $getpropath = 1;
                     my ($dir_list,$listerror) =                      my ($dir_list,$listerror) = 
                         &Apache::lonnet::dirlist($portfolio_root.$portfolio_path,                          &Apache::lonnet::dirlist($portfolio_root.$portfolio_path,
                                                  $domain,$stuname,$getpropath);                                                   $domain,$stuname,$getpropath);
     my $version = &get_next_version($answer_name,$answer_ext,$dir_list);      my $version = &Apache::lonnet::get_next_version($answer_name,$answer_ext,$dir_list);
                     # fix filename                      # fix filename
                     my ($save_file_name) = (($directory.$answer_name.".$version.".$answer_ext) =~ /^.+\/${stuname}\/(.*)/);                      my ($save_file_name) = (($directory.$answer_name.".$version.".$answer_ext) =~ /^.+\/${stuname}\/(.*)/);
                     my $result=&Apache::lonnet::finishuserfileupload($stuname,$domain,                      my $result=&Apache::lonnet::finishuserfileupload($stuname,$domain,
Line 3586  sub handback_files { Line 3445  sub handback_files {
     $$newrecord{"resource.$new_part.$resp_id.handback"}.=',';      $$newrecord{"resource.$new_part.$resp_id.handback"}.=',';
  }   }
                         $$newrecord{"resource.$new_part.$resp_id.handback"} .= $save_file_name;                          $$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 />";   $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 filename [_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>'));
                 }                  }
Line 3598  sub handback_files { Line 3456  sub handback_files {
         $request->print('<br />');          $request->print('<br />');
         my @what = ($symb,$env{'request.course.id'},'handback');          my @what = ($symb,$env{'request.course.id'},'handback');
         &Apache::lonnet::mark_as_readonly($domain,$stuname,\@handedback,\@what);          &Apache::lonnet::mark_as_readonly($domain,$stuname,\@handedback,\@what);
         my $user_lh = &Apache::loncommon::user_lang($stuname,$domain,$env{'request.course.id'});          my $user_lh = &Apache::loncommon::user_lang($stuname,$domain,$env{'request.course.id'});    
         my ($subject,$message);          my ($subject,$message);
         if (scalar(@handedback) == 1) {          if (scalar(@handedback) == 1) {
             $subject = &mt_user($user_lh,'File Handed Back by Instructor');              $subject = &mt_user($user_lh,'File Handed Back by Instructor');
Line 3718  sub version_portfiles { Line 3576  sub version_portfiles {
     my $version_parts = join('|',@$v_flag);      my $version_parts = join('|',@$v_flag);
     my @returned_keys;      my @returned_keys;
     my $parts = join('|', @$parts_graded);      my $parts = join('|', @$parts_graded);
     my $portfolio_root = '/userfiles/portfolio';  
     foreach my $key (keys(%$record)) {      foreach my $key (keys(%$record)) {
         my $new_portfiles;          my $new_portfiles;
         if ($key =~ /^resource\.($version_parts)\./ && $key =~ /\.portfiles$/ ) {          if ($key =~ /^resource\.($version_parts)\./ && $key =~ /\.portfiles$/ ) {
             my @versioned_portfiles;              my @versioned_portfiles;
             my @portfiles = split(/\s*,\s*/,$$record{$key});              my @portfiles = split(/\s*,\s*/,$$record{$key});
             foreach my $file (@portfiles) {              if (@portfiles) {
                 &Apache::lonnet::unmark_as_readonly($domain,$stu_name,[$symb,$env{'request.course.id'}],$file);                  &Apache::lonnet::portfiles_versioning($symb,$domain,$stu_name,\@portfiles,
                 my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*)$/);                                                        \@versioned_portfiles);
  my ($answer_name,$answer_ver,$answer_ext) =  
     &file_name_version_ext($answer_file);  
                 my $getpropath = 1;  
                 my ($dir_list,$listerror) =  
                     &Apache::lonnet::dirlist($portfolio_root.$directory,$domain,  
                                              $stu_name,$getpropath);  
                 my $version = &get_next_version($answer_name,$answer_ext,$dir_list);  
                 my $new_answer = &version_selected_portfile($domain, $stu_name, $directory, $answer_file, $version);  
                 if ($new_answer ne 'problem getting file') {  
                     push(@versioned_portfiles, $directory.$new_answer);  
                     &Apache::lonnet::mark_as_readonly($domain,$stu_name,  
                         [$directory.$new_answer],  
                         [$symb,$env{'request.course.id'},'graded']);  
                 }  
             }              }
             $$record{$key} = join(',',@versioned_portfiles);              $$record{$key} = join(',',@versioned_portfiles);
             push(@returned_keys,$key);              push(@returned_keys,$key);
Line 3749  sub version_portfiles { Line 3592  sub version_portfiles {
     return (@returned_keys);         return (@returned_keys);   
 }  }
   
 sub get_next_version {  
     my ($answer_name, $answer_ext, $dir_list) = @_;  
     my $version;  
     if (ref($dir_list) eq 'ARRAY') {  
         foreach my $row (@{$dir_list}) {  
             my ($file) = split(/\&/,$row,2);  
             my ($file_name,$file_version,$file_ext) =  
         &file_name_version_ext($file);  
             if (($file_name eq $answer_name) &&   
         ($file_ext eq $answer_ext)) {  
                 # gets here if filename and extension match,   
                 # regardless of version  
                 if ($file_version ne '') {  
                     # a versioned file is found  so save it for later  
                     if ($file_version > $version) {  
         $version = $file_version;  
                     }  
         }  
             }  
         }  
     }  
     $version ++;  
     return($version);  
 }  
   
 sub version_selected_portfile {  
     my ($domain,$stu_name,$directory,$file_name,$version) = @_;  
     my ($answer_name,$answer_ver,$answer_ext) =  
         &file_name_version_ext($file_name);  
     my $new_answer;  
     $env{'form.copy'} = &Apache::lonnet::getfile("/uploaded/$domain/$stu_name/portfolio$directory$file_name");  
     if($env{'form.copy'} eq '-1') {  
         $new_answer = 'problem getting file';  
     } else {  
         $new_answer = $answer_name.'.'.$version.'.'.$answer_ext;  
         my $copy_result = &Apache::lonnet::finishuserfileupload(  
                             $stu_name,$domain,'copy',  
         '/portfolio'.$directory.$new_answer);  
     }      
     return ($new_answer);  
 }  
   
 sub file_name_version_ext {  
     my ($file)=@_;  
     my @file_parts = split(/\./, $file);  
     my ($name,$version,$ext);  
     if (@file_parts > 1) {  
  $ext=pop(@file_parts);  
  if (@file_parts > 1 && $file_parts[-1] =~ /^\d+$/) {  
     $version=pop(@file_parts);  
  }  
  $name=join('.',@file_parts);  
     } else {  
  $name=join('.',@file_parts);  
     }  
     return($name,$version,$ext);  
 }  
   
 #--------------------------------------------------------------------------------------  #--------------------------------------------------------------------------------------
 #  #
 #-------------------------- Next few routines handles grading by section or whole class  #-------------------------- Next few routines handles grading by section or whole class
Line 3984  VIEWJAVASCRIPT Line 3769  VIEWJAVASCRIPT
 #--- show scores for a section or whole class w/ option to change/update a score  #--- show scores for a section or whole class w/ option to change/update a score
 sub viewgrades {  sub viewgrades {
     my ($request,$symb) = @_;      my ($request,$symb) = @_;
       my ($is_tool,$toolsymb);
       if ($symb =~ /ext\.tool$/) {
           $is_tool = 1;
           $toolsymb = $symb;
       }
     &viewgrades_js($request);      &viewgrades_js($request);
   
     #need to make sure we have the correct data for later EXT calls,       #need to make sure we have the correct data for later EXT calls, 
Line 4018  sub viewgrades { Line 3808  sub viewgrades {
     }      }
   
     my ($common_header,$specific_header,@sections,$section_display);      my ($common_header,$specific_header,@sections,$section_display);
     if ($env{'request.course.sec'} ne '') {      @sections = &Apache::loncommon::get_env_multiple('form.section');
         @sections = ($env{'request.course.sec'});  
     } else {  
         @sections = &Apache::loncommon::get_env_multiple('form.section');  
     }  
   
 # Check if Save button should be usable  
     my $disabled = ' disabled="disabled"';  
     if ($perm{'mgr'}) {  
         if (grep(/^all$/,@sections)) {  
             undef($disabled);  
         } else {  
             foreach my $sec (@sections) {  
                 if (&canmodify($sec)) {  
                     undef($disabled);  
                     last;  
                 }  
             }  
         }  
     }  
     if (grep(/^all$/,@sections)) {      if (grep(/^all$/,@sections)) {
         @sections = ('all');          @sections = ('all');
         if ($group_display) {          if ($group_display) {
Line 4047  sub viewgrades { Line 3818  sub viewgrades {
             $common_header = &mt('Assign Common Grade to Students not assigned to any groups');              $common_header = &mt('Assign Common Grade to Students not assigned to any groups');
             $specific_header = &mt('Assign Grade to Specific Students not assigned to any groups');              $specific_header = &mt('Assign Grade to Specific Students not assigned to any groups');
         } else {          } else {
             $common_header = &mt('Assign Common Grade to Class');      $common_header = &mt('Assign Common Grade to Class');
             $specific_header = &mt('Assign Grade to Specific Students in Class');              $specific_header = &mt('Assign Grade to Specific Students in Class');
         }          }
     } elsif (grep(/^none$/,@sections)) {      } elsif (grep(/^none$/,@sections)) {
Line 4060  sub viewgrades { Line 3831  sub viewgrades {
             $specific_header = &mt('Assign Grade to Specific Students in no Section and in no Group');              $specific_header = &mt('Assign Grade to Specific Students in no Section and in no Group');
         } else {          } else {
             $common_header = &mt('Assign Common Grade to Students in no Section');              $common_header = &mt('Assign Common Grade to Students in no Section');
             $specific_header = &mt('Assign Grade to Specific Students in no Section');      $specific_header = &mt('Assign Grade to Specific Students in no Section');
         }          }
     } else {      } else {
         $section_display = join (", ",@sections);          $section_display = join (", ",@sections);
Line 4074  sub viewgrades { Line 3845  sub viewgrades {
             $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1] and no Group',$section_display);              $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1] and no Group',$section_display);
         } else {          } else {
             $common_header = &mt('Assign Common Grade to Students in Section(s) [_1]',$section_display);              $common_header = &mt('Assign Common Grade to Students in Section(s) [_1]',$section_display);
             $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1]',$section_display);      $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1]',$section_display);
         }          }
     }      }
     my %submit_types = &substatus_options();      my %submit_types = &substatus_options();
Line 4083  sub viewgrades { Line 3854  sub viewgrades {
     if ($env{'form.submitonly'} eq 'all') {      if ($env{'form.submitonly'} eq 'all') {
         $result.= '<h3>'.$common_header.'</h3>';          $result.= '<h3>'.$common_header.'</h3>';
     } else {      } else {
         $result.= '<h3>'.$common_header.'&nbsp;'.&mt('(submission status: "[_1]")',$submission_status).'</h3>';           my $text;
           if ($is_tool) {
               $text = &mt('(transaction status: "[_1]")',$submission_status);
           } else {
               $text = &mt('(submission status: "[_1]")',$submission_status);
           }
           $result.= '<h3>'.$common_header.'&nbsp;'.$text.'</h3>';
     }      }
     $result .= &Apache::loncommon::start_data_table();      $result .= &Apache::loncommon::start_data_table();
     #radio buttons/text box for assigning points for a section or class.      #radio buttons/text box for assigning points for a section or class.
Line 4096  sub viewgrades { Line 3873  sub viewgrades {
     my %weight = ();      my %weight = ();
     my $ctsparts = 0;      my $ctsparts = 0;
     my %seen = ();      my %seen = ();
     my @part_response_id = &flatten_responseType($responseType);      my @part_response_id;
       if ($is_tool) {
           @part_response_id = ([0,'']);
       } else {
           @part_response_id = &flatten_responseType($responseType);
       }
     foreach my $part_response_id (@part_response_id) {      foreach my $part_response_id (@part_response_id) {
     my ($partid,$respid) = @{ $part_response_id };      my ($partid,$respid) = @{ $part_response_id };
  my $part_resp = join('_',@{ $part_response_id });   my $part_resp = join('_',@{ $part_response_id });
  next if $seen{$partid};   next if $seen{$partid};
  $seen{$partid}++;   $seen{$partid}++;
   # my $handgrade=$$handgrade{$part_resp};
  my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb);   my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb);
  $weight{$partid} = $wgt eq '' ? '1' : $wgt;   $weight{$partid} = $wgt eq '' ? '1' : $wgt;
   
Line 4120  sub viewgrades { Line 3903  sub viewgrades {
     $partid.'" size="4" '.'onchange="javascript:writePoint(\''.      $partid.'" size="4" '.'onchange="javascript:writePoint(\''.
  $partid.'\','.$weight{$partid}.',\'textval\')" /> /'.   $partid.'\','.$weight{$partid}.',\'textval\')" /> /'.
     $weight{$partid}.' '.&mt('(problem weight)').'</td>'."\n";      $weight{$partid}.' '.&mt('(problem weight)').'</td>'."\n";
  $line.= '<td><b>'.&mt('Grade Status').':</b>'.          $line.= '<td><b>'.&mt('Grade Status').':</b>'.
                 '<select name="SELVAL_'.$partid.'" '.              '<select name="SELVAL_'.$partid.'" '.
         'onchange="javascript:writeRadText(\''.$partid.'\','.              'onchange="javascript:writeRadText(\''.$partid.'\','.
  $weight{$partid}.')"> '.                  $weight{$partid}.')"> '.
     '<option selected="selected"> </option>'.      '<option selected="selected"> </option>'.
     '<option value="excused">'.&mt('excused').'</option>'.      '<option value="excused">'.&mt('excused').'</option>'.
     '<option value="reset status">'.&mt('reset status').'</option>'.      '<option value="reset status">'.&mt('reset status').'</option>'.
Line 4147  sub viewgrades { Line 3930  sub viewgrades {
   
     #table listing all the students in a section/class      #table listing all the students in a section/class
     #header of table      #header of table
     if ($env{'form.submitonly'} eq 'all') {       if ($env{'form.submitonly'} eq 'all') {
         $result.= '<h3>'.$specific_header.'</h3>';          $result.= '<h3>'.$specific_header.'</h3>';
     } else {      } else {
         $result.= '<h3>'.$specific_header.'&nbsp;'.&mt('(submission status: "[_1]")',$submission_status).'</h3>';          my $text;
           if ($is_tool) {
               $text = &mt('(transaction status: "[_1]")',$submission_status);
           } else {
               $text = &mt('(submission status: "[_1]")',$submission_status);
           }
           $result.= '<h3>'.$specific_header.'&nbsp;'.$text.'</h3>';
     }      }
     $result.= &Apache::loncommon::start_data_table().      $result.= &Apache::loncommon::start_data_table().
       &Apache::loncommon::start_data_table_header_row().        &Apache::loncommon::start_data_table_header_row().
Line 4164  sub viewgrades { Line 3953  sub viewgrades {
     my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);      my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
     my @partids = ();      my @partids = ();
     foreach my $part (@parts) {      foreach my $part (@parts) {
  my $display=&Apache::lonnet::metadata($url,$part.'.display');   my $display=&Apache::lonnet::metadata($url,$part.'.display',$toolsymb);
         my $narrowtext = &mt('Tries');          my $narrowtext = &mt('Tries');
  $display =~ s|^Number of Attempts|$narrowtext <br />|; # makes the column narrower   $display =~ s|^Number of Attempts|$narrowtext <br />|; # makes the column narrower
  if  (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); }   if  (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name',$toolsymb); }
  my ($partid) = &split_part_type($part);   my ($partid) = &split_part_type($part);
         push(@partids,$partid);          push(@partids,$partid);
 #  #
Line 4176  sub viewgrades { Line 3965  sub viewgrades {
  my $display_part=&get_display_part($partid,$symb);   my $display_part=&get_display_part($partid,$symb);
  if ($display =~ /^Partial Credit Factor/) {   if ($display =~ /^Partial Credit Factor/) {
     $result.='<th>'.      $result.='<th>'.
                 &mt('Score Part: [_1][_2](weight = [_3])',   &mt('Score Part: [_1][_2](weight = [_3])',
                     $display_part,'<br />',$weight{$partid}).'</th>'."\n";      $display_part,'<br />',$weight{$partid}).'</th>'."\n";
     next;      next;
           
  } else {   } else {
Line 4208  sub viewgrades { Line 3997  sub viewgrades {
  return $a cmp $b;   return $a cmp $b;
      } (keys(%$fullname))) {       } (keys(%$fullname))) {
  $result.=&viewstudentgrade($symb,$env{'request.course.id'},   $result.=&viewstudentgrade($symb,$env{'request.course.id'},
    $_,$$fullname{$_},\@parts,\%weight,\$ctr,\%last_resets);     $_,$$fullname{$_},\@parts,\%weight,\$ctr,\%last_resets,$is_tool);
     }      }
     $result.=&Apache::loncommon::end_data_table();      $result.=&Apache::loncommon::end_data_table();
     $result.='<input type="hidden" name="total" value="'.$ctr.'" />'."\n";      $result.='<input type="hidden" name="total" value="'.$ctr.'" />'."\n";
     $result.='<input type="button" value="'.&mt('Save').'"'.$disabled.' '.      $result.='<input type="button" value="'.&mt('Save').'" '.
  'onclick="javascript:submit();" target="_self" /></form>'."\n";   'onclick="javascript:submit();" target="_self" /></form>'."\n";
     if ($ctr == 0) {      if ($ctr == 0) {
         my $stu_status = join(' or ',&Apache::loncommon::get_env_multiple('form.Status'));          my $stu_status = join(' or ',&Apache::loncommon::get_env_multiple('form.Status'));
Line 4225  sub viewgrades { Line 4014  sub viewgrades {
                                    $stu_status);                                     $stu_status);
                 } elsif (grep(/^none$/,@groups)) {                  } elsif (grep(/^none$/,@groups)) {
                     $result .= &mt('There are no students with no group assigned and with enrollment status [_1] to modify or grade.',                      $result .= &mt('There are no students with no group assigned and with enrollment status [_1] to modify or grade.',
                                    $stu_status);                                     $stu_status); 
                 } else {                  } else {
                     $result .= &mt('There are no students in group(s) [_1] with enrollment status [_2] to modify or grade.',                      $result .= &mt('There are no students in group(s) [_1] with enrollment status [_2] to modify or grade.',
                                    $group_display,$stu_status);                                     $group_display,$stu_status);
Line 4278  sub viewgrades { Line 4067  sub viewgrades {
                 }                  }
             } else {              } else {
                 if (grep(/^all$/,@groups)) {                  if (grep(/^all$/,@groups)) {
                     $result .= &mt('There are no students in section(s) [_1] with enrollment status [_2] and submission status "[_3]" to modify or grade.',              $result .= &mt('There are no students in section(s) [_1] with enrollment status [_2] and submission status "[_3]" to modify or grade.',
                                    $section_display,$stu_status,$submission_status);                             $section_display,$stu_status,$submission_status);
                 } elsif (grep(/^none$/,@groups)) {                  } elsif (grep(/^none$/,@groups)) {
                     $result .= &mt('There are no students in section(s) [_1] and no group with enrollment status [_2] and submission status "[_3]" to modify or grade.',                      $result .= &mt('There are no students in section(s) [_1] and no group with enrollment status [_2] and submission status "[_3]" to modify or grade.',
                                    $section_display,$stu_status,$submission_status);                                     $section_display,$stu_status,$submission_status);
Line 4288  sub viewgrades { Line 4077  sub viewgrades {
                                    $section_display,$group_display,$stu_status,$submission_status);                                     $section_display,$group_display,$stu_status,$submission_status);
                 }                  }
             }              }
  }          }
  $result .= '</span><br />';   $result .= '</span><br />';
     }      }
     return $result;      return $result;
 }  }
   
 #--- call by previous routine to display each student who satisfies submission filter.  #--- call by previous routine to display each student who satisfies submission filter. 
 sub viewstudentgrade {  sub viewstudentgrade {
     my ($symb,$courseid,$student,$fullname,$parts,$weight,$ctr,$last_resets) = @_;      my ($symb,$courseid,$student,$fullname,$parts,$weight,$ctr,$last_resets,$is_tool) = @_;
     my ($uname,$udom) = split(/:/,$student);      my ($uname,$udom) = split(/:/,$student);
     my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname);      my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname);
     my $submitonly = $env{'form.submitonly'};      my $submitonly = $env{'form.submitonly'};
Line 4354  sub viewstudentgrade { Line 4143  sub viewstudentgrade {
         my ($aggtries,$totaltries);          my ($aggtries,$totaltries);
         unless (exists($aggregates{$part})) {          unless (exists($aggregates{$part})) {
     $totaltries = $record{'resource.'.$part.'.tries'};      $totaltries = $record{'resource.'.$part.'.tries'};
   
     $aggtries = $totaltries;      $aggtries = $totaltries;
             if ($$last_resets{$part}) {                if ($$last_resets{$part}) {  
                 $aggtries = &get_num_tries(\%record,$$last_resets{$part},                  $aggtries = &get_num_tries(\%record,$$last_resets{$part},
Line 4403  sub viewstudentgrade { Line 4191  sub viewstudentgrade {
 #    record does not get update if unchanged  #    record does not get update if unchanged
 sub editgrades {  sub editgrades {
     my ($request,$symb) = @_;      my ($request,$symb) = @_;
       my $toolsymb;
       if ($symb =~ /ext\.tool$/) {
           $toolsymb = $symb;
       }
   
     my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));      my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));
     my $title='<h2>'.&mt('Current Grade Status').'</h2>';      my $title='<h2>'.&mt('Current Grade Status').'</h2>';
Line 4449  sub editgrades { Line 4241  sub editgrades {
     my ($part,$type) = &split_part_type($stores);      my ($part,$type) = &split_part_type($stores);
     if ($part !~ m/^\Q$partid\E/) { next;}      if ($part !~ m/^\Q$partid\E/) { next;}
     if ($type eq 'awarded' || $type eq 'solved') { next; }      if ($type eq 'awarded' || $type eq 'solved') { next; }
     my $display=&Apache::lonnet::metadata($url,$stores.'.display');      my $display=&Apache::lonnet::metadata($url,$stores.'.display',$toolsymb);
     $display =~ s/\[Part: \Q$part\E\]//;      $display =~ s/\[Part: \Q$part\E\]//;
             my $narrowtext = &mt('Tries');              my $narrowtext = &mt('Tries');
     $display =~ s/Number of Attempts/$narrowtext/;      $display =~ s/Number of Attempts/$narrowtext/;
Line 4477  sub editgrades { Line 4269  sub editgrades {
  my ($uname,$udom)=split(/:/,$user);   my ($uname,$udom)=split(/:/,$user);
  my %newrecord;   my %newrecord;
  my $updateflag = 0;   my $updateflag = 0;
         my $usec=$classlist->{"$uname:$udom"}[5];   my $usec=$classlist->{"$uname:$udom"}[5];
         my $canmodify = &canmodify($usec);   my $canmodify = &canmodify($usec);
         my $line = '<td'.($canmodify?'':' colspan="2"').'>'.   my $line = '<td'.($canmodify?'':' colspan="2"').'>'.
                    &nameUserString(undef,$$fullname{$user},$uname,$udom).'</td>';     &nameUserString(undef,$$fullname{$user},$uname,$udom).'</td>';
         if (!$canmodify) {   if (!$canmodify) {
             push(@noupdate,      push(@noupdate,
                  $line."<td colspan=\"$totcolspan\"><span class=\"LC_warning\">".   $line."<td colspan=\"$totcolspan\"><span class=\"LC_warning\">".
                  &mt('Not allowed to modify student')."</span></td>");   &mt('Not allowed to modify student')."</span></td>");
             next;      next;
         }   }
         my %aggregate = ();          my %aggregate = ();
         my $aggregateflag = 0;          my $aggregateflag = 0;
  $user=~s/:/_/; # colon doen't work in javascript for names   $user=~s/:/_/; # colon doen't work in javascript for names
Line 4642  sub split_part_type { Line 4434  sub split_part_type {
 #  #
 #--- Javascript to handle csv upload  #--- Javascript to handle csv upload
 sub csvupload_javascript_reverse_associate {  sub csvupload_javascript_reverse_associate {
     my $error1=&mt('You need to specify the username or the student/employee ID');      my $error1=&mt('You need to specify the username, the student/employee ID, or the clicker ID');
     my $error2=&mt('You need to specify at least one grading field');      my $error2=&mt('You need to specify at least one grading field');
   &js_escape(\$error1);    &js_escape(\$error1);
   &js_escape(\$error2);    &js_escape(\$error2);
Line 4651  sub csvupload_javascript_reverse_associa Line 4443  sub csvupload_javascript_reverse_associa
     var foundsomething=0;      var foundsomething=0;
     var founduname=0;      var founduname=0;
     var foundID=0;      var foundID=0;
       var foundclicker=0;
     for (i=0;i<=vf.nfields.value;i++) {      for (i=0;i<=vf.nfields.value;i++) {
       tw=eval('vf.f'+i+'.selectedIndex');        tw=eval('vf.f'+i+'.selectedIndex');
       if (i==0 && tw!=0) { foundID=1; }        if (i==0 && tw!=0) { foundID=1; }
       if (i==1 && tw!=0) { founduname=1; }        if (i==1 && tw!=0) { founduname=1; }
       if (i!=0 && i!=1 && i!=2 && tw!=0) { foundsomething=1; }        if (i==2 && tw!=0) { foundclicker=1; }
         if (i!=0 && i!=1 && i!=2 && i!=3 && tw!=0) { foundsomething=1; }
     }      }
     if (founduname==0 && foundID==0) {      if (founduname==0 && foundID==0 && foundclicker==0) {
  alert('$error1');   alert('$error1');
  return;   return;
     }      }
Line 4684  ENDPICK Line 4478  ENDPICK
 }  }
   
 sub csvupload_javascript_forward_associate {  sub csvupload_javascript_forward_associate {
     my $error1=&mt('You need to specify the username or the student/employee ID');      my $error1=&mt('You need to specify the username, the student/employee ID, or the clicker ID');
     my $error2=&mt('You need to specify at least one grading field');      my $error2=&mt('You need to specify at least one grading field');
   &js_escape(\$error1);    &js_escape(\$error1);
   &js_escape(\$error2);    &js_escape(\$error2);
Line 4693  sub csvupload_javascript_forward_associa Line 4487  sub csvupload_javascript_forward_associa
     var foundsomething=0;      var foundsomething=0;
     var founduname=0;      var founduname=0;
     var foundID=0;      var foundID=0;
       var foundclicker=0;
     for (i=0;i<=vf.nfields.value;i++) {      for (i=0;i<=vf.nfields.value;i++) {
       tw=eval('vf.f'+i+'.selectedIndex');        tw=eval('vf.f'+i+'.selectedIndex');
       if (tw==1) { foundID=1; }        if (tw==1) { foundID=1; }
       if (tw==2) { founduname=1; }        if (tw==2) { founduname=1; }
       if (tw>3) { foundsomething=1; }        if (tw==3) { foundclicker=1; }
         if (tw>4) { foundsomething=1; }
     }      }
     if (founduname==0 && foundID==0) {      if (founduname==0 && foundID==0 && Æ’oundclicker==0) {
  alert('$error1');   alert('$error1');
  return;   return;
     }      }
Line 4731  sub csvuploadmap_header { Line 4527  sub csvuploadmap_header {
  $javascript=&csvupload_javascript_forward_associate();   $javascript=&csvupload_javascript_forward_associate();
     }      }
   
     my $checked=(($env{'form.noFirstLine'})?' checked="checked"':'');  
     my $ignore=&mt('Ignore First Line');  
     $symb = &Apache::lonenc::check_encrypt($symb);      $symb = &Apache::lonenc::check_encrypt($symb);
     $request->print('<form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">'.      $request->print('<form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">'.
                     &mt('Total number of records found in file: [_1]',$distotal).'<hr />'.                      &mt('Total number of records found in file: [_1]',$distotal).'<hr />'.
Line 4741  sub csvuploadmap_header { Line 4535  sub csvuploadmap_header {
     $request->print(<<ENDPICK);      $request->print(<<ENDPICK);
 <br />  <br />
 <input type="button" value="$reverse" onclick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" />  <input type="button" value="$reverse" onclick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" />
 <label><input type="checkbox" name="noFirstLine" $checked />$ignore</label>  
 <input type="hidden" name="associate"  value="" />  <input type="hidden" name="associate"  value="" />
 <input type="hidden" name="phase"      value="three" />  <input type="hidden" name="phase"      value="three" />
 <input type="hidden" name="datatoken"  value="$datatoken" />  <input type="hidden" name="datatoken"  value="$datatoken" />
Line 4760  ENDPICK Line 4553  ENDPICK
   
 sub csvupload_fields {  sub csvupload_fields {
     my ($symb,$errorref) = @_;      my ($symb,$errorref) = @_;
       my $toolsymb;
       if ($symb =~ /ext\.tool$/) {
           $toolsymb = $symb;
       }
     my (@parts) = &getpartlist($symb,$errorref);      my (@parts) = &getpartlist($symb,$errorref);
     if (ref($errorref)) {      if (ref($errorref)) {
         if ($$errorref) {          if ($$errorref) {
Line 4769  sub csvupload_fields { Line 4566  sub csvupload_fields {
   
     my @fields=(['ID','Student/Employee ID'],      my @fields=(['ID','Student/Employee ID'],
  ['username','Student Username'],   ['username','Student Username'],
    ['clicker','Clicker ID'],
  ['domain','Student Domain']);   ['domain','Student Domain']);
     my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);      my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);
     foreach my $part (sort(@parts)) {      foreach my $part (sort(@parts)) {
  my @datum;   my @datum;
  my $display=&Apache::lonnet::metadata($url,$part.'.display');   my $display=&Apache::lonnet::metadata($url,$part.'.display',$toolsymb);
  my $name=$part;   my $name=$part;
  if  (!$display) { $display = $name; }   if (!$display) { $display = $name; }
  @datum=($name,$display);   @datum=($name,$display);
  if ($name=~/^stores_(.*)_awarded/) {   if ($name=~/^stores_(.*)_awarded/) {
     push(@fields,['stores_'.$1.'_points',"Points [Part: $1]"]);      push(@fields,['stores_'.$1.'_points',"Points [Part: $1]"]);
Line 4831  sub upcsvScores_form { Line 4629  sub upcsvScores_form {
 <input type="hidden" name="command" value="csvuploadmap" />  <input type="hidden" name="command" value="csvuploadmap" />
 $upfile_select  $upfile_select
 <br /><input type="button" onclick="javascript:checkUpload(this.form);" value="$upload" />  <br /><input type="button" onclick="javascript:checkUpload(this.form);" value="$upload" />
 <label><input type="checkbox" name="noFirstLine" />$ignore</label>  
 </form>  </form>
 ENDUPFORM  ENDUPFORM
     $result.=&Apache::loncommon::help_open_topic("Course_Convert_To_CSV",      $result.=&Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
                            &mt("How do I create a CSV file from a spreadsheet")).                             &mt("How do I create a CSV file from a spreadsheet")).
             '</td>'.               '</td>'.
             &Apache::loncommon::end_data_table_row().              &Apache::loncommon::end_data_table_row().
             &Apache::loncommon::end_data_table();              &Apache::loncommon::end_data_table();
     return $result;      return $result;
Line 4851  sub csvuploadmap { Line 4648  sub csvuploadmap {
     if (!$env{'form.datatoken'}) {      if (!$env{'form.datatoken'}) {
  $datatoken=&Apache::loncommon::upfile_store($request);   $datatoken=&Apache::loncommon::upfile_store($request);
     } else {      } else {
         $datatoken=&Apache::loncommon::valid_datatoken($env{'form.datatoken'});   $datatoken=&Apache::loncommon::valid_datatoken($env{'form.datatoken'});
         if ($datatoken ne '') {           if ($datatoken ne '') {
     &Apache::loncommon::load_tmp_file($request,$datatoken);      &Apache::loncommon::load_tmp_file($request,$datatoken);
         }          }
     }      }
     my @records=&Apache::loncommon::upfile_record_sep();      my @records=&Apache::loncommon::upfile_record_sep();
     if ($env{'form.noFirstLine'}) { shift(@records); }  
     &csvuploadmap_header($request,$symb,$datatoken,$#records+1);      &csvuploadmap_header($request,$symb,$datatoken,$#records+1);
     my ($i,$keyfields);      my ($i,$keyfields);
     if (@records) {      if (@records) {
Line 4894  sub csvuploadmap { Line 4690  sub csvuploadmap {
 sub csvuploadoptions {  sub csvuploadoptions {
     my ($request,$symb)= @_;      my ($request,$symb)= @_;
     my $overwrite=&mt('Overwrite any existing score');      my $overwrite=&mt('Overwrite any existing score');
     my $checked=(($env{'form.noFirstLine'})?'1':'0');  
     my $ignore=&mt('Ignore First Line');  
     $request->print(<<ENDPICK);      $request->print(<<ENDPICK);
 <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">  <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
 <input type="hidden" name="command"    value="csvuploadassign" />  <input type="hidden" name="command"    value="csvuploadassign" />
Line 4909  ENDPICK Line 4703  ENDPICK
     my %fields=&get_fields();      my %fields=&get_fields();
     if (!defined($fields{'domain'})) {      if (!defined($fields{'domain'})) {
  my $domform = &Apache::loncommon::select_dom_form($env{'request.role.domain'},'default_domain');   my $domform = &Apache::loncommon::select_dom_form($env{'request.role.domain'},'default_domain');
         $request->print("\n<p>".&mt('Users are in domain: [_1]',$domform)."</p>\n");   $request->print("\n<p>".&mt('Users are in domain: [_1]',$domform)."</p>\n");
     }      }
     foreach my $key (sort(keys(%env))) {      foreach my $key (sort(keys(%env))) {
  if ($key !~ /^form\.(.*)$/) { next; }   if ($key !~ /^form\.(.*)$/) { next; }
Line 4947  sub csvuploadassign { Line 4741  sub csvuploadassign {
     if (!$symb) {return '';}      if (!$symb) {return '';}
     my $error_msg = '';      my $error_msg = '';
     my $datatoken = &Apache::loncommon::valid_datatoken($env{'form.datatoken'});      my $datatoken = &Apache::loncommon::valid_datatoken($env{'form.datatoken'});
     if ($datatoken ne '') {      if ($datatoken ne '') { 
         &Apache::loncommon::load_tmp_file($request,$datatoken);          &Apache::loncommon::load_tmp_file($request,$datatoken);
     }      }
     my @gradedata = &Apache::loncommon::upfile_record_sep();      my @gradedata = &Apache::loncommon::upfile_record_sep();
     if ($env{'form.noFirstLine'}) { shift(@gradedata); }  
     my %fields=&get_fields();      my %fields=&get_fields();
     my $courseid=$env{'request.course.id'};      my $courseid=$env{'request.course.id'};
     my ($classlist) = &getclasslist('all',0);      my ($classlist) = &getclasslist('all',0);
Line 4973  sub csvuploadassign { Line 4766  sub csvuploadassign {
  if (!$username) {   if (!$username) {
     my $id=$entries{$fields{'ID'}};      my $id=$entries{$fields{'ID'}};
     $id=~s/\s//g;      $id=~s/\s//g;
     my %ids=&Apache::lonnet::idget($domain,$id);              if ($id ne '') {
     $username=$ids{$id};          my %ids=&Apache::lonnet::idget($domain,[$id]);
           $username=$ids{$id};
               } else {
                   if ($entries{$fields{'clicker'}}) {
                       my $clicker = $entries{$fields{'clicker'}};
                       $clicker=~s/\s//g;
                       if ($clicker ne '') {
                           my %clickers = &Apache::lonnet::idget($domain,[$clicker],'clickers');
                           if ($clickers{$clicker} ne '') {  
                               my $match = 0;
                               my @inclass;
                               foreach my $poss (split(/,/,$clickers{$clicker})) {
                                   if (exists($$classlist{"$poss:$domain"})) {
                                       $username = $poss;
                                       push(@inclass,$poss);
                                       $match ++;
                                       
                                   }
                               }
                               if ($match > 1) {
                                   undef($username); 
                                   $request->print('<p class="LC_warning">'.
                                                   &mt('Score not saved for clicker: [_1] (matched multiple usernames: [_2])',
                                                   $clicker,join(', ',@inclass)).'</p>');
                               }
                           }
                       }
                   }
               }
  }   }
  if (!exists($$classlist{"$username:$domain"})) {   if (!exists($$classlist{"$username:$domain"})) {
     my $id=$entries{$fields{'ID'}};      my $id=$entries{$fields{'ID'}};
     $id=~s/\s//g;      $id=~s/\s//g;
     if ($id) {              my $clicker = $entries{$fields{'clicker'}};
               $clicker=~s/\s//g;
               if ($clicker) {
                   push(@skipped,"$clicker:$domain");
       } elsif ($id) {
  push(@skipped,"$id:$domain");   push(@skipped,"$id:$domain");
     } else {      } else {
  push(@skipped,"$username:$domain");   push(@skipped,"$username:$domain");
Line 5007  sub csvuploadassign { Line 4832  sub csvuploadassign {
                     my $award=($pcr == 0) ? 'incorrect_by_override'                      my $award=($pcr == 0) ? 'incorrect_by_override'
                                           : 'correct_by_override';                                            : 'correct_by_override';
                     if ($pcr>1) {                      if ($pcr>1) {
                         push(@warnings,&mt("[_1]: point value larger than weight","$username:$domain"));                         push(@warnings,&mt("[_1]: point value larger than weight","$username:$domain"));
                     }                      }
                     $grades{"resource.$part.awarded"}=$pcr;                      $grades{"resource.$part.awarded"}=$pcr;
                     $grades{"resource.$part.solved"}=$award;                      $grades{"resource.$part.solved"}=$award;
Line 5043  sub csvuploadassign { Line 4868  sub csvuploadassign {
                                              $env{'course.'.$env{'request.course.id'}.'.domain'},                                               $env{'course.'.$env{'request.course.id'}.'.domain'},
                                              $env{'course.'.$env{'request.course.id'}.'.num'},                                               $env{'course.'.$env{'request.course.id'}.'.num'},
                                              $domain,$username);                                               $domain,$username);
    } else {                $countdone++;
              } else {
       $request->print("<p><span class=\"LC_error\">".        $request->print("<p><span class=\"LC_error\">".
                               &mt("Failed to save data for student [_1]. Message when trying to save was: [_2]",                                &mt("Failed to save data for student [_1]. Message when trying to save was: [_2]",
                                   "$username:$domain",$result)."</span></p>");                                    "$username:$domain",$result)."</span></p>");
    }     }
    $request->rflush();     $request->rflush();
    $countdone++;  
         }          }
     }      }
     $request->print('<br />'.&Apache::lonhtmlcommon::confirm_success(&mt("Saved scores for [quant,_1,student]",$countdone),$countdone==0));      $request->print('<br />'.&Apache::lonhtmlcommon::confirm_success(&mt("Saved scores for [quant,_1,student]",$countdone),$countdone==0));
Line 5118  LISTJAVASCRIPT Line 4943  LISTJAVASCRIPT
     # Collection of hidden fields      # Collection of hidden fields
     my $ctr=0;      my $ctr=0;
     foreach (@$titles) {      foreach (@$titles) {
  my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);          my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
  $result.='<input type="hidden" name="page'.$ctr.'" value="'.$$symbx{$_}.'" />'."\n";          $result.='<input type="hidden" name="page'.$ctr.'" value="'.$$symbx{$_}.'" />'."\n";
  $result.='<input type="hidden" name="title'.$ctr.'" value="'.$showtitle.'" />'."\n";          $result.='<input type="hidden" name="title'.$ctr.'" value="'.$showtitle.'" />'."\n";
  $ctr++;          $ctr++;
     }      }
     $result.='<input type="hidden" name="page" />'."\n".      $result.='<input type="hidden" name="page" />'."\n".
  '<input type="hidden" name="title" />'."\n";          '<input type="hidden" name="title" />'."\n";
   
     $result.=&build_section_inputs();      $result.=&build_section_inputs();
     my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));      my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));
     $result.='<input type="hidden" name="Status"  value="'.$stu_status.'" />'."\n".      $result.='<input type="hidden" name="Status"  value="'.$stu_status.'" />'."\n".
         '<input type="hidden" name="command" value="displayPage" />'."\n".   '<input type="hidden" name="command" value="displayPage" />'."\n".
         '<input type="hidden" name="symb"    value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";   '<input type="hidden" name="symb"    value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";
   
     # Show grading options      # Show grading options
     $result.=&Apache::lonhtmlcommon::start_pick_box();      $result.=&Apache::lonhtmlcommon::start_pick_box();
     my $select = '<select name="selectpage">'."\n";      my $select = '<select name="selectpage">'."\n";
     $ctr=0;      $ctr=0;
     foreach (@$titles) {      foreach (@$titles) {
         my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);   my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
         $select.='<option value="'.$ctr.'"'.   $select.='<option value="'.$ctr.'"'.
             ($$symbx{$_} =~ /$curpage$/ ? ' selected="selected"' : '').      ($$symbx{$_} =~ /$curpage$/ ? ' selected="selected"' : '').
             '>'.$showtitle.'</option>'."\n";      '>'.$showtitle.'</option>'."\n";
         $ctr++;   $ctr++;
     }      }
     $select.= '</select>';      $select.= '</select>';
   
Line 5167  LISTJAVASCRIPT Line 4992  LISTJAVASCRIPT
        .'<label><input type="radio" name="lastSub" value="all" /> '         .'<label><input type="radio" name="lastSub" value="all" /> '
            .&mt('all submissions with details').' </label>'             .&mt('all submissions with details').' </label>'
        .&Apache::lonhtmlcommon::row_closure();         .&Apache::lonhtmlcommon::row_closure();
       
     $result.=      $result.=
         &Apache::lonhtmlcommon::row_title(&mt('Use CODE'))          &Apache::lonhtmlcommon::row_title(&mt('Use CODE'))
        .'<input type="text" name="CODE" value="" />'         .'<input type="text" name="CODE" value="" />'
Line 5239  sub getSymbMap { Line 5064  sub getSymbMap {
     my @sequences = $navmap->retrieveResources(undef, sub { shift->is_map(); },      my @sequences = $navmap->retrieveResources(undef, sub { shift->is_map(); },
        1,0,1);         1,0,1);
     for my $sequence ($navmap->getById('0.0'), @sequences) {      for my $sequence ($navmap->getById('0.0'), @sequences) {
  if ($navmap->hasResource($sequence, sub { shift->is_problem(); }, 0) ) {   if ($navmap->hasResource($sequence, sub { shift->is_gradable(); }, 0) ) {
     my $title = $minder.'.'.      my $title = $minder.'.'.
  &HTML::Entities::encode($sequence->compTitle(),'"\'&');   &HTML::Entities::encode($sequence->compTitle(),'"\'&');
     push(@titles, $title); # minder in case two titles are identical      push(@titles, $title); # minder in case two titles are identical
Line 5270  sub displayPage { Line 5095  sub displayPage {
     &Apache::lonnet::clear_EXT_cache_status();      &Apache::lonnet::clear_EXT_cache_status();
   
     if (!&canview($usec)) {      if (!&canview($usec)) {
  $request->print(          $request->print(
             '<span class="LC_warning">'.              '<span class="LC_warning">'.
             &mt('Unable to view requested student. ([_1])',              &mt('Unable to view requested student. ([_1])',
                 $env{'form.student'}).                      $env{'form.student'}).
             '</span>');              '</span>');
         return;          return;
     }      }
Line 5336  sub displayPage { Line 5161  sub displayPage {
         if($curRes == $iterator->BEGIN_MAP) { $depth++; }          if($curRes == $iterator->BEGIN_MAP) { $depth++; }
         if($curRes == $iterator->END_MAP) { $depth--; }          if($curRes == $iterator->END_MAP) { $depth--; }
   
         if (ref($curRes) && $curRes->is_problem()) {          if (ref($curRes) && $curRes->is_gradable()) {
     my $parts = $curRes->parts();      my $parts = $curRes->parts();
             my $title = $curRes->compTitle();              my $title = $curRes->compTitle();
     my $symbx = $curRes->symb();      my $symbx = $curRes->symb();
               my $is_tool = ($symbx =~ /ext\.tool$/);
     $studentTable.=      $studentTable.=
  &Apache::loncommon::start_data_table_row().   &Apache::loncommon::start_data_table_row().
  '<td align="center" valign="top" >'.$prob.   '<td align="center" valign="top" >'.$prob.
Line 5350  sub displayPage { Line 5176  sub displayPage {
  '</td>';   '</td>';
     $studentTable.='<td valign="top">';      $studentTable.='<td valign="top">';
     my %form = ('CODE' => $env{'form.CODE'},);      my %form = ('CODE' => $env{'form.CODE'},);
     if ($env{'form.vProb'} eq 'yes' ) {              if ($is_tool) {
  $studentTable.=&show_problem($request,$symbx,$uname,$udom,1,                  $studentTable.='&nbsp;<b>'.$title.'</b><br />';
      undef,'both',\%form);              } else {
     } else {          if ($env{'form.vProb'} eq 'yes' ) {
  my $companswer = &Apache::loncommon::get_student_answers($symbx,$uname,$udom,$env{'request.course.id'},%form);      $studentTable.=&show_problem($request,$symbx,$uname,$udom,1,
  $companswer =~ s|<form(.*?)>||g;           undef,'both',\%form);
  $companswer =~ s|</form>||g;          } else {
 # while ($companswer =~ /(<a href\=\"javascript:newWindow.*?Script Vars<\/a>)/s) { #<a href="javascript:newWindow</a>      my $companswer = &Apache::loncommon::get_student_answers($symbx,$uname,$udom,$env{'request.course.id'},%form);
 #    $companswer =~ s/$1/ /ms;      $companswer =~ s|<form(.*?)>||g;
 #    $request->print('match='.$1."<br />\n");      $companswer =~ s|</form>||g;
 # }  #    while ($companswer =~ /(<a href\=\"javascript:newWindow.*?Script Vars<\/a>)/s) { #<a href="javascript:newWindow</a>
 # $companswer =~ s|<table border=\"1\">|<table border=\"0\">|g;  #        $companswer =~ s/$1/ /ms;
  $studentTable.='&nbsp;<b>'.$title.'</b>&nbsp;<br />&nbsp;<b>'.&mt('Correct answer').':</b><br />'.$companswer;  #        $request->print('match='.$1."<br />\n");
   #    }
   #    $companswer =~ s|<table border=\"1\">|<table border=\"0\">|g;
       $studentTable.='&nbsp;<b>'.$title.'</b>&nbsp;<br />&nbsp;<b>'.&mt('Correct answer').':</b><br />'.$companswer;
    }
     }      }
   
     my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname);      my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname);
   
     if ($env{'form.lastSub'} eq 'datesub') {      if ($env{'form.lastSub'} eq 'datesub') {
  if ($record{'version'} eq '') {   if ($record{'version'} eq '') {
     $studentTable.='<br />&nbsp;<span class="LC_warning">'.&mt('No recorded submission for this problem.').'</span><br />';                      my $msg = &mt('No recorded submission for this problem.');
                       if ($is_tool) {
                           $msg = &mt('No recorded transactions for this external tool');
                       }
       $studentTable.='<br />&nbsp;<span class="LC_warning">'.$msg.'</span><br />';
  } else {   } else {
     my %responseType = ();      my %responseType = ();
     foreach my $partid (@{$parts}) {      foreach my $partid (@{$parts}) {
Line 5382  sub displayPage { Line 5216  sub displayPage {
  $responseType{$partid} = \%responseIds;   $responseType{$partid} = \%responseIds;
     }      }
     $studentTable.= &displaySubByDates($symbx,\%record,$parts,\%responseType,$checkIcon,$uname,$udom);      $studentTable.= &displaySubByDates($symbx,\%record,$parts,\%responseType,$checkIcon,$uname,$udom);
   
  }   }
     } elsif ($env{'form.lastSub'} eq 'all') {      } elsif ($env{'form.lastSub'} eq 'all') {
  my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : '');   my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : '');
                 my $identifier = (&canmodify($usec)? $prob : '');                  my $identifier = (&canmodify($usec)? $prob : ''); 
  $studentTable.=&Apache::loncommon::get_previous_attempt($symbx,$uname,$udom,   $studentTable.=&Apache::loncommon::get_previous_attempt($symbx,$uname,$udom,
  $env{'request.course.id'},   $env{'request.course.id'},
  '','.submission',undef,   '','.submission',undef,
Line 5408  sub displayPage { Line 5241  sub displayPage {
  }   }
         $curRes = $iterator->next();          $curRes = $iterator->next();
     }      }
     my $disabled;  
     unless (&canmodify($usec)) {  
         $disabled = ' disabled="disabled"';  
     }  
   
     $studentTable.=      $studentTable.=
         '</table>'."\n".          '</table>'."\n".
         '<input type="button" value="'.&mt('Save').'"'.$disabled.' '.          '<input type="button" value="'.&mt('Save').'" '.
         'onclick="javascript:checkSubmitPage(this.form,'.$question.');" />'.          'onclick="javascript:checkSubmitPage(this.form,'.$question.');" />'.
         '</form>'."\n";          '</form>'."\n";
     $request->print($studentTable);      $request->print($studentTable);
Line 5427  sub displaySubByDates { Line 5256  sub displaySubByDates {
     my ($symb,$record,$parts,$responseType,$checkIcon,$uname,$udom) = @_;      my ($symb,$record,$parts,$responseType,$checkIcon,$uname,$udom) = @_;
     my $isCODE=0;      my $isCODE=0;
     my $isTask = ($symb =~/\.task$/);      my $isTask = ($symb =~/\.task$/);
       my $is_tool = ($symb =~/\.tool$/);
     if (exists($record->{'resource.CODE'})) { $isCODE=1; }      if (exists($record->{'resource.CODE'})) { $isCODE=1; }
     my $studentTable=&Apache::loncommon::start_data_table().      my $studentTable=&Apache::loncommon::start_data_table().
  &Apache::loncommon::start_data_table_header_row().   &Apache::loncommon::start_data_table_header_row().
  '<th>'.&mt('Date/Time').'</th>'.   '<th>'.&mt('Date/Time').'</th>'.
  ($isCODE?'<th>'.&mt('CODE').'</th>':'').   ($isCODE?'<th>'.&mt('CODE').'</th>':'').
         ($isTask?'<th>'.&mt('Version').'</th>':'').          ($isTask?'<th>'.&mt('Version').'</th>':'').
  '<th>'.&mt('Submission').'</th>'.   '<th>'.($is_tool?&mt('Grade'):&mt('Submission')).'</th>'.
  '<th>'.&mt('Status').'</th>'.   '<th>'.&mt('Status').'</th>'.
  &Apache::loncommon::end_data_table_header_row();   &Apache::loncommon::end_data_table_header_row();
     my ($version);      my ($version);
Line 5441  sub displaySubByDates { Line 5271  sub displaySubByDates {
     my %orders;      my %orders;
     $mark{'correct_by_student'} = $checkIcon;      $mark{'correct_by_student'} = $checkIcon;
     if (!exists($$record{'1:timestamp'})) {      if (!exists($$record{'1:timestamp'})) {
  return '<br />&nbsp;<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br />';          if ($is_tool) {
               return '<br />&nbsp;<span class="LC_warning">'.&mt('No grade passed back.').'</span><br />';
           } else {
               return '<br />&nbsp;<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br />';
           }
     }      }
   
     my $interaction;      my $interaction;
Line 5474  sub displaySubByDates { Line 5308  sub displaySubByDates {
             if (($type eq 'anonsurvey') || ($type eq 'anonsurveycred')) {              if (($type eq 'anonsurvey') || ($type eq 'anonsurveycred')) {
                 $hidden = 1;                  $hidden = 1;
             }              }
     my @matchKey;              my @matchKey;
             if ($isTask) {              if ($isTask) {
                 @matchKey = sort(grep(/^resource\.\d+\.\Q$partid\E\.award$/,@versionKeys));                  @matchKey = sort(grep /^resource\.\d+\.\Q$partid\E\.award$/,@versionKeys);
               } elsif ($is_tool) {
                   @matchKey = sort(grep /^resource\.\Q$partid\E\.awarded$/,@versionKeys);
             } else {              } else {
  @matchKey = sort(grep(/^resource\.\Q$partid\E\..*?\.submission$/,@versionKeys));                  @matchKey = sort(grep /^resource\.\Q$partid\E\..*?\.submission$/,@versionKeys);
             }              }
 #    next if ($$record{"$version:resource.$partid.solved"} eq '');  #    next if ($$record{"$version:resource.$partid.solved"} eq '');
     my $display_part=&get_display_part($partid,$symb);      my $display_part=&get_display_part($partid,$symb);
     foreach my $matchKey (@matchKey) {      foreach my $matchKey (@matchKey) {
  if (exists($$record{$version.':'.$matchKey}) &&   if (exists($$record{$version.':'.$matchKey}) &&
     $$record{$version.':'.$matchKey} ne '') {      $$record{$version.':'.$matchKey} ne '') {
                                           if ($is_tool) {
     my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/)                          $displaySub[0].=$$record{"$version:resource.$partid.awarded"};
                : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/));  
                     $displaySub[0].='<span class="LC_nobreak">';  
                     $displaySub[0].='<b>'.&mt('Part: [_1]',$display_part).'</b>'  
                                    .' <span class="LC_internal_info">'  
                                    .'('.&mt('Response ID: [_1]',$responseId).')'  
                                    .'</span>'  
                                    .' <b>';  
                     if ($hidden) {  
                         $displaySub[0].= &mt('Anonymous Survey').'</b>';  
                     } else {                      } else {
                         my ($trial,$rndseed,$newvariation);          my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/)
                         if ($type eq 'randomizetry') {                     : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/));
                             $trial = $$record{"$where.$partid.tries"};                          $displaySub[0].='<span class="LC_nobreak">';
                             $rndseed = $$record{"$where.$partid.rndseed"};                          $displaySub[0].='<b>'.&mt('Part: [_1]',$display_part).'</b>'
                         }                                         .' <span class="LC_internal_info">'
         if ($$record{"$where.$partid.tries"} eq '') {                                         .'('.&mt('Response ID: [_1]',$responseId).')'
     $displaySub[0].=&mt('Trial not counted');                                         .'</span>'
         } else {                                         .' <b>';
     $displaySub[0].=&mt('Trial: [_1]',                          if ($hidden) {
     $$record{"$where.$partid.tries"});                              $displaySub[0].= &mt('Anonymous Survey').'</b>';
                             if (($rndseed ne '')  && ($lastrndseed{$partid} ne '')) {                          } else {
                                 if (($rndseed ne $lastrndseed{$partid}) &&                              my ($trial,$rndseed,$newvariation);
                                     (($type eq 'randomizetry') || ($lasttype{$partid} eq 'randomizetry'))) {                              if ($type eq 'randomizetry') {
                                     $newvariation = '&nbsp;('.&mt('New variation this try').')';                                  $trial = $$record{"$where.$partid.tries"};
                                 }                                  $rndseed = $$record{"$where.$partid.rndseed"};
                             }                              }
                             $lastrndseed{$partid} = $rndseed;              if ($$record{"$where.$partid.tries"} eq '') {
                             $lasttype{$partid} = $type;          $displaySub[0].=&mt('Trial not counted');
         }              } else {
         my $responseType=($isTask ? 'Task'          $displaySub[0].=&mt('Trial: [_1]',
           $$record{"$where.$partid.tries"});
                                   if (($rndseed ne '') && ($lastrndseed{$partid} ne '')) {
                                       if (($rndseed ne $lastrndseed{$partid}) &&
                                           (($type eq 'randomizetry') || ($lasttype{$partid} eq 'randomizetry'))) {
                                           $newvariation = '&nbsp;('.&mt('New variation this try').')';
                                       }
                                   }
                                   $lastrndseed{$partid} = $rndseed;
                                   $lasttype{$partid} = $type;
               }
               my $responseType=($isTask ? 'Task'
                                               : $responseType->{$partid}->{$responseId});                                                : $responseType->{$partid}->{$responseId});
         if (!exists($orders{$partid})) { $orders{$partid}={}; }              if (!exists($orders{$partid})) { $orders{$partid}={}; }
         if ((!exists($orders{$partid}->{$responseId})) || ($trial)) {              if ((!exists($orders{$partid}->{$responseId})) || ($trial)) {
     $orders{$partid}->{$responseId}=          $orders{$partid}->{$responseId}=
         &get_order($partid,$responseId,$symb,$uname,$udom,              &get_order($partid,$responseId,$symb,$uname,$udom,
                                            $no_increment,$type,$trial,$rndseed);                                                 $no_increment,$type,$trial,$rndseed);
         }              }
         $displaySub[0].='</b>'.$newvariation.'</span>'; # /nobreak              $displaySub[0].='</b>'.$newvariation.'</span>'; # /nobreak
         $displaySub[0].='&nbsp; '.              $displaySub[0].='&nbsp; '.
     &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:",$uname,$udom,$type,$trial,$rndseed).'<br />';          &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:",$uname,$udom,$type,$trial,$rndseed).'<br />';
                           }
                     }                      }
  }   }
     }      }
Line 5541  sub displaySubByDates { Line 5380  sub displaySubByDates {
     lc($$record{"$where.$partid.award"}).' '.      lc($$record{"$where.$partid.award"}).' '.
     $mark{$$record{"$where.$partid.solved"}}.      $mark{$$record{"$where.$partid.solved"}}.
     '<br />';      '<br />';
       } elsif (($is_tool) && (exists($$record{"$version:resource.$partid.solved"}))) {
    if ($$record{"$version:resource.$partid.solved"} =~ /^(in|)correct_by_passback$/) {
       $displaySub[1].=&mt('Grade passed back by external tool');
    }
     }      }
     if (exists $$record{"$where.$partid.regrader"}) {      if (exists $$record{"$where.$partid.regrader"}) {
  $displaySub[2].=$$record{"$where.$partid.regrader"}.   $displaySub[2].=$$record{"$where.$partid.regrader"};
     ' (<b>'.&mt('Part').':</b> '.$display_part.')';   unless ($is_tool) {
       $displaySub[2].=' (<b>'.&mt('Part').':</b> '.$display_part.')';
    }
     } elsif ($$record{"$version:resource.$partid.regrader"} =~ /\S/) {      } elsif ($$record{"$version:resource.$partid.regrader"} =~ /\S/) {
  $displaySub[2].=   $displaySub[2].=
     $$record{"$version:resource.$partid.regrader"}.      $$record{"$version:resource.$partid.regrader"};
     ' (<b>'.&mt('Part').':</b> '.$display_part.')';                  unless ($is_tool) {
       $displaySub[2].=' (<b>'.&mt('Part').':</b> '.$display_part.')';
                   }
     }      }
  }   }
  # needed because old essay regrader has not parts info   # needed because old essay regrader has not parts info
Line 6053  sub scantron_selectphase { Line 5900  sub scantron_selectphase {
     if (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) ||      if (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) ||
         &Apache::lonnet::allowed('usc',$env{'request.course.id'})) {          &Apache::lonnet::allowed('usc',$env{'request.course.id'})) {
   
         # Chunk of form to prompt for a scantron file upload.   # Chunk of form to prompt for a scantron file upload.
   
         $r->print('          $r->print('
     <br />');      <br />');
         my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'};      my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'};
         my $cnum= $env{'course.'.$env{'request.course.id'}.'.num'};      my $cnum= $env{'course.'.$env{'request.course.id'}.'.num'};
         my $alertmsg = &mt('Please use the browse button to select a file from your local directory.');      my $alertmsg = &mt('Please use the browse button to select a file from your local directory.');
         &js_escape(\$alertmsg);      &js_escape(\$alertmsg);
         my ($formatoptions,$formattitle,$formatjs) = &scantron_upload_dataformat($cdom);      my ($formatoptions,$formattitle,$formatjs) = &scantron_upload_dataformat($cdom);
         $r->print(&Apache::lonhtmlcommon::scripttag('      $r->print(&Apache::lonhtmlcommon::scripttag('
     function checkUpload(formname) {      function checkUpload(formname) {
         if (formname.upfile.value == "") {   if (formname.upfile.value == "") {
             alert("'.$alertmsg.'");      alert("'.$alertmsg.'");
             return false;      return false;
         }   }
         formname.submit();   formname.submit();
     }'."\n".$formatjs));      }'."\n".$formatjs));
         $r->print('      $r->print('
               <form enctype="multipart/form-data" action="/adm/grades" name="rules" method="post">                <form enctype="multipart/form-data" action="/adm/grades" name="rules" method="post">
                 '.$default_form_data.'                  '.$default_form_data.'
                 <input name="courseid" type="hidden" value="'.$cnum.'" />                  <input name="courseid" type="hidden" value="'.$cnum.'" />
Line 6085  sub scantron_selectphase { Line 5932  sub scantron_selectphase {
               '.&Apache::loncommon::start_data_table_row().'                '.&Apache::loncommon::start_data_table_row().'
             <td>              <td>
                 '.&mt('File to upload: [_1]','<input type="file" name="upfile" size="50" />').'<br />'."\n");                  '.&mt('File to upload: [_1]','<input type="file" name="upfile" size="50" />').'<br />'."\n");
         if ($formatoptions) {      if ($formatoptions) {
             $r->print('</td>          $r->print('</td>
                  '.&Apache::loncommon::end_data_table_row().'                   '.&Apache::loncommon::end_data_table_row().'
                  '.&Apache::loncommon::start_data_table_row().'                   '.&Apache::loncommon::start_data_table_row().'
                  <td>'.$formattitle.('&nbsp;'x2).$formatoptions.'                   <td>'.$formattitle.('&nbsp;'x2).$formatoptions.'
Line 6094  sub scantron_selectphase { Line 5941  sub scantron_selectphase {
                  '.&Apache::loncommon::end_data_table_row().'                   '.&Apache::loncommon::end_data_table_row().'
                  '.&Apache::loncommon::start_data_table_row().'                   '.&Apache::loncommon::start_data_table_row().'
                  <td>'                   <td>'
             );          );
         } else {      } else {
             $r->print(' <br />');          $r->print(' <br />');
         }      }
         $r->print('<input type="button" onclick="javascript:checkUpload(this.form);" value="'.&mt('Upload Bubblesheet Data').'" />      $r->print('<input type="button" onclick="javascript:checkUpload(this.form);" value="'.&mt('Upload Bubblesheet Data').'" />
               </td>                </td>
              '.&Apache::loncommon::end_data_table_row().'               '.&Apache::loncommon::end_data_table_row().'
              '.&Apache::loncommon::end_data_table().'               '.&Apache::loncommon::end_data_table().'
              </form>'               </form>'
         );      );
   
     }      }
   
Line 6220  sub scantron_selectphase { Line 6067  sub scantron_selectphase {
 =item username_to_idmap  =item username_to_idmap
   
     creates a hash keyed by student/employee ID with values of the corresponding      creates a hash keyed by student/employee ID with values of the corresponding
     student username:domain.      student username:domain. If a single ID occurs for more than one student,
       the status of the student is checked, and if Active, the value in the hash
       will be set to the Active student.
   
   Arguments:    Arguments:
   
Line 6420  sub digits_to_letters { Line 6269  sub digits_to_letters {
   
 =item scantron_parse_scanline  =item scantron_parse_scanline
   
   Decodes a scanline from the selected scantron file    Decodes a scanline from the selected bubblesheet file
   
  Arguments:   Arguments:
     line             - The text of the scantron file line to process      line             - The text of the bubblesheet file line to process
     whichline        - Line number      whichline        - Line number
     scantron_config  - Hash describing the format of the scantron lines.      scantron_config  - Hash describing the format of the bubblesheet lines.
     scan_data        - Hash of extra information about the scanline      scan_data        - Hash of extra information about the scanline
                        (see scantron_getfile for more information)                         (see scantron_getfile for more information)
     just_header      - True if should not process question answers but only      just_header      - True if should not process question answers but only
Line 6450  sub digits_to_letters { Line 6299  sub digits_to_letters {
     totalref         - Ref of scalar used to score total number of bubble      totalref         - Ref of scalar used to score total number of bubble
                        lines needed for responses in a scan line (used when                         lines needed for responses in a scan line (used when
                        randompick in use.                          randompick in use. 
       
  Returns:   Returns:
    Hash containing the result of parsing the scanline     Hash containing the result of parsing the scanline
   
Line 6543  sub scantron_parse_scanline { Line 6392  sub scantron_parse_scanline {
                                          $partids_by_symb,$orderedforcode,                                           $partids_by_symb,$orderedforcode,
                                          $respnumlookup,$startline);                                           $respnumlookup,$startline);
         if ($total) {          if ($total) {
             $lastpos = $total*$$scantron_config{'Qlength'};              $lastpos = $total*$$scantron_config{'Qlength'}; 
         }          }
         if (ref($totalref)) {          if (ref($totalref)) {
             $$totalref = $total;              $$totalref = $total;
Line 6557  sub scantron_parse_scanline { Line 6406  sub scantron_parse_scanline {
         if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) {          if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) {
             $answers_needed = $bubble_lines_per_response{$respnumlookup->{$questnum}};              $answers_needed = $bubble_lines_per_response{$respnumlookup->{$questnum}};
         } else {          } else {
             $answers_needed = $bubble_lines_per_response{$questnum};      $answers_needed = $bubble_lines_per_response{$questnum};
         }          }
         my $answer_length  = ($$scantron_config{'Qlength'} * $answers_needed)          my $answer_length  = ($$scantron_config{'Qlength'} * $answers_needed)
                              || 1;                               || 1;
Line 6618  sub scantron_parse_scanline { Line 6467  sub scantron_parse_scanline {
   
 sub get_master_seq {  sub get_master_seq {
     my ($resources,$master_seq,$symb_to_resource) = @_;      my ($resources,$master_seq,$symb_to_resource) = @_;
     return unless ((ref($resources) eq 'ARRAY') && (ref($master_seq) eq 'ARRAY') &&      return unless ((ref($resources) eq 'ARRAY') && (ref($master_seq) eq 'ARRAY') && 
                    (ref($symb_to_resource) eq 'HASH'));                     (ref($symb_to_resource) eq 'HASH'));
     my $resource_error;      my $resource_error;
     foreach my $resource (@{$resources}) {      foreach my $resource (@{$resources}) {
Line 6696  sub scantron_validator_lettnum { Line 6545  sub scantron_validator_lettnum {
     my $occurrences = 0;      my $occurrences = 0;
     my $responsenum = $questnum-1;      my $responsenum = $questnum-1;
     if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) {      if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) {
        $responsenum = $respnumlookup->{$questnum-1}         $responsenum = $respnumlookup->{$questnum-1} 
     }      }
     if (($responsetype_per_response{$responsenum} eq 'essayresponse') ||      if (($responsetype_per_response{$responsenum} eq 'essayresponse') ||
         ($responsetype_per_response{$responsenum} eq 'formularesponse') ||          ($responsetype_per_response{$responsenum} eq 'formularesponse') ||
Line 6992  sub scantron_process_corrections { Line 6841  sub scantron_process_corrections {
  }   }
     }      }
     if ($err) {      if ($err) {
  $r->print(          $r->print(
             '<p class="LC_error">'              '<p class="LC_error">'
            .&mt('Unable to accept last correction, an error occurred: [_1]',             .&mt('Unable to accept last correction, an error occurred: [_1]',
                 $errmsg)                  $errmsg)
Line 7295  sub scantron_validate_file { Line 7144  sub scantron_validate_file {
     while (!$stop && $currentphase < scalar(@validate_phases)) {      while (!$stop && $currentphase < scalar(@validate_phases)) {
  $r->print(&mt('Validating '.$validate_phases[$currentphase]).'<br />');   $r->print(&mt('Validating '.$validate_phases[$currentphase]).'<br />');
  $r->rflush();   $r->rflush();
        
  my $which="scantron_validate_".$validate_phases[$currentphase];   my $which="scantron_validate_".$validate_phases[$currentphase];
  {   {
     no strict 'refs';      no strict 'refs';
Line 7325  sub scantron_validate_file { Line 7174  sub scantron_validate_file {
     $r->print('<input type="submit" name="submit" value="'.&mt('Ignore').' &rarr; " />');      $r->print('<input type="submit" name="submit" value="'.&mt('Ignore').' &rarr; " />');
     $r->print(' '.&mt('this error').' <br />');      $r->print(' '.&mt('this error').' <br />');
   
             $r->print('<p>'.&mt('Or 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>');      $r->print('<p>'.&mt('Or 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>');
  } else {   } else {
             if ($validate_phases[$currentphase] eq 'doublebubble' || $validate_phases[$currentphase] eq 'missingbubbles') {              if ($validate_phases[$currentphase] eq 'doublebubble' || $validate_phases[$currentphase] eq 'missingbubbles') {
         $r->print('<input type="button" name="submitbutton" value="'.&mt('Continue').' &rarr;" onclick="javascript:verify_bubble_radio(this.form)" />');          $r->print('<input type="button" name="submitbutton" value="'.&mt('Continue').' &rarr;" onclick="javascript:verify_bubble_radio(this.form)" />');
Line 7704  sub scantron_validate_sequence { Line 7553  sub scantron_validate_sequence {
  my @resources=   my @resources=
     $navmap->retrieveResources($map,\&scantron_filter_not_exam,1,0);      $navmap->retrieveResources($map,\&scantron_filter_not_exam,1,0);
  if (@resources) {   if (@resources) {
     $r->print('<p class="LC_warning">'      $r->print(
                   '<p class="LC_warning">'
                .&mt('Some resources in the sequence currently are not set to'                 .&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.')                     .' work correctly.')
                .'</p>'                 .'</p>'
             );              );
Line 7828  sub scantron_get_correction { Line 7678  sub scantron_get_correction {
   
     if ($error =~ /ID$/) {      if ($error =~ /ID$/) {
  if ($error eq 'incorrectID') {   if ($error eq 'incorrectID') {
     $r->print('<p class="LC_warning">'.&mt("The encoded ID is not in the classlist").              $r->print('<p class="LC_warning">'.&mt("The encoded ID is not in the classlist").
       "</p>\n");        "</p>\n");
  } elsif ($error eq 'duplicateID') {   } elsif ($error eq 'duplicateID') {
     $r->print('<p class="LC_warning">'.&mt("The encoded ID has also been used by a previous paper [_1]",$arg)."</p>\n");              $r->print('<p class="LC_warning">'.&mt("The encoded ID has also been used by a previous paper [_1]",$arg)."</p>\n");
  }   }
  $r->print($message);   $r->print($message);
  $r->print("<p>".&mt("How should I handle this?")." <br /> \n");   $r->print("<p>".&mt("How should I handle this?")." <br /> \n");
Line 7851  sub scantron_get_correction { Line 7701  sub scantron_get_correction {
  } elsif ($error eq 'duplicateCODE') {   } elsif ($error eq 'duplicateCODE') {
     $r->print('<p class="LC_warning">'.&mt("The encoded CODE has also been used by a previous paper [_1], and CODEs are supposed to be unique.",join(', ',@{$arg}))."</p>\n");      $r->print('<p class="LC_warning">'.&mt("The encoded CODE has also been used by a previous paper [_1], and CODEs are supposed to be unique.",join(', ',@{$arg}))."</p>\n");
  }   }
         $r->print("<p>".&mt('The CODE on the form is [_1]',   $r->print("<p>".&mt('The CODE on the form is [_1]',
                             "<tt>'$$scan_record{'scantron.CODE'}'</tt>")      "<tt>'$$scan_record{'scantron.CODE'}'</tt>")
                  ."</p>\n");                   ."</p>\n");
  $r->print($message);   $r->print($message);
  $r->print("<p>".&mt("How should I handle this?")."</p>\n");   $r->print("<p>".&mt("How should I handle this?")."</p>\n");
Line 7949  ENDSCRIPT Line 7799  ENDSCRIPT
  # The form field scantron_questions is actually a list of line numbers not   # The form field scantron_questions is actually a list of line numbers not
  # a list of question numbers. Therefore:   # a list of question numbers. Therefore:
  #   #
   
  my $line_list = &questions_to_line_list($arg,$randomorder,$randompick,   my $line_list = &questions_to_line_list($arg,$randomorder,$randompick,
                                                 $respnumlookup,$startline);                                                  $respnumlookup,$startline);
   
Line 8059  sub questions_to_line_list { Line 7909  sub questions_to_line_list {
             } else {              } else {
                 $first = $first_bubble_line{$responsenum} + 1;                  $first = $first_bubble_line{$responsenum} + 1;
             }              }
             $count   = $bubble_lines_per_response{$responsenum};      $count   = $bubble_lines_per_response{$responsenum};
         }          }
         $last = $first+$count-1;          $last = $first+$count-1;
         push(@lines, ($first..$last));          push(@lines, ($first..$last));
Line 8090  for multi and missing bubble cases). Line 7940  for multi and missing bubble cases).
                   and value is number of first bubble line for current student                    and value is number of first bubble line for current student
                   or code-based randompick and/or randomorder.                    or code-based randompick and/or randomorder.
   
   
  Implicit inputs:   Implicit inputs:
    %bubble_lines_per_response   - Starting line numbers for each question.     %bubble_lines_per_response   - Starting line numbers for each question.
                                   Numbered from 0 (but question numbers are from                                    Numbered from 0 (but question numbers are from
Line 8142  sub prompt_for_corrections { Line 7993  sub prompt_for_corrections {
     } else {      } else {
         if (($randomorder || $randompick) && (ref($respnumlookup) eq 'HASH')) {          if (($randomorder || $randompick) && (ref($respnumlookup) eq 'HASH')) {
             $responsenum = $respnumlookup->{$question-1};              $responsenum = $respnumlookup->{$question-1};
             if (ref($startline) eq 'HASH') {              if (ref($startline) eq 'HASH') { 
                 $first = $startline->{$question-1};                  $first = $startline->{$question-1};
             }              }
         } else {          } else {
Line 8160  sub prompt_for_corrections { Line 8011  sub prompt_for_corrections {
             ($responsetype_per_response{$responsenum} eq 'imageresponse') ||              ($responsetype_per_response{$responsenum} eq 'imageresponse') ||
             ($responsetype_per_response{$responsenum} eq 'reactionresponse') ||              ($responsetype_per_response{$responsenum} eq 'reactionresponse') ||
             ($responsetype_per_response{$responsenum} eq 'organicresponse')) {              ($responsetype_per_response{$responsenum} eq 'organicresponse')) {
             $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 />');              $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 {          } else {
             $r->print(&mt("Select at most one bubble in a single line and select 'No Bubble' in all the other lines. ")."<br />");              $r->print(&mt("Select at most one bubble in a single line and select 'No Bubble' in all the other lines. ")."<br />");
         }          }
Line 8200  sub scantron_bubble_selector { Line 8060  sub scantron_bubble_selector {
     my $max=$$scan_config{'Qlength'};      my $max=$$scan_config{'Qlength'};
   
     my $scmode=$$scan_config{'Qon'};      my $scmode=$$scan_config{'Qon'};
     if ($scmode eq 'number' || $scmode eq 'letter') {      if ($scmode eq 'number' || $scmode eq 'letter') { 
         if (($$scan_config{'BubblesPerRow'} =~ /^\d+$/) &&          if (($$scan_config{'BubblesPerRow'} =~ /^\d+$/) &&
             ($$scan_config{'BubblesPerRow'} > 0)) {              ($$scan_config{'BubblesPerRow'} > 0)) {
             $max=$$scan_config{'BubblesPerRow'};              $max=$$scan_config{'BubblesPerRow'};
Line 8519  sub scantron_get_maxbubble { Line 8379  sub scantron_get_maxbubble {
     my $response_number = 0;      my $response_number = 0;
     my $bubble_line     = 0;      my $bubble_line     = 0;
     foreach my $resource (@resources) {      foreach my $resource (@resources) {
         my $resid = $resource->id();          my $resid = $resource->id(); 
         my ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname,          my ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname,
                                                           $udom,undef,$bubbles_per_row);                                                            $udom,undef,$bubbles_per_row);
         if ((ref($analysis) eq 'HASH') && (ref($parts) eq 'ARRAY')) {          if ((ref($analysis) eq 'HASH') && (ref($parts) eq 'ARRAY')) {
Line 8570  sub scantron_get_maxbubble { Line 8430  sub scantron_get_maxbubble {
         $bubble_lines_per_response{$response_number} = $lines;          $bubble_lines_per_response{$response_number} = $lines;
                 $responsetype_per_response{$response_number} =                   $responsetype_per_response{$response_number} = 
                     $analysis->{$part_id.'.type'};                      $analysis->{$part_id.'.type'};
                 $masterseq_id_responsenum{$resid.'_'.$part_id} = $response_number;                  $masterseq_id_responsenum{$resid.'_'.$part_id} = $response_number;  
         $response_number++;          $response_number++;
   
         $bubble_line +=  $lines;          $bubble_line +=  $lines;
Line 8651  sub scantron_validate_missingbubbles { Line 8511  sub scantron_validate_missingbubbles {
     for (my $i=0;$i<=$scanlines->{'count'};$i++) {      for (my $i=0;$i<=$scanlines->{'count'};$i++) {
  my $line=&scantron_get_line($scanlines,$scan_data,$i);   my $line=&scantron_get_line($scanlines,$scan_data,$i);
  if ($line=~/^[\s\cz]*$/) { next; }   if ($line=~/^[\s\cz]*$/) { next; }
         my $scan_record =   my $scan_record =
             &scantron_parse_scanline($line,$i,\%scantron_config,$scan_data,undef,\%idmap,              &scantron_parse_scanline($line,$i,\%scantron_config,$scan_data,undef,\%idmap,
                                      $randomorder,$randompick,$sequence,\@master_seq,       $randomorder,$randompick,$sequence,\@master_seq,
                                      \%symb_to_resource,\%grader_partids_by_symb,                                       \%symb_to_resource,\%grader_partids_by_symb,
                                      \%orderedforcode,\%respnumlookup,\%startline);                                       \%orderedforcode,\%respnumlookup,\%startline);
  if (!defined($$scan_record{'scantron.missingerror'})) { next; }   if (!defined($$scan_record{'scantron.missingerror'})) { next; }
Line 8664  sub scantron_validate_missingbubbles { Line 8524  sub scantron_validate_missingbubbles {
  foreach my $missing (@{$$scan_record{'scantron.missingerror'}}) {   foreach my $missing (@{$$scan_record{'scantron.missingerror'}}) {
             my $lastbubble;              my $lastbubble;
             if ($missing =~ /^(\d+)\.(\d+)$/) {              if ($missing =~ /^(\d+)\.(\d+)$/) {
                 my $question = $1;                 my $question = $1;
                 my $subquestion = $2;                 my $subquestion = $2;
                 my ($first,$responsenum);                 my ($first,$responsenum);
                 if ($randomorder || $randompick) {                 if ($randomorder || $randompick) {
                     $responsenum = $respnumlookup{$question-1};                     $responsenum = $respnumlookup{$question-1};
                     $first = $startline{$question-1};                     $first = $startline{$question-1};
                 } else {                 } else {
                     $responsenum = $question-1;                     $responsenum = $question-1; 
                     $first = $first_bubble_line{$responsenum};                     $first = $first_bubble_line{$responsenum};
                 }                 }
                 if (!defined($first)) { next; }                 if (!defined($first)) { next; }
                 my @subans = split(/,/,$subdivided_bubble_lines{$responsenum});                 my @subans = split(/,/,$subdivided_bubble_lines{$responsenum});
                 my $subcount = 1;                 my $subcount = 1;
                 while ($subcount<$subquestion) {                 while ($subcount<$subquestion) {
                     $first += $subans[$subcount-1];                     $first += $subans[$subcount-1];
                     $subcount ++;                     $subcount ++;
                 }                 }
                 my $count = $subans[$subquestion-1];                 my $count = $subans[$subquestion-1];
                 $lastbubble = $first + $count;                 $lastbubble = $first + $count;
             } else {              } else {
                 my ($first,$responsenum);                 my ($first,$responsenum);
                 if ($randomorder || $randompick) {                 if ($randomorder || $randompick) {
                     $responsenum = $respnumlookup{$missing-1};                     $responsenum = $respnumlookup{$missing-1};
                     $first = $startline{$missing-1};                     $first = $startline{$missing-1};
                 } else {                 } else {
                     $responsenum = $missing-1;                     $responsenum = $missing-1;
                     $first = $first_bubble_line{$responsenum};                     $first = $first_bubble_line{$responsenum};
                 }                 }
                 if (!defined($first)) { next; }                 if (!defined($first)) { next; }
                 $lastbubble = $first + $bubble_lines_per_response{$responsenum};                 $lastbubble = $first + $bubble_lines_per_response{$responsenum};
             }              }
             if ($lastbubble > $max_bubble) { next; }              if ($lastbubble > $max_bubble) { next; }
     push(@to_correct,$missing);      push(@to_correct,$missing);
Line 8756  sub scantron_process_students { Line 8616  sub scantron_process_students {
     my $default_form_data=&defaultFormData($symb);      my $default_form_data=&defaultFormData($symb);
   
     my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
     my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config);      my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config); 
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
     my $classlist=&Apache::loncoursedata::get_classlist();      my $classlist=&Apache::loncoursedata::get_classlist();
     my %idmap=&username_to_idmap($classlist);      my %idmap=&username_to_idmap($classlist);
Line 8840  SCANTRONFORM Line 8700  SCANTRONFORM
         my %startline = ();          my %startline = ();
         my $total;          my $total;
   my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,    my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,
   $scan_data,undef,\%idmap,$randomorder,                                                   $scan_data,undef,\%idmap,$randomorder,
                                                  $randompick,$sequence,\@master_seq,                                                   $randompick,$sequence,\@master_seq,
                                                  \%symb_to_resource,\%grader_partids_by_symb,                                                   \%symb_to_resource,\%grader_partids_by_symb,
                                                  \%orderedforcode,\%respnumlookup,\%startline,                                                   \%orderedforcode,\%respnumlookup,\%startline,
Line 8870  SCANTRONFORM Line 8730  SCANTRONFORM
   
         my @mapresources = @resources;          my @mapresources = @resources;
         if ($randomorder || $randompick) {          if ($randomorder || $randompick) {
             @mapresources =              @mapresources = 
                 &users_order($user,$scancode,$sequence,\@master_seq,\%symb_to_resource,                  &users_order($user,$scancode,$sequence,\@master_seq,\%symb_to_resource,
                              \%orderedforcode);                               \%orderedforcode);
         }          }
Line 8959  SCANTRONFORM Line 8819  SCANTRONFORM
                 if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,                  if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,
                                            \@mapresources,\%partids_by_symb,                                             \@mapresources,\%partids_by_symb,
                                            $bubbles_per_row,$randomorder,$randompick,                                             $bubbles_per_row,$randomorder,$randompick,
                                            \%respnumlookup,\%startline)                                             \%respnumlookup,\%startline) 
                     eq 'ssi_error') {                      eq 'ssi_error') {
                     $ssi_error = 0; # So end of handler error message does not trigger.                      $ssi_error = 0; # So end of handler error message does not trigger.
                     $r->print("</form>");                      $r->print("</form>");
Line 9052  sub graders_resources_pass { Line 8912  sub graders_resources_pass {
 =item users_order  =item users_order
   
   Returns array of resources in current map, ordered based on either CODE,    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    if this is a CODEd exam, or based on student's identity if this is a 
   "NAMEd" exam.    "NAMEd" exam.
   
   Should be used when randomorder and/or randompick applied when the     Should be used when randomorder and/or randompick applied when the 
Line 9079  sub users_order  { Line 8939  sub users_order  {
             if (ref($actual_seq) eq 'ARRAY') {              if (ref($actual_seq) eq 'ARRAY') {
                 @mapresources = map { $symb_to_resource->{$_}; } @{$actual_seq};                  @mapresources = map { $symb_to_resource->{$_}; } @{$actual_seq};
                 if (ref($orderedforcode) eq 'HASH') {                  if (ref($orderedforcode) eq 'HASH') {
                     if (@mapresources > 0) {                      if (@mapresources > 0) { 
                         $orderedforcode->{$scancode} = \@mapresources;                          $orderedforcode->{$scancode} = \@mapresources;
                     }                      }
                 }                  }
Line 9092  sub users_order  { Line 8952  sub users_order  {
                                                            $master_seq,                                                             $master_seq,
                                                            $user,undef,1);                                                             $user,undef,1);
         if (ref($actual_seq) eq 'ARRAY') {          if (ref($actual_seq) eq 'ARRAY') {
             @mapresources =              @mapresources = 
                 map { $symb_to_resource->{$_}; } @{$actual_seq};                  map { $symb_to_resource->{$_}; } @{$actual_seq};
         }          }
     }      }
Line 9157  sub scantron_upload_scantron_data { Line 9017  sub scantron_upload_scantron_data {
   'domainid',    'domainid',
   'coursename',$dom);    'coursename',$dom);
     my $syllabuslink = '<a href="javascript:ToSyllabus();">'.&mt('Syllabus').'</a>'.      my $syllabuslink = '<a href="javascript:ToSyllabus();">'.&mt('Syllabus').'</a>'.
                        ('&nbsp'x2).&mt('(shows course personnel)');                         ('&nbsp'x2).&mt('(shows course personnel)'); 
     my $default_form_data=&defaultFormData($symb);      my $default_form_data=&defaultFormData($symb);
     my $nofile_alert = &mt('Please use the browse button to select a file from your local directory.');      my $nofile_alert = &mt('Please use the browse button to select a file from your local directory.');
     &js_escape(\$nofile_alert);      &js_escape(\$nofile_alert);
Line 9238  END Line 9098  END
             if (keys(%{$domconfig{'scantron'}{'config'}}) > 1) {              if (keys(%{$domconfig{'scantron'}{'config'}}) > 1) {
                 if (($domconfig{'scantron'}{'config'}{'dat'}) &&                  if (($domconfig{'scantron'}{'config'}{'dat'}) &&
                     (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH')) {                      (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH')) {
                     if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {                      if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {  
                         if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}})) {                          if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}})) {
                             my ($onclick,$formatextra,$singleline);                              my ($onclick,$formatextra,$singleline);
                             my @lines = &Apache::lonnet::get_scantronformat_file();                              my @lines = &Apache::lonnet::get_scantronformat_file();
Line 9251  END Line 9111  END
                             if ($count > 1) {                              if ($count > 1) {
                                 $formatextra = '<div style="display:none" id="bubbletype">'.                                  $formatextra = '<div style="display:none" id="bubbletype">'.
                                                '<span class="LC_nobreak">'.                                                 '<span class="LC_nobreak">'.
                                                &mt('Bubblesheet type').':&nbsp;'.                                                 &mt('Bubblesheet type:').'&nbsp;'.
                                                &scantron_scantab().'</span></div>';                                                 &scantron_scantab().'</span></div>';
                                 $onclick = ' onclick="toggleScantab(this.form);"';                                  $onclick = ' onclick="toggleScantab(this.form);"';
                                 $formatjs = <<"END";                                  $formatjs = <<"END";
Line 9314  sub scantron_upload_scantron_data_save { Line 9174  sub scantron_upload_scantron_data_save {
  !&Apache::lonnet::allowed('usc',   !&Apache::lonnet::allowed('usc',
     $env{'form.domainid'}.'_'.$env{'form.courseid'})) {      $env{'form.domainid'}.'_'.$env{'form.courseid'})) {
  $r->print(&mt("You are not allowed to upload bubblesheet data to the requested course.")."<br />");   $r->print(&mt("You are not allowed to upload bubblesheet data to the requested course.")."<br />");
         unless ($symb) {   unless ($symb) {
     $r->print($doanotherupload);      $r->print($doanotherupload);
  }   }
  return '';   return '';
     }      }
     my %coursedata=&Apache::lonnet::coursedescription($env{'form.domainid'}.'_'.$env{'form.courseid'});      my %coursedata=&Apache::lonnet::coursedescription($env{'form.domainid'}.'_'.$env{'form.courseid'});
     my $uploadedfile;      my $uploadedfile;
     $r->print('<p>'.&mt("Uploading file to [_1]",$coursedata{'description'}).'</p>');      $r->print('<p>'.&mt('Uploading file to [_1]','"'.$coursedata{'description'}.'"').'</p>');
     if (length($env{'form.upfile'}) < 2) {      if (length($env{'form.upfile'}) < 2) {
         $r->print(          $r->print(
             &Apache::lonhtmlcommon::confirm_success(              &Apache::lonhtmlcommon::confirm_success(
Line 9361  sub scantron_upload_scantron_data_save { Line 9221  sub scantron_upload_scantron_data_save {
         my $result =          my $result =
             &Apache::lonnet::userfileupload('upfile','scantron','scantron',$parser,'','',              &Apache::lonnet::userfileupload('upfile','scantron','scantron',$parser,'','',
                                             $env{'form.courseid'},$env{'form.domainid'});                                              $env{'form.courseid'},$env{'form.domainid'});
  if ($result =~ m{^/uploaded/}) {          if ($result =~ m{^/uploaded/}) {
             $r->print(              $r->print(
                 &Apache::lonhtmlcommon::confirm_success(&mt('Upload successful')).'<br />'.                  &Apache::lonhtmlcommon::confirm_success(&mt('Upload successful')).'<br />'.
                 &mt('Uploaded [_1] bytes of data into location: [_2]',                  &mt('Uploaded [_1] bytes of data into location: [_2]',
Line 9370  sub scantron_upload_scantron_data_save { Line 9230  sub scantron_upload_scantron_data_save {
             ($uploadedfile) = ($result =~ m{/([^/]+)$});              ($uploadedfile) = ($result =~ m{/([^/]+)$});
             $r->print(&validate_uploaded_scantron_file($env{'form.domainid'},              $r->print(&validate_uploaded_scantron_file($env{'form.domainid'},
                                                        $env{'form.courseid'},$uploadedfile));                                                         $env{'form.courseid'},$uploadedfile));
  } else {          } else {
             $r->print(              $r->print(
                 &Apache::lonhtmlcommon::confirm_success(&mt('Upload failed'),1).'<br />'.                  &Apache::lonhtmlcommon::confirm_success(&mt('Upload failed'),1).'<br />'.
                     &mt('An error ([_1]) occurred when attempting to upload the file: [_2]',                      &mt('An error ([_1]) occurred when attempting to upload the file: [_2]',
Line 9565  sub checkscantron_results { Line 9425  sub checkscantron_results {
     my $map=$navmap->getResourceByUrl($sequence);      my $map=$navmap->getResourceByUrl($sequence);
     my ($randomorder,$randompick,@master_seq,%symb_to_resource,%grader_partids_by_symb,      my ($randomorder,$randompick,@master_seq,%symb_to_resource,%grader_partids_by_symb,
         %grader_randomlists_by_symb,%orderedforcode);          %grader_randomlists_by_symb,%orderedforcode);
     if (ref($map)) {      if (ref($map)) { 
         $randomorder=$map->randomorder();          $randomorder=$map->randomorder();
         $randompick=$map->randompick();          $randompick=$map->randompick();
     }      }
Line 9594  sub checkscantron_results { Line 9454  sub checkscantron_results {
         return '';          return '';
     }      }
   
     &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,      &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,'Processing first student');
                                           'Processing first student');  
     my $start=&Time::HiRes::time();      my $start=&Time::HiRes::time();
     my $i=-1;      my $i=-1;
   
Line 9605  sub checkscantron_results { Line 9464  sub checkscantron_results {
         my $line=&Apache::grades::scantron_get_line($scanlines,$scan_data,$i);          my $line=&Apache::grades::scantron_get_line($scanlines,$scan_data,$i);
         if ($line=~/^[\s\cz]*$/) { next; }          if ($line=~/^[\s\cz]*$/) { next; }
         if ($started) {          if ($started) {
             &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,              &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last student');
                                                      'last student');  
         }          }
         $started=1;          $started=1;
         my $scan_record=          my $scan_record=
Line 9718  sub checkscantron_results { Line 9576  sub checkscantron_results {
             }              }
         }          }
     }      }
     $r->print('<p>'.      $r->print(
               &mt('Comparison of bubblesheet data (including corrections) with corresponding submission records (most recent submission) for [_1][quant,_2,student][_3] ([quant,_4,bubblesheet line] per student).',          '<p>'
                   '<b>',         .&mt('Comparison of bubblesheet data (including corrections) with corresponding submission records (most recent submission) for [_1][quant,_2,student][_3] ([quant,_4,bubblesheet line] per student).',
                   $numstudents,              '<b>',
                   '</b>',              $numstudents,
                   $env{'form.scantron_maxbubble'}).              '</b>',
               '</p>'              $env{'form.scantron_maxbubble'})
          .'</p>'
     );      );
     $r->print('<p>'      $r->print('<p>'
              .&mt('Exact matches for [_1][quant,_2,student][_3].','<b>',$passed,'</b>')               .&mt('Exact matches for [_1][quant,_2,student][_3].','<b>',$passed,'</b>')
              .'<br />'               .'<br />'
              .&mt('Discrepancies detected for [_1][quant,_2,student][_3].','<b>',$failed,'</b>')               .&mt('Discrepancies detected for [_1][quant,_2,student][_3].','<b>',$failed,'</b>')
              .'</p>');               .'</p>'
       );
     if ($passed) {      if ($passed) {
         $r->print(&mt('Students with exact correspondence between bubblesheet data and submissions are as follows:').'<br /><br />');          $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".          $r->print(&Apache::loncommon::start_data_table()."\n".
Line 9895  sub grading_menu { Line 9755  sub grading_menu {
   
     my %fields = ('symb'=>&Apache::lonenc::check_encrypt($symb),      my %fields = ('symb'=>&Apache::lonenc::check_encrypt($symb),
                   'command'=>'individual');                    'command'=>'individual');
       
     my $url1a = &Apache::lonhtmlcommon::build_url('grades/',\%fields);      my $url1a = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
   
     $fields{'command'}='ungraded';      $fields{'command'}='ungraded';
Line 9909  sub grading_menu { Line 9769  sub grading_menu {
   
     $fields{'command'}='downloadfilesselect';      $fields{'command'}='downloadfilesselect';
     my $url1e=&Apache::lonhtmlcommon::build_url('grades/',\%fields);      my $url1e=&Apache::lonhtmlcommon::build_url('grades/',\%fields);
       
     $fields{'command'} = 'csvform';      $fields{'command'} = 'csvform';
     my $url2 = &Apache::lonhtmlcommon::build_url('grades/',\%fields);      my $url2 = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
           
Line 9921  sub grading_menu { Line 9781  sub grading_menu {
   
     $fields{'command'} = 'initialverifyreceipt';      $fields{'command'} = 'initialverifyreceipt';
     my $url5 = &Apache::lonhtmlcommon::build_url('grades/',\%fields);      my $url5 = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
       
     my %permissions;  
     if ($perm{'mgr'}) {  
         $permissions{'either'} = 'F';  
         $permissions{'mgr'} = 'F';  
     }  
     if ($perm{'vgr'}) {  
         $permissions{'either'} = 'F';  
         $permissions{'vgr'} = 'F';  
     }  
   
     my @menu = ({ categorytitle=>'Hand Grading',      my @menu = ({ categorytitle=>'Hand Grading',
             items =>[              items =>[
                         {       linktext => 'Select individual students to grade',                          { linktext => 'Select individual students to grade',
                                 url => $url1a,                      url => $url1a,
                                 permission => $permissions{'either'},                      permission => 'F',
                                 icon => 'grade_students.png',                      icon => 'grade_students.png',
                                 linktitle => 'Grade current resource for a selection of students.'                      linktitle => 'Grade current resource for a selection of students.'
                         },                          }, 
                         {       linktext => 'Grade ungraded submissions',                          {       linktext => 'Grade ungraded submissions',
                                 url => $url1b,                                  url => $url1b,
                                 permission => $permissions{'either'},                                  permission => 'F',
                                 icon => 'ungrade_sub.png',                                  icon => 'ungrade_sub.png',
                                 linktitle => 'Grade all submissions that have not been graded yet.'                                  linktitle => 'Grade all submissions that have not been graded yet.'
                         },                          },
   
                         {       linktext => 'Grading table',                          {       linktext => 'Grading table',
                                 url => $url1c,                                  url => $url1c,
                                 permission => $permissions{'either'},                                  permission => 'F',
                                 icon => 'grading_table.png',                                  icon => 'grading_table.png',
                                 linktitle => 'Grade current resource for all students.'                                  linktitle => 'Grade current resource for all students.'
                         },                          },
                         {       linktext => 'Grade page/folder for one student',                          {       linktext => 'Grade page/folder for one student',
                                 url => $url1d,                                  url => $url1d,
                                 permission => $permissions{'either'},                                  permission => 'F',
                                 icon => 'grade_PageFolder.png',                                  icon => 'grade_PageFolder.png',
                                 linktitle => 'Grade all resources in current page/sequence/folder for one student.'                                  linktitle => 'Grade all resources in current page/sequence/folder for one student.'
                         },                          },
                         {       linktext => 'Download submitted files',                          {       linktext => 'Download submissions',
                                 url => $url1e,                                  url => $url1e,
                                 permission => $permissions{'either'},                                  permission => 'F',
                                 icon => 'download_sub.png',                                  icon => 'download_sub.png',
                                 linktitle => 'Download all files submitted by students.'                                  linktitle => 'Download all students submissions.'
                         }]},                          }]},
                          { categorytitle=>'Automated Grading',                           { categorytitle=>'Automated Grading',
                items =>[                 items =>[
   
                    { linktext => 'Upload Scores',                     { linktext => 'Upload Scores',
                     url => $url2,                      url => $url2,
                     permission => $permissions{'mgr'},                      permission => 'F',
                     icon => 'uploadscores.png',                      icon => 'uploadscores.png',
                     linktitle => 'Specify a file containing the class scores for current resource.'                      linktitle => 'Specify a file containing the class scores for current resource.'
                    },                     },
                    { linktext => 'Process Clicker',                     { linktext => 'Process Clicker',
                     url => $url3,                      url => $url3,
                     permission => $permissions{'mgr'},                      permission => 'F',
                     icon => 'addClickerInfoFile.png',                      icon => 'addClickerInfoFile.png',
                     linktitle => 'Specify a file containing the clicker information for this resource.'                      linktitle => 'Specify a file containing the clicker information for this resource.'
                    },                     },
                    { linktext => 'Grade/Manage/Review Bubblesheets',                     { linktext => 'Grade/Manage/Review Bubblesheets',
                     url => $url4,                      url => $url4,
                     permission => $permissions{'mgr'},                      permission => 'F',
                     icon => 'bubblesheet.png',                      icon => 'bubblesheet.png',
                     linktitle => 'Grade bubblesheet exams, upload/download bubblesheet data files, and review previously graded bubblesheet exams.'                      linktitle => 'Grade bubblesheet exams, upload/download bubblesheet data files, and review previously graded bubblesheet exams.'
                    },                     },
                             {   linktext => 'Verify Receipt Number',                              {   linktext => 'Verify Receipt Number',
                                 url => $url5,                                  url => $url5,
                                 permission => $permissions{'either'},                                  permission => 'F',
                                 icon => 'receipt_number.png',                                  icon => 'receipt_number.png',
                                 linktitle => 'Verify a system-generated receipt number for correct problem solution.'                                  linktitle => 'Verify a system-generated receipt number for correct problem solution.'
                             }                              }
Line 10033  sub submit_options_table { Line 9883  sub submit_options_table {
     my ($request,$symb) = @_;      my ($request,$symb) = @_;
     if (!$symb) {return '';}      if (!$symb) {return '';}
     &commonJSfunctions($request);      &commonJSfunctions($request);
       my $is_tool = ($symb =~ /ext\.tool$/);
     my $result;      my $result;
   
     $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".      $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".
         '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";          '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";
   
     $result.=&selectfield(1).      $result.=&selectfield(1,$is_tool).
             '<input type="hidden" name="command" value="viewgrades" />              '<input type="hidden" name="command" value="viewgrades" />
             <div>              <div>
               <input type="submit" value="'.&mt('Next').' &rarr;" />                <input type="submit" value="'.&mt('Next').' &rarr;" />
Line 10052  sub submit_options_download { Line 9903  sub submit_options_download {
     my ($request,$symb) = @_;      my ($request,$symb) = @_;
     if (!$symb) {return '';}      if (!$symb) {return '';}
   
     my $res_error;      my $is_tool = ($symb =~ /ext\.tool$/);
     my ($partlist,$handgrade,$responseType,$numresp,$numessay,$numdropbox) =  
         &response_type($symb,\$res_error);  
     if ($res_error) {  
         $request->print(&mt('An error occurred retrieving response types'));  
         return;  
     }  
     unless ($numessay) {  
         $request->print(&mt('No essayresponse items found'));  
         return;  
     }  
     my $table;  
     if (ref($partlist) eq 'ARRAY') {  
         if (scalar(@$partlist) > 1 ) {  
             $table = &showResourceInfo($symb,$partlist,$responseType,'gradingMenu',1,1);  
         }  
     }  
   
     &commonJSfunctions($request);      &commonJSfunctions($request);
   
     my $result='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".      my $result='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".
         $table."\n".          '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";
         '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";  
     $result.='      $result.='
 <h2>  <h2>
   '.&mt('Select Students for whom to Download Submitted Files').'    '.&mt('Select Students for whom to Download Submissions').'
 </h2>'.&selectfield(1).'  </h2>'.&selectfield(1,$is_tool).'
                 <input type="hidden" name="command" value="downloadfileslink" />                  <input type="hidden" name="command" value="downloadfileslink" /> 
               <input type="submit" value="'.&mt('Next').' &rarr;" />                <input type="submit" value="'.&mt('Next').' &rarr;" />
             </div>              </div>
           </div>            </div>
Line 10094  sub submit_options { Line 9927  sub submit_options {
     my ($request,$symb) = @_;      my ($request,$symb) = @_;
     if (!$symb) {return '';}      if (!$symb) {return '';}
   
       my $is_tool = ($symb =~ /ext\.tool$/);
     &commonJSfunctions($request);      &commonJSfunctions($request);
     my $result;      my $result;
   
     $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".      $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".
  '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";   '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";
     $result.=&selectfield(1).'      $result.=&selectfield(1,$is_tool).'
                 <input type="hidden" name="command" value="submission" />                  <input type="hidden" name="command" value="submission" /> 
               <input type="submit" value="'.&mt('Next').' &rarr;" />        <input type="submit" value="'.&mt('Next').' &rarr;" />
             </div>              </div>
           </div>            </div>
   </form>';    </form>';
Line 10109  sub submit_options { Line 9943  sub submit_options {
 }  }
   
 sub selectfield {  sub selectfield {
    my ($full)=@_;     my ($full,$is_tool)=@_;
    my %options =     my %options;
        (&substatus_options,     if ($is_tool) {
         'select_form_order' => ['yes','queued','graded','incorrect','all']);         %options =
              (&transtatus_options,
               'select_form_order' => ['yes','incorrect','all']);
      } else {
          %options = 
              (&substatus_options,
               'select_form_order' => ['yes','queued','graded','incorrect','all']);
      }
    my $result='<div class="LC_columnSection">     my $result='<div class="LC_columnSection">
     
     <fieldset>      <fieldset>
       <legend>        <legend>
        '.&mt('Sections').'         '.&mt('Sections').'
       </legend>        </legend>
       '.&Apache::lonstatistics::SectionSelect('section','multiple',5).'        '.&Apache::lonstatistics::SectionSelect('section','multiple',5).'
     </fieldset>      </fieldset>
     
     <fieldset>      <fieldset>
       <legend>        <legend>
         '.&mt('Groups').'          '.&mt('Groups').'
       </legend>        </legend>
       '.&Apache::lonstatistics::GroupSelect('group','multiple',5).'        '.&Apache::lonstatistics::GroupSelect('group','multiple',5).'
     </fieldset>      </fieldset>
      
     <fieldset>      <fieldset>
       <legend>        <legend>
         '.&mt('Access Status').'          '.&mt('Access Status').'
Line 10136  sub selectfield { Line 9977  sub selectfield {
       '.&Apache::lonhtmlcommon::StatusOptions(undef,undef,5,undef,'mult').'        '.&Apache::lonhtmlcommon::StatusOptions(undef,undef,5,undef,'mult').'
     </fieldset>';      </fieldset>';
     if ($full) {      if ($full) {
           my $heading = &mt('Submission Status');
           if ($is_tool) {
               $heading = &mt('Transaction Status');
           }
         $result.='          $result.='
     <fieldset>      <fieldset>
       <legend>        <legend>
         '.&mt('Submission Status').'          '.$heading.'
       </legend>'.        </legend>'.
        &Apache::loncommon::select_form('all','submitonly',\%options).         &Apache::loncommon::select_form('all','submitonly',\%options).
    '</fieldset>';     '</fieldset>';
Line 10299  sub process_clicker { Line 10144  sub process_clicker {
     my $pcorrect=&mt("Percentage points for correct solution");      my $pcorrect=&mt("Percentage points for correct solution");
     my $pincorrect=&mt("Percentage points for incorrect solution");      my $pincorrect=&mt("Percentage points for incorrect solution");
     my $selectform=&Apache::loncommon::select_form($env{'form.upfiletype'},'upfiletype',      my $selectform=&Apache::loncommon::select_form($env{'form.upfiletype'},'upfiletype',
                                                    {'iclicker' => 'i>clicker',     {'iclicker' => 'i>clicker',
                                                     'interwrite' => 'interwrite PRS',                                                      'interwrite' => 'interwrite PRS',
                                                     'turning' => 'Turning Technologies'});                                                      'turning' => 'Turning Technologies'});
     $symb = &Apache::lonenc::check_encrypt($symb);      $symb = &Apache::lonenc::check_encrypt($symb);
Line 10702  sub turning_eval { Line 10547  sub turning_eval {
     return ($errormsg,$number);      return ($errormsg,$number);
 }  }
   
   
 sub assign_clicker_grades {  sub assign_clicker_grades {
     my ($r,$symb) = @_;      my ($r,$symb) = @_;
     if (!$symb) {return '';}      if (!$symb) {return '';}
Line 10714  sub assign_clicker_grades { Line 10560  sub assign_clicker_grades {
 # FIXME: This should probably look for the first handgradeable part  # FIXME: This should probably look for the first handgradeable part
     my $part=$$partlist[0];      my $part=$$partlist[0];
 # Start screen output  # Start screen output
     my $result = &Apache::loncommon::start_data_table().       my $result = &Apache::loncommon::start_data_table().
                  &Apache::loncommon::start_data_table_header_row().                   &Apache::loncommon::start_data_table_header_row().
                  '<th>'.&mt('Assigning grades based on clicker file').'</th>'.                   '<th>'.&mt('Assigning grades based on clicker file').'</th>'.
                  &Apache::loncommon::end_data_table_header_row().                   &Apache::loncommon::end_data_table_header_row().
Line 10773  sub assign_clicker_grades { Line 10619  sub assign_clicker_grades {
                       &mt('More than one entry found for [_1]!','<tt>'.$user.'</tt>').                        &mt('More than one entry found for [_1]!','<tt>'.$user.'</tt>').
                       '</span><br />';                        '</span><br />';
           }            }
           $users{$user}=1;            $users{$user}=1; 
           my @answer=split(/\,/,$env{$key});            my @answer=split(/\,/,$env{$key});
           my $sum=0;            my $sum=0;
           my $realnumber=$number;            my $realnumber=$number;
Line 10839  sub navmap_errormsg { Line 10685  sub navmap_errormsg {
 }  }
   
 sub startpage {  sub startpage {
     my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$head_extra,$onload,$divforres) = @_;      my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$js,$onload) = @_;
     my %args;      my %args;
     if ($onload) {      if ($onload) {
          my %loaditems = (           my %loaditems = (
Line 10848  sub startpage { Line 10694  sub startpage {
          $args{'add_entries'} = \%loaditems;           $args{'add_entries'} = \%loaditems;
     }      }
     if ($nomenu) {      if ($nomenu) {
         $args{'only_body'} = 1;          $args{'only_body'} = 1; 
         $r->print(&Apache::loncommon::start_page("Student's Version",$head_extra,\%args));          $r->print(&Apache::loncommon::start_page("Student's Version",$js,\%args));
     } else {      } else {
         unshift(@$crumbs,{href=>&href_symb_cmd($symb,'gradingmenu'),text=>"Grading"});          unshift(@$crumbs,{href=>&href_symb_cmd($symb,'gradingmenu'),text=>"Grading"});
         $args{'bread_crumbs'} = $crumbs;          $args{'bread_crumbs'} = $crumbs;
         $r->print(&Apache::loncommon::start_page('Grading',$head_extra,\%args));          $r->print(&Apache::loncommon::start_page('Grading',$js,\%args));
           if ($env{'request.course.id'}) {
               &Apache::lonquickgrades::startGradeScreen($r,($env{'form.symb'}?'probgrading':'grading'));
           }
     }      }
     unless ($nodisplayflag) {      unless ($nodisplayflag) {
        $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp,$divforres));          $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp));
     }      }
 }  }
   
 sub select_problem {  sub select_problem {
     my ($r)=@_;      my ($r)=@_;
     $r->print('<h3>'.&mt('Select the problem or one of the problems you want to grade').'</h3><form action="/adm/grades">');      $r->print('<h3>'.&mt('Select the problem or one of the problems you want to grade').'</h3><form action="/adm/grades">');
     $r->print(&Apache::lonstathelpers::problem_selector('.',undef,1,undef,undef,1));      $r->print(&Apache::lonstathelpers::problem_selector('.',undef,1,undef,undef,undef,undef,1));
     $r->print('<input type="hidden" name="command" value="gradingmenu" />');      $r->print('<input type="hidden" name="command" value="gradingmenu" />');
     $r->print('<input type="submit" value="'.&mt('Next').' &rarr;" /></form>');      $r->print('<input type="submit" value="'.&mt('Next').' &rarr;" /></form>');
 }  }
Line 10879  sub handler { Line 10728  sub handler {
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
   
 # see what command we need to execute  # see what command we need to execute
    
     my @commands=&Apache::loncommon::get_env_multiple('form.command');      my @commands=&Apache::loncommon::get_env_multiple('form.command');
     my $command=$commands[0];      my $command=$commands[0];
   
Line 10915  sub handler { Line 10764  sub handler {
     if (($symb eq '' || $command eq '') && ($env{'request.course.id'})) {      if (($symb eq '' || $command eq '') && ($env{'request.course.id'})) {
 #  #
 # Not called from a resource, but inside a course  # Not called from a resource, but inside a course
 #  #    
         &startpage($request,undef,[],1,1);          &startpage($request,undef,[],1,1);
         &select_problem($request);          &select_problem($request);
     } else {      } else {
         if ($command eq 'submission' && $perm{'vgr'}) {   if ($command eq 'submission' && $perm{'vgr'}) {
             my ($stuvcurrent,$stuvdisp,$versionform,$js,$onload);              my ($stuvcurrent,$stuvdisp,$versionform,$js);
             if (($env{'form.student'} ne '') && ($env{'form.userdom'} ne '')) {              if (($env{'form.student'} ne '') && ($env{'form.userdom'} ne '')) {
                 ($stuvcurrent,$stuvdisp,$versionform,$js) =                  ($stuvcurrent,$stuvdisp,$versionform,$js) =
                     &choose_task_version_form($symb,$env{'form.student'},                      &choose_task_version_form($symb,$env{'form.student'},
                                               $env{'form.userdom'});                                                $env{'form.userdom'});
             }              }
             my $divforres;              &startpage($request,$symb,[{href=>"", text=>"Student Submissions"}],undef,undef,$stuvcurrent,$stuvdisp,undef,$js);
             if ($env{'form.student'} eq '') {  
                 $js .= &part_selector_js();  
                 $onload = "toggleParts('gradesub');";  
             } else {  
                 $divforres = 1;  
             }  
             my $head_extra = $js;  
             unless ($env{'form.vProb'} eq 'no') {  
                 my $csslinks = &Apache::loncommon::css_links($symb);  
                 if ($csslinks) {  
                     $head_extra .= "\n$csslinks";  
                 }  
             }  
             &startpage($request,$symb,[{href=>"", text=>"Student Submissions"}],undef,undef,  
                        $stuvcurrent,$stuvdisp,undef,$head_extra,$onload,$divforres);  
             if ($versionform) {              if ($versionform) {
                 if ($divforres) {  
                     $request->print('<div style="padding:0;clear:both;margin:0;border:0"></div>');  
                 }  
                 $request->print($versionform);                  $request->print($versionform);
             }              }
             ($env{'form.student'} eq '' ? &listStudents($request,$symb,'',$divforres) : &submission($request,0,0,$symb,$divforres,$command));              $request->print('<br clear="all" />');
       ($env{'form.student'} eq '' ? &listStudents($request,$symb) : &submission($request,0,0,$symb));
         } elsif ($command eq 'versionsub' && $perm{'vgr'}) {          } elsif ($command eq 'versionsub' && $perm{'vgr'}) {
             my ($stuvcurrent,$stuvdisp,$versionform,$js) =              my ($stuvcurrent,$stuvdisp,$versionform,$js) =
                 &choose_task_version_form($symb,$env{'form.student'},                  &choose_task_version_form($symb,$env{'form.student'},
                                           $env{'form.userdom'},                                            $env{'form.userdom'},
                                           $env{'form.inhibitmenu'});                                            $env{'form.inhibitmenu'});
             my $head_extra = $js;              &startpage($request,$symb,[{href=>"", text=>"Previous Student Version"}],undef,undef,$stuvcurrent,$stuvdisp,$env{'form.inhibitmenu'},$js);
             unless ($env{'form.vProb'} eq 'no') {  
                 my $csslinks = &Apache::loncommon::css_links($symb);  
                 if ($csslinks) {  
                     $head_extra .= "\n$csslinks";  
                 }  
             }  
             &startpage($request,$symb,[{href=>"", text=>"Previous Student Version"}],undef,undef,  
                        $stuvcurrent,$stuvdisp,$env{'form.inhibitmenu'},$head_extra);  
             if ($versionform) {              if ($versionform) {
                 $request->print($versionform);                  $request->print($versionform);
             }              }
             $request->print('<br clear="all" />');              $request->print('<br clear="all" />');
             $request->print(&show_previous_task_version($request,$symb));              $request->print(&show_previous_task_version($request,$symb));
         } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {   } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},              &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},
                                        {href=>'',text=>'Select student'}],1,1);                                         {href=>'',text=>'Select student'}],1,1);
             &pickStudentPage($request,$symb);      &pickStudentPage($request,$symb);
         } elsif ($command eq 'displayPage' && $perm{'vgr'}) {   } elsif ($command eq 'displayPage' && $perm{'vgr'}) {
             my $csslinks;  
             unless ($env{'form.vProb'} eq 'no') {  
                 $csslinks = &Apache::loncommon::css_links($symb,'map');  
             }  
             &startpage($request,$symb,              &startpage($request,$symb,
                                       [{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},                                        [{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},
                                        {href=>'',text=>'Select student'},                                         {href=>'',text=>'Select student'},
                                        {href=>'',text=>'Grade student'}],1,1,undef,undef,undef,$csslinks);                                         {href=>'',text=>'Grade student'}],1,1);
             &displayPage($request,$symb);      &displayPage($request,$symb);
         } elsif ($command eq 'gradeByPage' && $perm{'mgr'}) {   } elsif ($command eq 'gradeByPage' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},              &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},
                                        {href=>'',text=>'Select student'},                                         {href=>'',text=>'Select student'},
                                        {href=>'',text=>'Grade student'},                                         {href=>'',text=>'Grade student'},
                                        {href=>'',text=>'Store grades'}],1,1);                                         {href=>'',text=>'Store grades'}],1,1);
             &updateGradeByPage($request,$symb);      &updateGradeByPage($request,$symb);
         } elsif ($command eq 'processGroup' && $perm{'vgr'}) {   } elsif ($command eq 'processGroup' && $perm{'vgr'}) {
             my $csslinks;  
             unless ($env{'form.vProb'} eq 'no') {  
                 $csslinks = &Apache::loncommon::css_links($symb);  
             }  
             &startpage($request,$symb,[{href=>'',text=>'...'},              &startpage($request,$symb,[{href=>'',text=>'...'},
                                        {href=>'',text=>'Modify grades'}],undef,undef,undef,undef,undef,$csslinks,undef,1);                                         {href=>'',text=>'Modify grades'}]);
             &processGroup($request,$symb);      &processGroup($request,$symb);
         } elsif ($command eq 'gradingmenu' && $perm{'vgr'}) {   } elsif ($command eq 'gradingmenu' && $perm{'vgr'}) {
             &startpage($request,$symb);              &startpage($request,$symb);
             $request->print(&grading_menu($request,$symb));      $request->print(&grading_menu($request,$symb));
         } elsif ($command eq 'individual' && $perm{'vgr'}) {   } elsif ($command eq 'individual' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>'',text=>'Select individual students to grade'}]);              &startpage($request,$symb,[{href=>'',text=>'Select individual students to grade'}]);
             $request->print(&submit_options($request,$symb));      $request->print(&submit_options($request,$symb));
         } elsif ($command eq 'ungraded' && $perm{'vgr'}) {          } elsif ($command eq 'ungraded' && $perm{'vgr'}) {
             my $js = &part_selector_js();              &startpage($request,$symb,[{href=>'',text=>'Grade ungraded submissions'}]);
             my $onload = "toggleParts('gradesub');";  
             &startpage($request,$symb,[{href=>'',text=>'Grade ungraded submissions'}],  
                        undef,undef,undef,undef,undef,$js,$onload);  
             $request->print(&listStudents($request,$symb,'graded'));              $request->print(&listStudents($request,$symb,'graded'));
         } elsif ($command eq 'table' && $perm{'vgr'}) {          } elsif ($command eq 'table' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>"", text=>"Grading table"}]);              &startpage($request,$symb,[{href=>"", text=>"Grading table"}]);
Line 11014  sub handler { Line 10827  sub handler {
         } elsif ($command eq 'all_for_one' && $perm{'vgr'}) {          } elsif ($command eq 'all_for_one' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>'',text=>'Grade page/folder for one student'}],1,1);              &startpage($request,$symb,[{href=>'',text=>'Grade page/folder for one student'}],1,1);
             $request->print(&submit_options_sequence($request,$symb));              $request->print(&submit_options_sequence($request,$symb));
         } elsif ($command eq 'viewgrades' && $perm{'vgr'}) {   } elsif ($command eq 'viewgrades' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},{href=>'', text=>"Modify grades"}]);              &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},{href=>'', text=>"Modify grades"}]);
             $request->print(&viewgrades($request,$symb));      $request->print(&viewgrades($request,$symb));
         } elsif ($command eq 'handgrade' && $perm{'mgr'}) {   } elsif ($command eq 'handgrade' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'',text=>'...'},              &startpage($request,$symb,[{href=>'',text=>'...'},
                                        {href=>'',text=>'Store grades'}]);                                         {href=>'',text=>'Store grades'}]);
             $request->print(&processHandGrade($request,$symb));      $request->print(&processHandGrade($request,$symb));
         } elsif ($command eq 'editgrades' && $perm{'mgr'}) {   } elsif ($command eq 'editgrades' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},              &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},
                                        {href=>&href_symb_cmd($symb,'viewgrades').'&group=all&section=all&Status=Active',                                         {href=>&href_symb_cmd($symb,'viewgrades').'&group=all&section=all&Status=Active',
                                                                              text=>"Modify grades"},                                                                               text=>"Modify grades"},
                                        {href=>'', text=>"Store grades"}]);                                         {href=>'', text=>"Store grades"}]);
             $request->print(&editgrades($request,$symb));      $request->print(&editgrades($request,$symb));
         } elsif ($command eq 'initialverifyreceipt' && $perm{'vgr'}) {          } elsif ($command eq 'initialverifyreceipt' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>'',text=>'Verify Receipt Number'}]);              &startpage($request,$symb,[{href=>'',text=>'Verify Receipt Number'}]);
             $request->print(&initialverifyreceipt($request,$symb));              $request->print(&initialverifyreceipt($request,$symb));
         } elsif ($command eq 'verify' && $perm{'vgr'}) {   } elsif ($command eq 'verify' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"initialverifyreceipt"),text=>'Verify Receipt Number'},              &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"initialverifyreceipt"),text=>'Verify Receipt Number'},
                                        {href=>'',text=>'Verification Result'}]);                                         {href=>'',text=>'Verification Result'}]);
             $request->print(&verifyreceipt($request,$symb));      $request->print(&verifyreceipt($request,$symb));
         } elsif ($command eq 'processclicker' && $perm{'mgr'}) {          } elsif ($command eq 'processclicker' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Process clicker'}]);              &startpage($request,$symb,[{href=>'', text=>'Process clicker'}]);
             $request->print(&process_clicker($request,$symb));              $request->print(&process_clicker($request,$symb));
Line 11046  sub handler { Line 10859  sub handler {
                                        {href=>'', text=>'Process clicker file'},                                         {href=>'', text=>'Process clicker file'},
                                        {href=>'', text=>'Store grades'}]);                                         {href=>'', text=>'Store grades'}]);
             $request->print(&assign_clicker_grades($request,$symb));              $request->print(&assign_clicker_grades($request,$symb));
         } elsif ($command eq 'csvform' && $perm{'mgr'}) {   } elsif ($command eq 'csvform' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
             $request->print(&upcsvScores_form($request,$symb));      $request->print(&upcsvScores_form($request,$symb));
         } elsif ($command eq 'csvupload' && $perm{'mgr'}) {   } elsif ($command eq 'csvupload' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
             $request->print(&csvupload($request,$symb));      $request->print(&csvupload($request,$symb));
         } elsif ($command eq 'csvuploadmap' && $perm{'mgr'} ) {   } elsif ($command eq 'csvuploadmap' && $perm{'mgr'} ) {
             &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
             $request->print(&csvuploadmap($request,$symb));      $request->print(&csvuploadmap($request,$symb));
         } elsif ($command eq 'csvuploadoptions' && $perm{'mgr'}) {   } elsif ($command eq 'csvuploadoptions' && $perm{'mgr'}) {
             if ($env{'form.associate'} ne 'Reverse Association') {      if ($env{'form.associate'} ne 'Reverse Association') {
                 &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);                  &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
                 $request->print(&csvuploadoptions($request,$symb));   $request->print(&csvuploadoptions($request,$symb));
             } else {      } else {
                 if ( $env{'form.upfile_associate'} ne 'reverse' ) {   if ( $env{'form.upfile_associate'} ne 'reverse' ) {
                     $env{'form.upfile_associate'} = 'reverse';      $env{'form.upfile_associate'} = 'reverse';
                 } else {   } else {
                     $env{'form.upfile_associate'} = 'forward';      $env{'form.upfile_associate'} = 'forward';
                 }   }
                 &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);                  &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
                 $request->print(&csvuploadmap($request,$symb));   $request->print(&csvuploadmap($request,$symb));
             }      }
         } elsif ($command eq 'csvuploadassign' && $perm{'mgr'} ) {   } elsif ($command eq 'csvuploadassign' && $perm{'mgr'} ) {
             &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
             $request->print(&csvuploadassign($request,$symb));      $request->print(&csvuploadassign($request,$symb));
         } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) {   } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1,              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1,
                        undef,undef,undef,undef,'toggleScantab(document.rules);');                         undef,undef,undef,undef,'toggleScantab(document.rules);');
             $request->print(&scantron_selectphase($request,undef,$symb));      $request->print(&scantron_selectphase($request,undef,$symb));
         } elsif ($command eq 'scantron_warning' && $perm{'mgr'}) {    } elsif ($command eq 'scantron_warning' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
             $request->print(&scantron_do_warning($request,$symb));       $request->print(&scantron_do_warning($request,$symb));
         } elsif ($command eq 'scantron_validate' && $perm{'mgr'}) {   } elsif ($command eq 'scantron_validate' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
             $request->print(&scantron_validate_file($request,$symb));      $request->print(&scantron_validate_file($request,$symb));
         } elsif ($command eq 'scantron_process' && $perm{'mgr'}) {   } elsif ($command eq 'scantron_process' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
             $request->print(&scantron_process_students($request,$symb));      $request->print(&scantron_process_students($request,$symb));
         } elsif ($command eq 'scantronupload' &&    } elsif ($command eq 'scantronupload' && 
                  (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})||    (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})||
                   &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) {    &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1,              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1,
                        undef,undef,undef,undef,'toggleScantab(document.rules);');                         undef,undef,undef,undef,'toggleScantab(document.rules);');
             $request->print(&scantron_upload_scantron_data($request,$symb));       $request->print(&scantron_upload_scantron_data($request,$symb)); 
         } elsif ($command eq 'scantronupload_save' &&    } elsif ($command eq 'scantronupload_save' &&
                  (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})||    (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})||
                   &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) {    &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
             $request->print(&scantron_upload_scantron_data_save($request,$symb));       $request->print(&scantron_upload_scantron_data_save($request,$symb));
         } elsif ($command eq 'scantron_download' &&    } elsif ($command eq 'scantron_download' &&
                  &Apache::lonnet::allowed('usc',$env{'request.course.id'})) {   &Apache::lonnet::allowed('usc',$env{'request.course.id'})) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
             $request->print(&scantron_download_scantron_data($request,$symb));       $request->print(&scantron_download_scantron_data($request,$symb));
         } elsif ($command eq 'checksubmissions' && $perm{'vgr'}) {          } elsif ($command eq 'checksubmissions' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
             $request->print(&checkscantron_results($request,$symb));              $request->print(&checkscantron_results($request,$symb));
         } elsif ($command eq 'downloadfilesselect' && $perm{'vgr'}) {          } elsif ($command eq 'downloadfilesselect' && $perm{'vgr'}) {
             my $js = &part_selector_js();              &startpage($request,$symb,[{href=>'', text=>'Select which submissions to download'}]);
             my $onload = "toggleParts('gradingMenu');";  
             &startpage($request,$symb,[{href=>'', text=>'Select which submissions to download'}],  
                        undef,undef,undef,undef,undef,$js,$onload);  
             $request->print(&submit_options_download($request,$symb));              $request->print(&submit_options_download($request,$symb));
          } elsif ($command eq 'downloadfileslink' && $perm{'vgr'}) {           } elsif ($command eq 'downloadfileslink' && $perm{'vgr'}) {
             &startpage($request,$symb,              &startpage($request,$symb,
    [{href=>&href_symb_cmd($symb,'downloadfilesselect'), text=>'Select which submissions to download'},     [{href=>&href_symb_cmd($symb,'downloadfilesselect'), text=>'Select which submissions to download'},
     {href=>'', text=>'Download submitted files'}],      {href=>'', text=>'Download submitted files'}]);
                undef,undef,undef,undef,undef,undef,undef,1);  
             $request->print('<div style="padding:0;clear:both;margin:0;border:0"></div>');  
             &submit_download_link($request,$symb);              &submit_download_link($request,$symb);
         } elsif ($command) {   } elsif ($command) {
             &startpage($request,$symb,[{href=>'', text=>'Access denied'}]);              &startpage($request,$symb,[{href=>'', text=>'Access denied'}]);
             $request->print('<p class="LC_error">'.&mt('Access Denied ([_1])',$command).'</p>');      $request->print('<p class="LC_error">'.&mt('Access Denied ([_1])',$command).'</p>');
         }   }
     }      }
     if ($ssi_error) {      if ($ssi_error) {
  &ssi_print_error($request);   &ssi_print_error($request);
     }      }
     $request->print(&Apache::loncommon::end_page());      if ($env{'form.inhibitmenu'}) {
           $request->print(&Apache::loncommon::end_page());
       } elsif ($env{'request.course.id'}) {
           &Apache::lonquickgrades::endGradeScreen($request);
       }
     &reset_caches();      &reset_caches();
     return OK;      return OK;
 }  }
Line 11147  described at http://www.lon-capa.org. Line 10959  described at http://www.lon-capa.org.
 =head1 OVERVIEW  =head1 OVERVIEW
   
 Do an ssi with retries:  Do an ssi with retries:
 While I'd love to factor out this with the vesrion in lonprintout,  While I'd love to factor out this with the version in lonprintout,
 that would either require a data coupling between modules, which I refuse to perpetuate (there's quite enough of that already), or would require the invention of another infrastructure  that would either require a data coupling between modules, which I refuse to perpetuate (there's quite enough of that already), or would require the invention of another infrastructure
 I'm not quite ready to invent (e.g. an ssi_with_retry object).  I'm not quite ready to invent (e.g. an ssi_with_retry object).
   
Line 11194  ssi_with_retries() Line 11006  ssi_with_retries()
   
 =over  =over
   
   =head1 Routines to display previous version of a Task for a specific student
   
   Tasks are graded pass/fail. Students who have yet to pass a particular Task
   can receive another opportunity. Access to tasks is slot-based. If a slot
   requires a proctor to check-in the student, a new version of the Task will
   be created when the student is checked in to the new opportunity.
   
   If a particular student has tried two or more versions of a particular task,
   the submission screen provides a user with vgr privileges (e.g., a Course
   Coordinator) the ability to display a previous version worked on by the
   student.  By default, the current version is displayed. If a previous version
   has been selected for display, submission data are only shown that pertain
   to that particular version, and the interface to submit grades is not shown.
   
   =over 4
   
   =item show_previous_task_version()
   
   Displays a specified version of a student's Task, as the student sees it.
   
   Inputs: 2
           request - request object
           symb    - unique symb for current instance of resource
   
   Output: None.
   
   Side Effects: calls &show_problem() to print version of Task, with
                 version contained in form item: $env{'form.previousversion'}
   
   =item choose_task_version_form()
   
   Displays a web form used to select which version of a student's view of a
   Task should be displayed.  Either launches a pop-up window, or replaces
   content in existing pop-up, or replaces page in main window.
   
   Inputs: 4
           symb    - unique symb for current instance of resource
           uname   - username of student
           udom    - domain of student
           nomenu  - 1 if display is in a pop-up window, and hence no menu
                     breadcrumbs etc., are displayed
   
   Output: 4
           current   - student's current version
           displayed - student's version being displayed
           result    - scalar containing HTML for web form used to switch to
                       a different version (or a link to close window, if pop-up).
           js        - javascript for processing selection in versions web form
   
   Side Effects: None.
   
   =item previous_display_javascript()
   
   Inputs: 2
           nomenu  - 1 if display is in a pop-up window, and hence no menu
                     breadcrumbs etc., are displayed.
           current - student's current version number.
   
   Output: 1
           js      - javascript for processing selection in versions web form.
   
   Side Effects: None.
   
   =back
   
   =head1 Routines to process bubblesheet data.
   
   =over 4
   
 =item scantron_get_correction() :   =item scantron_get_correction() : 
   
    Builds the interface screen to interact with the operator to fix a     Builds the interface screen to interact with the operator to fix a
Line 11230  ssi_with_retries() Line 11111  ssi_with_retries()
                   or code-based randompick and/or randomorder.                    or code-based randompick and/or randomorder.
   
   
   
 =item  scantron_get_maxbubble() :   =item  scantron_get_maxbubble() : 
   
    Arguments:     Arguments:
Line 11309  ssi_with_retries() Line 11191  ssi_with_retries()
 =item navmap_errormsg() :  =item navmap_errormsg() :
   
    Returns HTML mark-up inside a <div></div> with a link to re-initialize the course.     Returns HTML mark-up inside a <div></div> with a link to re-initialize the course.
    Should be called whenever the request to instantiate a navmap object fails.       Should be called whenever the request to instantiate a navmap object fails.
   
   =back
   
 =back  =back
   

Removed from v.1.596.2.12.2.56  
changed lines
  Added in v.1.768


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>