Diff for /loncom/homework/grades.pm between versions 1.596.2.12.2.25 and 1.596.2.12.2.49

version 1.596.2.12.2.25, 2013/12/30 15:31:00 version 1.596.2.12.2.49, 2019/08/17 17:43:43
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::bridgetask();  use Apache::bridgetask();
   use Apache::lontexconvert();
   use HTML::Parser();
   use File::MMagic;
 use String::Similarity;  use String::Similarity;
 use LONCAPA;  use LONCAPA;
   
Line 354  sub reset_caches { Line 357  sub reset_caches {
     }      }
   
     sub scantron_partids_tograde {      sub scantron_partids_tograde {
         my ($resource,$cid,$uname,$udom,$check_for_randomlist,$bubbles_per_row) = @_;          my ($resource,$cid,$uname,$udom,$check_for_randomlist,$bubbles_per_row,$scancode) = @_;
         my (%analysis,@parts);          my (%analysis,@parts);
         if (ref($resource)) {          if (ref($resource)) {
             my $symb = $resource->symb();              my $symb = $resource->symb();
Line 362  sub reset_caches { Line 365  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,};
             }              }
               if ($scancode) {
                   if (ref($add_to_form) eq 'HASH') {
                       $add_to_form->{'code_for_randomlist'} = $scancode;
                   } else {
                       $add_to_form = { 'code_for_randomlist' => $scancode,};
                   }
               }
             my $analyze =              my $analyze =
                 &get_analyze($symb,$uname,$udom,undef,$add_to_form,                  &get_analyze($symb,$uname,$udom,undef,$add_to_form,
                              undef,undef,undef,$bubbles_per_row);                               undef,undef,undef,$bubbles_per_row);
Line 391  sub cleanRecord { Line 401  sub cleanRecord {
     my $grayFont = '<span class="LC_internal_info">';      my $grayFont = '<span class="LC_internal_info">';
     if ($response =~ /^(option|rank)$/) {      if ($response =~ /^(option|rank)$/) {
  my %answer=&Apache::lonnet::str2hash($answer);   my %answer=&Apache::lonnet::str2hash($answer);
           my @answer = %answer;
           %answer = map {&HTML::Entities::encode($_, '"<>&')} @answer;
  my %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"});   my %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"});
  my ($toprow,$bottomrow);   my ($toprow,$bottomrow);
  foreach my $foil (@$order) {   foreach my $foil (@$order) {
Line 407  sub cleanRecord { Line 419  sub cleanRecord {
     $bottomrow.'</tr></table></blockquote>';      $bottomrow.'</tr></table></blockquote>';
     } elsif ($response eq 'match') {      } elsif ($response eq 'match') {
  my %answer=&Apache::lonnet::str2hash($answer);   my %answer=&Apache::lonnet::str2hash($answer);
           my @answer = %answer;
           %answer = map {&HTML::Entities::encode($_, '"<>&')} @answer;
  my %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"});   my %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"});
  my @items=&Apache::lonnet::str2array($record->{$version."resource.$partid.$respid.submissionitems"});   my @items=&Apache::lonnet::str2array($record->{$version."resource.$partid.$respid.submissionitems"});
  my ($toprow,$middlerow,$bottomrow);   my ($toprow,$middlerow,$bottomrow);
Line 461  sub cleanRecord { Line 475  sub cleanRecord {
     $env{'form.kwstyle'}  = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : '';      $env{'form.kwstyle'}  = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : '';
     $env{'form.'.$symb} = 1; # so that we don't have to read it from disk for multiple sub of the same prob.      $env{'form.'.$symb} = 1; # so that we don't have to read it from disk for multiple sub of the same prob.
  }   }
  $answer =~ s-\n-<br />-g;          $answer = &Apache::lontexconvert::msgtexconverted($answer);
  return '<br /><br /><blockquote><tt>'.&keywords_highlight($answer).'</tt></blockquote>';   return '<br /><br /><blockquote><tt>'.&keywords_highlight($answer).'</tt></blockquote>';
     } elsif ( $response eq 'organic') {      } elsif ( $response eq 'organic') {
  my $result='Smile representation: "<tt>'.$answer.'</tt>"';          my $result=&mt('Smile representation: [_1]',
                              '"<tt>'.&HTML::Entities::encode($answer, '"<>&').'</tt>"');
  my $jme=$record->{$version."resource.$partid.$respid.molecule"};   my $jme=$record->{$version."resource.$partid.$respid.molecule"};
  $result.=&Apache::chemresponse::jme_img($jme,$answer,400);   $result.=&Apache::chemresponse::jme_img($jme,$answer,400);
  return $result;   return $result;
Line 498  sub cleanRecord { Line 513  sub cleanRecord {
     $result.='</ul>';      $result.='</ul>';
     return $result;      return $result;
  }   }
     } elsif ( $response =~ m/(?:numerical|formula)/) {      } elsif ( $response =~ m/(?:numerical|formula|custom)/) {
           # 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);
           return $answer;
     }      }
     return $answer;      return &HTML::Entities::encode($answer, '"<>&');
 }  }
   
 #-- A couple of common js functions  #-- A couple of common js functions
Line 908  sub listStudents { Line 925  sub listStudents {
   
     my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($symb,$env{'form.probTitle'},($env{'form.showgrading'} eq 'yes'));      my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($symb,$env{'form.probTitle'},($env{'form.showgrading'} eq 'yes'));
   
     my %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.',
  'single'   => 'Please select the student before clicking on the Next button.',   'single'   => 'Please select the student before clicking on the Next button.',
      );       );
       &js_escape(\%js_lt);
     $request->print(<<LISTJAVASCRIPT);      $request->print(<<LISTJAVASCRIPT);
 <script type="text/javascript" language="javascript">  <script type="text/javascript" language="javascript">
     function checkSelect(checkBox) {      function checkSelect(checkBox) {
Line 923  sub listStudents { Line 941  sub listStudents {
     ctr++;      ctr++;
  }   }
     }      }
     sense = '$lt{'multiple'}';      sense = '$js_lt{'multiple'}';
  } else {   } else {
     if (checkBox.checked) {      if (checkBox.checked) {
  ctr = 1;   ctr = 1;
     }      }
     sense = '$lt{'single'}';      sense = '$js_lt{'single'}';
  }   }
  if (ctr == 0) {   if (ctr == 0) {
     alert(sense);      alert(sense);
Line 1247  sub processGroup { Line 1265  sub processGroup {
 #--- Javascript to handle the submission page functionality ---  #--- Javascript to handle the submission page functionality ---
 sub sub_page_js {  sub sub_page_js {
     my $request = shift;      my $request = shift;
     my $alertmsg = &mt('A number equal or greater than 0 is expected. Entered value = ');      my $alertmsg = &mt('A number equal or greater than 0 is expected. Entered value = ');
       &js_escape(\$alertmsg);
     $request->print(<<SUBJAVASCRIPT);      $request->print(<<SUBJAVASCRIPT);
 <script type="text/javascript" language="javascript">  <script type="text/javascript" language="javascript">
     function updateRadio(formname,id,weight) {      function updateRadio(formname,id,weight) {
Line 1366  sub sub_page_js { Line 1385  sub sub_page_js {
     }      }
  }   }
     }      }
       
  }   }
     }      }
       
  }   }
  if (val == "Grade Student") {   if (val == "Grade Student") {
     formname.showgrading.value = "yes";      formname.showgrading.value = "yes";
Line 1503  INNERJS Line 1520  INNERJS
   
     my $docopen=&Apache::lonhtmlcommon::javascript_docopen();      my $docopen=&Apache::lonhtmlcommon::javascript_docopen();
     $docopen=~s/^document\.//;      $docopen=~s/^document\.//;
     my %lt = &Apache::lonlocal::texthash(      my %js_lt = &Apache::lonlocal::texthash(
                 keyw => 'Keywords list, separated by a space. Add/delete to list if desired.',                  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.',                  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.',                  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(
                 comp => 'Compose Message for: ',                  comp => 'Compose Message for: ',
                 incl => 'Include',                  incl => 'Include',
                 type => 'Type',                  type => 'Type',
Line 1520  INNERJS Line 1548  INNERJS
                 font => 'Font Size',                  font => 'Font Size',
                 fnst => 'Font Style',                  fnst => 'Font Style',
              );               );
       &js_escape(\%js_lt);
       &html_escape(\%html_js_lt);
       &js_escape(\%html_js_lt);
     $request->print(<<SUBJAVASCRIPT);      $request->print(<<SUBJAVASCRIPT);
 <script type="text/javascript" language="javascript">  <script type="text/javascript" language="javascript">
   
 //===================== Show list of keywords ====================  //===================== Show list of keywords ====================
   function keywords(formname) {    function keywords(formname) {
     var nret = prompt("$lt{'keyw'}",formname.keywords.value);      var nret = prompt("$js_lt{'keyw'}",formname.keywords.value);
     if (nret==null) return;      if (nret==null) return;
     formname.keywords.value = nret;      formname.keywords.value = nret;
   
Line 1552  INNERJS Line 1583  INNERJS
     else return;      else return;
     var cleantxt = txt.replace(new RegExp('([\\f\\n\\r\\t\\v ])+', 'g')," ");      var cleantxt = txt.replace(new RegExp('([\\f\\n\\r\\t\\v ])+', 'g')," ");
     if (cleantxt=="") {      if (cleantxt=="") {
  alert("$lt{'plse'}");   alert("$js_lt{'plse'}");
  return;   return;
     }      }
     var nret = prompt("$lt{'adds'}",cleantxt);      var nret = prompt("$js_lt{'adds'}",cleantxt);
     if (nret==null) return;      if (nret==null) return;
     document.SCORE.keywords.value = document.SCORE.keywords.value+" "+nret;      document.SCORE.keywords.value = document.SCORE.keywords.value+" "+nret;
     if (document.SCORE.keywords.value != "") {      if (document.SCORE.keywords.value != "") {
Line 1635  INNERJS Line 1666  INNERJS
   
     pDoc.write("<form action=\\"inactive\\" name=\\"msgcenter\\">");      pDoc.write("<form action=\\"inactive\\" name=\\"msgcenter\\">");
     pDoc.write("<input value=\\""+usrctr+"\\" name=\\"usrctr\\" type=\\"hidden\\">");      pDoc.write("<input value=\\""+usrctr+"\\" name=\\"usrctr\\" type=\\"hidden\\">");
     pDoc.write("<h3><span class=\\"LC_info\\">&nbsp;$lt{'comp'}\"+fullname+\"<\\/span><\\/h3><br /><br />");      pDoc.write("<h3><span class=\\"LC_info\\">&nbsp;$html_js_lt{'comp'}\"+fullname+\"<\\/span><\\/h3><br /><br />");
   
     pDoc.write('<table border="0" width="100%"><tr><td bgcolor="#777777">');      pDoc.write('<table border="0" width="100%"><tr><td bgcolor="#777777">');
     pDoc.write('<table border="0" width="100%"><tr bgcolor="#DDFFFF">');      pDoc.write('<table border="0" width="100%"><tr bgcolor="#DDFFFF">');
     pDoc.write("<td><b>$lt{'type'}<\\/b><\\/td><td><b>$lt{'incl'}<\\/b><\\/td><td><b>$lt{'mesa'}<\\/td><\\/tr>");      pDoc.write("<td><b>$html_js_lt{'type'}<\\/b><\\/td><td><b>$html_js_lt{'incl'}<\\/b><\\/td><td><b>$html_js_lt{'mesa'}<\\/td><\\/tr>");
 }  }
     function displaySubject(msg,shwsel) {      function displaySubject(msg,shwsel) {
     pDoc = pWin.document;      pDoc = pWin.document;
     pDoc.write("<tr bgcolor=\\"#ffffdd\\">");      pDoc.write("<tr bgcolor=\\"#ffffdd\\">");
     pDoc.write("<td>$lt{'subj'}<\\/td>");      pDoc.write("<td>$html_js_lt{'subj'}<\\/td>");
     pDoc.write("<td align=\\"center\\"><input name=\\"subchk\\" type=\\"checkbox\\"" +shwsel+"><\\/td>");      pDoc.write("<td align=\\"center\\"><input name=\\"subchk\\" type=\\"checkbox\\"" +shwsel+"><\\/td>");
     pDoc.write("<td><input name=\\"msgsub\\" type=\\"text\\" value=\\""+msg+"\\"size=\\"60\\" maxlength=\\"80\\"><\\/td><\\/tr>");      pDoc.write("<td><input name=\\"msgsub\\" type=\\"text\\" value=\\""+msg+"\\"size=\\"60\\" maxlength=\\"80\\"><\\/td><\\/tr>");
 }  }
Line 1660  INNERJS Line 1691  INNERJS
   function newMsg(newmsg,shwsel) {    function newMsg(newmsg,shwsel) {
     pDoc = pWin.document;      pDoc = pWin.document;
     pDoc.write("<tr bgcolor=\\"#ffffdd\\">");      pDoc.write("<tr bgcolor=\\"#ffffdd\\">");
     pDoc.write("<td align=\\"center\\">$lt{'new'}<\\/td>");      pDoc.write("<td align=\\"center\\">$html_js_lt{'new'}<\\/td>");
     pDoc.write("<td align=\\"center\\"><input name=\\"newmsgchk\\" type=\\"checkbox\\"" +shwsel+"><\\/td>");      pDoc.write("<td align=\\"center\\"><input name=\\"newmsgchk\\" type=\\"checkbox\\"" +shwsel+"><\\/td>");
     pDoc.write("<td><textarea name=\\"newmsg\\" cols=\\"60\\" rows=\\"3\\" onchange=\\"javascript:this.form.newmsgchk.checked=true\\" >"+newmsg+"<\\/textarea><\\/td><\\/tr>");      pDoc.write("<td><textarea name=\\"newmsg\\" cols=\\"60\\" rows=\\"3\\" onchange=\\"javascript:this.form.newmsgchk.checked=true\\" >"+newmsg+"<\\/textarea><\\/td><\\/tr>");
 }  }
Line 1669  INNERJS Line 1700  INNERJS
     pDoc = pWin.document;      pDoc = pWin.document;
     pDoc.write("<\\/table>");      pDoc.write("<\\/table>");
     pDoc.write("<\\/td><\\/tr><\\/table>&nbsp;");      pDoc.write("<\\/td><\\/tr><\\/table>&nbsp;");
     pDoc.write("<input type=\\"button\\" value=\\"$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=\\"$lt{'canc'}\\" onclick=\\"self.close()\\"><br /><br />");      pDoc.write("<input type=\\"button\\" value=\\"$html_js_lt{'canc'}\\" onclick=\\"self.close()\\"><br /><br />");
     pDoc.write("<\\/form>");      pDoc.write("<\\/form>");
     pDoc.write('$end_page_msg_central');      pDoc.write('$end_page_msg_central');
     pDoc.close();      pDoc.close();
Line 1684  INNERJS Line 1715  INNERJS
     var redsel = "";      var redsel = "";
     var grnsel = "";      var grnsel = "";
     var blusel = "";      var blusel = "";
     if (kwclr=="red")   {var redsel="checked"};      var txtcol1 = "$js_lt{'col1'}";
     if (kwclr=="green") {var grnsel="checked"};      var txtcol2 = "$js_lt{'col2'}";
     if (kwclr=="blue")  {var blusel="checked"};      var txtcol3 = "$js_lt{'col3'}";
       var txtsiz1 = "$js_lt{'siz1'}";
       var txtsiz2 = "$js_lt{'siz2'}";
       var txtsiz3 = "$js_lt{'siz3'}";
       var txtsty1 = "$js_lt{'sty1'}";
       var txtsty2 = "$js_lt{'sty2'}";
       var txtsty3 = "$js_lt{'sty3'}";
       if (kwclr=="red")   {var redsel="checked='checked'"};
       if (kwclr=="green") {var grnsel="checked='checked'"};
       if (kwclr=="blue")  {var blusel="checked='checked'"};
     var sznsel = "";      var sznsel = "";
     var sz1sel = "";      var sz1sel = "";
     var sz2sel = "";      var sz2sel = "";
     if (kwsize=="0")  {var sznsel="checked"};      if (kwsize=="0")  {var sznsel="checked='checked'"};
     if (kwsize=="+1") {var sz1sel="checked"};      if (kwsize=="+1") {var sz1sel="checked='checked'"};
     if (kwsize=="+2") {var sz2sel="checked"};      if (kwsize=="+2") {var sz2sel="checked='checked'"};
     var synsel = "";      var synsel = "";
     var syisel = "";      var syisel = "";
     var sybsel = "";      var sybsel = "";
     if (kwstyle=="")    {var synsel="checked"};      if (kwstyle=="")    {var synsel="checked='checked'"};
     if (kwstyle=="<i>") {var syisel="checked"};      if (kwstyle=="<i>") {var syisel="checked='checked'"};
     if (kwstyle=="<b>") {var sybsel="checked"};      if (kwstyle=="<b>") {var sybsel="checked='checked'"};
     highlightCentral();      highlightCentral();
     highlightbody('red','red',redsel,'0','normal',sznsel,'','normal',synsel);      highlightbody('red',txtcol1,redsel,'0',txtsiz1,sznsel,'',txtsty1,synsel);
     highlightbody('green','green',grnsel,'+1','+1',sz1sel,'<i>','italic',syisel);      highlightbody('green',txtcol2,grnsel,'+1',txtsiz2,sz1sel,'<i>',txtsty2,syisel);
     highlightbody('blue','blue',blusel,'+2','+2',sz2sel,'<b>','bold',sybsel);      highlightbody('blue',txtcol3,blusel,'+2',txtsiz3,sz2sel,'<b>',txtsty3,sybsel);
     highlightend();      highlightend();
     return;      return;
   }    }
Line 1720  INNERJS Line 1760  INNERJS
     hDoc.$docopen;      hDoc.$docopen;
     hDoc.write('$start_page_highlight_central');      hDoc.write('$start_page_highlight_central');
     hDoc.write("<form action=\\"inactive\\" name=\\"hlCenter\\">");      hDoc.write("<form action=\\"inactive\\" name=\\"hlCenter\\">");
     hDoc.write("<h3><span class=\\"LC_info\\">&nbsp;$lt{'kehi'}<\\/span><\\/h3><br /><br />");      hDoc.write("<h1>$html_js_lt{'kehi'}<\\/h1>");
   
     hDoc.write('<table border="0" width="100%"><tr><td bgcolor="#777777">');      hDoc.write('<table border="0" width="100%"><tr style="background-color:#A1D676">');
     hDoc.write('<table border="0" width="100%"><tr bgcolor="#DDFFFF">');      hDoc.write("<th>$html_js_lt{'txtc'}<\\/th><th>$html_js_lt{'font'}<\\/th><th>$html_js_lt{'fnst'}<\\/th><\\/tr>");
     hDoc.write("<td><b>$lt{'txtc'}<\\/b><\\/td><td><b>$lt{'font'}<\\/b><\\/td><td><b>$lt{'fnst'}<\\/td><\\/tr>");  
   }    }
   
   function highlightbody(clrval,clrtxt,clrsel,szval,sztxt,szsel,syval,sytxt,sysel) {     function highlightbody(clrval,clrtxt,clrsel,szval,sztxt,szsel,syval,sytxt,sysel) { 
     var hDoc = hwdWin.document;      var hDoc = hwdWin.document;
     hDoc.write("<tr bgcolor=\\"#ffffdd\\">");      hDoc.write("<tr>");
     hDoc.write("<td align=\\"left\\">");      hDoc.write("<td align=\\"left\\">");
     hDoc.write("<input name=\\"kwdclr\\" type=\\"radio\\" value=\\""+clrval+"\\" "+clrsel+">&nbsp;"+clrtxt+"<\\/td>");      hDoc.write("<input name=\\"kwdclr\\" type=\\"radio\\" value=\\""+clrval+"\\" "+clrsel+" \\/>&nbsp;"+clrtxt+"<\\/td>");
     hDoc.write("<td align=\\"left\\">");      hDoc.write("<td align=\\"left\\">");
     hDoc.write("<input name=\\"kwdsize\\" type=\\"radio\\" value=\\""+szval+"\\" "+szsel+">&nbsp;"+sztxt+"<\\/td>");      hDoc.write("<input name=\\"kwdsize\\" type=\\"radio\\" value=\\""+szval+"\\" "+szsel+" \\/>&nbsp;"+sztxt+"<\\/td>");
     hDoc.write("<td align=\\"left\\">");      hDoc.write("<td align=\\"left\\">");
     hDoc.write("<input name=\\"kwdstyle\\" type=\\"radio\\" value=\\""+syval+"\\" "+sysel+">&nbsp;"+sytxt+"<\\/td>");      hDoc.write("<input name=\\"kwdstyle\\" type=\\"radio\\" value=\\""+syval+"\\" "+sysel+" \\/>&nbsp;"+sytxt+"<\\/td>");
     hDoc.write("<\\/tr>");      hDoc.write("<\\/tr>");
   }    }
   
   function highlightend() {     function highlightend() { 
     var hDoc = hwdWin.document;      var hDoc = hwdWin.document;
     hDoc.write("<\\/table>");      hDoc.write("<\\/table><br \\/>");
     hDoc.write("<\\/td><\\/tr><\\/table>&nbsp;");      hDoc.write("<input type=\\"button\\" value=\\"$html_js_lt{'save'}\\" onclick=\\"javascript:updateChoice(1)\\" \\/>&nbsp;&nbsp;");
     hDoc.write("<input type=\\"button\\" value=\\"$lt{'save'}\\" onclick=\\"javascript:updateChoice(1)\\">&nbsp;&nbsp;");      hDoc.write("<input type=\\"button\\" value=\\"$html_js_lt{'canc'}\\" onclick=\\"self.close()\\" \\/><br /><br />");
     hDoc.write("<input type=\\"button\\" value=\\"$lt{'canc'}\\" onclick=\\"self.close()\\"><br /><br />");  
     hDoc.write("<\\/form>");      hDoc.write("<\\/form>");
     hDoc.write('$end_page_highlight_central');      hDoc.write('$end_page_highlight_central');
     hDoc.close();      hDoc.close();
Line 2017  sub submission { Line 2055  sub submission {
     $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 ''; }
       my ($essayurl,%coursedesc_by_cid);
   
     if (!&canview($usec)) {      if (!&canview($usec)) {
  $request->print('<span class="LC_warning">Unable to view requested student.('.          $request->print(
  $uname.':'.$udom.' in section '.$usec.' in course id '.              '<span class="LC_warning">'.
  $env{'request.course.id'}.')</span>');              &mt('Unable to view requested student.').
               ' '.&mt('([_1] in section [_2] in course id [_3])',
                           $uname.':'.$udom,$usec,$env{'request.course.id'}).
               '</span>');
  $request->print(&show_grading_menu_form($symb));   $request->print(&show_grading_menu_form($symb));
  return;   return;
     }      }
Line 2127  sub submission { Line 2169  sub submission {
  if ($env{'form.handgrade'} eq 'yes' && $env{'form.showgrading'} eq 'yes') {   if ($env{'form.handgrade'} eq 'yes' && $env{'form.showgrading'} eq 'yes') {
   
             my %lt = &Apache::lonlocal::texthash(              my %lt = &Apache::lonlocal::texthash(
                             keyh => 'Keyword Highlighting for Essays',
                           keyw => 'Keyword Options',                            keyw => 'Keyword Options',
                           list => 'List',                            list => 'List',
                           past => 'Paste Selection to List',                            past => 'Paste Selection to List',
Line 2135  sub submission { Line 2178  sub submission {
 #  #
 # Print out the keyword options line  # Print out the keyword options line
 #  #
     $request->print(<<KEYWORDS);              $request->print(
 &nbsp;<b>$lt{'keyw'}:</b>&nbsp;                  '<div class="LC_columnSection">'
 <a href="javascript:keywords(document.SCORE);" target="_self">$lt{'list'}</a>&nbsp; &nbsp;                 .'<fieldset><legend>'.$lt{'keyh'}.'</legend>'
 <a href="#" onmousedown="javascript:getSel(); return false"                 .&Apache::lonhtmlcommon::funclist_from_array(
  class="page">$lt{'past'}</a>&nbsp; &nbsp;                      ['<a href="javascript:keywords(document.SCORE);" target="_self">'.$lt{'list'}.'</a>',
 <a href="javascript:kwhighlight();" target="_self">$lt{'high'}</a><br /><br />                       '<a href="#" onmousedown="javascript:getSel(); return false"
 KEYWORDS   class="page">'.$lt{'past'}.'</a>',
                        '<a href="javascript:kwhighlight();" target="_self">'.$lt{'high'}.'</a>'],
                       {legend => $lt{'keyw'}})
                  .'</fieldset></div>'
               );
   
 #  #
 # Load the other essays for similarity check  # Load the other essays for similarity check
 #  #
             my (undef,undef,$essayurl) = &Apache::lonnet::decode_symb($symb);              (undef,undef,$essayurl) = &Apache::lonnet::decode_symb($symb);
     my ($adom,$aname,$apath)=($essayurl=~/^($LONCAPA::domain_re)\/($LONCAPA::username_re)\/(.*)$/);              if ($essayurl eq 'lib/templates/simpleproblem.problem') {
     $apath=&escape($apath);                  my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
     $apath=~s/\W/\_/gs;                  my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
             &init_old_essays($symb,$apath,$adom,$aname);                  if ($cdom ne '' && $cnum ne '') {
                       my ($map,$id,$res) = &Apache::lonnet::decode_symb($symb);
                       if ($map =~ m{^\Quploaded/$cdom/$cnum/\E(default(?:|_\d+)\.(?:sequence|page))$}) {
                           my $apath = $1.'_'.$id;
                           $apath=~s/\W/\_/gs;
                           &init_old_essays($symb,$apath,$cdom,$cnum);
                       }
                   }
               } else {
           my ($adom,$aname,$apath)=($essayurl=~/^($LONCAPA::domain_re)\/($LONCAPA::username_re)\/(.*)$/);
           $apath=&escape($apath);
           $apath=~s/\W/\_/gs;
                   &init_old_essays($symb,$apath,$adom,$aname);
               }
         }          }
     }      }
   
Line 2276  KEYWORDS Line 2337  KEYWORDS
  foreach my $submission (@$string) {   foreach my $submission (@$string) {
     my ($partid,$respid) = ($submission =~ /^resource\.([^\.]*)\.([^\.]*)\.submission/);      my ($partid,$respid) = ($submission =~ /^resource\.([^\.]*)\.([^\.]*)\.submission/);
     if (join('_',@{$part}) ne ($partid.'_'.$respid)) { next; }      if (join('_',@{$part}) ne ($partid.'_'.$respid)) { next; }
     my ($ressub,$hide,$subval) = split(/:/,$submission,3);      my ($ressub,$hide,$draft,$subval) = split(/:/,$submission,4);
     # Similarity check      # Similarity check
     my $similar='';      my $similar='';
                     my ($type,$trial,$rndseed);                      my ($type,$trial,$rndseed);
Line 2290  KEYWORDS Line 2351  KEYWORDS
     &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);
     my %old_course_desc =   
  &Apache::lonnet::coursedescription($ocrsid,  
    {'one_time' => 1});  
   
                             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 />';
                             } else {                              } else {
         $similar="<hr /><h3><span class=\"LC_warning\">".          $similar='<hr />';
     &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',                                  if ($essayurl eq 'lib/templates/simpleproblem.problem') {
         $osim,                                      $similar .= '<h3><span class="LC_warning">'.
         &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',                                                  &mt('Essay is [_1]% similar to an essay by [_2]',
         $old_course_desc{'description'},                                                      $osim,
         $old_course_desc{'num'},                                                      &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').
         $old_course_desc{'domain'}).                                                  '</span></h3>';
     '</span></h3><blockquote><i>'.                                  } elsif ($ocrsid ne '') {
     &keywords_highlight($oessay).                                      my %old_course_desc;
     '</i></blockquote><hr />';                                      if (ref($coursedesc_by_cid{$ocrsid}) eq 'HASH') {
                             }                                          %old_course_desc = %{$coursedesc_by_cid{$ocrsid}};
  }                                      } else {
     }                                          my $args;
                                           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;
                                       }
                                       $similar .=
           &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>'.
                                               &keywords_highlight($oessay).
                                               '</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' || $env{'form.lastSub'} eq 'datesub' || $env{'form.lastSub'} =~ /^(last|all)$/ || ($env{'form.lastSub'} eq 'hdgrade' &&                      if ($env{'form.lastSub'} eq 'lastonly' || $env{'form.lastSub'} eq 'datesub' || $env{'form.lastSub'} =~ /^(last|all)$/ || ($env{'form.lastSub'} eq 'hdgrade' &&
Line 2345  KEYWORDS Line 2431  KEYWORDS
                         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) {
                                   $lastsubonly.= ' <span class="LC_warning">'.&mt('Draft Copy').'</span>';
                               }
                               $subval =
         &cleanRecord($subval,$responsetype,$symb,$partid,          &cleanRecord($subval,$responsetype,$symb,$partid,
      $respid,\%record,$order,undef,$uname,$udom,$type,$trial,$rndseed);       $respid,\%record,$order,undef,$uname,$udom,$type,$trial,$rndseed);
                               if ($responsetype eq 'essay') {
                                   $subval =~ s{\n}{<br />}g;
                               }
                               $lastsubonly.=$subval."\n";
                         }                          }
  if ($similar) {$lastsubonly.="<br /><br />$similar\n";}   if ($similar) {$lastsubonly.="<br /><br />$similar\n";}
  $lastsubonly.='</div>';   $lastsubonly.='</div>';
Line 2362  KEYWORDS Line 2456  KEYWORDS
  $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 : '');
  $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',
                                                                    $usec,$identifier));
     }      }
   
     $request->print('<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':'      $request->print('<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':'
Line 2593  sub get_last_submission { Line 2689  sub get_last_submission {
             }              }
             unless ($hide) {              unless ($hide) {
                 if (@randomize) {                  if (@randomize) {
                     foreach my $id (@hidden) {                      foreach my $id (@randomize) {
                         if ($key =~ /^\Q$id\E/) {                          if ($key =~ /^\Q$id\E/) {
                             $hide = 'rand';                              $hide = 'rand';
                             last;                              last;
Line 2602  sub get_last_submission { Line 2698  sub get_last_submission {
                 }                  }
             }              }
     my ($partid,$foo) = split(/submission$/,$key);      my ($partid,$foo) = split(/submission$/,$key);
     my $draft  = $lasthash{$partid.'awarddetail'} eq 'DRAFT' ?      my $draft  = $lasthash{$partid.'awarddetail'} eq 'DRAFT' ? 1: 0;
  '<span class="LC_warning">Draft Copy</span> ' : '';              push(@string, join(':', $key, $hide, $draft, (
     push(@string, join(':', $key, $hide, $draft.$lasthash{$key}));                  ref($lasthash{$key}) eq 'ARRAY' ?
                       join(',', @{$lasthash{$key}}) : $lasthash{$key}) ));
  }   }
     }      }
     if (!@string) {      if (!@string) {
Line 2632  sub keywords_highlight { Line 2729  sub keywords_highlight {
 sub show_previous_task_version {  sub show_previous_task_version {
     my ($request,$symb) = @_;      my ($request,$symb) = @_;
     if ($symb eq '') {      if ($symb eq '') {
         $request->print("Unable to handle ambiguous references.");          $request->print(
               '<span class="LC_error">'.
               &mt('Unable to handle ambiguous references.').
               '</span>');
         return '';          return '';
     }      }
     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">Unable to view previous version for requested student.('.          $request->print('<span class="LC_warning">'.
                         $uname.':'.$udom.' in section '.$usec.' in course id '.                          &mt('Unable to view previous version for requested student.').
                         $env{'request.course.id'}.')</span>');                          ' '.&mt('([_1] in section [_2] in course id [_3])',
                                   $uname.':'.$udom,$usec,$env{'request.course.id'}).
                           '</span>');
         return;          return;
     }      }
     my $mode = 'both';      my $mode = 'both';
Line 2819  sub processHandGrade { Line 2920  sub processHandGrade {
  my $ctr = 0;   my $ctr = 0;
  while ($ctr < $ngrade) {   while ($ctr < $ngrade) {
     my ($uname,$udom) = split(/:/,$env{'form.unamedom'.$ctr});      my ($uname,$udom) = split(/:/,$env{'form.unamedom'.$ctr});
     my ($errorflag,$pts,$wgt) = &saveHandGrade($request,$symb,$uname,$udom,$ctr);      my ($errorflag,$pts,$wgt,$numhidden) = 
                   &saveHandGrade($request,$symb,$uname,$udom,$ctr);
     if ($errorflag eq 'no_score') {      if ($errorflag eq 'no_score') {
  $ctr++;   $ctr++;
  next;   next;
     }      }
     if ($errorflag eq 'not_allowed') {      if ($errorflag eq 'not_allowed') {
  $request->print("<span class=\"LC_warning\">Not allowed to modify grades for $uname:$udom</span>");                  $request->print(
                       '<span class="LC_error">'
                      .&mt('Not allowed to modify grades for [_1]',"$uname:$udom")
                      .'</span>');
  $ctr++;   $ctr++;
  next;   next;
     }      }
               if ($numhidden) {
                   $request->print(
                       '<span class="LC_info">'
                      .&mt('For [_1]: [quant,_2,transaction] hidden',"$uname:$udom",$numhidden)
                      .'</span><br />');
               }
     my $includemsg = $env{'form.includemsg'.$ctr};      my $includemsg = $env{'form.includemsg'.$ctr};
     my ($subject,$message,$msgstatus) = ('','','');      my ($subject,$message,$msgstatus) = ('','','');
     my $restitle = &Apache::lonnet::gettitle($symb);      my $restitle = &Apache::lonnet::gettitle($symb);
Line 3060  sub saveHandGrade { Line 3171  sub saveHandGrade {
     my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$domain,$stuname);      my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$domain,$stuname);
     my @parts_graded;      my @parts_graded;
     my %newrecord  = ();      my %newrecord  = ();
     my ($pts,$wgt) = ('','');      my ($pts,$wgt,$totchg) = ('','',0);
     my %aggregate = ();      my %aggregate = ();
     my $aggregateflag = 0;      my $aggregateflag = 0;
       if ($env{'form.HIDE'.$newflg}) {
           my ($version,$parts) = split(/:/,$env{'form.HIDE'.$newflg},2);
           my $numchgs = &makehidden($version,$parts,\%record,$symb,$domain,$stuname,1);
           $totchg += $numchgs;
       }
     my @parts = split(/:/,$env{'form.partlist'.$newflg});      my @parts = split(/:/,$env{'form.partlist'.$newflg});
     foreach my $new_part (@parts) {      foreach my $new_part (@parts) {
  #collaborator ($submi may vary for different parts   #collaborator ($submi may vary for different parts
Line 3165  sub saveHandGrade { Line 3281  sub saveHandGrade {
         &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate,          &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate,
       $cdom,$cnum);        $cdom,$cnum);
     }      }
     return ('',$pts,$wgt);      return ('',$pts,$wgt,$totchg);
   }
   
   sub makehidden {
       my ($version,$parts,$record,$symb,$domain,$stuname,$tolog) = @_;
       return unless (ref($record) eq 'HASH');
       my %modified;
       my $numchanged = 0;
       if (exists($record->{$version.':keys'})) {
           my $partsregexp = $parts;
           $partsregexp =~ s/,/|/g;
           foreach my $key (split(/\:/,$record->{$version.':keys'})) {
               if ($key =~ /^resource\.(?:$partsregexp)\.([^\.]+)$/) {
                    my $item = $1;
                    unless (($item eq 'solved') || ($item =~ /^award(|msg|ed)$/)) {
                        $modified{$key} = $record->{$version.':'.$key};
                    }
               } elsif ($key =~ m{^(resource\.(?:$partsregexp)\.[^\.]+\.)(.+)$}) {
                   $modified{$1.'hidden'.$2} = $record->{$version.':'.$key};
               } elsif ($key =~ /^(ip|timestamp|host)$/) {
                   $modified{$key} = $record->{$version.':'.$key};
               }
           }
           if (keys(%modified)) {
               if (&Apache::lonnet::putstore($env{'request.course.id'},$symb,$version,\%modified,
                                             $domain,$stuname,$tolog) eq 'ok') {
                   $numchanged ++;
               }
           }
       }
       return $numchanged;
 }  }
   
 sub check_and_remove_from_queue {  sub check_and_remove_from_queue {
Line 3462  sub viewgrades_js { Line 3608  sub viewgrades_js {
     my ($request) = shift;      my ($request) = shift;
   
     my $alertmsg = &mt('A number equal or greater than 0 is expected. Entered value = ');      my $alertmsg = &mt('A number equal or greater than 0 is expected. Entered value = ');
       &js_escape(\$alertmsg);
     $request->print(<<VIEWJAVASCRIPT);      $request->print(<<VIEWJAVASCRIPT);
 <script type="text/javascript" language="javascript">  <script type="text/javascript" language="javascript">
    function writePoint(partid,weight,point) {     function writePoint(partid,weight,point) {
Line 3657  sub viewgrades { Line 3804  sub viewgrades {
  '<input type="hidden" name="Status" value="'.$env{'stu_status'}.'" />'."\n".   '<input type="hidden" name="Status" value="'.$env{'stu_status'}.'" />'."\n".
  '<input type="hidden" name="probTitle" value="'.$env{'form.probTitle'}.'" />'."\n";   '<input type="hidden" name="probTitle" value="'.$env{'form.probTitle'}.'" />'."\n";
   
     my ($common_header,$specific_header);      #retrieve selected groups
     if ($env{'form.section'} eq 'all') {      my (@groups,$group_display);
  $common_header = &mt('Assign Common Grade to Class');      @groups = &Apache::loncommon::get_env_multiple('form.group');
         $specific_header = &mt('Assign Grade to Specific Students in Class');      if (grep(/^all$/,@groups)) {
     } elsif ($env{'form.section'} eq 'none') {          @groups = ('all');
         $common_header = &mt('Assign Common Grade to Students in no Section');      } elsif (grep(/^none$/,@groups)) {
  $specific_header = &mt('Assign Grade to Specific Students in no Section');          @groups = ('none');
     } else {      } elsif (@groups > 0) {
         my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));          $group_display = join(', ',@groups);
         $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);  
       my ($common_header,$specific_header,@sections,$section_display);
       @sections = &Apache::loncommon::get_env_multiple('form.section');
       if (grep(/^all$/,@sections)) {
           @sections = ('all');
           if ($group_display) {
               $common_header = &mt('Assign Common Grade to Students in Group(s) [_1]',$group_display);
               $specific_header = &mt('Assign Grade to Specific Students in Group(s) [_1]',$group_display);
           } elsif (grep(/^none$/,@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');
           } else {
               $common_header = &mt('Assign Common Grade to Class');
               $specific_header = &mt('Assign Grade to Specific Students in Class');
           }
       } elsif (grep(/^none$/,@sections)) {
           @sections = ('none');
           if ($group_display) {
               $common_header = &mt('Assign Common Grade to Students in no Section and in Group(s) [_1]',$group_display);
               $specific_header = &mt('Assign Grade to Specific Students in no Section and in Group(s)',$group_display);
           } elsif (grep(/^none$/,@groups)) {
               $common_header = &mt('Assign Common Grade to Students in no Section and in no Group');
               $specific_header = &mt('Assign Grade to Specific Students in no Section and in no Group');
           } else {
               $common_header = &mt('Assign Common Grade to Students in no Section');
               $specific_header = &mt('Assign Grade to Specific Students in no Section');
           }
       } else {
           $section_display = join (", ",@sections);
           if ($group_display) {
               $common_header = &mt('Assign Common Grade to Students in Section(s) [_1], and in Group(s) [_2]',
                                    $section_display,$group_display);
               $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1], and in Group(s) [_2]',
                                      $section_display,$group_display);
           } elsif (grep(/^none$/,@groups)) {
               $common_header = &mt('Assign Common Grade to 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 {
               $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);
           }
     }      }
     $result.= '<h3>'.$common_header.'</h3>'.&Apache::loncommon::start_data_table();      my %submit_types = &substatus_options();
       my $submission_status = $submit_types{$env{'form.submitonly'}};
   
       if ($env{'form.submitonly'} eq 'all') {
           $result.= '<h3>'.$common_header.'</h3>';
       } else {
           $result.= '<h3>'.$common_header.'&nbsp;'.&mt('(submission status: "[_1]")',$submission_status).'</h3>'; 
       }
       $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.
     #handles different parts of a problem      #handles different parts of a problem
     my $res_error;      my $res_error;
Line 3732  sub viewgrades { Line 3927  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
     $result.= '<h3>'.$specific_header.'</h3>'.      if ($env{'form.submitonly'} eq 'all') { 
               &Apache::loncommon::start_data_table().          $result.= '<h3>'.$specific_header.'</h3>';
       } else {
           $result.= '<h3>'.$specific_header.'&nbsp;'.&mt('(submission status: "[_1]")',$submission_status).'</h3>';
       }
       $result.= &Apache::loncommon::start_data_table().
       &Apache::loncommon::start_data_table_header_row().        &Apache::loncommon::start_data_table_header_row().
       '<th>'.&mt('No.').'</th>'.        '<th>'.&mt('No.').'</th>'.
       '<th>'.&nameUserString('header')."</th>\n";        '<th>'.&nameUserString('header')."</th>\n";
Line 3776  sub viewgrades { Line 3975  sub viewgrades {
   
     #get info for each student      #get info for each student
     #list all the students - with points and grade status      #list all the students - with points and grade status
     my (undef,undef,$fullname) = &getclasslist($env{'form.section'},'1');      my (undef,undef,$fullname) = &getclasslist(\@sections,'1',\@groups);
     my $ctr = 0;      my $ctr = 0;
     foreach (sort       foreach (sort 
      {       {
Line 3785  sub viewgrades { Line 3984  sub viewgrades {
  }   }
  return $a cmp $b;   return $a cmp $b;
      } (keys(%$fullname))) {       } (keys(%$fullname))) {
  $ctr++;  
  $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);
     }      }
     $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').'" '.      $result.='<input type="button" value="'.&mt('Save').'" '.
  'onclick="javascript:submit();" target="_self" /></form>'."\n";   'onclick="javascript:submit();" target="_self" /></form>'."\n";
     if (scalar(%$fullname) eq 0) {      if ($ctr == 0) {
  my $colspan=3+scalar(@parts);  
  my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));  
         my $stu_status = join(' or ',&Apache::loncommon::get_env_multiple('form.Status'));          my $stu_status = join(' or ',&Apache::loncommon::get_env_multiple('form.Status'));
  $result='<span class="LC_warning">'.          $result='<h3><span class="LC_info">'.&mt('Manual Grading').'</span></h3>'.
     &mt('There are no students in section(s) [_1] with enrollment status [_2] to modify or grade.',                  '<span class="LC_warning">';
         $section_display, $stu_status).          if ($env{'form.submitonly'} eq 'all') {
     '</span>';              if (grep(/^all$/,@sections)) {
                   if (grep(/^all$/,@groups)) {
                       $result .= &mt('There are no students with enrollment status [_1] to modify or grade.',
                                      $stu_status);
                   } elsif (grep(/^none$/,@groups)) {
                       $result .= &mt('There are no students with no group assigned and with enrollment status [_1] to modify or grade.',
                                      $stu_status);
                   } else {
                       $result .= &mt('There are no students in group(s) [_1] with enrollment status [_2] to modify or grade.',
                                      $group_display,$stu_status);
                   }
               } elsif (grep(/^none$/,@sections)) {
                   if (grep(/^all$/,@groups)) {
                       $result .= &mt('There are no students in no section with enrollment status [_1] to modify or grade.',
                                      $stu_status);
                   } elsif (grep(/^none$/,@groups)) {
                       $result .= &mt('There are no students in no section and no group with enrollment status [_1] to modify or grade.',
                                      $stu_status);
                   } else {
                       $result .= &mt('There are no students in no section in group(s) [_1] with enrollment status [_2] to modify or grade.',
                                      $group_display,$stu_status);
                   }
               } else {
                   if (grep(/^all$/,@groups)) {
                       $result .= &mt('There are no students in section(s) [_1] with enrollment status [_2] to modify or grade.',
                                      $section_display,$stu_status);
                   } elsif (grep(/^none$/,@groups)) {
                       $result .= &mt('There are no students in section(s) [_1] and no group with enrollment status [_2] to modify or grade.',
                                      $section_display,$stu_status);
                   } else {
                       $result .= &mt('There are no students in section(s) [_1] and group(s) [_2] with enrollment status [_3] to modify or grade.',
                                      $section_display,$group_display,$stu_status);
                   }
               }
           } else {
               if (grep(/^all$/,@sections)) {
                   if (grep(/^all$/,@groups)) {
                       $result .= &mt('There are no students with enrollment status [_1] and submission status "[_2]" to modify or grade.',
                                      $stu_status,$submission_status);
                   } elsif (grep(/^none$/,@groups)) {
                       $result .= &mt('There are no students with no group assigned with enrollment status [_1] and submission status "[_2]" to modify or grade.',
                                      $stu_status,$submission_status);
                   } else {
                       $result .= &mt('There are no students in group(s) [_1] with enrollment status [_2] and submission status "[_3]" to modify or grade.',
                                      $group_display,$stu_status,$submission_status);
                   }
               } elsif (grep(/^none$/,@sections)) {
                   if (grep(/^all$/,@groups)) {
                       $result .= &mt('There are no students in no section with enrollment status [_1] and submission status "[_2]" to modify or grade.',
                                      $stu_status,$submission_status);
                   } elsif (grep(/^none$/,@groups)) {
                       $result .= &mt('There are no students in no section and no group with enrollment status [_1] and submission status "[_2]" to modify or grade.',
                                      $stu_status,$submission_status);
                   } else {
                       $result .= &mt('There are no students in no section in group(s) [_1] with enrollment status [_2] and submission status "[_3]" to modify or grade.',
                                      $group_display,$stu_status,$submission_status);
                   }
               } else {
                   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.',
                                      $section_display,$stu_status,$submission_status);
                   } 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.',
                                      $section_display,$stu_status,$submission_status);
                   } else {
                       $result .= &mt('There are no students in section(s) [_1] and group(s) [_2] with enrollment status [_3] and submission status "[_4]" to modify or grade.',
                                      $section_display,$group_display,$stu_status,$submission_status);
                   }
               }
    }
    $result .= '</span><br />';
     }      }
     $result.=&show_grading_menu_form($symb);      $result.=&show_grading_menu_form($symb);
     return $result;      return $result;
 }  }
   
 #--- call by previous routine to display each student  #--- 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) = @_;
     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 %aggregates = ();       my $submitonly = $env{'form.submitonly'};
       unless (($submitonly eq 'all') || ($submitonly eq 'queued')) {
           my %partstatus = ();
           if (ref($parts) eq 'ARRAY') {
               foreach my $apart (@{$parts}) {
                   my ($part,$type) = &split_part_type($apart);
                   my ($status,undef) = split(/_/,$record{"resource.$part.solved"},2);
                   $status = 'nothing' if ($status eq '');
                   $partstatus{$part}      = $status;
                   my $subkey = "resource.$part.submitted_by";
                   $partstatus{$subkey} = $record{$subkey} if ($record{$subkey} ne '');
               }
               my $submitted = 0;
               my $graded = 0;
               my $incorrect = 0;
               foreach my $key (keys(%partstatus)) {
                   $submitted = 1 if ($partstatus{$key} ne 'nothing');
                   $graded = 1 if ($partstatus{$key} =~ /^ungraded/);
                   $incorrect = 1 if ($partstatus{$key} =~ /^incorrect/);
   
                   my $partid = (split(/\./,$key))[1];
                   if ($partstatus{'resource.'.$partid.'.'.$key.'.submitted_by'} ne '') {
                       $submitted = 0;
                   }
               }
               return if (!$submitted && ($submitonly eq 'yes' ||
                                          $submitonly eq 'incorrect' ||
                                          $submitonly eq 'graded'));
               return if (!$graded && ($submitonly eq 'graded'));
               return if (!$incorrect && $submitonly eq 'incorrect');
           }
       }
       if ($submitonly eq 'queued') {
           my ($cdom,$cnum) = split(/_/,$courseid);
           my %queue_status =
               &Apache::bridgetask::get_student_status($symb,$cdom,$cnum,
                                                       $udom,$uname);
           return if (!defined($queue_status{'gradingqueue'}));
       }
       $$ctr++;
       my %aggregates = ();
     my $result=&Apache::loncommon::start_data_table_row().'<td align="right">'.      my $result=&Apache::loncommon::start_data_table_row().'<td align="right">'.
  '<input type="hidden" name="ctr'.($ctr-1).'" value="'.$student.'" />'.   '<input type="hidden" name="ctr'.($$ctr-1).'" value="'.$student.'" />'.
  "\n".$ctr.'&nbsp;</td><td>&nbsp;'.   "\n".$$ctr.'&nbsp;</td><td>&nbsp;'.
  '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.   '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.
  '\');" target="_self">'.$fullname.'</a> '.   '\');" target="_self">'.$fullname.'</a> '.
  '<span class="LC_internal_info">('.$uname.($env{'user.domain'} eq $udom ? '' : ':'.$udom).')</span></td>'."\n";   '<span class="LC_internal_info">('.$uname.($env{'user.domain'} eq $udom ? '' : ':'.$udom).')</span></td>'."\n";
Line 3914  sub editgrades { Line 4220  sub editgrades {
  $ctr++;   $ctr++;
     }      }
     my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);      my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);
       my $totcolspan = 0;
     foreach my $partid (@partid) {      foreach my $partid (@partid) {
  $header .= '<th align="center">'.&mt('Old Score').'</th>'.   $header .= '<th align="center">'.&mt('Old Score').'</th>'.
     '<th align="center">'.&mt('New Score').'</th>';      '<th align="center">'.&mt('New Score').'</th>';
Line 3930  sub editgrades { Line 4237  sub editgrades {
  '<th align="center">'.&mt('New').' '.$display.'</th>';   '<th align="center">'.&mt('New').' '.$display.'</th>';
     $columns{$partid}+=2;      $columns{$partid}+=2;
  }   }
           $totcolspan += $columns{$partid};
     }      }
     foreach my $partid (@partid) {      foreach my $partid (@partid) {
  my $display_part=&get_display_part($partid,$symb);   my $display_part=&get_display_part($partid,$symb);
Line 3945  sub editgrades { Line 4253  sub editgrades {
     my @noupdate;      my @noupdate;
     my ($updateCtr,$noupdateCtr) = (1,1);      my ($updateCtr,$noupdateCtr) = (1,1);
     for ($i=0; $i<$env{'form.total'}; $i++) {      for ($i=0; $i<$env{'form.total'}; $i++) {
  my $line;  
  my $user = $env{'form.ctr'.$i};   my $user = $env{'form.ctr'.$i};
  my ($uname,$udom)=split(/:/,$user);   my ($uname,$udom)=split(/:/,$user);
  my %newrecord;   my %newrecord;
  my $updateflag = 0;   my $updateflag = 0;
  $line .= '<td>'.&nameUserString(undef,$$fullname{$user},$uname,$udom).'</td>';          my $usec=$classlist->{"$uname:$udom"}[5];
  my $usec=$classlist->{"$uname:$udom"}[5];          my $canmodify = &canmodify($usec);
  if (!&canmodify($usec)) {          my $line = '<td'.($canmodify?'':' colspan="2"').'>'.
     my $numcols=scalar(@partid)*4+2;                     &nameUserString(undef,$$fullname{$user},$uname,$udom).'</td>';
     push(@noupdate,          if (!$canmodify) {
  $line."<td colspan=\"$numcols\"><span class=\"LC_warning\">".              push(@noupdate,
  &mt('Not allowed to modify student')."</span></td></tr>");                   $line."<td colspan=\"$totcolspan\"><span class=\"LC_warning\">".
     next;                   &mt('Not allowed to modify student')."</span></td>");
  }              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 4073  sub editgrades { Line 4381  sub editgrades {
         }          }
     }      }
     if (@noupdate) {      if (@noupdate) {
 # my $numcols=(scalar(@partid)*(scalar(@parts)-1)*2)+3;          my $numcols=$totcolspan+2;
  my $numcols=scalar(@partid)*4+2;  
  $result .= &Apache::loncommon::start_data_table_row('LC_empty_row').   $result .= &Apache::loncommon::start_data_table_row('LC_empty_row').
     '<td align="center" colspan="'.$numcols.'">'.      '<td align="center" colspan="'.$numcols.'">'.
     &mt('No Changes Occurred For the Students Below').      &mt('No Changes Occurred For the Students Below').
Line 4118  sub split_part_type { Line 4425  sub split_part_type {
 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 or the student/employee 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(\$error2);
   return(<<ENDPICK);    return(<<ENDPICK);
   function verify(vf) {    function verify(vf) {
     var foundsomething=0;      var foundsomething=0;
Line 4158  ENDPICK Line 4467  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 or the student/employee 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(\$error2);
   return(<<ENDPICK);    return(<<ENDPICK);
   function verify(vf) {    function verify(vf) {
     var foundsomething=0;      var foundsomething=0;
Line 4277  ENDPICK Line 4588  ENDPICK
   
 sub checkforfile_js {  sub checkforfile_js {
     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);
     my $result =<<CSVFORMJS;      my $result =<<CSVFORMJS;
 <script type="text/javascript" language="javascript">  <script type="text/javascript" language="javascript">
     function checkUpload(formname) {      function checkUpload(formname) {
Line 4337  sub csvuploadmap { Line 4649  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=$env{'form.datatoken'};          $datatoken=&Apache::loncommon::valid_datatoken($env{'form.datatoken'});
  &Apache::loncommon::load_tmp_file($request);          if ($datatoken ne '') { 
       &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); }      if ($env{'form.noFirstLine'}) { shift(@records); }
Line 4442  sub csvuploadassign { Line 4756  sub csvuploadassign {
     my ($symb)=&get_symb($request);      my ($symb)=&get_symb($request);
     if (!$symb) {return '';}      if (!$symb) {return '';}
     my $error_msg = '';      my $error_msg = '';
     &Apache::loncommon::load_tmp_file($request);      my $datatoken = &Apache::loncommon::valid_datatoken($env{'form.datatoken'});
       if ($datatoken ne '') {
           &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); }      if ($env{'form.noFirstLine'}) { shift(@gradedata); }
     my %fields=&get_fields();      my %fields=&get_fields();
Line 4573  sub pickStudentPage { Line 4890  sub pickStudentPage {
     my ($request) = shift;      my ($request) = shift;
   
     my $alertmsg = &mt('Please select the student you wish to grade.');      my $alertmsg = &mt('Please select the student you wish to grade.');
       &js_escape(\$alertmsg);
     $request->print(<<LISTJAVASCRIPT);      $request->print(<<LISTJAVASCRIPT);
 <script type="text/javascript" language="javascript">  <script type="text/javascript" language="javascript">
   
Line 4594  LISTJAVASCRIPT Line 4912  LISTJAVASCRIPT
     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'};
       my $getgroup  = $env{'form.group'} eq '' ? 'all' : $env{'form.group'};
   
     my $result='<h3><span class="LC_info">&nbsp;'.      my $result='<h3><span class="LC_info">&nbsp;'.
  &mt('Manual Grading by Page or Sequence').'</span></h3>';   &mt('Manual Grading by Page or Sequence').'</span></h3>';
Line 4664  LISTJAVASCRIPT Line 4983  LISTJAVASCRIPT
  '<th>'.&nameUserString('header').'</th>'.   '<th>'.&nameUserString('header').'</th>'.
  &Apache::loncommon::end_data_table_header_row();   &Apache::loncommon::end_data_table_header_row();
     
     my (undef,undef,$fullname) = &getclasslist($getsec,'1');      my (undef,undef,$fullname) = &getclasslist($getsec,'1',$getgroup);
     my $ptr = 1;      my $ptr = 1;
     foreach my $student (sort       foreach my $student (sort 
  {   {
Line 4748  sub displayPage { Line 5067  sub displayPage {
     &Apache::lonnet::clear_EXT_cache_status();      &Apache::lonnet::clear_EXT_cache_status();
   
     if (!&canview($usec)) {      if (!&canview($usec)) {
  $request->print('<span class="LC_warning">'.&mt('Unable to view requested student. ([_1])',$env{'form.student'}).'</span>');   $request->print('<span class="LC_warning">'.
  $request->print(&show_grading_menu_form($symb));                          &mt('Unable to view requested student. ([_1])',
  return;                              $env{'form.student'}).
                           '</span>');
           $request->print(&show_grading_menu_form($symb));
           return;
     }      }
     my $result='<h3><span class="LC_info">&nbsp;'.$env{'form.title'}.'</span></h3>';      my $result='<h3><span class="LC_info">&nbsp;'.$env{'form.title'}.'</span></h3>';
     $result.='<h3>&nbsp;'.&mt('Student: [_1]',&nameUserString(undef,$$fullname{$env{'form.student'}},$uname,$udom)).      $result.='<h3>&nbsp;'.&mt('Student: [_1]',&nameUserString(undef,$$fullname{$env{'form.student'}},$uname,$udom)).
Line 4864  sub displayPage { Line 5186  sub displayPage {
  }   }
     } 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 : '');
  $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');   '','.submission',undef,
                                                                           $usec,$identifier);
     
     }      }
     if (&canmodify($usec)) {      if (&canmodify($usec)) {
Line 4919  sub displaySubByDates { Line 5243  sub displaySubByDates {
   
     my $interaction;      my $interaction;
     my $no_increment = 1;      my $no_increment = 1;
     my %lastrndseed;      my (%lastrndseed,%lasttype);
     for ($version=1;$version<=$$record{'version'};$version++) {      for ($version=1;$version<=$$record{'version'};$version++) {
  my $timestamp =    my $timestamp = 
     &Apache::lonlocal::locallocaltime($$record{$version.':timestamp'});      &Apache::lonlocal::locallocaltime($$record{$version.':timestamp'});
Line 4977  sub displaySubByDates { Line 5301  sub displaySubByDates {
         } else {          } else {
     $displaySub[0].=&mt('Trial: [_1]',      $displaySub[0].=&mt('Trial: [_1]',
     $$record{"$where.$partid.tries"});      $$record{"$where.$partid.tries"});
                             if ($rndseed || $lastrndseed{$partid}) {                              if (($rndseed ne '')  && ($lastrndseed{$partid} ne '')) {
                                 if ($rndseed ne $lastrndseed{$partid}) {                                  if (($rndseed ne $lastrndseed{$partid}) &&
                                       (($type eq 'randomizetry') || ($lasttype{$partid} eq 'randomizetry'))) {
                                     $newvariation = '&nbsp;('.&mt('New variation this try').')';                                      $newvariation = '&nbsp;('.&mt('New variation this try').')';
                                 }                                  }
                             }                              }
                               $lastrndseed{$partid} = $rndseed;
                               $lasttype{$partid} = $type;
         }          }
         my $responseType=($isTask ? 'Task'          my $responseType=($isTask ? 'Task'
                                               : $responseType->{$partid}->{$responseId});                                                : $responseType->{$partid}->{$responseId});
Line 5082  sub updateGradeByPage { Line 5409  sub updateGradeByPage {
   
     $iterator->next(); # skip the first BEGIN_MAP      $iterator->next(); # skip the first BEGIN_MAP
     my $curRes = $iterator->next(); # for "current resource"      my $curRes = $iterator->next(); # for "current resource"
     my ($depth,$question,$prob,$changeflag)= (1,1,1,0);      my ($depth,$question,$prob,$changeflag,$hideflag)= (1,1,1,0,0);
     while ($depth > 0) {      while ($depth > 0) {
         if($curRes == $iterator->BEGIN_MAP) { $depth++; }          if($curRes == $iterator->BEGIN_MAP) { $depth++; }
         if($curRes == $iterator->END_MAP) { $depth--; }          if($curRes == $iterator->END_MAP) { $depth--; }
Line 5103  sub updateGradeByPage { Line 5430  sub updateGradeByPage {
     my @displayPts=();      my @displayPts=();
             my %aggregate = ();              my %aggregate = ();
             my $aggregateflag = 0;              my $aggregateflag = 0;
               if ($env{'form.HIDE'.$prob}) {
                   my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname);
                   my ($version,$parts) = split(/:/,$env{'form.HIDE'.$prob},2);
                   my $numchgs = &makehidden($version,$parts,\%record,$symbx,$udom,$uname,1);
                   $hideflag += $numchgs;
               }
     foreach my $partid (@{$parts}) {      foreach my $partid (@{$parts}) {
  my $newpts = $env{'form.GD_BOX'.$question.'_'.$partid};   my $newpts = $env{'form.GD_BOX'.$question.'_'.$partid};
  my $oldpts = $env{'form.oldpts'.$question.'_'.$partid};   my $oldpts = $env{'form.oldpts'.$question.'_'.$partid};
Line 5194  sub updateGradeByPage { Line 5527  sub updateGradeByPage {
     $studentTable.=&show_grading_menu_form($env{'form.symb'});      $studentTable.=&show_grading_menu_form($env{'form.symb'});
     my $grademsg=($changeflag == 0 ? &mt('No score was changed or updated.') :      my $grademsg=($changeflag == 0 ? &mt('No score was changed or updated.') :
   &mt('The scores were changed for [quant,_1,problem].',    &mt('The scores were changed for [quant,_1,problem].',
   $changeflag));    $changeflag).'<br />');
     $request->print($grademsg.$studentTable);      my $hidemsg=($hideflag == 0 ? '' :
                    &mt('Submissions were marked "hidden" for [quant,_1,transaction].',
                        $hideflag).'<br />');
       $request->print($hidemsg.$grademsg.$studentTable);
   
     return '';      return '';
 }  }
Line 5424  sub scantron_uploads { Line 5760  sub scantron_uploads {
 sub scantron_scantab {  sub scantron_scantab {
     my $result='<select name="scantron_format">'."\n";      my $result='<select name="scantron_format">'."\n";
     $result.='<option></option>'."\n";      $result.='<option></option>'."\n";
     my @lines = &get_scantronformat_file();      my @lines = &Apache::lonnet::get_scantronformat_file();
     if (@lines > 0) {      if (@lines > 0) {
         foreach my $line (@lines) {          foreach my $line (@lines) {
             next if (($line =~ /^\#/) || ($line eq ''));              next if (($line =~ /^\#/) || ($line eq ''));
Line 5436  sub scantron_scantab { Line 5772  sub scantron_scantab {
     return $result;      return $result;
 }  }
   
 =pod  
   
 =item get_scantronformat_file  
   
   Returns an array containing lines from the scantron format file for  
   the domain of the course.  
   
   If a url for a custom.tab file is listed in domain's configuration.db,   
   lines are from this file.  
   
   Otherwise, if a default.tab has been published in RES space by the   
   domainconfig user, lines are from this file.  
   
   Otherwise, fall back to getting lines from the legacy file on the  
   local server:  /home/httpd/lonTabs/default_scantronformat.tab      
   
 =cut  
   
 sub get_scantronformat_file {  
     my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'};  
     my %domconfig = &Apache::lonnet::get_dom('configuration',['scantron'],$cdom);  
     my $gottab = 0;  
     my @lines;  
     if (ref($domconfig{'scantron'}) eq 'HASH') {  
         if ($domconfig{'scantron'}{'scantronformat'} ne '') {  
             my $formatfile = &Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonDocRoot'}.$domconfig{'scantron'}{'scantronformat'});  
             if ($formatfile ne '-1') {  
                 @lines = split("\n",$formatfile,-1);  
                 $gottab = 1;  
             }  
         }  
     }  
     if (!$gottab) {  
         my $confname = $cdom.'-domainconfig';  
         my $default = $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'.$cdom.'/'.$confname.'/default.tab';  
         my $formatfile =  &Apache::lonnet::getfile($default);  
         if ($formatfile ne '-1') {  
             @lines = split("\n",$formatfile,-1);  
             $gottab = 1;  
         }  
     }  
     if (!$gottab) {  
         my @domains = &Apache::lonnet::current_machine_domains();  
         if (grep(/^\Q$cdom\E$/,@domains)) {  
             my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');  
             @lines = <$fh>;  
             close($fh);  
         } else {  
             my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab');  
             @lines = <$fh>;  
             close($fh);  
         }  
     }  
     return @lines;  
 }  
   
 =pod   =pod 
   
 =item scantron_CODElist  =item scantron_CODElist
Line 5578  sub scantron_selectphase { Line 5858  sub scantron_selectphase {
         # 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 />');
     '.&Apache::loncommon::start_data_table('LC_scantron_action').'          my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'};
        '.&Apache::loncommon::start_data_table_header_row().'          my $cnum= $env{'course.'.$env{'request.course.id'}.'.num'};
             <th>          my $alertmsg = &mt('Please use the browse button to select a file from your local directory.');
               &nbsp;'.&mt('Specify a bubblesheet data file to upload.').'          &js_escape(\$alertmsg);
             </th>          my ($formatoptions,$formattitle,$formatjs) = &scantron_upload_dataformat($cdom);
        '.&Apache::loncommon::end_data_table_header_row().'          $r->print(&Apache::lonhtmlcommon::scripttag('
        '.&Apache::loncommon::start_data_table_row().'  
             <td>  
 ');  
     my $default_form_data=&defaultFormData(&get_symb($r,1));  
     my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'};  
     my $cnum= $env{'course.'.$env{'request.course.id'}.'.num'};  
     $r->print('  
               <script type="text/javascript" language="javascript">  
     function checkUpload(formname) {      function checkUpload(formname) {
         if (formname.upfile.value == "") {          if (formname.upfile.value == "") {
             alert("'.&mt('Please use the browse button to select a file from your local directory.').'");              alert("'.$alertmsg.'");
             return false;              return false;
         }          }
         formname.submit();          formname.submit();
     }      }'."\n".$formatjs));
               </script>          $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.'" />
                 <input name="domainid" type="hidden" value="'.$cdom.'" />                  <input name="domainid" type="hidden" value="'.$cdom.'" />
                 <input name="command" value="scantronupload_save" type="hidden" />                  <input name="command" value="scantronupload_save" type="hidden" />
                 '.&mt('File to upload: [_1]','<input type="file" name="upfile" size="50" />').'                '.&Apache::loncommon::start_data_table('LC_scantron_action').'
                 <br />                '.&Apache::loncommon::start_data_table_header_row().'
                 <input type="button" onclick="javascript:checkUpload(this.form);" value="'.&mt('Upload Bubblesheet Data').'" />                  <th>
               </form>                  &nbsp;'.&mt('Specify a bubblesheet data file to upload.').'
 ');                  </th>
                 '.&Apache::loncommon::end_data_table_header_row().'
                 '.&Apache::loncommon::start_data_table_row().'
               <td>
                   '.&mt('File to upload: [_1]','<input type="file" name="upfile" size="50" />').'<br />'."\n");
           if ($formatoptions) {
               $r->print('</td>
                    '.&Apache::loncommon::end_data_table_row().'
                    '.&Apache::loncommon::start_data_table_row().'
                    <td>'.$formattitle.('&nbsp;'x2).$formatoptions.'
                    </td>
                    '.&Apache::loncommon::end_data_table_row().'
                    '.&Apache::loncommon::start_data_table_row().'
                    <td>'
               );
           } else {
               $r->print(' <br />');
           }
           $r->print('<input type="button" onclick="javascript:checkUpload(this.form);" value="'.&mt('Upload Bubblesheet Data').'" />
                 </td>
                '.&Apache::loncommon::end_data_table_row().'
                '.&Apache::loncommon::end_data_table().'
                </form>'
           );
   
         $r->print('  
             </td>  
        '.&Apache::loncommon::end_data_table_row().'  
        '.&Apache::loncommon::end_data_table().'  
 ');  
     }      }
   
     # Chunk of form to prompt for a file to grade and how:      # Chunk of form to prompt for a file to grade and how:
Line 5729  sub scantron_selectphase { Line 6018  sub scantron_selectphase {
     return;      return;
 }  }
   
 =pod  
   
 =item get_scantron_config  
   
    Parse and return the scantron configuration line selected as a  
    hash of configuration file fields.  
   
  Arguments:  
     which - the name of the configuration to parse from the file.  
   
   
  Returns:  
             If the named configuration is not in the file, an empty  
             hash is returned.  
     a hash with the fields  
       name         - internal name for the this configuration setup  
       description  - text to display to operator that describes this config  
       CODElocation - if 0 or the string 'none'  
                           - no CODE exists for this config  
                      if -1 || the string 'letter'  
                           - a CODE exists for this config and is  
                             a string of letters  
                      Unsupported value (but planned for future support)  
                           if a positive integer  
                                - The CODE exists as the first n items from  
                                  the question section of the form  
                           if the string 'number'  
                                - The CODE exists for this config and is  
                                  a string of numbers  
       CODEstart   - (only matter if a CODE exists) column in the line where  
                      the CODE starts  
       CODElength  - length of the CODE  
       IDstart     - column where the student/employee ID starts  
       IDlength    - length of the student/employee ID info  
       Qstart      - column where the information from the bubbled  
                     'questions' start  
       Qlength     - number of columns comprising a single bubble line from  
                     the sheet. (usually either 1 or 10)  
       Qon         - either a single character representing the character used  
                     to signal a bubble was chosen in the positional setup, or  
                     the string 'letter' if the letter of the chosen bubble is  
                     in the final, or 'number' if a number representing the  
                     chosen bubble is in the file (1->A 0->J)  
       Qoff        - the character used to represent that a bubble was  
                     left blank  
       PaperID     - if the scanning process generates a unique number for each  
                     sheet scanned the column that this ID number starts in  
       PaperIDlength - number of columns that comprise the unique ID number  
                       for the sheet of paper  
       FirstName   - column that the first name starts in  
       FirstNameLength - number of columns that the first name spans  
    
       LastName    - column that the last name starts in  
       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  
   
 sub get_scantron_config {  
     my ($which) = @_;  
     my @lines = &get_scantronformat_file();  
     my %config;  
     #FIXME probably should move to XML it has already gotten a bit much now  
     foreach my $line (@lines) {  
  my ($name,$descrip)=split(/:/,$line);  
  if ($name ne $which ) { next; }  
  chomp($line);  
  my @config=split(/:/,$line);  
  $config{'name'}=$config[0];  
  $config{'description'}=$config[1];  
  $config{'CODElocation'}=$config[2];  
  $config{'CODEstart'}=$config[3];  
  $config{'CODElength'}=$config[4];  
  $config{'IDstart'}=$config[5];  
  $config{'IDlength'}=$config[6];  
  $config{'Qstart'}=$config[7];  
   $config{'Qlength'}=$config[8];  
  $config{'Qoff'}=$config[9];  
  $config{'Qon'}=$config[10];  
  $config{'PaperID'}=$config[11];  
  $config{'PaperIDlength'}=$config[12];  
  $config{'FirstName'}=$config[13];  
  $config{'FirstNamelength'}=$config[14];  
  $config{'LastName'}=$config[15];  
  $config{'LastNamelength'}=$config[16];  
         $config{'BubblesPerRow'}=$config[17];  
  last;  
     }  
     return %config;  
 }  
   
 =pod   =pod 
   
 =item username_to_idmap  =item username_to_idmap
Line 5844  sub username_to_idmap { Line 6041  sub username_to_idmap {
     my ($classlist)= @_;      my ($classlist)= @_;
     my %idmap;      my %idmap;
     foreach my $student (keys(%$classlist)) {      foreach my $student (keys(%$classlist)) {
  $idmap{$classlist->{$student}->[&Apache::loncoursedata::CL_ID]}=          my $id = $classlist->{$student}->[&Apache::loncoursedata::CL_ID];
     $student;          unless ($id eq '') {
               if (!exists($idmap{$id})) {
                   $idmap{$id} = $student;
               } else {
                   my $status = $classlist->{$student}->[&Apache::loncoursedata::CL_STATUS];
                   if ($status eq 'Active') {
                       $idmap{$id} = $student;
                   }
               }
           }
     }      }
     return %idmap;      return %idmap;
 }  }
Line 5857  sub username_to_idmap { Line 6063  sub username_to_idmap {
    Process a requested correction to a scanline.     Process a requested correction to a scanline.
   
   Arguments:    Arguments:
     $scantron_config   - hash from &get_scantron_config()      $scantron_config   - hash from &Apache::lonnet::get_scantron_config()
     $scan_data         - hash of correction information       $scan_data         - hash of correction information 
                           (see &scantron_getfile())                            (see &scantron_getfile())
     $line              - existing scanline      $line              - existing scanline
Line 6540  sub scantron_filter { Line 6746  sub scantron_filter {
   
 sub scantron_process_corrections {  sub scantron_process_corrections {
     my ($r) = @_;      my ($r) = @_;
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
     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 $which=$env{'form.scantron_line'};      my $which=$env{'form.scantron_line'};
Line 6709  sub check_for_error { Line 6915  sub check_for_error {
 sub scantron_warning_screen {  sub scantron_warning_screen {
     my ($button_text)=@_;      my ($button_text)=@_;
     my $title=&Apache::lonnet::gettitle($env{'form.selectpage'});      my $title=&Apache::lonnet::gettitle($env{'form.selectpage'});
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
     my $CODElist;      my $CODElist;
     if ($scantron_config{'CODElocation'} &&      if ($scantron_config{'CODElocation'} &&
  $scantron_config{'CODEstart'} &&   $scantron_config{'CODEstart'} &&
  $scantron_config{'CODElength'}) {   $scantron_config{'CODElength'}) {
  $CODElist=$env{'form.scantron_CODElist'};   $CODElist=$env{'form.scantron_CODElist'};
  if ($env{'form.scantron_CODElist'} eq '') { $CODElist='<span class="LC_warning">None</span>'; }   if ($env{'form.scantron_CODElist'} eq '') { $CODElist='<span class="LC_warning">'.&mt('None').'</span>'; }
  $CODElist=   $CODElist=
     '<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>';
Line 6729  sub scantron_warning_screen { Line 6935  sub scantron_warning_screen {
     return ('      return ('
 <p>  <p>
 <span class="LC_warning">  <span class="LC_warning">
 '.&mt('Please double check the information below before clicking on \'[_1]\'',&mt($button_text)).'</span>  '.&mt("Please double check the information below before clicking on '[_1]'",&mt($button_text)).'</span>
 </p>  </p>
 <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>
Line 6868  sub scantron_validate_file { Line 7074  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 %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
     my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config);      my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config);
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
Line 7327  sub scantron_validate_ID { Line 7533  sub scantron_validate_ID {
     my %idmap=&username_to_idmap($classlist);      my %idmap=&username_to_idmap($classlist);
   
     #get scantron line setup      #get scantron line setup
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&Apache::lonnet::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;
Line 7575  sub verify_bubbles_checked { Line 7781  sub verify_bubbles_checked {
     my (@ansnums) = @_;      my (@ansnums) = @_;
     my $ansnumstr = join('","',@ansnums);      my $ansnumstr = join('","',@ansnums);
     my $warning = &mt("A bubble or 'No bubble' selection has not been made for one or more lines.");      my $warning = &mt("A bubble or 'No bubble' selection has not been made for one or more lines.");
       &js_escape(\$warning);
     my $output = (<<ENDSCRIPT);      my $output = (<<ENDSCRIPT);
 <script type="text/javascript">  <script type="text/javascript">
 function verify_bubble_radio(form) {  function verify_bubble_radio(form) {
Line 7732  sub prompt_for_corrections { Line 7939  sub prompt_for_corrections {
             }              }
         } else {          } else {
             $responsenum = $question-1;              $responsenum = $question-1;
             $first = $first_bubble_line{$responsenum} + 1;              $first = $first_bubble_line{$responsenum};
         }          }
         $current_line = $first + 1 ;          $current_line = $first + 1 ;
         my @subans = split(/,/,$subdivided_bubble_lines{$responsenum});          my @subans = split(/,/,$subdivided_bubble_lines{$responsenum});
Line 7790  sub prompt_for_corrections { Line 7997  sub prompt_for_corrections {
   
  Arguments:   Arguments:
     $r           - Apache request object      $r           - Apache request object
     $scan_config - hash from &get_scantron_config()      $scan_config - hash from &Apache::lonnet::get_scantron_config()
     $line        - Number of the line being displayed.      $line        - Number of the line being displayed.
     $questionnum - Question number (may include subquestion)      $questionnum - Question number (may include subquestion)
     $error       - Type of error.      $error       - Type of error.
Line 7954  sub get_codes { Line 8161  sub get_codes {
   
 sub scantron_validate_CODE {  sub scantron_validate_CODE {
     my ($r,$currentphase) = @_;      my ($r,$currentphase) = @_;
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
     if ($scantron_config{'CODElocation'} &&      if ($scantron_config{'CODElocation'} &&
  $scantron_config{'CODEstart'} &&   $scantron_config{'CODEstart'} &&
  $scantron_config{'CODElength'}) {   $scantron_config{'CODElength'}) {
Line 8028  sub scantron_validate_doublebubble { Line 8235  sub scantron_validate_doublebubble {
         &Apache::lonnet::decode_symb($env{'form.selectpage'});          &Apache::lonnet::decode_symb($env{'form.selectpage'});
   
     #get scantron line setup      #get scantron line setup
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
   
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
Line 8210  sub scantron_validate_missingbubbles { Line 8417  sub scantron_validate_missingbubbles {
         &Apache::lonnet::decode_symb($env{'form.selectpage'});          &Apache::lonnet::decode_symb($env{'form.selectpage'});
   
     #get scantron line setup      #get scantron line setup
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
   
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
Line 8339  sub hand_bubble_option { Line 8546  sub hand_bubble_option {
         }          }
     }      }
     if ($needs_hand_bubbles) {      if ($needs_hand_bubbles) {
         my %scantron_config=&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);
         return &mt('The sequence to be graded contains response types which are handgraded.').'<p>'.          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 />').                 &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="'.$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>';                 '<label><input type="radio" name="scantron_lastbubblepoints" value="0" />'.&mt('0 points').'</label></p>';
     }      }
     return;      return;
 }  }
Line 8359  sub scantron_process_students { Line 8566  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=&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();
Line 8429  SCANTRONFORM Line 8636  SCANTRONFORM
  return ''; # Dunno why the other returns return '' rather than just returning.   return ''; # Dunno why the other returns return '' rather than just returning.
     }      }
   
     my %lettdig = &letter_to_digits();      my %lettdig = &Apache::lonnet::letter_to_digits();
     my $numletts = scalar(keys(%lettdig));      my $numletts = scalar(keys(%lettdig));
     my %orderedforcode;      my %orderedforcode;
   
Line 8492  SCANTRONFORM Line 8699  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 $currcode;
                   if (exists($grader_randomlists_by_symb{$ressymb})) {
                       $currcode = $scancode;
                   }
                 my ($analysis,$parts) =                  my ($analysis,$parts) =
                     &scantron_partids_tograde($resource,$env{'request.course.id'},                      &scantron_partids_tograde($resource,$env{'request.course.id'},
                                               $uname,$udom,undef,$bubbles_per_row);                                                $uname,$udom,undef,$bubbles_per_row,
                                                 $currcode);
                 $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 8755  sub grade_student_bubbles { Line 8967  sub grade_student_bubbles {
 sub scantron_upload_scantron_data {  sub scantron_upload_scantron_data {
     my ($r)=@_;      my ($r)=@_;
     my $dom = $env{'request.role.domain'};      my $dom = $env{'request.role.domain'};
       my ($formatoptions,$formattitle,$formatjs) = &scantron_upload_dataformat($dom);
     my $domdesc = &Apache::lonnet::domain($dom,'description');      my $domdesc = &Apache::lonnet::domain($dom,'description');
     $r->print(&Apache::loncommon::coursebrowser_javascript($dom));      $r->print(&Apache::loncommon::coursebrowser_javascript($dom));
     my $select_link=&Apache::loncommon::selectcourse_link('rules','courseid',      my $select_link=&Apache::loncommon::selectcourse_link('rules','courseid',
Line 8765  sub scantron_upload_scantron_data { Line 8978  sub scantron_upload_scantron_data {
     my ($symb) = &get_symb($r,1);      my ($symb) = &get_symb($r,1);
     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);
     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('      &js_escape(\$nocourseid_alert);
 <script type="text/javascript" language="javascript">      $r->print(&Apache::lonhtmlcommon::scripttag('
     function checkUpload(formname) {      function checkUpload(formname) {
  if (formname.upfile.value == "") {   if (formname.upfile.value == "") {
     alert("'.$nofile_alert.'");      alert("'.$nofile_alert.'");
Line 8794  sub scantron_upload_scantron_data { Line 9008  sub scantron_upload_scantron_data {
         return;          return;
     }      }
   
 </script>      '.$formatjs.'
   '));
       $r->print('
 <h3>'.&mt('Send bubblesheet data to a course').'</h3>  <h3>'.&mt('Send bubblesheet data to a course').'</h3>
   
 <form enctype="multipart/form-data" action="/adm/grades" name="rules" method="post">  <form enctype="multipart/form-data" action="/adm/grades" name="rules" method="post">
Line 8809  sub scantron_upload_scantron_data { Line 9024  sub scantron_upload_scantron_data {
   &Apache::lonhtmlcommon::row_closure().    &Apache::lonhtmlcommon::row_closure().
   &Apache::lonhtmlcommon::row_title(&mt('Domain')).    &Apache::lonhtmlcommon::row_title(&mt('Domain')).
   '<input name="domainid" type="hidden" />'.$domdesc.    '<input name="domainid" type="hidden" />'.$domdesc.
   &Apache::lonhtmlcommon::row_closure().    &Apache::lonhtmlcommon::row_closure());
       if ($formatoptions) {
           $r->print(&Apache::lonhtmlcommon::row_title($formattitle).$formatoptions.
                     &Apache::lonhtmlcommon::row_closure());
       }
       $r->print(
   &Apache::lonhtmlcommon::row_title(&mt('File to upload')).    &Apache::lonhtmlcommon::row_title(&mt('File to upload')).
   '<input type="file" name="upfile" size="50" />'.    '<input type="file" name="upfile" size="50" />'.
   &Apache::lonhtmlcommon::row_closure(1).    &Apache::lonhtmlcommon::row_closure(1).
Line 8822  sub scantron_upload_scantron_data { Line 9042  sub scantron_upload_scantron_data {
     return '';      return '';
 }  }
   
   sub scantron_upload_dataformat {
       my ($dom) = @_;
       my ($formatoptions,$formattitle,$formatjs);
       $formatjs = <<'END';
   function toggleScantab(form) {
      return;
   }
   END
       my %domconfig = &Apache::lonnet::get_dom('configuration',['scantron'],$dom);
       if (ref($domconfig{'scantron'}) eq 'HASH') {
           if (ref($domconfig{'scantron'}{'config'}) eq 'HASH') {
               if (keys(%{$domconfig{'scantron'}{'config'}}) > 1) {
                   if (($domconfig{'scantron'}{'config'}{'dat'}) &&
                       (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH')) {
                       if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
                           if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}})) {
                               my ($onclick,$formatextra,$singleline);
                               my @lines = &Apache::lonnet::get_scantronformat_file();
                               my $count = 0;
                               foreach my $line (@lines) {
                                   next if ($line =~ /^#/);
                                   $singleline = $line;
                                   $count ++;
                               }
                               if ($count > 1) {
                                   $formatextra = '<div style="display:none" id="bubbletype">'.
                                                  '<span class="LC_nobreak">'.
                                                  &mt('Bubblesheet type:').'&nbsp;'.
                                                  &scantron_scantab().'</span></div>';
                                   $onclick = ' onclick="toggleScantab(this.form);"';
                                   $formatjs = <<"END";
   function toggleScantab(form) {
       var divid = 'bubbletype';
       if (document.getElementById(divid)) {
           var radioname = 'fileformat';
           var num = form.elements[radioname].length;
           if (num) {
               for (var i=0; i<num; i++) {
                   if (form.elements[radioname][i].checked) {
                       var chosen = form.elements[radioname][i].value;
                       if (chosen == 'dat') {
                           document.getElementById(divid).style.display = 'none';
                       } else if (chosen == 'csv') {
                           document.getElementById(divid).style.display = 'block';
                       }
                   }
               }
           }
       }
       return;
   }
   
   END
                               } elsif ($count == 1) {
                                   my $formatname = (split(/:/,$singleline,2))[0];
                                   $formatextra = '<input type="hidden" name="scantron_format" value="'.$formatname.'" />';
                               }
                               $formattitle = &mt('File format');
                               $formatoptions = '<label><input name="fileformat" type="radio" value="dat" checked="checked"'.$onclick.' />'.
                                                &mt('Plain Text (no delimiters)').
                                                '</label>'.('&nbsp;'x2).
                                                '<label><input name="fileformat" type="radio" value="csv"'.$onclick.' />'.
                                                &mt('Comma separated values').'</label>'.$formatextra;
                           }
                       }
                   }
               } elsif (keys(%{$domconfig{'scantron'}{'config'}}) == 1) {
                   if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
                       if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}})) {
                           $formattitle = &mt('Bubblesheet type');
                           $formatoptions = &scantron_scantab();
                       }
                   }
               }
           }
       }
       return ($formatoptions,$formattitle,$formatjs);
   }
   
 sub scantron_upload_scantron_data_save {  sub scantron_upload_scantron_data_save {
     my($r)=@_;      my($r)=@_;
Line 8851  sub scantron_upload_scantron_data_save { Line 9149  sub scantron_upload_scantron_data_save {
                 &mt('The file: [_1] you attempted to upload contained no information. Please check that you entered the correct filename.',                  &mt('The file: [_1] you attempted to upload contained no information. Please check that you entered the correct filename.',
                         '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'),1));                          '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'),1));
     } else {      } else {
         my $result =           my %domconfig = &Apache::lonnet::get_dom('configuration',['scantron'],$env{'form.domainid'});
             &Apache::lonnet::userfileupload('upfile','','scantron','','','',          my $parser;
           if (ref($domconfig{'scantron'}) eq 'HASH') {
               if (ref($domconfig{'scantron'}{'config'}) eq 'HASH') {
                   my $is_csv;
                   my @possibles = keys(%{$domconfig{'scantron'}{'config'}});
                   if (@possibles > 1) {
                       if ($env{'form.fileformat'} eq 'csv') {
                           if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {
                               if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
                                   if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}}) > 1) {
                                       $is_csv = 1;
                                   }
                               }
                           }
                       }
                   } elsif (@possibles == 1) {
                       if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {
                           if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
                               if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}}) > 1) {
                                   $is_csv = 1;
                               }
                           }
                       }
                   }
                   if ($is_csv) {
                      $parser = $domconfig{'scantron'}{'config'}{'csv'};
                   }
               }
           }
           my $result =
               &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(
Line 8897  sub validate_uploaded_scantron_file { Line 9225  sub validate_uploaded_scantron_file {
             $idmap{$lckey} = $idmap{$key};              $idmap{$lckey} = $idmap{$key};
         }          }
         my %unique_formats;          my %unique_formats;
         my @formatlines = &get_scantronformat_file();          my @formatlines = &Apache::lonnet::get_scantronformat_file();
         foreach my $line (@formatlines) {          foreach my $line (@formatlines) {
             chomp($line);              chomp($line);
             my @config = split(/:/,$line);              my @config = split(/:/,$line);
Line 9021  sub scantron_download_scantron_data { Line 9349  sub scantron_download_scantron_data {
     &Apache::lonnet::allowuploaded('/adm/grades',$skipped);      &Apache::lonnet::allowuploaded('/adm/grades',$skipped);
     $r->print('      $r->print('
     <p>      <p>
  '.&mt('[_1]Original[_2] file as uploaded by the scantron office.',   '.&mt('[_1]Original[_2] file as uploaded by bubblesheet scanning office.',
       '<a href="'.$orig.'">','</a>').'        '<a href="'.$orig.'">','</a>').'
     </p>      </p>
     <p>      <p>
Line 9043  sub checkscantron_results { Line 9371  sub checkscantron_results {
     if (!$symb) {return '';}      if (!$symb) {return '';}
     my $grading_menu_button=&show_grading_menu_form($symb);      my $grading_menu_button=&show_grading_menu_form($symb);
     my $cid = $env{'request.course.id'};      my $cid = $env{'request.course.id'};
     my %lettdig = &letter_to_digits();      my %lettdig = &Apache::lonnet::letter_to_digits();
     my $numletts = scalar(keys(%lettdig));      my $numletts = scalar(keys(%lettdig));
     my $cnum = $env{'course.'.$cid.'.num'};      my $cnum = $env{'course.'.$cid.'.num'};
     my $cdom = $env{'course.'.$cid.'.domain'};      my $cdom = $env{'course.'.$cid.'.domain'};
     my (undef, undef, $sequence) = &Apache::lonnet::decode_symb($env{'form.selectpage'});      my (undef, undef, $sequence) = &Apache::lonnet::decode_symb($env{'form.selectpage'});
     my %record;      my %record;
     my %scantron_config =      my %scantron_config =
         &Apache::grades::get_scantron_config($env{'form.scantron_format'});          &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)=&Apache::grades::scantron_getfile();      my ($scanlines,$scan_data)=&Apache::grades::scantron_getfile();
     my $classlist=&Apache::loncoursedata::get_classlist();      my $classlist=&Apache::loncoursedata::get_classlist();
Line 9085  sub checkscantron_results { Line 9413  sub checkscantron_results {
   
     my $count=&get_todo_count($scanlines,$scan_data);      my $count=&get_todo_count($scanlines,$scan_data);
     my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,$count);      my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,$count);
     my ($username,$domain,$started,%ordered);      my ($username,$domain,$started);
     &scantron_get_maxbubble(\$nav_error,\%scantron_config); # 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());
Line 9162  sub checkscantron_results { Line 9490  sub checkscantron_results {
             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 $currcode;
                   if (exists($grader_randomlists_by_symb{$ressymb})) {
                       $currcode = $scancode;
                   }
                 (my $analysis,$parts) =                  (my $analysis,$parts) =
                     &scantron_partids_tograde($resource,$env{'request.course.id'},                      &scantron_partids_tograde($resource,$env{'request.course.id'},
                                               $username,$domain,undef,                                                $username,$domain,undef,
                                               $bubbles_per_row);                                                $bubbles_per_row,$currcode);
             } else {              } else {
                 $parts = $grader_partids_by_symb{$ressymb};                  $parts = $grader_partids_by_symb{$ressymb};
             }              }
Line 9197  sub checkscantron_results { Line 9529  sub checkscantron_results {
 '<td>'.&mt('Bubblesheet').'</td><td>'.$showscandata.'</td><td rowspan="2">'.$last.'</td><td rowspan="2">'.$pid.'</td>'."\n".  '<td>'.&mt('Bubblesheet').'</td><td>'.$showscandata.'</td><td rowspan="2">'.$last.'</td><td rowspan="2">'.$pid.'</td>'."\n".
 '</tr>'."\n".  '</tr>'."\n".
 '<tr class="'.$css_class.'">'."\n".  '<tr class="'.$css_class.'">'."\n".
 '<td>Submissions</td><td>'.$showrecord.'</td></tr>'."\n";  '<td>'.&mt('Submissions').'</td><td>'.$showrecord.'</td></tr>'."\n";
                     $passed ++;                      $passed ++;
                 } else {                  } else {
                     my $css_class = ($failed % 2)?'LC_odd_row':'LC_even_row';                      my $css_class = ($failed % 2)?'LC_odd_row':'LC_even_row';
                     $badstudents .= '<tr class="'.$css_class.'"><td>'.&mt('Bubblesheet').'</td><td><span class="LC_nobreak">'.$scandata{$pid}.'</span></td><td rowspan="2">'.$last.'</td><td rowspan="2">'.$pid.'</td>'."\n".                      $badstudents .= '<tr class="'.$css_class.'"><td>'.&mt('Bubblesheet').'</td><td><span class="LC_nobreak">'.$scandata{$pid}.'</span></td><td rowspan="2">'.$last.'</td><td rowspan="2">'.$pid.'</td>'."\n".
 '</tr>'."\n".  '</tr>'."\n".
 '<tr class="'.$css_class.'">'."\n".  '<tr class="'.$css_class.'">'."\n".
 '<td>Submissions</td><td><span class="LC_nobreak">'.$record{$pid}.'</span></td>'."\n".  '<td>'.&mt('Submissions').'</td><td><span class="LC_nobreak">'.$record{$pid}.'</span></td>'."\n".
 '</tr>'."\n";  '</tr>'."\n";
                     $failed ++;                      $failed ++;
                 }                  }
Line 9370  sub verify_scantron_grading { Line 9702  sub verify_scantron_grading {
     return ($counter,$record);      return ($counter,$record);
 }  }
   
 sub letter_to_digits {  
     my %lettdig = (  
                     A => 1,  
                     B => 2,  
                     C => 3,  
                     D => 4,  
                     E => 5,  
                     F => 6,  
                     G => 7,  
                     H => 8,  
                     I => 9,  
                     J => 0,  
                   );  
     return %lettdig;  
 }  
   
   
 #-------- end of section for handling grading scantron forms -------  #-------- end of section for handling grading scantron forms -------
 #  #
 #-------------------------------------------------------------------  #-------------------------------------------------------------------
Line 9709  GRADINGMENUJS Line 10024  GRADINGMENUJS
     return $result;      return $result;
 }  }
   
   sub substatus_options {
       return &Apache::lonlocal::texthash(
                                         'yes'       => 'with submissions',
                                         'queued'    => 'in grading queue',
                                         'graded'    => 'with ungraded submissions',
                                         'incorrect' => 'with incorrect submissions',
                                         'all'       => 'with any status',
                                         );
   }
   
 sub reset_perm {  sub reset_perm {
     undef(%perm);      undef(%perm);
 }  }
Line 9981  sub process_clicker_file { Line 10306  sub process_clicker_file {
             $result .=              $result .=
                  &Apache::lonhtmlcommon::confirm_success(                   &Apache::lonhtmlcommon::confirm_success(
                      &mt('No IDs found to determine correct answer'),1);                       &mt('No IDs found to determine correct answer'),1);
             return $result,.&show_grading_menu_form($symb);              return $result.&show_grading_menu_form($symb);
         }          }
     }      }
     if (length($env{'form.upfile'}) < 2) {      if (length($env{'form.upfile'}) < 2) {
Line 9991  sub process_clicker_file { Line 10316  sub process_clicker_file {
                         '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'),1);                          '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'),1);
         return $result.&show_grading_menu_form($symb);          return $result.&show_grading_menu_form($symb);
     }      }
       my $mimetype;
       if ($env{'form.upfiletype'} eq 'iclicker') {
           my $mm = new File::MMagic;
           $mimetype = $mm->checktype_contents($env{'form.upfile'});
           unless (($mimetype eq 'text/plain') || ($mimetype eq 'text/html')) {
               $result.= '<p>'.
                   &Apache::lonhtmlcommon::confirm_success(
                       &mt('File format is neither csv (iclicker 6) nor xml (iclicker 7)'),1).'</p>';
               return $result.&show_grading_menu_form($symb);
           }
       } elsif (($env{'form.upfiletype'} ne 'interwrite') && ($env{'form.upfiletype'} ne 'turning')) {
           $result .= '<p>'.
               &Apache::lonhtmlcommon::confirm_success(
                   &mt('Invalid clicker type: choose one of: i>clicker, Interwrite PRS, or Turning Technologies.'),1).'</p>';
           return $result.&show_grading_menu_form($symb);
       }
   
 # Were able to get all the info needed, now analyze the file  # Were able to get all the info needed, now analyze the file
   
Line 10018  ENDHEADER Line 10359  ENDHEADER
     my $errormsg='';      my $errormsg='';
     my $number=0;      my $number=0;
     if ($env{'form.upfiletype'} eq 'iclicker') {      if ($env{'form.upfiletype'} eq 'iclicker') {
  ($errormsg,$number)=&iclicker_eval(\@questiontitles,\%responses);          if ($mimetype eq 'text/plain') {
     }              ($errormsg,$number)=&iclicker_eval(\@questiontitles,\%responses);
     if ($env{'form.upfiletype'} eq 'interwrite') {          } elsif ($mimetype eq 'text/html') {
               ($errormsg,$number)=&iclickerxml_eval(\@questiontitles,\%responses);
           }
       } elsif ($env{'form.upfiletype'} eq 'interwrite') {
         ($errormsg,$number)=&interwrite_eval(\@questiontitles,\%responses);          ($errormsg,$number)=&interwrite_eval(\@questiontitles,\%responses);
     }      } elsif ($env{'form.upfiletype'} eq 'turning') {
     if ($env{'form.upfiletype'} eq 'turning') {  
         ($errormsg,$number)=&turning_eval(\@questiontitles,\%responses);          ($errormsg,$number)=&turning_eval(\@questiontitles,\%responses);
     }      }
     $result.='<br />'.&mt('Found [_1] question(s)',$number).'<br />'.      $result.='<br />'.&mt('Found [_1] question(s)',$number).'<br />'.
Line 10126  sub iclicker_eval { Line 10469  sub iclicker_eval {
     return ($errormsg,$number);      return ($errormsg,$number);
 }  }
   
   sub iclickerxml_eval {
       my ($questiontitles,$responses)=@_;
       my $number=0;
       my $errormsg='';
       my @state;
       my %respbyid;
       my $p = HTML::Parser->new
       (
           xml_mode => 1,
           start_h =>
               [sub {
                    my ($tagname,$attr) = @_;
                    push(@state,$tagname);
                    if ("@state" eq "ssn p") {
                        my $title = $attr->{qn};
                        $title =~ s/(^\s+|\s+$)//g;
                        $questiontitles->[$number]=$title;
                    } elsif ("@state" eq "ssn p v") {
                        my $id = $attr->{id};
                        my $entry = $attr->{ans};
                        $id=~s/^[\#0]+//;
                        $entry =~s/[^a-zA-Z0-9\.\*\-\+]+//g;
                        $respbyid{$id}[$number] = $entry;
                    }
               }, "tagname, attr"],
            end_h =>
                  [sub {
                      my ($tagname) = @_;
                      if ("@state" eq "ssn p") {
                          $number++;
                      }
                      pop(@state);
                   }, "tagname"],
       );
   
       $p->parse($env{'form.upfile'});
       $p->eof;
       foreach my $id (keys(%respbyid)) {
           $responses->{$id}=join(',',@{$respbyid{$id}});
       }
       return ($errormsg,$number);
   }
   
 sub interwrite_eval {  sub interwrite_eval {
     my ($questiontitles,$responses)=@_;      my ($questiontitles,$responses)=@_;
     my $number=0;      my $number=0;
Line 10324  sub navmap_errormsg { Line 10710  sub navmap_errormsg {
 }  }
   
 sub startpage {  sub startpage {
     my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$js) = @_;      my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$js,$onload) = @_;
       my %args;
       if ($onload) {
            my %loaditems = (
                           'onload' => $onload,
                         );
            $args{'add_entries'} = \%loaditems;
       }
     if ($nomenu) {      if ($nomenu) {
         $r->print(&Apache::loncommon::start_page("Student's Version",$js,{'only_body' => '1'}));          $args{'only_body'} = 1;
           $r->print(&Apache::loncommon::start_page("Student's Version",$js,\%args));
     } else {      } else {
         $r->print(&Apache::loncommon::start_page('Grading',$js,          $args{'bread_crumbs'} = $crumbs;
                                                  {'bread_crumbs' => $crumbs}));          $r->print(&Apache::loncommon::start_page('Grading',$js,\%args));
     }      }
     unless ($nodisplayflag) {      unless ($nodisplayflag) {
        $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp));         $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp));
Line 10411  sub handler { Line 10805  sub handler {
         }          }
         &Apache::loncommon::content_type($request,'text/html');          &Apache::loncommon::content_type($request,'text/html');
         $request->send_http_header;          $request->send_http_header;
         unless ((($command eq 'submission' || $command eq 'versionsub')) && ($perm{'vgr'})) {          if (($command eq 'scantron_selectphase' && $perm{'mgr'}) ||
             $request->print($start_page);               (($command eq 'scantronupload') &&
                (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) ||
                 &Apache::lonnet::allowed('usc',$env{'request.course.id'})))) {
               &startpage($request,$symb,[{href=>'/adm/grades', text=>"Grading"}],1,1,
                          undef,undef,undef,undef,'toggleScantab(document.rules);');
           } else {
               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);              my ($stuvcurrent,$stuvdisp,$versionform,$js);
Line 10546  At least the logic that drives this has Line 10948  At least the logic that drives this has
 ssi_with_retries - Does the server side include of a resource.  ssi_with_retries - Does the server side include of a resource.
                      if the ssi call returns an error we'll retry it up to                       if the ssi call returns an error we'll retry it up to
                      the number of times requested by the caller.                       the number of times requested by the caller.
                      If we still have a proble, no text is appended to the                       If we still have a problem, no text is appended to the
                      output and we set some global variables.                       output and we set some global variables.
                      to indicate to the caller an SSI error occurred.                         to indicate to the caller an SSI error occurred.  
                      All of this is supposed to deal with the issues described                       All of this is supposed to deal with the issues described
                      in LonCAPA BZ 5631 see:                       in LON-CAPA BZ 5631 see:
                      http://bugs.lon-capa.org/show_bug.cgi?id=5631                       http://bugs.lon-capa.org/show_bug.cgi?id=5631
                      by informing the user that this happened.                       by informing the user that this happened.
   
Line 10591  ssi_with_retries() Line 10993  ssi_with_retries()
     $r           - Apache request object      $r           - Apache request object
     $i           - number of the current scanline      $i           - number of the current scanline
     $scan_record - hash ref as returned from &scantron_parse_scanline()      $scan_record - hash ref as returned from &scantron_parse_scanline()
     $scan_config - hash ref as returned from &get_scantron_config()      $scan_config - hash ref as returned from &Apache::lonnet::get_scantron_config()
     $line        - full contents of the current scanline      $line        - full contents of the current scanline
     $error       - error condition, valid values are      $error       - error condition, valid values are
                    'incorrectCODE', 'duplicateCODE',                     'incorrectCODE', 'duplicateCODE',

Removed from v.1.596.2.12.2.25  
changed lines
  Added in v.1.596.2.12.2.49


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