Diff for /loncom/homework/grades.pm between versions 1.596.2.12 and 1.596.2.12.2.13

version 1.596.2.12, 2011/12/01 00:36:59 version 1.596.2.12.2.13, 2013/05/10 23:31:37
Line 52  use POSIX qw(floor); Line 52  use POSIX qw(floor);
   
   
 my %perm=();  my %perm=();
   my %old_essays=();
   
 #  These variables are used to recover from ssi errors  #  These variables are used to recover from ssi errors
   
Line 124  sub getpartlist { Line 125  sub getpartlist {
 # --- Get the symbolic name of a problem and the url  # --- Get the symbolic name of a problem and the url
 sub get_symb {  sub get_symb {
     my ($request,$silent) = @_;      my ($request,$silent) = @_;
     (my $url=$env{'form.url'}) =~ s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;      my $symb=$env{'form.symb'};
     my $symb=($env{'form.symb'} ne '' ? $env{'form.symb'} : (&Apache::lonnet::symbread($url)));      unless ($symb) {
     if ($symb eq '') {           (my $url=$env{'form.url'}) =~ s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
  if (!$silent) {          $symb = &Apache::lonnet::symbread($url);
             $request->print(&mt("Unable to handle ambiguous references: [_1].",$url));          if ($symb eq '') { 
     return ();      if (!$silent) {
  }                  $request->print(&mt("Unable to handle ambiguous references: [_1].",$url));
           return ();
       }
           }
     }      }
     &Apache::lonenc::check_decrypt(\$symb);      &Apache::lonenc::check_decrypt(\$symb);
     return ($symb);      return ($symb);
Line 249  sub showResourceInfo { Line 253  sub showResourceInfo {
             $result.='<td>'.$display_part.'</td>'              $result.='<td>'.$display_part.'</td>'
                     .'<td>'.'<span class="LC_internal_info">'.$resID.'</span></td>'                      .'<td>'.'<span class="LC_internal_info">'.$resID.'</span></td>'
                     .'<td>'.&mt($responsetype).'</td>'                      .'<td>'.&mt($responsetype).'</td>'
 #                   .'<td>'.&mt('<b>Handgrade: </b>[_1]',$handgrade).'</td>'  #                   .'<td><b>'.&mt('Handgrade: [_1]',$handgrade).'</b></td>'
                     .&Apache::loncommon::end_data_table_row();                      .&Apache::loncommon::end_data_table_row();
         }          }
     }      }
Line 260  sub showResourceInfo { Line 264  sub showResourceInfo {
 sub reset_caches {  sub reset_caches {
     &reset_analyze_cache();      &reset_analyze_cache();
     &reset_perm();      &reset_perm();
       &reset_old_essays();
 }  }
   
 {  {
Line 272  sub reset_caches { Line 277  sub reset_caches {
     }      }
   
     sub get_analyze {      sub get_analyze {
  my ($symb,$uname,$udom,$no_increment,$add_to_hash,$type,$trial,$rndseed)=@_;   my ($symb,$uname,$udom,$no_increment,$add_to_hash,$type,$trial,$rndseed,$bubbles_per_row)=@_;
  my $key = "$symb\0$uname\0$udom";   my $key = "$symb\0$uname\0$udom";
         if ($type eq 'randomizetry') {          if ($type eq 'randomizetry') {
             if ($trial ne '') {              if ($trial ne '') {
Line 306  sub reset_caches { Line 311  sub reset_caches {
                     'grade_courseid'    =>  $env{'request.course.id'},                      'grade_courseid'    =>  $env{'request.course.id'},
                     'grade_username'    => $uname,                      'grade_username'    => $uname,
                     'grade_noincrement' => $no_increment);                      'grade_noincrement' => $no_increment);
           if ($bubbles_per_row ne '') {
               $form{'bubbles_per_row'} = $bubbles_per_row;
           }
         if ($type eq 'randomizetry') {          if ($type eq 'randomizetry') {
             $form{'grade_questiontype'} = $type;              $form{'grade_questiontype'} = $type;
             if ($rndseed ne '') {              if ($rndseed ne '') {
Line 346  sub reset_caches { Line 354  sub reset_caches {
     }      }
   
     sub scantron_partids_tograde {      sub scantron_partids_tograde {
         my ($resource,$cid,$uname,$udom,$check_for_randomlist) = @_;          my ($resource,$cid,$uname,$udom,$check_for_randomlist,$bubbles_per_row) = @_;
         my (%analysis,@parts);          my (%analysis,@parts);
         if (ref($resource)) {          if (ref($resource)) {
             my $symb = $resource->symb();              my $symb = $resource->symb();
Line 354  sub reset_caches { Line 362  sub reset_caches {
             if ($check_for_randomlist) {              if ($check_for_randomlist) {
                 $add_to_form = { 'check_parts_withrandomlist' => 1,};                  $add_to_form = { 'check_parts_withrandomlist' => 1,};
             }              }
             my $analyze = &get_analyze($symb,$uname,$udom,undef,$add_to_form);              my $analyze =
                   &get_analyze($symb,$uname,$udom,undef,$add_to_form,
                                undef,undef,undef,$bubbles_per_row);
             if (ref($analyze) eq 'HASH') {              if (ref($analyze) eq 'HASH') {
                 %analysis = %{$analyze};                  %analysis = %{$analyze};
             }              }
Line 738  sub compute_points { Line 748  sub compute_points {
 #  #
   
 sub most_similar {  sub most_similar {
     my ($uname,$udom,$uessay,$old_essays)=@_;      my ($uname,$udom,$symb,$uessay)=@_;
   
       unless ($symb) { return ''; }
   
       unless (ref($old_essays{$symb}) eq 'HASH') { return ''; }
   
 # ignore spaces and punctuation  # ignore spaces and punctuation
   
Line 755  sub most_similar { Line 769  sub most_similar {
     my $scrsid='';      my $scrsid='';
     my $sessay='';      my $sessay='';
 # go through all essays ...  # go through all essays ...
     foreach my $tkey (keys(%$old_essays)) {      foreach my $tkey (keys(%{$old_essays{$symb}})) {
  my ($tname,$tdom,$tcrsid)=map {&unescape($_)} (split(/\./,$tkey));   my ($tname,$tdom,$tcrsid)=map {&unescape($_)} (split(/\./,$tkey));
 # ... except the same student  # ... except the same student
         next if (($tname eq $uname) && ($tdom eq $udom));          next if (($tname eq $uname) && ($tdom eq $udom));
  my $tessay=$old_essays->{$tkey};   my $tessay=$old_essays{$symb}{$tkey};
  $tessay=~s/\W+/ /gs;   $tessay=~s/\W+/ /gs;
 # String similarity gives up if not even limit  # String similarity gives up if not even limit
  my $tsimilar=&String::Similarity::similarity($uessay,$tessay,$limit);   my $tsimilar=&String::Similarity::similarity($uessay,$tessay,$limit);
Line 769  sub most_similar { Line 783  sub most_similar {
     $sname=$tname;      $sname=$tname;
     $sdom=$tdom;      $sdom=$tdom;
     $scrsid=$tcrsid;      $scrsid=$tcrsid;
     $sessay=$old_essays->{$tkey};      $sessay=$old_essays{$symb}{$tkey};
  }   }
     }      }
     if ($limit>0.6) {      if ($limit>0.6) {
Line 1605  INNERJS Line 1619  INNERJS
   
   function savedMsgHeader(Nmsg,usrctr,fullname) {    function savedMsgHeader(Nmsg,usrctr,fullname) {
     var height = 70*Nmsg+250;      var height = 70*Nmsg+250;
     var scrollbar = "no";  
     if (height > 600) {      if (height > 600) {
  height = 600;   height = 600;
  scrollbar = "yes";  
     }      }
     var xpos = (screen.width-600)/2;      var xpos = (screen.width-600)/2;
     xpos = (xpos < 0) ? '0' : xpos;      xpos = (xpos < 0) ? '0' : xpos;
     var ypos = (screen.height-height)/2-30;      var ypos = (screen.height-height)/2-30;
     ypos = (ypos < 0) ? '0' : ypos;      ypos = (ypos < 0) ? '0' : ypos;
   
     pWin = window.open('', 'MessageCenter', 'resizable=yes,toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=700,height='+height);      pWin = window.open('', 'MessageCenter', 'resizable=yes,toolbar=no,location=no,scrollbars=yes,screenx='+xpos+',screeny='+ypos+',width=700,height='+height);
     pWin.focus();      pWin.focus();
     pDoc = pWin.document;      pDoc = pWin.document;
     pDoc.$docopen;      pDoc.$docopen;
Line 1825  sub gradeBox { Line 1837  sub gradeBox {
     $line.='<option value="reset status">'.&mt('reset status').'</option></select>'."\n";      $line.='<option value="reset status">'.&mt('reset status').'</option></select>'."\n";
   
   
  #&mt('<td><b>Part:</b></td><td>[_1]</td><td><b>Points:</b></td><td>[_2]</td><td>or</td><td>[_3]</td>',$display_part,$radio,$line);  
     $result .=       $result .= 
     '<td>'.$display_part.'</td><td>'.$radio.'</td><td>'.&mt('or').'</td><td>'.$line.'</td>';      '<td>'.$display_part.'</td><td>'.$radio.'</td><td>'.&mt('or').'</td><td>'.$line.'</td>';
     $result.=&Apache::loncommon::end_data_table_row();      $result.=&Apache::loncommon::end_data_table_row();
Line 1912  sub show_problem { Line 1923  sub show_problem {
  $companswer=~s|</form>||g;   $companswer=~s|</form>||g;
  $companswer=~s|name="submit"|name="would_have_been_submit"|g;   $companswer=~s|name="submit"|name="would_have_been_submit"|g;
     }      }
       my $renderheading = &mt('View of the problem');
       my $answerheading = &mt('Correct answer');
       if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
           my $stu_fullname = $env{'form.fullname'};
           if ($stu_fullname eq '') {
               $stu_fullname = &Apache::loncommon::plainname($uname,$udom,'lastname');
           }
           my $forwhom = &nameUserString(undef,$stu_fullname,$uname,$udom);
           if ($forwhom ne '') {
               $renderheading = &mt('View of the problem for[_1]',$forwhom);
               $answerheading = &mt('Correct answer for[_1]',$forwhom);
           }
       }
     $rendered=      $rendered=
         '<div class="LC_Box">'          '<div class="LC_Box">'
        .'<h3 class="LC_hcell">'.&mt('View of the problem').'</h3>'         .'<h3 class="LC_hcell">'.$renderheading.'</h3>'
        .$rendered         .$rendered
        .'</div>';         .'</div>';
     $companswer=      $companswer=
         '<div class="LC_Box">'          '<div class="LC_Box">'
        .'<h3 class="LC_hcell">'.&mt('Correct answer').'</h3>'         .'<h3 class="LC_hcell">'.$answerheading.'</h3>'
        .$companswer         .$companswer
        .'</div>';         .'</div>';
     my $result;      my $result;
Line 1990  sub submission { Line 2014  sub submission {
     $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 $symb = &get_symb($request);       my ($symb) = &get_symb($request); 
     if ($symb eq '') { $request->print("Unable to handle ambiguous references:."); return ''; }      if ($symb eq '') { $request->print("Unable to handle ambiguous references:."); return ''; }
   
     if (!&canview($usec)) {      if (!&canview($usec)) {
Line 2009  sub submission { Line 2033  sub submission {
  '" src="'.$request->dir_config('lonIconsURL').   '" src="'.$request->dir_config('lonIconsURL').
  '/check.gif" height="16" border="0" />';   '/check.gif" height="16" border="0" />';
   
     my %old_essays;  
     # header info      # header info
     if ($counter == 0) {      if ($counter == 0) {
  &sub_page_js($request);   &sub_page_js($request);
Line 2125  KEYWORDS Line 2148  KEYWORDS
     my ($adom,$aname,$apath)=($essayurl=~/^($LONCAPA::domain_re)\/($LONCAPA::username_re)\/(.*)$/);      my ($adom,$aname,$apath)=($essayurl=~/^($LONCAPA::domain_re)\/($LONCAPA::username_re)\/(.*)$/);
     $apath=&escape($apath);      $apath=&escape($apath);
     $apath=~s/\W/\_/gs;      $apath=~s/\W/\_/gs;
     %old_essays=&Apache::lonnet::dump('nohist_essay_'.$apath,$adom,$aname);              &init_old_essays($symb,$apath,$adom,$aname);
         }          }
     }      }
   
Line 2262  KEYWORDS Line 2285  KEYWORDS
                     }                      }
     if($env{'form.checkPlag'}){      if($env{'form.checkPlag'}){
  my ($oname,$odom,$ocrsid,$oessay,$osim)=   my ($oname,$odom,$ocrsid,$oessay,$osim)=
     &most_similar($uname,$udom,$subval,\%old_essays);      &most_similar($uname,$udom,$symb,$subval);
  if ($osim) {   if ($osim) {
     $osim=int($osim*100.0);      $osim=int($osim*100.0);
     my %old_course_desc =       my %old_course_desc = 
Line 2594  sub keywords_highlight { Line 2617  sub keywords_highlight {
     return $string;      return $string;
 }  }
   
   # For Tasks provide a mechanism to display previous version for one specific student
   
   sub show_previous_task_version {
       my ($request,$symb) = @_;
       if ($symb eq '') {
           $request->print("Unable to handle ambiguous references.");
   
           return '';
       }
       my ($uname,$udom) = ($env{'form.student'},$env{'form.userdom'});
       my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'});
       if (!&canview($usec)) {
           $request->print('<span class="LC_warning">Unable to view previous version for requested student.('.
                           $uname.':'.$udom.' in section '.$usec.' in course id '.
                           $env{'request.course.id'}.')</span>');
           return;
       }
       my $mode = 'both';
       my $isTask = ($symb =~/\.task$/);
       if ($isTask) {
           if ($env{'form.previousversion'} =~ /^\d+$/) {
               if ($env{'form.fullname'} eq '') {
                   $env{'form.fullname'} =
                       &Apache::loncommon::plainname($uname,$udom,'lastname');
               }
               my $probtitle=&Apache::lonnet::gettitle($symb);
               $request->print("\n\n".
                               '<div class="LC_grade_show_user">'.
                               '<h2>'.&nameUserString(undef,$env{'form.fullname'},$uname,$udom).
                               '</h2>'."\n");
               &Apache::lonxml::clear_problem_counter();
               $request->print(&show_problem($request,$symb,$uname,$udom,1,1,$mode,
                               {'previousversion' => $env{'form.previousversion'} }));
               $request->print("\n</div>");
           }
       }
       return;
   }
   
   sub choose_task_version_form {
       my ($symb,$uname,$udom,$nomenu) = @_;
       my $isTask = ($symb =~/\.task$/);
       my ($current,$version,$result,$js,$displayed,$rowtitle);
       if ($isTask) {
           my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},
                                                 $udom,$uname);
           if (($record{'resource.0.version'} eq '') ||
               ($record{'resource.0.version'} < 2)) {
               return ($record{'resource.0.version'},
                       $record{'resource.0.version'},$result,$js);
           } else {
               $current = $record{'resource.0.version'};
           }
           if ($env{'form.previousversion'}) {
               $displayed = $env{'form.previousversion'};
               $rowtitle = &mt('Choose another version:')
           } else {
               $displayed = $current;
               $rowtitle = &mt('Show earlier version:');
           }
           $result = '<div class="LC_left_float">';
           my $list;
           my $numversions = 0;
           for (my $i=1; $i<=$record{'resource.0.version'}; $i++) {
               if ($i == $current) {
                   if (!$env{'form.previousversion'} || $nomenu) {
                       next;
                   } else {
                       $list .= '<option value="'.$i.'">'.&mt('Current').'</option>'."\n";
                       $numversions ++;
                   }
               } elsif (defined($record{'resource.'.$i.'.0.status'})) {
                   unless ($i == $env{'form.previousversion'}) {
                       $numversions ++;
                   }
                   $list .= '<option value="'.$i.'">'.$i.'</option>'."\n";
               }
           }
           if ($numversions) {
               $symb = &HTML::Entities::encode($symb,'<>"&');
               $result .=
                   '<form name="getprev" method="post" action=""'.
                   ' onsubmit="return previousVersion('."'$uname','$udom','$symb','$displayed'".');">'.
                   &Apache::loncommon::start_data_table().
                   &Apache::loncommon::start_data_table_row().
                   '<th align="left">'.$rowtitle.'</th>'.
                   '<td><select name="version">'.
                   '<option>'.&mt('Select').'</option>'.
                   $list.
                   '</select></td>'.
                   &Apache::loncommon::end_data_table_row();
               unless ($nomenu) {
                   $result .= &Apache::loncommon::start_data_table_row().
                   '<th align="left">'.&mt('Open in new window').'</th>'.
                   '<td><span class="LC_nobreak">'.
                   '<label><input type="radio" name="prevwin" value="1" />'.
                   &mt('Yes').'</label>'.
                   '<label><input type="radio" name="prevwin" value="0" checked="checked" />'.&mt('No').'</label>'.
                   '</span></td>'.
                   &Apache::loncommon::end_data_table_row();
               }
               $result .=
                   &Apache::loncommon::start_data_table_row().
                   '<th align="left">&nbsp;</th>'.
                   '<td>'.
                   '<input type="submit" name="prevsub" value="'.&mt('Display').'" />'.
                   '</td>'.
                   &Apache::loncommon::end_data_table_row().
                   &Apache::loncommon::end_data_table().
                   '</form>';
               $js = &previous_display_javascript($nomenu,$current);
           } elsif ($displayed && $nomenu) {
               $result .= '<a href="javascript:window.close()">'.&mt('Close window').'</a>';
           } else {
               $result .= &mt('No previous versions to show for this student');
           }
           $result .= '</div>';
       }
       return ($current,$displayed,$result,$js);
   }
   
   sub previous_display_javascript {
       my ($nomenu,$current) = @_;
       my $js = <<"JSONE";
   <script type="text/javascript">
   // <![CDATA[
   function previousVersion(uname,udom,symb) {
       var current = '$current';
       var version = document.getprev.version.options[document.getprev.version.selectedIndex].value;
       var prevstr = new RegExp("^\\\\d+\$");
       if (!prevstr.test(version)) {
           return false;
       }
       var url = '';
       if (version == current) {
           url = '/adm/grades?student='+uname+'&userdom='+udom+'&symb='+symb+'&command=submission';
       } else {
           url = '/adm/grades?student='+uname+'&userdom='+udom+'&symb='+symb+'&command=versionsub&previousversion='+version;
       }
   JSONE
       if ($nomenu) {
           $js .= <<"JSTWO";
       document.location.href = url;
   JSTWO
       } else {
           $js .= <<"JSTHREE";
       var newwin = 0;
       for (var i=0; i<document.getprev.prevwin.length; i++) {
           if (document.getprev.prevwin[i].checked == true) {
               newwin = document.getprev.prevwin[i].value;
           }
       }
       if (newwin == 1) {
           var options = 'height=600,width=800,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no';
           url = url+'&inhibitmenu=yes';
           if (typeof(previousWin) == 'undefined' || previousWin.closed) {
               previousWin = window.open(url,'',options,1);
           } else {
               previousWin.location.href = url;
           }
           previousWin.focus();
           return false;
       } else {
           document.location.href = url;
           return false;
       }
   JSTHREE
       }
       $js .= <<"ENDJS";
       return false;
   }
   // ]]>
   </script>
   ENDJS
   
   }
   
 #--- Called from submission routine  #--- Called from submission routine
 sub processHandGrade {  sub processHandGrade {
     my ($request) = shift;      my ($request) = shift;
     my $symb   = &get_symb($request);      my ($symb)   = &get_symb($request);
     my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);      my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);
     my $button = $env{'form.gradeOpt'};      my $button = $env{'form.gradeOpt'};
     my $ngrade = $env{'form.NCT'};      my $ngrade = $env{'form.NCT'};
Line 3002  sub handback_files { Line 3202  sub handback_files {
         &file_name_version_ext($answer_file);          &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 = &Apache::lonnet::dirlist($portfolio_root.$portfolio_path,$domain,$stuname,$getpropath);                      my ($dir_list,$listerror) =
     my $version = &get_next_version($answer_name, $answer_ext, \@dir_list);                          &Apache::lonnet::dirlist($portfolio_root.$portfolio_path,
                     # fix file name                                                   $domain,$stuname,$getpropath);
       my $version = &get_next_version($answer_name,$answer_ext,$dir_list);
                       # 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,
                                            $newflg.'_'.$part_resp.'_returndoc'.$counter,                                             $newflg.'_'.$part_resp.'_returndoc'.$counter,
Line 3024  sub handback_files { Line 3226  sub handback_files {
  $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 file name [_2]','<span class="LC_info">'.$fname.'</span>','<span class="LC_filename">'.$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter}.'</span>'));                      $request->print('<br />'.&mt('[_1] will be the uploaded filename [_2]','<span class="LC_info">'.$fname.'</span>','<span class="LC_filename">'.$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter}.'</span>'));
                 }                  }
             }              }
         }          }
Line 3163  sub version_portfiles { Line 3365  sub version_portfiles {
                 my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*)$/);                  my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*)$/);
  my ($answer_name,$answer_ver,$answer_ext) =   my ($answer_name,$answer_ver,$answer_ext) =
     &file_name_version_ext($answer_file);      &file_name_version_ext($answer_file);
                 my $getpropath = 1;                      my $getpropath = 1;
                 my @dir_list = &Apache::lonnet::dirlist($portfolio_root.$directory,$domain,$stu_name,$getpropath);                  my ($dir_list,$listerror) =
                 my $version = &get_next_version($answer_name, $answer_ext, \@dir_list);                      &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);                  my $new_answer = &version_selected_portfile($domain, $stu_name, $directory, $answer_file, $version);
                 if ($new_answer ne 'problem getting file') {                  if ($new_answer ne 'problem getting file') {
                     push(@versioned_portfiles, $directory.$new_answer);                      push(@versioned_portfiles, $directory.$new_answer);
Line 3184  sub version_portfiles { Line 3388  sub version_portfiles {
 sub get_next_version {  sub get_next_version {
     my ($answer_name, $answer_ext, $dir_list) = @_;      my ($answer_name, $answer_ext, $dir_list) = @_;
     my $version;      my $version;
     foreach my $row (@$dir_list) {      if (ref($dir_list) eq 'ARRAY') {
         my ($file) = split(/\&/,$row,2);          foreach my $row (@{$dir_list}) {
         my ($file_name,$file_version,$file_ext) =              my ($file) = split(/\&/,$row,2);
     &file_name_version_ext($file);              my ($file_name,$file_version,$file_ext) =
         if (($file_name eq $answer_name) &&           &file_name_version_ext($file);
     ($file_ext eq $answer_ext)) {              if (($file_name eq $answer_name) && 
                 # gets here if filename and extension match, regardless of version          ($file_ext eq $answer_ext)) {
                   # gets here if filename and extension match, 
                   # regardless of version
                 if ($file_version ne '') {                  if ($file_version ne '') {
                 # a versioned file is found  so save it for later                      # a versioned file is found  so save it for later
                 if ($file_version > $version) {                      if ($file_version > $version) {
     $version = $file_version;          $version = $file_version;
                       }
         }          }
             }              }
         }          }
     }       }
     $version ++;      $version ++;
     return($version);      return($version);
 }  }
Line 3658  sub viewstudentgrade { Line 3865  sub viewstudentgrade {
 sub editgrades {  sub editgrades {
     my ($request) = @_;      my ($request) = @_;
   
     my $symb=&get_symb($request);      my ($symb)=&get_symb($request);
     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>';
     $title.='<h4>'.&mt('<b>Current Resource: </b>[_1]',$env{'form.probTitle'}).'</h4>'."\n";      $title.='<h4>'.&mt('<b>Current Resource: </b>[_1]',$env{'form.probTitle'}).'</h4>'."\n";
Line 4603  sub displayPage { Line 4810  sub displayPage {
  &Apache::loncommon::start_data_table_row().   &Apache::loncommon::start_data_table_row().
  '<td align="center" valign="top" >'.$prob.   '<td align="center" valign="top" >'.$prob.
  (scalar(@{$parts}) == 1 ? ''    (scalar(@{$parts}) == 1 ? '' 
                         : '<br />('.&mt('[_1]parts)',                          : '<br />('.&mt('[_1]parts',
  scalar(@{$parts}).'&nbsp;')   scalar(@{$parts}).'&nbsp;').')'
  ).   ).
  '</td>';   '</td>';
     $studentTable.='<td valign="top">';      $studentTable.='<td valign="top">';
Line 4686  sub displaySubByDates { Line 4893  sub displaySubByDates {
  &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>':'').
  '<th>'.&mt('Submission').'</th>'.   '<th>'.&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();
Line 4706  sub displaySubByDates { Line 4914  sub displaySubByDates {
  if (exists($$record{$version.':resource.0.version'})) {   if (exists($$record{$version.':resource.0.version'})) {
     $interaction = $$record{$version.':resource.0.version'};      $interaction = $$record{$version.':resource.0.version'};
  }   }
           if ($isTask && $env{'form.previousversion'}) {
               next unless ($interaction == $env{'form.previousversion'});
           }
  my $where = ($isTask ? "$version:resource.$interaction"   my $where = ($isTask ? "$version:resource.$interaction"
              : "$version:resource");               : "$version:resource");
  $studentTable.=&Apache::loncommon::start_data_table_row().   $studentTable.=&Apache::loncommon::start_data_table_row().
Line 4714  sub displaySubByDates { Line 4924  sub displaySubByDates {
  if ($isCODE) {   if ($isCODE) {
     $studentTable.='<td>'.$record->{$version.':resource.CODE'}.'</td>';      $studentTable.='<td>'.$record->{$version.':resource.CODE'}.'</td>';
  }   }
           if ($isTask) {
               $studentTable.='<td>'.$interaction.'</td>';
           }
  my @versionKeys = split(/\:/,$$record{$version.':keys'});   my @versionKeys = split(/\:/,$$record{$version.':keys'});
  my @displaySub = ();   my @displaySub = ();
  foreach my $partid (@{$parts}) {   foreach my $partid (@{$parts}) {
Line 4733  sub displaySubByDates { Line 4946  sub displaySubByDates {
                                           
     my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/)      my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/)
                : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/));                 : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/));
                     $displaySub[0].='<span class="LC_nobreak"';                      $displaySub[0].='<span class="LC_nobreak">';
                     $displaySub[0].='<b>'.&mt('Part: [_1]',$display_part).'</b>'                      $displaySub[0].='<b>'.&mt('Part: [_1]',$display_part).'</b>'
                                    .' <span class="LC_internal_info">'                                     .' <span class="LC_internal_info">'
                                    .'('.&mt('Response ID: [_1]',$responseId).')'                                     .'('.&mt('Response ID: [_1]',$responseId).')'
Line 5157  sub scantron_filenames { Line 5370  sub scantron_filenames {
     my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};      my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
     my $cname=$env{'course.'.$env{'request.course.id'}.'.num'};      my $cname=$env{'course.'.$env{'request.course.id'}.'.num'};
     my $getpropath = 1;      my $getpropath = 1;
     my @files=&Apache::lonnet::dirlist('userfiles',$cdom,$cname,      my ($dirlist,$listerror) = &Apache::lonnet::dirlist('userfiles',$cdom,
                                        $getpropath);                                                          $cname,$getpropath);
     my @possiblenames;      my @possiblenames;
     foreach my $filename (sort(@files)) {      if (ref($dirlist) eq 'ARRAY') {
  ($filename)=split(/&/,$filename);          foreach my $filename (sort(@{$dirlist})) {
  if ($filename!~/^scantron_orig_/) { next ; }      ($filename)=split(/&/,$filename);
  $filename=~s/^scantron_orig_//;      if ($filename!~/^scantron_orig_/) { next ; }
  push(@possiblenames,$filename);      $filename=~s/^scantron_orig_//;
       push(@possiblenames,$filename);
           }
     }      }
     return @possiblenames;      return @possiblenames;
 }  }
Line 5562  sub scantron_selectphase { Line 5777  sub scantron_selectphase {
     
       LastName    - column that the last name starts in        LastName    - column that the last name starts in
       LastNameLength - number of columns that the last name spans        LastNameLength - number of columns that the last name spans
         BubblesPerRow - number of bubbles available in each row used to
                         bubble an answer. (If not specified, 10 assumed).
   
 =cut  =cut
   
Line 5592  sub get_scantron_config { Line 5809  sub get_scantron_config {
  $config{'FirstNamelength'}=$config[14];   $config{'FirstNamelength'}=$config[14];
  $config{'LastName'}=$config[15];   $config{'LastName'}=$config[15];
  $config{'LastNamelength'}=$config[16];   $config{'LastNamelength'}=$config[16];
           $config{'BubblesPerRow'}=$config[17];
  last;   last;
     }      }
     return %config;      return %config;
Line 6376  sub scantron_warning_screen { Line 6594  sub scantron_warning_screen {
     '<tr><td><b>'.&mt('List of CODES to validate against:').'</b></td><td><tt>'.      '<tr><td><b>'.&mt('List of CODES to validate against:').'</b></td><td><tt>'.
     $env{'form.scantron_CODElist'}.'</tt></td></tr>';      $env{'form.scantron_CODElist'}.'</tt></td></tr>';
     }      }
       my $lastbubblepoints;
       if ($env{'form.scantron_lastbubblepoints'} ne '') {
           $lastbubblepoints =
               '<tr><td><b>'.&mt('Hand-graded items: points from last bubble in row').'</b></td><td><tt>'.
               $env{'form.scantron_lastbubblepoints'}.'</tt></td></tr>';
       }
     return ('      return ('
 <p>  <p>
 <span class="LC_warning">  <span class="LC_warning">
Line 6384  sub scantron_warning_screen { Line 6608  sub scantron_warning_screen {
 <table>  <table>
 <tr><td><b>'.&mt('Sequence to be Graded:').'</b></td><td>'.$title.'</td></tr>  <tr><td><b>'.&mt('Sequence to be Graded:').'</b></td><td>'.$title.'</td></tr>
 <tr><td><b>'.&mt('Data File that will be used:').'</b></td><td><tt>'.$env{'form.scantron_selectfile'}.'</tt></td></tr>  <tr><td><b>'.&mt('Data File that will be used:').'</b></td><td><tt>'.$env{'form.scantron_selectfile'}.'</tt></td></tr>
 '.$CODElist.'  '.$CODElist.$lastbubblepoints.'
 </table>  </table>
 <br />  <br />
 <p> '.&mt('If this information is correct, please click on \'[_1]\'.',&mt($button_text)).'</p>  <p> '.&mt("If this information is correct, please click on '[_1]'.",&mt($button_text)).'</p>
 <p> '.&mt('If something is incorrect, please click the \'Grading Menu\' button to start over.').'</p>  <p> '.&mt("If something is incorrect, please click the 'Grading Menu' button to start over.").'</p>
   
 <br />  <br />
 ');  ');
Line 6424  sub scantron_do_warning { Line 6648  sub scantron_do_warning {
  }    } 
     } else {      } else {
  my $warning=&scantron_warning_screen('Grading: Validate Records');   my $warning=&scantron_warning_screen('Grading: Validate Records');
           my $bubbledbyhand=&hand_bubble_option();
  $r->print('   $r->print('
 '.$warning.'  '.$warning.$bubbledbyhand.'
 <input type="submit" name="submit" value="'.&mt('Grading: Validate Records').'" />  <input type="submit" name="submit" value="'.&mt('Grading: Validate Records').'" />
 <input type="hidden" name="command" value="scantron_validate" />  <input type="hidden" name="command" value="scantron_validate" />
 ');  ');
Line 6515  sub scantron_validate_file { Line 6740  sub scantron_validate_file {
     #get the student pick code ready      #get the student pick code ready
     $r->print(&Apache::loncommon::studentbrowser_javascript());      $r->print(&Apache::loncommon::studentbrowser_javascript());
     my $nav_error;      my $nav_error;
     my $max_bubble=&scantron_get_maxbubble(\$nav_error);      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
       my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config);
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
         return '';          return '';
     }      }
     my $result=&scantron_form_start($max_bubble).$default_form_data;      my $result=&scantron_form_start($max_bubble).$default_form_data;
       if ($env{'form.scantron_lastbubblepoints'} ne '') {
           $result .= '<input type="hidden" name="scantron_lastbubblepoints" value="'.$env{'form.scantron_lastbubblepoints'}.'" />';
       }
     $r->print($result);      $r->print($result);
           
     my @validate_phases=( 'sequence',      my @validate_phases=( 'sequence',
Line 6946  sub scantron_validate_sequence { Line 7175  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>".&mt('Some resources in the sequence currently are not set to exam mode. Grading these resources currently may not work correctly.')."</p>");      $r->print('<p class="LC_warning">'
                  .&mt('Some resources in the sequence currently are not set to'
                      .' exam mode. Grading these resources currently may not'
                      .' work correctly.')
                  .'</p>'
               );
     return (1,$currentphase);      return (1,$currentphase);
  }   }
     }      }
Line 6968  sub scantron_validate_ID { Line 7202  sub scantron_validate_ID {
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
   
     my $nav_error;      my $nav_error;
     &scantron_get_maxbubble(\$nav_error); # parse needs the bubble_lines.. array.      &scantron_get_maxbubble(\$nav_error,\%scantron_config); # parse needs the bubble_lines.. array.
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
         return(1,$currentphase);          return(1,$currentphase);
Line 7077  sub scantron_get_correction { Line 7311  sub scantron_get_correction {
  $r->print(&Apache::loncommon::selectstudent_link('scantronupload',   $r->print(&Apache::loncommon::selectstudent_link('scantronupload',
        'scantron_username','scantron_domain'));         'scantron_username','scantron_domain'));
  $r->print(": <input type='text' name='scantron_username' value='' />");   $r->print(": <input type='text' name='scantron_username' value='' />");
  $r->print("\n@".   $r->print("\n:\n".
  &Apache::loncommon::select_dom_form($env{'request.role.domain'},'scantron_domain'));   &Apache::loncommon::select_dom_form($env{'request.role.domain'},'scantron_domain'));
   
  $r->print('</li>');   $r->print('</li>');
Line 7381  sub scantron_bubble_selector { Line 7615  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') { $max=10; }           if ($scmode eq 'number' || $scmode eq 'letter') {
           if (($$scan_config{'BubblesPerRow'} =~ /^\d+$/) &&
               ($$scan_config{'BubblesPerRow'} > 0)) {
               $max=$$scan_config{'BubblesPerRow'};
               if (($scmode eq 'number') && ($max > 10)) {
                   $max = 10;
               } elsif (($scmode eq 'letter') && $max > 26) {
                   $max = 26;
               }
           } else {
               $max = 10;
           }
       }
   
     my @alphabet=('A'..'Z');      my @alphabet=('A'..'Z');
     $r->print(&Apache::loncommon::start_data_table().      $r->print(&Apache::loncommon::start_data_table().
Line 7536  sub scantron_validate_CODE { Line 7782  sub scantron_validate_CODE {
     my %allcodes=&get_codes();      my %allcodes=&get_codes();
   
     my $nav_error;      my $nav_error;
     &scantron_get_maxbubble(\$nav_error); # parse needs the lines per response array.      &scantron_get_maxbubble(\$nav_error,\%scantron_config); # parse needs the lines per response array.
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
         return(1,$currentphase);          return(1,$currentphase);
Line 7595  sub scantron_validate_doublebubble { Line 7841  sub scantron_validate_doublebubble {
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
     my $nav_error;      my $nav_error;
     &scantron_get_maxbubble(\$nav_error); # parse needs the bubble line array.      &scantron_get_maxbubble(\$nav_error,\%scantron_config); # parse needs the bubble line array.
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
         return(1,$currentphase);          return(1,$currentphase);
Line 7617  sub scantron_validate_doublebubble { Line 7863  sub scantron_validate_doublebubble {
   
   
 sub scantron_get_maxbubble {  sub scantron_get_maxbubble {
     my ($nav_error) = @_;      my ($nav_error,$scantron_config) = @_;
     if (defined($env{'form.scantron_maxbubble'}) &&      if (defined($env{'form.scantron_maxbubble'}) &&
  $env{'form.scantron_maxbubble'}) {   $env{'form.scantron_maxbubble'}) {
  &restore_bubble_lines();   &restore_bubble_lines();
Line 7636  sub scantron_get_maxbubble { Line 7882  sub scantron_get_maxbubble {
     }      }
     my $map=$navmap->getResourceByUrl($sequence);      my $map=$navmap->getResourceByUrl($sequence);
     my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);      my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
       my $bubbles_per_row = &bubblesheet_bubbles_per_row($scantron_config);
   
     &Apache::lonxml::clear_problem_counter();      &Apache::lonxml::clear_problem_counter();
   
Line 7651  sub scantron_get_maxbubble { Line 7898  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 ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname,$udom);          my ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname,
                                                             $udom,$bubbles_per_row);
         if ((ref($analysis) eq 'HASH') && (ref($parts) eq 'ARRAY')) {          if ((ref($analysis) eq 'HASH') && (ref($parts) eq 'ARRAY')) {
     foreach my $part_id (@{$parts}) {      foreach my $part_id (@{$parts}) {
                 my $lines;                  my $lines;
Line 7680  sub scantron_get_maxbubble { Line 7928  sub scantron_get_maxbubble {
                     if (ref($analysis->{$part_id.'.shown'}) eq 'ARRAY') {                      if (ref($analysis->{$part_id.'.shown'}) eq 'ARRAY') {
                         $numshown = scalar(@{$analysis->{$part_id.'.shown'}});                          $numshown = scalar(@{$analysis->{$part_id.'.shown'}});
                     }                      }
                     my $bubbles_per_line = 10;                      my $bubbles_per_row =
                     my $inner_bubble_lines = int($numbub/$bubbles_per_line);                          &bubblesheet_bubbles_per_row($scantron_config);
                     if (($numbub % $bubbles_per_line) != 0) {                      my $inner_bubble_lines = int($numbub/$bubbles_per_row);
                       if (($numbub % $bubbles_per_row) != 0) {
                         $inner_bubble_lines++;                          $inner_bubble_lines++;
                     }                      }
                     for (my $i=0; $i<$numshown; $i++) {                      for (my $i=0; $i<$numshown; $i++) {
Line 7693  sub scantron_get_maxbubble { Line 7942  sub scantron_get_maxbubble {
                     $lines = $numshown * $inner_bubble_lines;                      $lines = $numshown * $inner_bubble_lines;
                 } else {                  } else {
                     $lines = $analysis->{"$part_id.bubble_lines"};                      $lines = $analysis->{"$part_id.bubble_lines"};
                 }                   }
   
                 $first_bubble_line{$response_number} = $bubble_line;                  $first_bubble_line{$response_number} = $bubble_line;
         $bubble_lines_per_response{$response_number} = $lines;          $bubble_lines_per_response{$response_number} = $lines;
Line 7714  sub scantron_get_maxbubble { Line 7963  sub scantron_get_maxbubble {
     return $env{'form.scantron_maxbubble'};      return $env{'form.scantron_maxbubble'};
 }  }
   
   sub bubblesheet_bubbles_per_row {
       my ($scantron_config) = @_;
       my $bubbles_per_row;
       if (ref($scantron_config) eq 'HASH') {
           $bubbles_per_row = $scantron_config->{'BubblesPerRow'};
       }
       if ((!$bubbles_per_row) || ($bubbles_per_row < 1)) {
           $bubbles_per_row = 10;
       }
       return $bubbles_per_row;
   }
   
 sub scantron_validate_missingbubbles {  sub scantron_validate_missingbubbles {
     my ($r,$currentphase) = @_;      my ($r,$currentphase) = @_;
     #get student info      #get student info
Line 7724  sub scantron_validate_missingbubbles { Line 7985  sub scantron_validate_missingbubbles {
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
     my $nav_error;      my $nav_error;
     my $max_bubble=&scantron_get_maxbubble(\$nav_error);      my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config);
     if ($nav_error) {      if ($nav_error) {
         return(1,$currentphase);          return(1,$currentphase);
     }      }
Line 7771  sub scantron_validate_missingbubbles { Line 8032  sub scantron_validate_missingbubbles {
     return (0,$currentphase+1);      return (0,$currentphase+1);
 }  }
   
   sub hand_bubble_option {
       my (undef, undef, $sequence) =
           &Apache::lonnet::decode_symb($env{'form.selectpage'});
       return if ($sequence eq '');
       my $navmap = Apache::lonnavmaps::navmap->new();
       unless (ref($navmap)) {
           return;
       }
       my $needs_hand_bubbles;
       my $map=$navmap->getResourceByUrl($sequence);
       my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
       foreach my $res (@resources) {
           if (ref($res)) {
               if ($res->is_problem()) {
                   my $partlist = $res->parts();
                   foreach my $part (@{ $partlist }) {
                       my @types = $res->responseType($part);
                       if (grep(/^(chem|essay|image|formula|math|string|functionplot)$/,@types)) {
                           $needs_hand_bubbles = 1;
                           last;
                       }
                   }
               }
           }
       }
       if ($needs_hand_bubbles) {
           my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
           my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config);
           return &mt('The sequence to be graded contains response types which are handgraded.').'<p>'.
                  &mt('If you have already graded these by bubbling sheets to indicate points awarded, [_1]what point value is assigned to a filled last bubble in each row?','<br />').
                  '<label><input type="radio" name="scantron_lastbubblepoints" value="'.$bubbles_per_row.'" checked="checked" />'.&mt('[quant,_1,point]',$bubbles_per_row).'</label>&nbsp;'.&mt('or').'&nbsp;'.
                  '<label><input type="radio" name="scantron_lastbubblepoints" value="0"/>0 points</label></p>';
       }
       return;
   }
   
 sub scantron_process_students {  sub scantron_process_students {
     my ($r) = @_;      my ($r) = @_;
Line 7783  sub scantron_process_students { Line 8079  sub scantron_process_students {
     my $default_form_data=&defaultFormData($symb);      my $default_form_data=&defaultFormData($symb);
   
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
       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 7792  sub scantron_process_students { Line 8090  sub scantron_process_students {
         return '';          return '';
     }        }  
     my $map=$navmap->getResourceByUrl($sequence);      my $map=$navmap->getResourceByUrl($sequence);
       my $randomorder;
       if (ref($map)) {
           $randomorder = $map->randomorder();
       }
     my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);      my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
     my (%grader_partids_by_symb,%grader_randomlists_by_symb);      my (%grader_partids_by_symb,%grader_randomlists_by_symb,%ordered);
     &graders_resources_pass(\@resources,\%grader_partids_by_symb,      &graders_resources_pass(\@resources,\%grader_partids_by_symb,
                             \%grader_randomlists_by_symb);                              \%grader_randomlists_by_symb,$bubbles_per_row);
     my $resource_error;      my ($resource_error,%symb_to_resource,@master_seq);
     foreach my $resource (@resources) {      foreach my $resource (@resources) {
         my $ressymb;          my $ressymb;
         if (ref($resource)) {          if (ref($resource)) {
             $ressymb = $resource->symb();              $ressymb = $resource->symb();
               push(@master_seq,$ressymb);
               $symb_to_resource{$ressymb} = $resource;
         } else {          } else {
             $resource_error = 1;              $resource_error = 1;
             last;              last;
         }          }
         my ($analysis,$parts) =          my ($analysis,$parts) =
             &scantron_partids_tograde($resource,$env{'request.course.id'},              &scantron_partids_tograde($resource,$env{'request.course.id'},
                                       $env{'user.name'},$env{'user.domain'},1);                                        $env{'user.name'},$env{'user.domain'},
                                         1,$bubbles_per_row);
         $grader_partids_by_symb{$ressymb} = $parts;          $grader_partids_by_symb{$ressymb} = $parts;
         if (ref($analysis) eq 'HASH') {          if (ref($analysis) eq 'HASH') {
             if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') {              if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') {
Line 7834  SCANTRONFORM Line 8139  SCANTRONFORM
           
     my $lock=&Apache::lonnet::set_lock(&mt('Grading bubblesheet exam'));      my $lock=&Apache::lonnet::set_lock(&mt('Grading bubblesheet exam'));
     my $count=&get_todo_count($scanlines,$scan_data);      my $count=&get_todo_count($scanlines,$scan_data);
     my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Bubblesheet Status',      my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,$count);
      'Bubblesheet Progress',$count,  
     'inline',undef,'scantronupload');  
     &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,      &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,
   'Processing first student');    'Processing first student');
     $r->print('<br />');      $r->print('<br />');
Line 7845  SCANTRONFORM Line 8148  SCANTRONFORM
     my $started;      my $started;
   
     my $nav_error;      my $nav_error;
     &scantron_get_maxbubble(\$nav_error); # Need the bubble lines array to parse.      &scantron_get_maxbubble(\$nav_error,\%scantron_config); # Need the bubble lines array to parse.
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
         return '';          return '';
Line 7888  SCANTRONFORM Line 8191  SCANTRONFORM
   'Student '.$uname.' has multiple sheets',2);    'Student '.$uname.' has multiple sheets',2);
      next;       next;
   }    }
           my $usec = $classlist->{$uname}->[&Apache::loncoursedata::CL_SECTION];
           my $user = $uname.':'.$usec;
   ($uname,$udom)=split(/:/,$uname);    ($uname,$udom)=split(/:/,$uname);
   
           my $scancode;
           if ((exists($scan_record->{'scantron.CODE'})) &&
               (&Apache::lonnet::validCODE($scan_record->{'scantron.CODE'}))) {
               $scancode = $scan_record->{'scantron.CODE'};
           } else {
               $scancode = '';
           }
   
           my @mapresources = @resources;
           if ($randomorder) {
               @mapresources =
                   &users_order($user,$scancode,$sequence,\@master_seq,\%ordered,
                                \%symb_to_resource);
           }
         my (%partids_by_symb,$res_error);          my (%partids_by_symb,$res_error);
         foreach my $resource (@resources) {          foreach my $resource (@mapresources) {
             my $ressymb;              my $ressymb;
             if (ref($resource)) {              if (ref($resource)) {
                 $ressymb = $resource->symb();                  $ressymb = $resource->symb();
Line 7902  SCANTRONFORM Line 8221  SCANTRONFORM
             if ((exists($grader_randomlists_by_symb{$ressymb})) ||              if ((exists($grader_randomlists_by_symb{$ressymb})) ||
                 (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {                  (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {
                 my ($analysis,$parts) =                  my ($analysis,$parts) =
                     &scantron_partids_tograde($resource,$env{'request.course.id'},$uname,$udom);                      &scantron_partids_tograde($resource,$env{'request.course.id'},
                                                 $uname,$udom,undef,$bubbles_per_row);
                 $partids_by_symb{$ressymb} = $parts;                  $partids_by_symb{$ressymb} = $parts;
             } else {              } else {
                 $partids_by_symb{$ressymb} = $grader_partids_by_symb{$ressymb};                  $partids_by_symb{$ressymb} = $grader_partids_by_symb{$ressymb};
Line 7922  SCANTRONFORM Line 8242  SCANTRONFORM
     &scantron_putfile($scanlines,$scan_data);      &scantron_putfile($scanlines,$scan_data);
  }   }
   
         my $scancode;  
         if ((exists($scan_record->{'scantron.CODE'})) &&  
             (&Apache::lonnet::validCODE($scan_record->{'scantron.CODE'}))) {  
             $scancode = $scan_record->{'scantron.CODE'};  
         } else {  
             $scancode = '';  
         }  
   
         if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,          if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,
                                    \@resources,\%partids_by_symb) eq 'ssi_error') {                                     \@mapresources,\%partids_by_symb,
                                      $bubbles_per_row) 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>");
             &ssi_print_error($r);              &ssi_print_error($r);
Line 7948  SCANTRONFORM Line 8261  SCANTRONFORM
             $studentdata =~ s/\r$//;              $studentdata =~ s/\r$//;
             my $studentrecord = '';              my $studentrecord = '';
             my $counter = -1;              my $counter = -1;
             foreach my $resource (@resources) {              foreach my $resource (@mapresources) {
                 my $ressymb = $resource->symb();                  my $ressymb = $resource->symb();
                 ($counter,my $recording) =                  ($counter,my $recording) =
                     &verify_scantron_grading($resource,$udom,$uname,$env{'request.course.id'},                      &verify_scantron_grading($resource,$udom,$uname,$env{'request.course.id'},
Line 7959  SCANTRONFORM Line 8272  SCANTRONFORM
             if ($studentrecord ne $studentdata) {              if ($studentrecord ne $studentdata) {
                 &Apache::lonxml::clear_problem_counter();                  &Apache::lonxml::clear_problem_counter();
                 if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,                  if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,
                                            \@resources,\%partids_by_symb) eq 'ssi_error') {                                             \@mapresources,\%partids_by_symb,
                                              $bubbles_per_row) 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>");
                     &ssi_print_error($r);                      &ssi_print_error($r);
Line 7970  SCANTRONFORM Line 8284  SCANTRONFORM
                 }                  }
                 $counter = -1;                  $counter = -1;
                 $studentrecord = '';                  $studentrecord = '';
                 foreach my $resource (@resources) {                  foreach my $resource (@mapresources) {
                     my $ressymb = $resource->symb();                      my $ressymb = $resource->symb();
                     ($counter,my $recording) =                      ($counter,my $recording) =
                         &verify_scantron_grading($resource,$udom,$uname,$env{'request.course.id'},                          &verify_scantron_grading($resource,$udom,$uname,$env{'request.course.id'},
Line 8024  SCANTRONFORM Line 8338  SCANTRONFORM
 }  }
   
 sub graders_resources_pass {  sub graders_resources_pass {
     my ($resources,$grader_partids_by_symb,$grader_randomlists_by_symb) = @_;      my ($resources,$grader_partids_by_symb,$grader_randomlists_by_symb,
           $bubbles_per_row) = @_;
     if ((ref($resources) eq 'ARRAY') && (ref($grader_partids_by_symb)) &&       if ((ref($resources) eq 'ARRAY') && (ref($grader_partids_by_symb)) && 
         (ref($grader_randomlists_by_symb) eq 'HASH')) {          (ref($grader_randomlists_by_symb) eq 'HASH')) {
         foreach my $resource (@{$resources}) {          foreach my $resource (@{$resources}) {
             my $ressymb = $resource->symb();              my $ressymb = $resource->symb();
             my ($analysis,$parts) =              my ($analysis,$parts) =
                 &scantron_partids_tograde($resource,$env{'request.course.id'},                  &scantron_partids_tograde($resource,$env{'request.course.id'},
                                           $env{'user.name'},$env{'user.domain'},1);                                            $env{'user.name'},$env{'user.domain'},
                                             1,$bubbles_per_row);
             $grader_partids_by_symb->{$ressymb} = $parts;              $grader_partids_by_symb->{$ressymb} = $parts;
             if (ref($analysis) eq 'HASH') {              if (ref($analysis) eq 'HASH') {
                 if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') {                  if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') {
Line 8044  sub graders_resources_pass { Line 8360  sub graders_resources_pass {
     return;      return;
 }  }
   
   =pod
   
   =item users_order
   
     Returns array of resources in current map, ordered based on either CODE,
     if this is a CODEd exam, or based on student's identity if this is a
     "NAMEd" exam.
   
     Should be used when randomorder applied when the corresponding exam was
     printed, prior to students completing bubblesheets for the version of the
     exam the student received.
   
   =cut
   
   sub users_order  {
       my ($user,$scancode,$mapurl,$master_seq,$ordered,$symb_to_resource) = @_;
       my @mapresources;
       unless ((ref($ordered) eq 'HASH') && (ref($symb_to_resource) eq 'HASH')) {
           return @mapresources;
       }
       if (($scancode) && (ref($ordered->{$scancode}) eq 'ARRAY')) {
           @mapresources = @{$ordered->{$scancode}};
       } elsif ($scancode) {
           $env{'form.CODE'} = $scancode;
           my $actual_seq =
               &Apache::lonprintout::master_seq_to_person_seq($mapurl,
                                                              $master_seq,
                                                              $user,$scancode);
           if (ref($actual_seq) eq 'ARRAY') {
               @{$ordered->{$scancode}} =
                   map { $symb_to_resource->{$_}; } @{$actual_seq};
               @mapresources = @{$ordered->{$scancode}};
           }
           delete($env{'form.CODE'});
       } else {
           my $actual_seq =
               &Apache::lonprintout::master_seq_to_person_seq($mapurl,
                                                              $master_seq,
                                                              $user);
           if (ref($actual_seq) eq 'ARRAY') {
               @mapresources =
                   map { $symb_to_resource->{$_}; } @{$actual_seq};
           }
        }
        return @mapresources;
   }
   
 sub grade_student_bubbles {  sub grade_student_bubbles {
     my ($r,$uname,$udom,$scan_record,$scancode,$resources,$parts) = @_;      my ($r,$uname,$udom,$scan_record,$scancode,$resources,$parts,$bubbles_per_row) = @_;
     if (ref($resources) eq 'ARRAY') {      if (ref($resources) eq 'ARRAY') {
         my $count = 0;          my $count = 0;
         foreach my $resource (@{$resources}) {          foreach my $resource (@{$resources}) {
Line 8058  sub grade_student_bubbles { Line 8421  sub grade_student_bubbles {
                         'grade_symb'     => $ressymb,                          'grade_symb'     => $ressymb,
                         'CODE'           => $scancode                          'CODE'           => $scancode
                        );                         );
               if ($bubbles_per_row ne '') {
                   $form{'bubbles_per_row'} = $bubbles_per_row;
               }
               if ($env{'form.scantron_lastbubblepoints'} ne '') {
                   $form{'scantron_lastbubblepoints'} = $env{'form.scantron_lastbubblepoints'};
               }
             if (ref($parts) eq 'HASH') {              if (ref($parts) eq 'HASH') {
                 if (ref($parts->{$ressymb}) eq 'ARRAY') {                  if (ref($parts->{$ressymb}) eq 'ARRAY') {
                     foreach my $part (@{$parts->{$ressymb}}) {                      foreach my $part (@{$parts->{$ressymb}}) {
Line 8084  sub scantron_upload_scantron_data { Line 8453  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(&get_symb($r,1));      my ($symb) = &get_symb($r,1);
       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.');
     my $nocourseid_alert = &mt("Please use the 'Select Course' link to open a separate window where you can search for a course to which a file can be uploaded.");      my $nocourseid_alert = &mt("Please use the 'Select Course' link to open a separate window where you can search for a course to which a file can be uploaded.");
     $r->print('      $r->print('
Line 8290  sub valid_file { Line 8660  sub valid_file {
   
 sub scantron_download_scantron_data {  sub scantron_download_scantron_data {
     my ($r)=@_;      my ($r)=@_;
     my $default_form_data=&defaultFormData(&get_symb($r,1));      my ($symb) = &get_symb($r,1);
       my $default_form_data=&defaultFormData($symb);
     my $cname=$env{'course.'.$env{'request.course.id'}.'.num'};      my $cname=$env{'course.'.$env{'request.course.id'}.'.num'};
     my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};      my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
     my $file=$env{'form.scantron_selectfile'};      my $file=$env{'form.scantron_selectfile'};
     if (! &valid_file($file)) {      if (! &valid_file($file)) {
  $r->print('   $r->print('
  <p>   <p>
     '.&mt('The requested file name was invalid.').'      '.&mt('The requested filename was invalid.').'
         </p>          </p>
 ');  ');
  $r->print(&show_grading_menu_form(&get_symb($r,1)));   $r->print(&show_grading_menu_form($symb));
  return;   return;
     }      }
     my $orig='/uploaded/'.$cdom.'/'.$cname.'/scantron_orig_'.$file;      my $orig='/uploaded/'.$cdom.'/'.$cname.'/scantron_orig_'.$file;
Line 8323  sub scantron_download_scantron_data { Line 8694  sub scantron_download_scantron_data {
       '<a href="'.$skipped.'">','</a>').'        '<a href="'.$skipped.'">','</a>').'
     </p>      </p>
 ');  ');
     $r->print(&show_grading_menu_form(&get_symb($r,1)));      $r->print(&show_grading_menu_form($symb));
     return '';      return '';
 }  }
   
Line 8341  sub checkscantron_results { Line 8712  sub checkscantron_results {
     my %record;      my %record;
     my %scantron_config =      my %scantron_config =
         &Apache::grades::get_scantron_config($env{'form.scantron_format'});          &Apache::grades::get_scantron_config($env{'form.scantron_format'});
       my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config);
     my ($scanlines,$scan_data)=&Apache::grades::scantron_getfile();      my ($scanlines,$scan_data)=&Apache::grades::scantron_getfile();
     my $classlist=&Apache::loncoursedata::get_classlist();      my $classlist=&Apache::loncoursedata::get_classlist();
     my %idmap=&Apache::grades::username_to_idmap($classlist);      my %idmap=&Apache::grades::username_to_idmap($classlist);
Line 8350  sub checkscantron_results { Line 8722  sub checkscantron_results {
         return '';          return '';
     }      }
     my $map=$navmap->getResourceByUrl($sequence);      my $map=$navmap->getResourceByUrl($sequence);
       my ($randomorder,@master_seq,%symb_to_resource);
       if (ref($map)) {
           $randomorder=$map->randomorder();
       }
     my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);      my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
       foreach my $resource (@resources) {
           if (ref($resource)) {
               my $ressymb = $resource->symb();
               push(@master_seq,$ressymb);
               $symb_to_resource{$ressymb} = $resource;
           }
       }
     my (%grader_partids_by_symb,%grader_randomlists_by_symb);      my (%grader_partids_by_symb,%grader_randomlists_by_symb);
     &graders_resources_pass(\@resources,\%grader_partids_by_symb,                             \%grader_randomlists_by_symb);      &graders_resources_pass(\@resources,\%grader_partids_by_symb,
                               \%grader_randomlists_by_symb,$bubbles_per_row);
     my ($uname,$udom);      my ($uname,$udom);
     my (%scandata,%lastname,%bylast);      my (%scandata,%lastname,%bylast);
     $r->print('      $r->print('
Line 8363  sub checkscantron_results { Line 8746  sub checkscantron_results {
     my %completedstudents;      my %completedstudents;
   
     my $count=&Apache::grades::get_todo_count($scanlines,$scan_data);      my $count=&Apache::grades::get_todo_count($scanlines,$scan_data);
     my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Bubblesheet/Submissions Comparison Status',      my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,$count);
                                     'Progress of Bubblesheet Data/Submission Records Comparison',$count,      my ($username,$domain,$started,%ordered);
                                     'inline',undef,'checkscantron');  
     my ($username,$domain,$started);  
     my $nav_error;      my $nav_error;
     &scantron_get_maxbubble(\$nav_error); # Need the bubble lines array to parse.      &scantron_get_maxbubble(\$nav_error,\%scantron_config); # Need the bubble lines array to parse.
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
         return '';          return '';
Line 8410  sub checkscantron_results { Line 8791  sub checkscantron_results {
         $scandata{$pid} = substr($line,$scantron_config{'Qstart'}-1,$lastpos);          $scandata{$pid} = substr($line,$scantron_config{'Qstart'}-1,$lastpos);
         chomp($scandata{$pid});          chomp($scandata{$pid});
         $scandata{$pid} =~ s/\r$//;          $scandata{$pid} =~ s/\r$//;
           my $usec = $classlist->{$uname}->[&Apache::loncoursedata::CL_SECTION];
           my $user = $uname.':'.$usec;
         ($username,$domain)=split(/:/,$uname);          ($username,$domain)=split(/:/,$uname);
   
           my $scancode;
           if ((exists($scan_record->{'scantron.CODE'})) &&
               (&Apache::lonnet::validCODE($scan_record->{'scantron.CODE'}))) {
               $scancode = $scan_record->{'scantron.CODE'};
           } else {
               $scancode = '';
           }
   
           my @mapresources = @resources;
           if ($randomorder) {
               @mapresources =
                   &users_order($user,$scancode,$sequence,\@master_seq,\%ordered,
                                \%symb_to_resource);
           }
         my $counter = -1;          my $counter = -1;
         foreach my $resource (@resources) {          foreach my $resource (@mapresources) {
             my $parts;              my $parts;
             my $ressymb = $resource->symb();              my $ressymb = $resource->symb();
             if ((exists($grader_randomlists_by_symb{$ressymb})) ||              if ((exists($grader_randomlists_by_symb{$ressymb})) ||
                 (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {                  (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {
                 (my $analysis,$parts) =                  (my $analysis,$parts) =
                     &scantron_partids_tograde($resource,$env{'request.course.id'},$username,$domain);                      &scantron_partids_tograde($resource,$env{'request.course.id'},
                                                 $username,$domain,undef,
                                                 $bubbles_per_row);
             } else {              } else {
                 $parts = $grader_partids_by_symb{$ressymb};                  $parts = $grader_partids_by_symb{$ressymb};
             }              }
Line 8471  sub checkscantron_results { Line 8871  sub checkscantron_results {
                   $env{'form.scantron_maxbubble'}).                    $env{'form.scantron_maxbubble'}).
               '</p>'                '</p>'
     );      );
     $r->print('<p>'.&mt('Exact matches for <b>[quant,_1,student]</b>.',$passed).'<br />'.&mt('Discrepancies detected for <b>[quant,_1,student]</b>.',$failed).'</p>');      $r->print('<p>'
                .&mt('Exact matches for [_1][quant,_2,student][_3].','<b>',$passed,'</b>')
                .'<br />'
                .&mt('Discrepancies detected for [_1][quant,_2,student][_3].','<b>',$failed,'</b>')
                .'</p>');
     if ($passed) {      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 8657  sub savedState { Line 9061  sub savedState {
     return \%savedState;      return \%savedState;
 }  }
   
   #--- Href with symb and command ---
   
   sub href_symb_cmd {
       my ($symb,$cmd)=@_;
       return '/adm/grades?symb='.&HTML::Entities::encode(&Apache::lonenc::check_encrypt($symb),'<>&"').'&amp;command='.$cmd;
   }
   
 sub grading_menu {  sub grading_menu {
     my ($request) = @_;      my ($request) = @_;
     my ($symb)=&get_symb($request);      my ($symb)=&get_symb($request);
Line 8964  sub init_perm { Line 9375  sub init_perm {
     }      }
 }  }
   
   sub init_old_essays {
       my ($symb,$apath,$adom,$aname) = @_;
       if ($symb ne '') {
           my %essays = &Apache::lonnet::dump('nohist_essay_'.$apath,$adom,$aname);
           if (keys(%essays) > 0) {
               $old_essays{$symb} = \%essays;
           }
       }
       return;
   }
   
   sub reset_old_essays {
       undef(%old_essays);
   }
   
 sub gather_clicker_ids {  sub gather_clicker_ids {
     my %clicker_ids;      my %clicker_ids;
   
Line 9065  sub process_clicker { Line 9491  sub process_clicker {
     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'});
     $symb = &Apache::lonenc::check_encrypt($symb);      $symb = &Apache::lonenc::check_encrypt($symb);
     $result.=<<ENDUPFORM;      $result.=<<ENDUPFORM;
 <script type="text/javascript">  <script type="text/javascript">
Line 9238  ENDHEADER Line 9665  ENDHEADER
     if ($env{'form.upfiletype'} eq 'interwrite') {      if ($env{'form.upfiletype'} eq 'interwrite') {
         ($errormsg,$number)=&interwrite_eval(\@questiontitles,\%responses);          ($errormsg,$number)=&interwrite_eval(\@questiontitles,\%responses);
     }      }
       if ($env{'form.upfiletype'} eq 'turning') {
           ($errormsg,$number)=&turning_eval(\@questiontitles,\%responses);
       }
     $result.='<br />'.&mt('Found [_1] question(s)',$number).'<br />'.      $result.='<br />'.&mt('Found [_1] question(s)',$number).'<br />'.
              '<input type="hidden" name="number" value="'.$number.'" />'.               '<input type="hidden" name="number" value="'.$number.'" />'.
              &mt('Awarding [_1] percent for correct and [_2] percent for incorrect responses',               &mt('Awarding [_1] percent for correct and [_2] percent for incorrect responses',
Line 9369  sub interwrite_eval { Line 9799  sub interwrite_eval {
     return ($errormsg,$number);      return ($errormsg,$number);
 }  }
   
   sub turning_eval {
       my ($questiontitles,$responses)=@_;
       my $number=0;
       my $errormsg='';
       foreach my $line (split(/[\n\r]/,$env{'form.upfile'})) {
           my %components=&Apache::loncommon::record_sep($line);
           my @entries=map {$components{$_}} (sort(keys(%components)));
           if ($#entries>$number) { $number=$#entries; }
           my $id=$entries[0];
           my @idresponses;
           $id=~s/^[\#0]+//;
           unless ($id) { next; }
           for (my $idx=1;$idx<=$#entries;$idx++) {
               $entries[$idx]=~s/\,/\;/g;
               $entries[$idx]=~s/[^a-zA-Z0-9\.\*\-\+\;]+//g;
               push(@idresponses,$entries[$idx]);
           }
           $$responses{$id}=join(',',@idresponses);
       }
       for (my $i=1; $i<=$number; $i++) {
           $$questiontitles[$i]=&mt('Question [_1]',$i);
       }
       return ($errormsg,$number);
   }
   
 sub assign_clicker_grades {  sub assign_clicker_grades {
     my ($r)=@_;      my ($r)=@_;
     my ($symb)=&get_symb($r);      my ($symb)=&get_symb($r);
Line 9510  sub navmap_errormsg { Line 9965  sub navmap_errormsg {
            '</div>';             '</div>';
 }  }
   
   sub startpage {
       my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$js) = @_;
       if ($nomenu) {
           $r->print(&Apache::loncommon::start_page("Student's Version",$js,{'only_body' => '1'}));
       } else {
           $r->print(&Apache::loncommon::start_page('Grading',$js,
                                                    {'bread_crumbs' => $crumbs}));
       }
       unless ($nodisplayflag) {
          $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp));
       }
   }
   
 sub handler {  sub handler {
     my $request=$_[0];      my $request=$_[0];
     &reset_caches();      &reset_caches();
Line 9531  sub handler { Line 9999  sub handler {
     $ssi_error = 0;      $ssi_error = 0;
     my $brcrum = [{href=>"/adm/grades",text=>"Grading"}];      my $brcrum = [{href=>"/adm/grades",text=>"Grading"}];
     my $start_page = &Apache::loncommon::start_page('Grading',undef,      my $start_page = &Apache::loncommon::start_page('Grading',undef,
                                           {'bread_crumbs' => $brcrum});                                                      {'bread_crumbs' => $brcrum});
     if ($symb eq '' && $command eq '') {      if ($symb eq '' && $command eq '') {
  if ($env{'user.adv'}) {   if ($env{'user.adv'}) {
             &Apache::loncommon::content_type($request,'text/html');              &Apache::loncommon::content_type($request,'text/html');
Line 9564  sub handler { Line 10032  sub handler {
             &init_perm();               &init_perm(); 
             if (!%perm) {              if (!%perm) {
                 $request->internal_redirect('/adm/quickgrades');                  $request->internal_redirect('/adm/quickgrades');
                   return OK;
             } else {              } else {
                 &Apache::loncommon::content_type($request,'text/html');                  &Apache::loncommon::content_type($request,'text/html');
                 $request->send_http_header;                  $request->send_http_header;
Line 9584  sub handler { Line 10053  sub handler {
         }          }
         &Apache::loncommon::content_type($request,'text/html');          &Apache::loncommon::content_type($request,'text/html');
         $request->send_http_header;          $request->send_http_header;
         $request->print($start_page);          unless ((($command eq 'submission' || $command eq 'versionsub')) && ($perm{'vgr'})) {
               $request->print($start_page); 
           }
  if ($command eq 'submission' && $perm{'vgr'}) {   if ($command eq 'submission' && $perm{'vgr'}) {
               my ($stuvcurrent,$stuvdisp,$versionform,$js);
               if (($env{'form.student'} ne '') && ($env{'form.userdom'} ne '')) {
                   ($stuvcurrent,$stuvdisp,$versionform,$js) =
                       &choose_task_version_form($symb,$env{'form.student'},
                                                 $env{'form.userdom'});
               }
               &startpage($request,$symb,[{href=>"", text=>"Student Submissions"}],undef,undef,$stuvcurrent,$stuvdisp,undef,$js);
               if ($versionform) {
                   $request->print($versionform);
               }
               $request->print('<br clear="all" />');
     ($env{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0));      ($env{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0));
           } elsif ($command eq 'versionsub' && $perm{'vgr'}) {
               my ($stuvcurrent,$stuvdisp,$versionform,$js) =
                   &choose_task_version_form($symb,$env{'form.student'},
                                             $env{'form.userdom'},
                                             $env{'form.inhibitmenu'});
               &startpage($request,$symb,[{href=>"", text=>"Previous Student Version"}],undef,undef,$stuvcurrent,$stuvdisp,$env{'form.inhibitmenu'},$js);
               if ($versionform) {
                   $request->print($versionform);
               }
               $request->print('<br clear="all" />');
               $request->print(&show_previous_task_version($request,$symb));
  } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {   } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {
     &pickStudentPage($request);      &pickStudentPage($request);
  } elsif ($command eq 'displayPage' && $perm{'vgr'}) {   } elsif ($command eq 'displayPage' && $perm{'vgr'}) {
Line 9766  ssi_with_retries() Line 10259  ssi_with_retries()
        calling routine should trap the error condition and display the warning         calling routine should trap the error condition and display the warning
        found in &navmap_errormsg().         found in &navmap_errormsg().
   
          $scantron_config - Reference to bubblesheet format configuration hash.
   
    Returns the maximum number of bubble lines that are expected to     Returns the maximum number of bubble lines that are expected to
    occur. Does this by walking the selected sequence rendering the     occur. Does this by walking the selected sequence rendering the
    resource and then checking &Apache::lonxml::get_problem_counter()     resource and then checking &Apache::lonxml::get_problem_counter()

Removed from v.1.596.2.12  
changed lines
  Added in v.1.596.2.12.2.13


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