Diff for /loncom/homework/grades.pm between versions 1.582 and 1.596.2.12.2.1

version 1.582, 2009/12/09 17:53:55 version 1.596.2.12.2.1, 2012/05/02 14:01:32
Line 40  use Apache::lonhomework; Line 40  use Apache::lonhomework;
 use Apache::lonpickcode;  use Apache::lonpickcode;
 use Apache::loncoursedata;  use Apache::loncoursedata;
 use Apache::lonmsg();  use Apache::lonmsg();
 use Apache::Constants qw(:common);  use Apache::Constants qw(:common :http);
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonenc;  use Apache::lonenc;
   use Apache::bridgetask();
 use String::Similarity;  use String::Similarity;
 use LONCAPA;  use LONCAPA;
   
Line 127  sub get_symb { Line 128  sub get_symb {
     my $symb=($env{'form.symb'} ne '' ? $env{'form.symb'} : (&Apache::lonnet::symbread($url)));      my $symb=($env{'form.symb'} ne '' ? $env{'form.symb'} : (&Apache::lonnet::symbread($url)));
     if ($symb eq '') {       if ($symb eq '') { 
  if (!$silent) {   if (!$silent) {
     $request->print("Unable to handle ambiguous references:$url:.");              $request->print(&mt("Unable to handle ambiguous references: [_1].",$url));
     return ();      return ();
  }   }
     }      }
Line 160  sub response_type { Line 161  sub response_type {
         return;          return;
     }      }
     my $res = $navmap->getBySymb($symb);      my $res = $navmap->getBySymb($symb);
       unless (ref($res)) {
           $$response_error = 1;
           return;
       }
     my $partlist = $res->parts();      my $partlist = $res->parts();
     my %vPart =       my %vPart = 
  map { $_ => 1 } (&Apache::loncommon::get_env_multiple('form.vPart'));   map { $_ => 1 } (&Apache::loncommon::get_env_multiple('form.vPart'));
Line 207  sub get_display_part { Line 212  sub get_display_part {
 #--- and parts and response type  #--- and parts and response type
 sub showResourceInfo {  sub showResourceInfo {
     my ($symb,$probTitle,$checkboxes,$res_error) = @_;      my ($symb,$probTitle,$checkboxes,$res_error) = @_;
     my $col=3;  
     if ($checkboxes) { $col=4; }  
     my $result = '<h3>'.&mt('Current Resource').': '.$probTitle.'</h3>'."\n";      my $result = '<h3>'.&mt('Current Resource').': '.$probTitle.'</h3>'."\n";
     my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error);      my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error);
     if (ref($res_error)) {      if (ref($res_error)) {
Line 216  sub showResourceInfo { Line 219  sub showResourceInfo {
             return;              return;
         }          }
     }      }
     $result .='<table border="0">';      $result.=&Apache::loncommon::start_data_table()
               .&Apache::loncommon::start_data_table_header_row();
       if ($checkboxes) {
           $result.='<th>&nbsp;</th>';
       }
       $result.='<th>'.&mt('Problem Part').'</th>'
               .'<th>'.&mt('Res. ID').'</th>'
               .'<th>'.&mt('Type').'</th>'
               .&Apache::loncommon::end_data_table_header_row();
     my %resptype = ();      my %resptype = ();
     my $hdgrade='no';      my $hdgrade='no';
     my %partsseen;      my %partsseen;
     foreach my $partID (sort(keys(%$responseType))) {      foreach my $partID (sort(keys(%$responseType))) {
  foreach my $resID (sort(keys(%{ $responseType->{$partID} }))) {          foreach my $resID (sort(keys(%{ $responseType->{$partID} }))) {
     my $handgrade=$$handgrade{$partID.'_'.$resID};              my $handgrade=$$handgrade{$partID.'_'.$resID};
     my $responsetype = $responseType->{$partID}->{$resID};              my $responsetype = $responseType->{$partID}->{$resID};
     $hdgrade = $handgrade if ($handgrade eq 'yes');              $hdgrade = $handgrade if ($handgrade eq 'yes');
     $result.='<tr>';              $result.=&Apache::loncommon::start_data_table_row();
     if ($checkboxes) {              if ($checkboxes) {
  if (exists($partsseen{$partID})) {                  if (exists($partsseen{$partID})) {
     $result.="<td>&nbsp;</td>";                      $result.="<td>&nbsp;</td>";
  } else {                  } else {
     $result.="<td><input type='checkbox' name='vPart' value='$partID' checked='checked' /></td>";                      $result.="<td><input type='checkbox' name='vPart' value='$partID' checked='checked' /></td>";
  }                  }
  $partsseen{$partID}=1;                  $partsseen{$partID}=1;
     }              }
     my $display_part=&get_display_part($partID,$symb);              my $display_part=&get_display_part($partID,$symb);
             $result.='<td><b>'.&mt('Part: [_1]',$display_part).'</b>'.              $result.='<td>'.$display_part.'</td>'
                 ' <span class="LC_internal_info">'.$resID.'</span></td>'.                      .'<td>'.'<span class="LC_internal_info">'.$resID.'</span></td>'
                 '<td><b>'.&mt('Type: [_1]',$responsetype).'</b></td></tr>';                      .'<td>'.&mt($responsetype).'</td>'
 #    '<td>'.&mt('<b>Handgrade: </b>[_1]',$handgrade).'</td></tr>';  #                   .'<td>'.&mt('<b>Handgrade: </b>[_1]',$handgrade).'</td>'
  }                      .&Apache::loncommon::end_data_table_row();
           }
     }      }
     $result.='</table>'."\n";      $result.=&Apache::loncommon::end_data_table();
     return $result,$responseType,$hdgrade,$partlist,$handgrade;      return $result,$responseType,$hdgrade,$partlist,$handgrade;
 }  }
   
Line 260  sub reset_caches { Line 272  sub reset_caches {
     }      }
   
     sub get_analyze {      sub get_analyze {
  my ($symb,$uname,$udom,$no_increment,$add_to_hash)=@_;   my ($symb,$uname,$udom,$no_increment,$add_to_hash,$type,$trial,$rndseed,$bubbles_per_row)=@_;
  my $key = "$symb\0$uname\0$udom";   my $key = "$symb\0$uname\0$udom";
           if ($type eq 'randomizetry') {
               if ($trial ne '') {
                   $key .= "\0".$trial;
               }
           }
  if (exists($analyze_cache{$key})) {   if (exists($analyze_cache{$key})) {
             my $getupdate = 0;              my $getupdate = 0;
             if (ref($add_to_hash) eq 'HASH') {              if (ref($add_to_hash) eq 'HASH') {
Line 289  sub reset_caches { Line 306  sub reset_caches {
                     'grade_courseid'    =>  $env{'request.course.id'},                      'grade_courseid'    =>  $env{'request.course.id'},
                     'grade_username'    => $uname,                      'grade_username'    => $uname,
                     'grade_noincrement' => $no_increment);                      'grade_noincrement' => $no_increment);
           if ($bubbles_per_row ne '') {
               $form{'bubbles_per_row'} = $bubbles_per_row;
           }
           if ($type eq 'randomizetry') {
               $form{'grade_questiontype'} = $type;
               if ($rndseed ne '') {
                   $form{'grade_rndseed'} = $rndseed;
               }
           }
         if (ref($add_to_hash)) {          if (ref($add_to_hash)) {
             %form = (%form,%{$add_to_hash});              %form = (%form,%{$add_to_hash});
         }           }
  my $subresult=&ssi_with_retries($url, $ssi_retries,%form);   my $subresult=&ssi_with_retries($url, $ssi_retries,%form);
  (undef,$subresult)=split(/_HASH_REF__/,$subresult,2);   (undef,$subresult)=split(/_HASH_REF__/,$subresult,2);
  my %analyze=&Apache::lonnet::str2hash($subresult);   my %analyze=&Apache::lonnet::str2hash($subresult);
Line 304  sub reset_caches { Line 330  sub reset_caches {
     }      }
   
     sub get_order {      sub get_order {
  my ($partid,$respid,$symb,$uname,$udom,$no_increment)=@_;   my ($partid,$respid,$symb,$uname,$udom,$no_increment,$type,$trial,$rndseed)=@_;
  my $analyze = &get_analyze($symb,$uname,$udom,$no_increment);   my $analyze = &get_analyze($symb,$uname,$udom,$no_increment,undef,$type,$trial,$rndseed);
  return $analyze->{"$partid.$respid.shown"};   return $analyze->{"$partid.$respid.shown"};
     }      }
   
     sub get_radiobutton_correct_foil {      sub get_radiobutton_correct_foil {
  my ($partid,$respid,$symb,$uname,$udom)=@_;   my ($partid,$respid,$symb,$uname,$udom,$type,$trial,$rndseed)=@_;
  my $analyze = &get_analyze($symb,$uname,$udom);   my $analyze = &get_analyze($symb,$uname,$udom,undef,undef,$type,$trial,$rndseed);
         my $foils = &get_order($partid,$respid,$symb,$uname,$udom);          my $foils = &get_order($partid,$respid,$symb,$uname,$udom,undef,$type,$trial,$rndseed);
         if (ref($foils) eq 'ARRAY') {          if (ref($foils) eq 'ARRAY') {
     foreach my $foil (@{$foils}) {      foreach my $foil (@{$foils}) {
         if ($analyze->{"$partid.$respid.foil.value.$foil"} eq 'true') {          if ($analyze->{"$partid.$respid.foil.value.$foil"} eq 'true') {
Line 323  sub reset_caches { Line 349  sub reset_caches {
     }      }
   
     sub scantron_partids_tograde {      sub scantron_partids_tograde {
         my ($resource,$cid,$uname,$udom,$check_for_randomlist) = @_;          my ($resource,$cid,$uname,$udom,$check_for_randomlist,$bubbles_per_row) = @_;
         my (%analysis,@parts);          my (%analysis,@parts);
         if (ref($resource)) {          if (ref($resource)) {
             my $symb = $resource->symb();              my $symb = $resource->symb();
Line 331  sub reset_caches { Line 357  sub reset_caches {
             if ($check_for_randomlist) {              if ($check_for_randomlist) {
                 $add_to_form = { 'check_parts_withrandomlist' => 1,};                  $add_to_form = { 'check_parts_withrandomlist' => 1,};
             }              }
             my $analyze = &get_analyze($symb,$uname,$udom,undef,$add_to_form);              my $analyze =
                   &get_analyze($symb,$uname,$udom,undef,$add_to_form,
                                undef,undef,undef,$bubbles_per_row);
             if (ref($analyze) eq 'HASH') {              if (ref($analyze) eq 'HASH') {
                 %analysis = %{$analyze};                  %analysis = %{$analyze};
             }              }
Line 354  sub reset_caches { Line 382  sub reset_caches {
 #        response types only.  #        response types only.
 sub cleanRecord {  sub cleanRecord {
     my ($answer,$response,$symb,$partid,$respid,$record,$order,$version,      my ($answer,$response,$symb,$partid,$respid,$record,$order,$version,
  $uname,$udom) = @_;   $uname,$udom,$type,$trial,$rndseed) = @_;
     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);
Line 371  sub cleanRecord { Line 399  sub cleanRecord {
  return '<blockquote><table border="1">'.   return '<blockquote><table border="1">'.
     '<tr valign="top"><td>'.&mt('Answer').'</td>'.$toprow.'</tr>'.      '<tr valign="top"><td>'.&mt('Answer').'</td>'.$toprow.'</tr>'.
     '<tr valign="top"><td>'.$grayFont.&mt('Option ID').'</span></td>'.      '<tr valign="top"><td>'.$grayFont.&mt('Option ID').'</span></td>'.
     $grayFont.$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 %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"});   my %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"});
Line 393  sub cleanRecord { Line 421  sub cleanRecord {
     '<tr valign="top"><td>'.$grayFont.&mt('Item ID').'</span></td>'.      '<tr valign="top"><td>'.$grayFont.&mt('Item ID').'</span></td>'.
     $middlerow.'</tr>'.      $middlerow.'</tr>'.
     '<tr valign="top"><td>'.$grayFont.&mt('Option ID').'</span></td>'.      '<tr valign="top"><td>'.$grayFont.&mt('Option ID').'</span></td>'.
     $bottomrow.'</tr>'.'</table></blockquote>';      $bottomrow.'</tr></table></blockquote>';
     } elsif ($response eq 'radiobutton') {      } elsif ($response eq 'radiobutton') {
  my %answer=&Apache::lonnet::str2hash($answer);   my %answer=&Apache::lonnet::str2hash($answer);
  my ($toprow,$bottomrow);   my ($toprow,$bottomrow);
  my $correct =    my $correct = 
     &get_radiobutton_correct_foil($partid,$respid,$symb,$uname,$udom);      &get_radiobutton_correct_foil($partid,$respid,$symb,$uname,$udom,$type,$trial,$rndseed);
  foreach my $foil (@$order) {   foreach my $foil (@$order) {
     if (exists($answer{$foil})) {      if (exists($answer{$foil})) {
  if ($foil eq $correct) {   if ($foil eq $correct) {
Line 414  sub cleanRecord { Line 442  sub cleanRecord {
  return '<blockquote><table border="1">'.   return '<blockquote><table border="1">'.
     '<tr valign="top"><td>'.&mt('Answer').'</td>'.$toprow.'</tr>'.      '<tr valign="top"><td>'.&mt('Answer').'</td>'.$toprow.'</tr>'.
     '<tr valign="top"><td>'.$grayFont.&mt('Option ID').'</span></td>'.      '<tr valign="top"><td>'.$grayFont.&mt('Option ID').'</span></td>'.
     $grayFont.$bottomrow.'</tr>'.'</table></blockquote>';      $bottomrow.'</tr></table></blockquote>';
     } elsif ($response eq 'essay') {      } elsif ($response eq 'essay') {
  if (! exists ($env{'form.'.$symb})) {   if (! exists ($env{'form.'.$symb})) {
     my (%keyhash) = &Apache::lonnet::dump('nohist_handgrade',      my (%keyhash) = &Apache::lonnet::dump('nohist_handgrade',
Line 723  sub most_similar { Line 751  sub most_similar {
   
 # ignore empty submissions (occuring when only files are sent)  # ignore empty submissions (occuring when only files are sent)
   
     unless ($uessay=~/\w+/) { return ''; }      unless ($uessay=~/\w+/s) { return ''; }
   
 # these will be returned. Do not care if not at least 50 percent similar  # these will be returned. Do not care if not at least 50 percent similar
     my $limit=0.6;      my $limit=0.6;
Line 772  sub verifyreceipt { Line 800  sub verifyreceipt {
   
     my $title.=      my $title.=
  '<h3><span class="LC_info">'.   '<h3><span class="LC_info">'.
  &mt('Verifying  Receipt No. [_1]',$receipt).   &mt('Verifying Receipt No. [_1]',$receipt).
  '</span></h3>'."\n".   '</span></h3>'."\n".
  '<h4>'.&mt('<b>Resource: </b>[_1]',$env{'form.probTitle'}).   '<h4>'.&mt('<b>Resource: </b>[_1]',$env{'form.probTitle'}).
  '</h4>'."\n";   '</h4>'."\n";
Line 832  sub verifyreceipt { Line 860  sub verifyreceipt {
  }   }
     }      }
     if ($matches == 0) {      if ($matches == 0) {
  $string = $title.&mt('No match found for the above receipt.');          $string = $title
                    .'<p class="LC_warning">'
                    .&mt('No match found for the above receipt number.')
                    .'</p>';
     } else {      } else {
  $string = &jscriptNform($symb).$title.   $string = &jscriptNform($symb).$title.
     '<p>'.      '<p>'.
     &mt('The above receipt matches the following [numerate,_1,student].',$matches).      &mt('The above receipt number matches the following [quant,_1,student].',$matches).
     '</p>'.      '</p>'.
     $header.      $header.
     $contents.      $contents.
Line 934  LISTJAVASCRIPT Line 965  LISTJAVASCRIPT
     my $saveStatus = $stu_status eq '' ? 'Active' : $stu_status;      my $saveStatus = $stu_status eq '' ? 'Active' : $stu_status;
     $env{'form.Status'} = $saveStatus;      $env{'form.Status'} = $saveStatus;
     $submission_options.=      $submission_options.=
  '<label><input type="radio" name="lastSub" value="lastonly" '.$checklastsub.' /> '.&mt('last submission only').' </label>'."\n".          '<span class="LC_nobreak">'.
  '<label><input type="radio" name="lastSub" value="last" /> '.&mt('last submission &amp; parts info').' </label>'."\n".          '<label><input type="radio" name="lastSub" value="lastonly" '.$checklastsub.' /> '.
  '<label><input type="radio" name="lastSub" value="datesub" /> '.&mt('by dates and submissions').' </label>'."\n".          &mt('last submission only').' </label></span>'."\n".
  '<label><input type="radio" name="lastSub" value="all" /> '.&mt('all details').'</label>';          '<span class="LC_nobreak">'.
           '<label><input type="radio" name="lastSub" value="last" /> '.
           &mt('last submission &amp; parts info').' </label></span>'."\n".
           '<span class="LC_nobreak">'.
           '<label><input type="radio" name="lastSub" value="datesub" /> '.
           &mt('by dates and submissions').'</label></span>'."\n".
           '<span class="LC_nobreak">'.
           '<label><input type="radio" name="lastSub" value="all" /> '.
           &mt('all details').'</label></span>';
     $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Submissions'))      $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Submissions'))
                   .$submission_options                    .$submission_options
                   .&Apache::lonhtmlcommon::row_closure();                    .&Apache::lonhtmlcommon::row_closure();
Line 983  LISTJAVASCRIPT Line 1022  LISTJAVASCRIPT
 # checkall buttons  # checkall buttons
     $gradeTable.=&check_script('gradesub', 'stuinfo');      $gradeTable.=&check_script('gradesub', 'stuinfo');
     $gradeTable.='<input type="button" '."\n".      $gradeTable.='<input type="button" '."\n".
  'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n".          'onclick="javascript:checkSelect(this.form.stuinfo);" '."\n".
  'value="'.&mt('Next').' &rarr;" /> <br />'."\n";          'value="'.&mt('Next').' &rarr;" /> <br />'."\n";
     $gradeTable.=&check_buttons();      $gradeTable.=&check_buttons();
     my ($classlist, undef, $fullname) = &getclasslist($getsec,'1',$getgroup);      my ($classlist, undef, $fullname) = &getclasslist($getsec,'1',$getgroup);
     $gradeTable.= &Apache::loncommon::start_data_table().      $gradeTable.= &Apache::loncommon::start_data_table().
Line 1101  LISTJAVASCRIPT Line 1140  LISTJAVASCRIPT
     }      }
   
     $gradeTable.=&Apache::loncommon::end_data_table()."\n".      $gradeTable.=&Apache::loncommon::end_data_table()."\n".
  '<input type="button" '.          '<input type="button" '.
  'onClick="javascript:checkSelect(this.form.stuinfo);" '.          'onclick="javascript:checkSelect(this.form.stuinfo);" '.
  'value="'.&mt('Next').' &rarr;" /></form>'."\n";          'value="'.&mt('Next').' &rarr;" /></form>'."\n";
     if ($ctr == 0) {      if ($ctr == 0) {
  my $num_students=(scalar(keys(%$fullname)));   my $num_students=(scalar(keys(%$fullname)));
  if ($num_students eq 0) {   if ($num_students eq 0) {
Line 1455  INNERJS Line 1494  INNERJS
   
     my $docopen=&Apache::lonhtmlcommon::javascript_docopen();      my $docopen=&Apache::lonhtmlcommon::javascript_docopen();
     $docopen=~s/^document\.//;      $docopen=~s/^document\.//;
     my $alertmsg = &mt('Please select a word or group of words from document and then click this link.');      my %lt = &Apache::lonlocal::texthash(
                   keyw => 'Keywords list, separated by a space. Add/delete to list if desired.',
                   plse => 'Please select a word or group of words from document and then click this link.',
                   adds => 'Add selection to keyword list? Edit if desired.',
                   comp => 'Compose Message for: ',
                   incl => 'Include',
                   type => 'Type',
                   subj => 'Subject',
                   mesa => 'Message',
                   new  => 'New',
                   save => 'Save',
                   canc => 'Cancel',
                   kehi => 'Keyword Highlight Options',
                   txtc => 'Text Color',
                   font => 'Font Size',
                   fnst => 'Font Style',
                );
     $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("Keywords list, separated by a space. Add/delete to list if desired.",formname.keywords.value);      var nret = prompt("$lt{'keyw'}",formname.keywords.value);
     if (nret==null) return;      if (nret==null) return;
     formname.keywords.value = nret;      formname.keywords.value = nret;
   
Line 1488  INNERJS Line 1543  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("$alertmsg");   alert("$lt{'plse'}");
  return;   return;
     }      }
     var nret = prompt("Add selection to keyword list? Edit if desired.",cleantxt);      var nret = prompt("$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 1565  INNERJS Line 1620  INNERJS
     var ypos = (screen.height-height)/2-30;      var ypos = (screen.height-height)/2-30;
     ypos = (ypos < 0) ? '0' : ypos;      ypos = (ypos < 0) ? '0' : ypos;
   
     pWin = window.open('', 'MessageCenter', 'resizable=yes,toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=600,height='+height);      pWin = window.open('', 'MessageCenter', 'resizable=yes,toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=700,height='+height);
     pWin.focus();      pWin.focus();
     pDoc = pWin.document;      pDoc = pWin.document;
     pDoc.$docopen;      pDoc.$docopen;
Line 1573  INNERJS Line 1628  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;Compose Message for \"+fullname+\"<\\/span><\\/h3><br /><br />");      pDoc.write("<h3><span class=\\"LC_info\\">&nbsp;$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>Type<\\/b><\\/td><td><b>Include<\\/b><\\/td><td><b>Message<\\/td><\\/tr>");      pDoc.write("<td><b>$lt{'type'}<\\/b><\\/td><td><b>$lt{'incl'}<\\/b><\\/td><td><b>$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>Subject<\\/td>");      pDoc.write("<td>$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 1598  INNERJS Line 1653  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\\">New<\\/td>");      pDoc.write("<td align=\\"center\\">$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 1607  INNERJS Line 1662  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=\\"Save\\" onClick=\\"javascript:checkInput()\\">&nbsp;&nbsp;");      pDoc.write("<input type=\\"button\\" value=\\"$lt{'save'}\\" onclick=\\"javascript:checkInput()\\">&nbsp;&nbsp;");
     pDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br /><br />");      pDoc.write("<input type=\\"button\\" value=\\"$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 1658  INNERJS Line 1713  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;Keyword Highlight Options<\\/span><\\/h3><br /><br />");      hDoc.write("<h3><span class=\\"LC_info\\">&nbsp;$lt{'kehi'}<\\/span><\\/h3><br /><br />");
   
     hDoc.write('<table border="0" width="100%"><tr><td bgcolor="#777777">');      hDoc.write('<table border="0" width="100%"><tr><td bgcolor="#777777">');
     hDoc.write('<table border="0" width="100%"><tr bgcolor="#DDFFFF">');      hDoc.write('<table border="0" width="100%"><tr bgcolor="#DDFFFF">');
     hDoc.write("<td><b>Text Color<\\/b><\\/td><td><b>Font Size<\\/b><\\/td><td><b>Font Style<\\/td><\\/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) { 
Line 1681  INNERJS Line 1736  INNERJS
     var hDoc = hwdWin.document;      var hDoc = hwdWin.document;
     hDoc.write("<\\/table>");      hDoc.write("<\\/table>");
     hDoc.write("<\\/td><\\/tr><\\/table>&nbsp;");      hDoc.write("<\\/td><\\/tr><\\/table>&nbsp;");
     hDoc.write("<input type=\\"button\\" value=\\"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=\\"Cancel\\" 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 1701  sub get_increment { Line 1756  sub get_increment {
     return $increment;      return $increment;
 }  }
   
   sub gradeBox_start {
       return (
           &Apache::loncommon::start_data_table()
          .&Apache::loncommon::start_data_table_header_row()
          .'<th>'.&mt('Part').'</th>'
          .'<th>'.&mt('Points').'</th>'
          .'<th>&nbsp;</th>'
          .'<th>'.&mt('Assign Grade').'</th>'
          .'<th>'.&mt('Weight').'</th>'
          .'<th>'.&mt('Grade Status').'</th>'
          .&Apache::loncommon::end_data_table_header_row()
       );
   }
   
   sub gradeBox_end {
       return (
           &Apache::loncommon::end_data_table()
       );
   }
 #--- displays the grading box, used in essay type problem and grading by page/sequence  #--- displays the grading box, used in essay type problem and grading by page/sequence
 sub gradeBox {  sub gradeBox {
     my ($request,$symb,$uname,$udom,$counter,$partid,$record) = @_;      my ($request,$symb,$uname,$udom,$counter,$partid,$record) = @_;
Line 1720  sub gradeBox { Line 1794  sub gradeBox {
     if ($last_resets{$partid}) {      if ($last_resets{$partid}) {
         $aggtries = &get_num_tries($record,$last_resets{$partid},$partid);          $aggtries = &get_num_tries($record,$last_resets{$partid},$partid);
     }      }
     $result.='<table border="0"><tr>';      $result.=&Apache::loncommon::start_data_table_row();
     my $ctr = 0;      my $ctr = 0;
     my $thisweight = 0;      my $thisweight = 0;
     my $increment = &get_increment();      my $increment = &get_increment();
Line 1728  sub gradeBox { Line 1802  sub gradeBox {
     my $radio.='<table border="0"><tr>'."\n";  # display radio buttons in a nice table 10 across      my $radio.='<table border="0"><tr>'."\n";  # display radio buttons in a nice table 10 across
     while ($thisweight<=$wgt) {      while ($thisweight<=$wgt) {
  $radio.= '<td><span class="LC_nobreak"><label><input type="radio" name="RADVAL'.$counter.'_'.$partid.'" '.   $radio.= '<td><span class="LC_nobreak"><label><input type="radio" name="RADVAL'.$counter.'_'.$partid.'" '.
     'onclick="javascript:writeBox(this.form,\''.$counter.'_'.$partid.'\','.          'onclick="javascript:writeBox(this.form,\''.$counter.'_'.$partid.'\','.
     $thisweight.')" value="'.$thisweight.'" '.      $thisweight.')" value="'.$thisweight.'" '.
     ($score eq $thisweight ? 'checked="checked"':'').' /> '.$thisweight."</label></span></td>\n";      ($score eq $thisweight ? 'checked="checked"':'').' /> '.$thisweight."</label></span></td>\n";
  $radio.=(($ctr+1)%10 == 0 ? '</tr><tr>' : '');   $radio.=(($ctr+1)%10 == 0 ? '</tr><tr>' : '');
Line 1739  sub gradeBox { Line 1813  sub gradeBox {
   
     my $line.='<input type="text" name="GD_BOX'.$counter.'_'.$partid.'"'.      my $line.='<input type="text" name="GD_BOX'.$counter.'_'.$partid.'"'.
  ($score ne ''? ' value = "'.$score.'"':'').' size="4" '.   ($score ne ''? ' value = "'.$score.'"':'').' size="4" '.
  'onChange="javascript:updateRadio(this.form,\''.$counter.'_'.$partid.'\','.   'onchange="javascript:updateRadio(this.form,\''.$counter.'_'.$partid.'\','.
  $wgt.')" /></td>'."\n";   $wgt.')" /></td>'."\n";
     $line.='<td>/'.$wgt.' '.$wgtmsg.      $line.='<td>/'.$wgt.' '.$wgtmsg.
  ($$record{'resource.'.$partid.'.solved'} eq 'correct_by_student' ? '&nbsp;'.$checkIcon : '').   ($$record{'resource.'.$partid.'.solved'} eq 'correct_by_student' ? '&nbsp;'.$checkIcon : '').
  ' </td><td><b>'.&mt('Grade Status').':</b>'."\n";   ' </td>'."\n";
     $line.='<select name="GD_SEL'.$counter.'_'.$partid.'" '.      $line.='<td><select name="GD_SEL'.$counter.'_'.$partid.'" '.
  'onChange="javascript:clearRadBox(this.form,\''.$counter.'_'.$partid.'\')" >'."\n";   'onchange="javascript:clearRadBox(this.form,\''.$counter.'_'.$partid.'\')" >'."\n";
     if ($$record{'resource.'.$partid.'.solved'} eq 'excused') {      if ($$record{'resource.'.$partid.'.solved'} eq 'excused') {
  $line.='<option></option>'.   $line.='<option></option>'.
     '<option value="excused" selected="selected">'.&mt('excused').'</option>';      '<option value="excused" selected="selected">'.&mt('excused').'</option>';
Line 1756  sub gradeBox { Line 1830  sub gradeBox {
     $line.='<option value="reset status">'.&mt('reset status').'</option></select>'."\n";      $line.='<option value="reset status">'.&mt('reset status').'</option></select>'."\n";
   
   
  #&mt('<td><b>Part:</b></td><td>[_1]</td><td><b>Points:</b></td><td>[_2]</td><td>or</td><td>[_3]</td>',$display_part,$radio,$line);  
     $result .=       $result .= 
     '<td><b>'.&mt('Part:').'</b></td><td>'.$display_part.'</td><td><b>'.&mt('Points:').'</b></td><td>'.$radio.'</td><td>'.&mt('or').'</td><td>'.$line.'</td>';      '<td>'.$display_part.'</td><td>'.$radio.'</td><td>'.&mt('or').'</td><td>'.$line.'</td>';
     $result.='</tr></table>'."\n";      $result.=&Apache::loncommon::end_data_table_row();
     $result.='<input type="hidden" name="stores'.$counter.'_'.$partid.'" value="" />'."\n".      $result.='<input type="hidden" name="stores'.$counter.'_'.$partid.'" value="" />'."\n".
  '<input type="hidden" name="oldpts'.$counter.'_'.$partid.'" value="'.$score.'" />'."\n".   '<input type="hidden" name="oldpts'.$counter.'_'.$partid.'" value="'.$score.'" />'."\n".
  '<input type="hidden" name="solved'.$counter.'_'.$partid.'" value="'.   '<input type="hidden" name="solved'.$counter.'_'.$partid.'" value="'.
Line 1780  sub handback_box { Line 1853  sub handback_box {
     my ($symb,$uname,$udom,$counter,$partid,$record,$res_error) = @_;      my ($symb,$uname,$udom,$counter,$partid,$record,$res_error) = @_;
     my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error);      my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error);
     my (@respids);      my (@respids);
      my @part_response_id = &flatten_responseType($responseType);      my @part_response_id = &flatten_responseType($responseType);
     foreach my $part_response_id (@part_response_id) {      foreach my $part_response_id (@part_response_id) {
     my ($part,$resp) = @{ $part_response_id };      my ($part,$resp) = @{ $part_response_id };
         if ($part eq $partid) {          if ($part eq $partid) {
Line 1792  sub handback_box { Line 1865  sub handback_box {
  my $prefix = $counter.'_'.$partid.'_'.$respid.'_';   my $prefix = $counter.'_'.$partid.'_'.$respid.'_';
  my $files=&get_submitted_files($udom,$uname,$partid,$respid,$record);   my $files=&get_submitted_files($udom,$uname,$partid,$respid,$record);
  next if (!@$files);   next if (!@$files);
  my $file_counter = 1;   my $file_counter = 0;
  foreach my $file (@$files) {   foreach my $file (@$files) {
     if ($file =~ /\/portfolio\//) {      if ($file =~ /\/portfolio\//) {
                   $file_counter++;
            my ($file_path, $file_disp) = ($file =~ m|(.+/)(.+)$|);             my ($file_path, $file_disp) = ($file =~ m|(.+/)(.+)$|);
            my ($name,$version,$ext) = &file_name_version_ext($file_disp);             my ($name,$version,$ext) = &file_name_version_ext($file_disp);
            $file_disp = "$name.$ext";             $file_disp = "$name.$ext";
Line 1802  sub handback_box { Line 1876  sub handback_box {
            $result.=&mt('Return commented version of [_1] to student.',             $result.=&mt('Return commented version of [_1] to student.',
     '<span class="LC_filename">'.$file_disp.'</span>');      '<span class="LC_filename">'.$file_disp.'</span>');
            $result.='<input type="file"   name="'.$prefix.'returndoc'.$file_counter.'" />'."\n";             $result.='<input type="file"   name="'.$prefix.'returndoc'.$file_counter.'" />'."\n";
            $result.='<input type="hidden" name="'.$prefix.'origdoc'.$file_counter.'" value="'.$file.'" /><br />';             $result.='<input type="hidden" name="'.$prefix.'origdoc'.$file_counter.'" value="'.$file.'" /><br />'."\n";
            $result.='('.&mt('File will be uploaded when you click on Save &amp; Next below.').')<br />';  
            $file_counter++;  
     }      }
  }   }
           if ($file_counter) {
               $result .= '<input type="hidden" name="'.$prefix.'countreturndoc" value="'.$file_counter.'" />'."\n".
                          '<span class="LC_info">'.
                          '('.&mt('File(s) will be uploaded when you click on Save &amp; Next below.',$file_counter).')</span><br /><br />';
           }
     }      }
     return $result;          return $result;    
 }  }
Line 1840  sub show_problem { Line 1917  sub show_problem {
  $companswer=~s|name="submit"|name="would_have_been_submit"|g;   $companswer=~s|name="submit"|name="would_have_been_submit"|g;
     }      }
     $rendered=      $rendered=
  '<div class="LC_grade_show_problem_header">'.          '<div class="LC_Box">'
  &mt('View of the problem').         .'<h3 class="LC_hcell">'.&mt('View of the problem').'</h3>'
  '</div><div class="LC_grade_show_problem_problem">'.         .$rendered
  $rendered.         .'</div>';
  '</div>';  
     $companswer=      $companswer=
  '<div class="LC_grade_show_problem_header">'.          '<div class="LC_Box">'
  &mt('Correct answer').         .'<h3 class="LC_hcell">'.&mt('Correct answer').'</h3>'
  '</div><div class="LC_grade_show_problem_problem">'.         .$companswer
  $companswer.         .'</div>';
  '</div>';  
     my $result;      my $result;
     if ($mode eq 'both') {      if ($mode eq 'both') {
  $result=$rendered.$companswer;          $result=$rendered.$companswer;
     } elsif ($mode eq 'text') {      } elsif ($mode eq 'text') {
  $result=$rendered;          $result=$rendered;
     } elsif ($mode eq 'answer') {      } elsif ($mode eq 'answer') {
  $result=$companswer;          $result=$companswer;
     }      }
     $result='<div class="LC_grade_show_problem">'.$result.'</div>';  
     return $result;      return $result;
 }  }
   
Line 2031  sub submission { Line 2105  sub submission {
  $request->print($prnmsg);   $request->print($prnmsg);
   
  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(
                             keyw => 'Keyword Options',
                             list => 'List',
                             past => 'Paste Selection to List',
                             high => 'Highlight Attribute',
                        );
 #  #
 # Print out the keyword options line  # Print out the keyword options line
 #  #
     $request->print(<<KEYWORDS);      $request->print(<<KEYWORDS);
 &nbsp;<b>Keyword Options:</b>&nbsp;  &nbsp;<b>$lt{'keyw'}:</b>&nbsp;
 <a href="javascript:keywords(document.SCORE);" target="_self">List</a>&nbsp; &nbsp;  <a href="javascript:keywords(document.SCORE);" target="_self">$lt{'list'}</a>&nbsp; &nbsp;
 <a href="#" onMouseDown="javascript:getSel(); return false"  <a href="#" onmousedown="javascript:getSel(); return false"
  CLASS="page">Paste Selection to List</a>&nbsp; &nbsp;   CLASS="page">$lt{'past'}</a>&nbsp; &nbsp;
 <a href="javascript:kwhighlight();" target="_self">Highlight Attribute</a><br /><br />  <a href="javascript:kwhighlight();" target="_self">$lt{'high'}</a><br /><br />
 KEYWORDS  KEYWORDS
 #  #
 # Load the other essays for similarity check  # Load the other essays for similarity check
Line 2053  KEYWORDS Line 2134  KEYWORDS
     }      }
   
 # This is where output for one specific student would start  # This is where output for one specific student would start
     my $add_class = ($counter%2) ? 'LC_grade_show_user_odd_row' : '';      my $add_class = ($counter%2) ? ' LC_grade_show_user_odd_row' : '';
     $request->print("\n\n".      $request->print(
                     '<div class="LC_grade_show_user '.$add_class.'">'.          "\n\n"
     '<div class="LC_grade_user_name">'.&nameUserString(undef,$env{'form.fullname'},$uname,$udom).'</div>'.         .'<div class="LC_grade_show_user'.$add_class.'">'
     '<div class="LC_grade_show_user_body">'."\n");         .'<h2>'.&nameUserString(undef,$env{'form.fullname'},$uname,$udom).'</h2>'
          ."\n"
       );
   
       # Show additional functions if allowed
       if ($perm{'vgr'}) {
           $request->print(
               &Apache::loncommon::track_student_link(
                   &mt('View recent activity'),
                   $uname,$udom,'check')
              .' '
           );
       }
       if ($perm{'opa'}) {
           $request->print(
               &Apache::loncommon::pprmlink(
                   &mt('Set/Change parameters'),
                   $uname,$udom,$symb,'check'));
       }
   
       # Show Problem
     if ($env{'form.vProb'} eq 'all' or $env{'form.vAns'} eq 'all') {      if ($env{'form.vProb'} eq 'all' or $env{'form.vAns'} eq 'all') {
  my $mode;   my $mode;
  if ($env{'form.vProb'} eq 'all' && $env{'form.vAns'} eq 'all') {   if ($env{'form.vProb'} eq 'all' && $env{'form.vAns'} eq 'all') {
Line 2082  KEYWORDS Line 2182  KEYWORDS
   
     # Display student info      # Display student info
     $request->print(($counter == 0 ? '' : '<br />'));      $request->print(($counter == 0 ? '' : '<br />'));
     my $result='<div class="LC_grade_submissions">';  
           my $result='<div class="LC_Box">'
     $result.='<div class="LC_grade_submissions_header">';                .'<h3 class="LC_hcell">'.&mt('Submissions').'</h3>';
     $result.= &mt('Submissions');  
     $result.='<input type="hidden" name="name'.$counter.      $result.='<input type="hidden" name="name'.$counter.
  '" value="'.$env{'form.fullname'}.'" />'."\n";               '" value="'.$env{'form.fullname'}.'" />'."\n";
     if ($env{'form.handgrade'} eq 'no') {      if ($env{'form.handgrade'} eq 'no') {
  $result.='<span class="LC_grade_check_note">'.          $result.='<p class="LC_info">'
     &mt('Part(s) graded correct by the computer is marked with a [_1] symbol.',$checkIcon)."</span>\n";                  .&mt('Part(s) graded correct by the computer is marked with a [_1] symbol.',$checkIcon)
                   ."</p>\n";
     }      }
   
   
   
     # If any part of the problem is an essay-response (handgraded), then check for collaborators      # If any part of the problem is an essay-response (handgraded), then check for collaborators
     my $fullname;      my $fullname;
     my $col_fullnames = [];      my $col_fullnames = [];
Line 2106  KEYWORDS Line 2203  KEYWORDS
  $result.=$sub_result;   $result.=$sub_result;
     }      }
     $request->print($result."\n");      $request->print($result."\n");
     $request->print('</div>'."\n");  
     # print student answer/submission      # print student answer/submission
     # Options are (1) Handgaded submission only      # Options are (1) Handgraded submission only
     #             (2) Last submission, includes submission that is not handgraded       #             (2) Last submission, includes submission that is not handgraded 
     #                  (for multi-response type part)      #                  (for multi-response type part)
     #             (3) Last submission plus the parts info      #             (3) Last submission plus the parts info
Line 2118  KEYWORDS Line 2215  KEYWORDS
   
  my $lastsubonly;   my $lastsubonly;
   
  if ($$timestamp eq '') {          if ($$timestamp eq '') {
     $lastsubonly.='<div class="LC_grade_submissions_body">'.$$string[0].'</div>';               $lastsubonly.='<div class="LC_grade_submissions_body">'.$$string[0].'</div>'; 
  } else {          } else {
     $lastsubonly = '<div class="LC_grade_submissions_body"> <b>Date Submitted:</b> '.$$timestamp."\n";              $lastsubonly =
                   '<div class="LC_grade_submissions_body">'
                  .'<b>'.&mt('Date Submitted:').'</b> '.$$timestamp."\n";
   
     my %seenparts;      my %seenparts;
     my @part_response_id = &flatten_responseType($responseType);      my @part_response_id = &flatten_responseType($responseType);
Line 2148  KEYWORDS Line 2247  KEYWORDS
                     $lastsubonly.="\n".'<div class="LC_grade_submission_part">'.                      $lastsubonly.="\n".'<div class="LC_grade_submission_part">'.
                         '<b>'.&mt('Part: [_1]',$display_part).'</b>'.                          '<b>'.&mt('Part: [_1]',$display_part).'</b>'.
                         ' <span class="LC_internal_info">'.                          ' <span class="LC_internal_info">'.
                         '('.&mt('Part ID: [_1]',$respid).')</b>'.                          '('.&mt('Response ID: [_1]',$respid).')'.
                         '</span>&nbsp; &nbsp;'.                          '</span>&nbsp; &nbsp;'.
  '<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br /><br /></div>';   '<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br /><br /></div>';
     next;      next;
Line 2156  KEYWORDS Line 2255  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,$subval) = split(/:/,$submission,2);      my ($ressub,$hide,$subval) = split(/:/,$submission,3);
     # Similarity check      # Similarity check
     my $similar='';      my $similar='';
                       my ($type,$trial,$rndseed);
                       if ($hide eq 'rand') {
                           $type = 'randomizetry';
                           $trial = $record{"resource.$partid.tries"};
                           $rndseed = $record{"resource.$partid.rndseed"};
                       }
     if($env{'form.checkPlag'}){      if($env{'form.checkPlag'}){
  my ($oname,$odom,$ocrsid,$oessay,$osim)=   my ($oname,$odom,$ocrsid,$oessay,$osim)=
     &most_similar($uname,$udom,$subval,\%old_essays);      &most_similar($uname,$udom,$subval,\%old_essays);
Line 2168  KEYWORDS Line 2273  KEYWORDS
  &Apache::lonnet::coursedescription($ocrsid,   &Apache::lonnet::coursedescription($ocrsid,
    {'one_time' => 1});     {'one_time' => 1});
   
     $similar="<hr /><h3><span class=\"LC_warning\">".                              if ($hide eq 'anon') {
  &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',                                  $similar='<hr /><span class="LC_warning">'.&mt("Essay was found to be similar to another essay submitted for this assignment.").'<br />'.
     $osim,                                           &mt('As the current submission is for an anonymous survey, no other details are available.').'</span><hr />';
     &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',                              } else {
     $old_course_desc{'description'},          $similar="<hr /><h3><span class=\"LC_warning\">".
     $old_course_desc{'num'},      &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',
     $old_course_desc{'domain'}).          $osim,
  '</span></h3><blockquote><i>'.          &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',
  &keywords_highlight($oessay).          $old_course_desc{'description'},
  '</i></blockquote><hr />';          $old_course_desc{'num'},
           $old_course_desc{'domain'}).
       '</span></h3><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);
     if ($env{'form.lastSub'} eq 'lastonly' ||       if ($env{'form.lastSub'} eq 'lastonly' || 
  ($env{'form.lastSub'} eq 'hdgrade' &&    ($env{'form.lastSub'} eq 'hdgrade' && 
  $$handgrade{$$part[0].'_'.$$part[1]} eq 'yes')) {   $$handgrade{$$part[0].'_'.$$part[1]} eq 'yes')) {
Line 2188  KEYWORDS Line 2299  KEYWORDS
                         $lastsubonly.='<div class="LC_grade_submission_part">'.                          $lastsubonly.='<div class="LC_grade_submission_part">'.
                             '<b>'.&mt('Part: [_1]',$display_part).'</b>'.                              '<b>'.&mt('Part: [_1]',$display_part).'</b>'.
                             ' <span class="LC_internal_info">'.                              ' <span class="LC_internal_info">'.
                             '('.&mt('Part ID: [_1]',$respid).')'.                              '('.&mt('Response ID: [_1]',$respid).')'.
                             '</b></span>&nbsp; &nbsp;';                              '</span>&nbsp; &nbsp;';
  my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record);   my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record);
  if (@$files) {   if (@$files) {
     $lastsubonly.='<br /><span class="LC_warning">'.&mt('Like all files provided by users, this file may contain viruses').'</span><br />';                              if ($hide eq 'anon') {
     my $file_counter = 0;                                  $lastsubonly.='<br />'.&mt('[quant,_1,file] uploaded to this anonymous survey',scalar(@{$files}));
     foreach my $file (@$files) {                              } else {
         $file_counter++;                                  $lastsubonly.='<br /><span class="LC_warning">'.&mt('Like all files provided by users, this file may contain viruses').'</span><br />';
  &Apache::lonnet::allowuploaded('/adm/grades',$file);                                  foreach my $file (@$files) {
  $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0" /> '.$file.'</a>';                                      &Apache::lonnet::allowuploaded('/adm/grades',$file);
     }                                      $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0" /> '.$file.'</a>';
                                   }
                               }
     $lastsubonly.='<br />';      $lastsubonly.='<br />';
  }   }
  $lastsubonly.='<b>'.&mt('Submitted Answer:').' </b>'.                          if ($hide eq 'anon') {
     &cleanRecord($subval,$responsetype,$symb,$partid,                              $lastsubonly.='<b>'.&mt('Anonymous Survey').'</b>'; 
  $respid,\%record,$order,undef,$uname,$udom);                          } else {
       $lastsubonly.='<b>'.&mt('Submitted Answer:').' </b>'.
           &cleanRecord($subval,$responsetype,$symb,$partid,
        $respid,\%record,$order,undef,$uname,$udom,$type,$trial,$rndseed);
                           }
  if ($similar) {$lastsubonly.="<br /><br />$similar\n";}   if ($similar) {$lastsubonly.="<br /><br />$similar\n";}
  $lastsubonly.='</div>';   $lastsubonly.='</div>';
     }      }
  }   }
     }      }
     $lastsubonly.='</div>'."\n";      $lastsubonly.='</div>'."\n"; # End: LC_grade_submissions_body
  }   }
  $request->print($lastsubonly);   $request->print($lastsubonly);
    } elsif ($env{'form.lastSub'} eq 'datesub') {     } elsif ($env{'form.lastSub'} eq 'datesub') {
Line 2227  KEYWORDS Line 2344  KEYWORDS
     # return if view submission with no grading option      # return if view submission with no grading option
     if ($env{'form.showgrading'} eq '' || (!&canmodify($usec))) {      if ($env{'form.showgrading'} eq '' || (!&canmodify($usec))) {
  my $toGrade.='<input type="button" value="Grade Student" '.   my $toGrade.='<input type="button" value="Grade Student" '.
     'onClick="javascript:checksubmit(this.form,\'Grade Student\',\''      'onclick="javascript:checksubmit(this.form,\'Grade Student\',\''
     .$counter.'\');" target="_self" /> &nbsp;'."\n" if (&canmodify($usec));      .$counter.'\');" target="_self" /> &nbsp;'."\n" if (&canmodify($usec));
  $toGrade.='</div>'."\n";   $toGrade.='</div>'."\n";
  if (($env{'form.command'} eq 'submission') ||    if (($env{'form.command'} eq 'submission') || 
Line 2271  KEYWORDS Line 2388  KEYWORDS
     my @partlist;      my @partlist;
     my @gradePartRespid;      my @gradePartRespid;
     my @part_response_id = &flatten_responseType($responseType);      my @part_response_id = &flatten_responseType($responseType);
     $request->print('<div class="LC_grade_assign">'.      $request->print(
               '<div class="LC_Box">'
     '<div class="LC_grade_assign_header">'.         .'<h3 class="LC_hcell">'.&mt('Assign Grades').'</h3>'
     &mt('Assign Grades').'</div>'.      );
     '<div class="LC_grade_assign_body">');      $request->print(&gradeBox_start());
     foreach my $part_response_id (@part_response_id) {      foreach my $part_response_id (@part_response_id) {
     my ($partid,$respid) = @{ $part_response_id };      my ($partid,$respid) = @{ $part_response_id };
  my $part_resp = join('_',@{ $part_response_id });   my $part_resp = join('_',@{ $part_response_id });
Line 2287  KEYWORDS Line 2404  KEYWORDS
  push(@gradePartRespid,$partid.'.'.$respid);   push(@gradePartRespid,$partid.'.'.$respid);
  $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record));   $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record));
     }      }
     $request->print('</div></div>');      $request->print(&gradeBox_end()); # </div>
       $request->print('</div>');
   
     $request->print('<div class="LC_grade_info_links">');      $request->print('<div class="LC_grade_info_links">');
     if ($perm{'vgr'}) {  
  $request->print(  
     &Apache::loncommon::track_student_link(&mt('View recent activity'),  
    $uname,$udom,'check'));  
     }  
     if ($perm{'opa'}) {  
  $request->print(  
     &Apache::loncommon::pprmlink(&mt('Set/Change parameters'),  
  $uname,$udom,$symb,'check'));  
     }  
     $request->print('</div>');      $request->print('</div>');
   
     $result='<input type="hidden" name="partlist'.$counter.      $result='<input type="hidden" name="partlist'.$counter.
Line 2316  KEYWORDS Line 2424  KEYWORDS
   
 # Done with printing info for one student  # Done with printing info for one student
   
     $request->print('</div>');#LC_grade_show_user_body  
     $request->print('</div>');#LC_grade_show_user      $request->print('</div>');#LC_grade_show_user
   
   
     # print end of form      # print end of form
     if ($counter == $total) {      if ($counter == $total) {
  my $endform='<table border="0"><tr><td>'."\n";          my $endform='<br /><hr /><table border="0"><tr><td>'."\n";
  $endform.='<input type="button" value="'.&mt('Save &amp; Next').'" '.   $endform.='<input type="button" value="'.&mt('Save &amp; Next').'" '.
     'onClick="javascript:checksubmit(this.form,\'Save & Next\','.      'onclick="javascript:checksubmit(this.form,\'Save & Next\','.
     $total.','.scalar(@partlist).');" target="_self" /> &nbsp;'."\n";      $total.','.scalar(@partlist).');" target="_self" /> &nbsp;'."\n";
  my $ntstu ='<select name="NTSTU">'.   my $ntstu ='<select name="NTSTU">'.
     '<option>1</option><option>2</option>'.      '<option>1</option><option>2</option>'.
Line 2334  KEYWORDS Line 2441  KEYWORDS
  $ntstu =~ s/<option>$nsel</<option selected="selected">$nsel</;   $ntstu =~ s/<option>$nsel</<option selected="selected">$nsel</;
         $endform.=&mt('[_1]student(s)',$ntstu);          $endform.=&mt('[_1]student(s)',$ntstu);
  $endform.='&nbsp;&nbsp;<input type="button" value="'.&mt('Previous').'" '.   $endform.='&nbsp;&nbsp;<input type="button" value="'.&mt('Previous').'" '.
     'onClick="javascript:checksubmit(this.form,\'Previous\');" target="_self" /> &nbsp;'."\n".      'onclick="javascript:checksubmit(this.form,\'Previous\');" target="_self" /> &nbsp;'."\n".
     '<input type="button" value="'.&mt('Next').'" '.      '<input type="button" value="'.&mt('Next').'" '.
     'onClick="javascript:checksubmit(this.form,\'Next\');" target="_self" /> &nbsp;';      'onclick="javascript:checksubmit(this.form,\'Next\');" target="_self" /> &nbsp;';
  $endform.=&mt('(Next and Previous (student) do not save the scores.)')."\n" ;          $endform.='<span class="LC_warning">'.
                     &mt('(Next and Previous (student) do not save the scores.)').
                     '</span>'."\n" ;
         $endform.="<input type='hidden' value='".&get_increment().          $endform.="<input type='hidden' value='".&get_increment().
             "' name='increment' />";              "' name='increment' />";
  $endform.='</td></tr></table></form>';   $endform.='</td></tr></table></form>';
Line 2360  sub check_collaborators { Line 2469  sub check_collaborators {
  next if ($record->{'resource.'.$part.'.collaborators'} eq '');   next if ($record->{'resource.'.$part.'.collaborators'} eq '');
  my (@good_collaborators, @bad_collaborators);   my (@good_collaborators, @bad_collaborators);
  foreach my $possible_collaborator   foreach my $possible_collaborator
     (split(/,?\s+/,$record->{'resource.'.$part.'.collaborators'})) {       (split(/[,;\s]+/,$record->{'resource.'.$part.'.collaborators'})) { 
     $possible_collaborator =~ s/[\$\^\(\)]//g;      $possible_collaborator =~ s/[\$\^\(\)]//g;
     next if ($possible_collaborator eq '');      next if ($possible_collaborator eq '');
     my ($co_name,$co_dom) = split(/\@|:/,$possible_collaborator);      my ($co_name,$co_dom) = split(/:/,$possible_collaborator);
     $co_dom = $udom if (! defined($co_dom) || $co_dom =~ /^domain$/i);      $co_dom = $udom if (! defined($co_dom) || $co_dom =~ /^domain$/i);
     next if ($co_name eq $uname && $co_dom eq $udom);      next if ($co_name eq $uname && $co_dom eq $udom);
     # Doing this grep allows 'fuzzy' specification      # Doing this grep allows 'fuzzy' specification
Line 2376  sub check_collaborators { Line 2485  sub check_collaborators {
     }      }
  }   }
  if (scalar(@good_collaborators) != 0) {   if (scalar(@good_collaborators) != 0) {
     $result.='<br />'.&mt('Collaborators: ');      $result.='<br />'.&mt('Collaborators:').'<ol>';
     foreach my $name (@good_collaborators) {      foreach my $name (@good_collaborators) {
  my ($lastname,$givenn) = split(/,/,$$fullname{$name});   my ($lastname,$givenn) = split(/,/,$$fullname{$name});
  push(@col_fullnames, $givenn.' '.$lastname);   push(@col_fullnames, $givenn.' '.$lastname);
  $result.=$fullname->{$name}.'&nbsp; &nbsp; &nbsp;';   $result.='<li>'.$fullname->{$name}.'</li>';
     }      }
     $result.='<br />'."\n";      $result.='</ol><br />'."\n";
     my ($part)=split(/\./,$part);      my ($part)=split(/\./,$part);
     $result.='<input type="hidden" name="collaborator'.$counter.      $result.='<input type="hidden" name="collaborator'.$counter.
  '" value="'.$part.':'.(join ':',@good_collaborators).'" />'.   '" value="'.$part.':'.(join ':',@good_collaborators).'" />'.
Line 2406  sub check_collaborators { Line 2515  sub check_collaborators {
 #--- Retrieve the last submission for all the parts  #--- Retrieve the last submission for all the parts
 sub get_last_submission {  sub get_last_submission {
     my ($returnhash)=@_;      my ($returnhash)=@_;
     my (@string,$timestamp);      my (@string,$timestamp,%lasthidden);
     if ($$returnhash{'version'}) {      if ($$returnhash{'version'}) {
  my %lasthash=();   my %lasthash=();
  my ($version);   my ($version);
Line 2418  sub get_last_submission { Line 2527  sub get_last_submission {
     &Apache::lonlocal::locallocaltime($$returnhash{$version.':timestamp'});      &Apache::lonlocal::locallocaltime($$returnhash{$version.':timestamp'});
     }      }
  }   }
           my (%typeparts,%randombytry);
           my $showsurv = 
               &Apache::lonnet::allowed('vas',$env{'request.course.id'});
           foreach my $key (sort(keys(%lasthash))) {
               if ($key =~ /\.type$/) {
                   if (($lasthash{$key} eq 'anonsurvey') || 
                       ($lasthash{$key} eq 'anonsurveycred') ||
                       ($lasthash{$key} eq 'randomizetry')) {
                       my ($ign,@parts) = split(/\./,$key);
                       pop(@parts);
                       my $id = join('.',@parts);
                       if ($lasthash{$key} eq 'randomizetry') {
                           $randombytry{$ign.'.'.$id} = $lasthash{$key};
                       } else {
                           unless ($showsurv) {
                               $typeparts{$ign.'.'.$id} = $lasthash{$key};
                           }
                       }
                       delete($lasthash{$key});
                   }
               }
           }
           my @hidden = keys(%typeparts);
           my @randomize = keys(%randombytry);
  foreach my $key (keys(%lasthash)) {   foreach my $key (keys(%lasthash)) {
     next if ($key !~ /\.submission$/);      next if ($key !~ /\.submission$/);
               my $hide;
               if (@hidden) {
                   foreach my $id (@hidden) {
                       if ($key =~ /^\Q$id\E/) {
                           $hide = 'anon';
                           last;
                       }
                   }
               }
               unless ($hide) {
                   if (@randomize) {
                       foreach my $id (@hidden) {
                           if ($key =~ /^\Q$id\E/) {
                               $hide = 'rand';
                               last;
                           }
                       }
                   }
               }
     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' ?
  '<span class="LC_warning">Draft Copy</span> ' : '';   '<span class="LC_warning">Draft Copy</span> ' : '';
     push(@string, join(':', $key, $draft.$lasthash{$key}));      push(@string, join(':', $key, $hide, $draft.$lasthash{$key}));
  }   }
     }      }
     if (!@string) {      if (!@string) {
Line 2499  sub processHandGrade { Line 2650  sub processHandGrade {
                                                      undef,undef,$showsymb,                                                       undef,undef,$showsymb,
                                                      $restitle);                                                       $restitle);
  $request->print('<br />'.&mt('Sending message to [_1]',$uname.':'.$udom).': '.   $request->print('<br />'.&mt('Sending message to [_1]',$uname.':'.$udom).': '.
  $msgstatus);   $msgstatus.'<br />');
     }      }
     if ($env{'form.collaborator'.$ctr}) {      if ($env{'form.collaborator'.$ctr}) {
  my @collabstrs=&Apache::loncommon::get_env_multiple("form.collaborator$ctr");   my @collabstrs=&Apache::loncommon::get_env_multiple("form.collaborator$ctr");
Line 2685  sub processHandGrade { Line 2836  sub processHandGrade {
     }      }
     if ($total < 0) {      if ($total < 0) {
  my $the_end = '<h3><span class="LC_info">'.&mt('LON-CAPA User Message').'</span></h3><br />'."\n";   my $the_end = '<h3><span class="LC_info">'.&mt('LON-CAPA User Message').'</span></h3><br />'."\n";
  $the_end.=&mt('<b>Message: </b> No more students for this section or class.').'<br /><br />'."\n";   $the_end.='<p>'.&mt('[_1]Message:[_2] No more students for this section or class.','<b>','</b>').'</p>'."\n";
  $the_end.=&mt('Click on the button below to return to the grading menu.').'<br /><br />'."\n";   $the_end.=&mt('Click on the button below to return to the grading menu.').'<br /><br />'."\n";
  $the_end.=&show_grading_menu_form($symb);   $the_end.=&show_grading_menu_form($symb);
  $request->print($the_end);   $request->print($the_end);
Line 2838  sub handback_files { Line 2989  sub handback_files {
         $request->print('<br />'.&navmap_errormsg().'<br />');          $request->print('<br />'.&navmap_errormsg().'<br />');
         return;          return;
     }      }
       my @handedback;
       my $file_msg;
     my @part_response_id = &flatten_responseType($responseType);      my @part_response_id = &flatten_responseType($responseType);
     foreach my $part_response_id (@part_response_id) {      foreach my $part_response_id (@part_response_id) {
     my ($part_id,$resp_id) = @{ $part_response_id };      my ($part_id,$resp_id) = @{ $part_response_id };
  my $part_resp = join('_',@{ $part_response_id });   my $part_resp = join('_',@{ $part_response_id });
             if (($env{'form.'.$newflg.'_'.$part_resp.'_returndoc1'}) && ($new_part == $part_id)) {          if (($env{'form.'.$newflg.'_'.$part_resp.'_countreturndoc'} =~ /^\d+$/) & ($new_part eq $part_id)) {
               for (my $counter=1; $counter<=$env{'form.'.$newflg.'_'.$part_resp.'_countreturndoc'}; $counter++) {
                 # if multiple files are uploaded names will be 'returndoc2','returndoc3'                  # if multiple files are uploaded names will be 'returndoc2','returndoc3'
                 my $file_counter = 1;   if ($env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter}) {
  my $file_msg;                      my $fname=$env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter.'.filename'};
                 while ($env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$file_counter}) {  
                     my $fname=$env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$file_counter.'.filename'};  
                     my ($directory,$answer_file) =                       my ($directory,$answer_file) = 
                         ($env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$file_counter} =~ /^(.*?)([^\/]*)$/);                          ($env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter} =~ /^(.*?)([^\/]*)$/);
                     my ($answer_name,$answer_ver,$answer_ext) =                      my ($answer_name,$answer_ver,$answer_ext) =
         &file_name_version_ext($answer_file);          &file_name_version_ext($answer_file);
     my ($portfolio_path) = ($directory =~ /^.+$stuname\/portfolio(.*)/);      my ($portfolio_path) = ($directory =~ /^.+$stuname\/portfolio(.*)/);
Line 2859  sub handback_files { Line 3011  sub handback_files {
                     # fix file name                      # fix file name
                     my ($save_file_name) = (($directory.$answer_name.".$version.".$answer_ext) =~ /^.+\/${stuname}\/(.*)/);                      my ($save_file_name) = (($directory.$answer_name.".$version.".$answer_ext) =~ /^.+\/${stuname}\/(.*)/);
                     my $result=&Apache::lonnet::finishuserfileupload($stuname,$domain,                      my $result=&Apache::lonnet::finishuserfileupload($stuname,$domain,
                                            $newflg.'_'.$part_resp.'_returndoc'.$file_counter,                                             $newflg.'_'.$part_resp.'_returndoc'.$counter,
                                            $save_file_name);                                             $save_file_name);
                     if ($result !~ m|^/uploaded/|) {                      if ($result !~ m|^/uploaded/|) {
                         $request->print('<br /><span class="LC_error">'.                          $request->print('<br /><span class="LC_error">'.
                             &mt('An error occurred ([_1]) while trying to upload [_2].',                              &mt('An error occurred ([_1]) while trying to upload [_2].',
                                 $result,$newflg.'_'.$part_resp.'_returndoc'.$file_counter).                                  $result,$newflg.'_'.$part_resp.'_returndoc'.$counter).
                                         '</span>');                                          '</span>');
                     } else {                      } else {
                         # mark the file as read only                          # mark the file as read only
                         my @files = ($save_file_name);                          push(@handedback,$save_file_name);
                         my @what = ($symb,$env{'request.course.id'},'handback');  
                         &Apache::lonnet::mark_as_readonly($domain,$stuname,\@files,\@what);  
  if (exists($$newrecord{"resource.$new_part.$resp_id.handback"})) {   if (exists($$newrecord{"resource.$new_part.$resp_id.handback"})) {
     $$newrecord{"resource.$new_part.$resp_id.handback"}.=',';      $$newrecord{"resource.$new_part.$resp_id.handback"}.=',';
  }   }
                         $$newrecord{"resource.$new_part.$resp_id.handback"} .= $save_file_name;                          $$newrecord{"resource.$new_part.$resp_id.handback"} .= $save_file_name;
  $file_msg.= "\n".'<br /><span class="LC_filename"><a href="/uploaded/'."$domain/$stuname/".$save_file_name.'">'.$save_file_name."</a></span><br />";   $file_msg.='<span class="LC_filename"><a href="/uploaded/'."$domain/$stuname/".$save_file_name.'">'.$save_file_name."</a></span> <br />";
   
                     }                      }
                     $request->print("<br />".$fname." will be the uploaded file name");                      $request->print('<br />'.&mt('[_1] will be the uploaded file name [_2]','<span class="LC_info">'.$fname.'</span>','<span class="LC_filename">'.$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter}.'</span>'));
                     $request->print(" ".$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$file_counter});  
                     $file_counter++;  
                 }                  }
  my $subject = "File Handed Back by Instructor ";  
  my $message = "A file has been returned that was originally submitted in reponse to: <br />";  
  $message .= "<strong>".&Apache::lonnet::gettitle($symb)."</strong><br />";  
  $message .= ' The returned file(s) are named: '. $file_msg;  
  $message .= " and can be found in your portfolio space.";  
  my ($feedurl,$showsymb) =   
     &get_feedurl_and_symb($symb,$domain,$stuname);  
                 my $restitle = &Apache::lonnet::gettitle($symb);  
  my $msgstatus =   
                    &Apache::lonmsg::user_normal_msg($stuname,$domain,$subject.  
  ' (File Returned) ['.$restitle.']',$message,undef,  
                          $feedurl,undef,undef,undef,$showsymb,$restitle);  
             }              }
         }          }
       }
       if (@handedback > 0) {
           $request->print('<br />');
           my @what = ($symb,$env{'request.course.id'},'handback');
           &Apache::lonnet::mark_as_readonly($domain,$stuname,\@handedback,\@what);
           my $user_lh = &Apache::loncommon::user_lang($stuname,$domain,$env{'request.course.id'});
           my ($subject,$message);
           if (scalar(@handedback) == 1) {
               $subject = &mt_user($user_lh,'File Handed Back by Instructor');
           } else {
               $subject = &mt_user($user_lh,'Files Handed Back by Instructor');
               $message = &mt_user($user_lh,'Files have been returned that were originally submitted in response to: ');
           }
           $message .= "<p><strong>".&Apache::lonnet::gettitle($symb)." </strong></p>";
           $message .= &mt_user($user_lh,'The returned file(s) are named: [_1]',"<br />$file_msg <br />").
                       &mt_user($user_lh,'The file(s) can be found in your [_1]portfolio[_2].','<a href="/adm/portfolio">','</a>');
           my ($feedurl,$showsymb) =
               &get_feedurl_and_symb($symb,$domain,$stuname);
           my $restitle = &Apache::lonnet::gettitle($symb);
           $subject .= ' '.&mt_user($user_lh,'(File Returned)').' ['.$restitle.']';
           my $msgstatus =
                &Apache::lonmsg::user_normal_msg($stuname,$domain,$subject,
                    $message,undef,$feedurl,undef,undef,undef,$showsymb,
                    $restitle);
           if ($msgstatus) {
               $request->print(&mt('Notification message status: [_1]','<span class="LC_info">'.$msgstatus.'</span>').'<br />');
           }
       }
     return;      return;
 }  }
   
Line 3325  sub viewgrades { Line 3489  sub viewgrades {
  }   }
  $radio.='</tr></table>';   $radio.='</tr></table>';
  my $line = '<input type="text" name="TEXTVAL_'.   my $line = '<input type="text" name="TEXTVAL_'.
     $partid.'" size="4" '.'onChange="javascript:writePoint(\''.      $partid.'" size="4" '.'onchange="javascript:writePoint(\''.
  $partid.'\','.$weight{$partid}.',\'textval\')" /> /'.   $partid.'\','.$weight{$partid}.',\'textval\')" /> /'.
     $weight{$partid}.' '.&mt('(problem weight)').'</td>'."\n";      $weight{$partid}.' '.&mt('(problem weight)').'</td>'."\n";
  $line.= '<td><b>'.&mt('Grade Status').':</b><select name="SELVAL_'.$partid.'"'.   $line.= '<td><b>'.&mt('Grade Status').':</b><select name="SELVAL_'.$partid.'"'.
     'onChange="javascript:writeRadText(\''.$partid.'\','.      'onchange="javascript:writeRadText(\''.$partid.'\','.
  $weight{$partid}.')"> '.   $weight{$partid}.')"> '.
     '<option selected="selected"> </option>'.      '<option selected="selected"> </option>'.
     '<option value="excused">'.&mt('excused').'</option>'.      '<option value="excused">'.&mt('excused').'</option>'.
Line 3350  sub viewgrades { Line 3514  sub viewgrades {
     $result.=&Apache::loncommon::end_data_table()."\n".      $result.=&Apache::loncommon::end_data_table()."\n".
  '<input type="hidden" name="totalparts" value="'.$ctsparts.'" />';   '<input type="hidden" name="totalparts" value="'.$ctsparts.'" />';
     $result.='<input type="button" value="'.&mt('Revert to Default').'" '.      $result.='<input type="button" value="'.&mt('Revert to Default').'" '.
  'onClick="javascript:resetEntry('.$ctsparts.');" />';   'onclick="javascript:resetEntry('.$ctsparts.');" />';
   
     #table listing all the students in a section/class      #table listing all the students in a section/class
     #header of table      #header of table
Line 3414  sub viewgrades { Line 3578  sub viewgrades {
     $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 (scalar(%$fullname) eq 0) {
  my $colspan=3+scalar(@parts);   my $colspan=3+scalar(@parts);
  my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));   my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));
Line 3466  sub viewstudentgrade { Line 3630  sub viewstudentgrade {
  'GD_'.$student.'_'.$part.'_awarded_s" value="'.$pts.'" />'."\n";   'GD_'.$student.'_'.$part.'_awarded_s" value="'.$pts.'" />'."\n";
     $result.='<input type="text" name="'.      $result.='<input type="text" name="'.
  'GD_'.$student.'_'.$part.'_awarded" '.   'GD_'.$student.'_'.$part.'_awarded" '.
  'onChange="javascript:changeSelect(\''.$part.'\',\''.$student.                  'onchange="javascript:changeSelect(\''.$part.'\',\''.$student.
  '\')" value="'.$pts.'" size="4" /></td>'."\n";   '\')" value="'.$pts.'" size="4" /></td>'."\n";
  } elsif ($type eq 'solved') {   } elsif ($type eq 'solved') {
     my ($status,$foo)=split(/_/,$score,2);      my ($status,$foo)=split(/_/,$score,2);
Line 3475  sub viewstudentgrade { Line 3639  sub viewstudentgrade {
  $part.'_solved_s" value="'.$status.'" />'."\n";   $part.'_solved_s" value="'.$status.'" />'."\n";
     $result.='&nbsp;<select name="'.      $result.='&nbsp;<select name="'.
  'GD_'.$student.'_'.$part.'_solved" '.   'GD_'.$student.'_'.$part.'_solved" '.
  'onChange="javascript:changeOneScore(\''.$part.'\',\''.$student.'\')" >'."\n";                  'onchange="javascript:changeOneScore(\''.$part.'\',\''.$student.'\')" >'."\n";
     $result.= (($status eq 'excused') ? '<option> </option><option selected="selected" value="excused">'.&mt('excused').'</option>'       $result.= (($status eq 'excused') ? '<option> </option><option selected="selected" value="excused">'.&mt('excused').'</option>' 
  : '<option selected="selected"> </option><option value="excused">'.&mt('excused').'</option>')."\n";   : '<option selected="selected"> </option><option value="excused">'.&mt('excused').'</option>')."\n";
     $result.='<option value="reset status">'.&mt('reset status').'</option>';      $result.='<option value="reset status">'.&mt('reset status').'</option>';
Line 3513  sub editgrades { Line 3677  sub editgrades {
     'incorrect'=>'incorrect_by_override',      'incorrect'=>'incorrect_by_override',
     'excused'  =>'excused',      'excused'  =>'excused',
     'ungraded' =>'ungraded_attempted',      'ungraded' =>'ungraded_attempted',
                       'credited' =>'credit_attempted',
     'nothing'  => '',      'nothing'  => '',
     );      );
     my ($classlist,undef,$fullname) = &getclasslist($env{'form.section'},'0');      my ($classlist,undef,$fullname) = &getclasslist($env{'form.section'},'0');
Line 3835  $result Line 4000  $result
 Total number of records found in file: $distotal <hr />  Total number of records found in file: $distotal <hr />
 Enter as many fields as you can. The system will inform you and bring you back  Enter as many fields as you can. The system will inform you and bring you back
 to this page if the data selected is insufficient to run your class.<hr />  to this page if the data selected is insufficient to run your class.<hr />
 <input type="button" value="Reverse Association" onClick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" />  <input type="button" value="Reverse Association" onclick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" />
 <label><input type="checkbox" name="noFirstLine" $checked />$ignore</label>  <label><input type="checkbox" name="noFirstLine" $checked />$ignore</label>
 <input type="hidden" name="associate"  value="" />  <input type="hidden" name="associate"  value="" />
 <input type="hidden" name="phase"      value="three" />  <input type="hidden" name="phase"      value="three" />
Line 3890  sub csvuploadmap_footer { Line 4055  sub csvuploadmap_footer {
 </table>  </table>
 <input type="hidden" name="nfields" value="$i" />  <input type="hidden" name="nfields" value="$i" />
 <input type="hidden" name="keyfields" value="$keyfields" />  <input type="hidden" name="keyfields" value="$keyfields" />
 <input type="button" onClick="javascript:verify(this.form)" value="Assign Grades" /><br />  <input type="button" onclick="javascript:verify(this.form)" value="Assign Grades" /><br />
 </form>  </form>
 ENDPICK  ENDPICK
 }  }
Line 3923  sub upcsvScores_form { Line 4088  sub upcsvScores_form {
     $result.='<table width="100%" border="0"><tr bgcolor="#e6ffff"><td>'."\n";      $result.='<table width="100%" border="0"><tr bgcolor="#e6ffff"><td>'."\n";
     $result.='&nbsp;<b>'.&mt('Specify a file containing the class scores for current resource.').      $result.='&nbsp;<b>'.&mt('Specify a file containing the class scores for current resource.').
  '</b></td></tr>'."\n";   '</b></td></tr>'."\n";
     $result.='<tr bgcolor=#ffffe6><td>'."\n";      $result.='<tr bgcolor="#ffffe6"><td>'."\n";
     my $upload=&mt("Upload Scores");      my $upload=&mt("Upload Scores");
     my $upfile_select=&Apache::loncommon::upfile_select_html();      my $upfile_select=&Apache::loncommon::upfile_select_html();
     my $ignore=&mt('Ignore First Line');      my $ignore=&mt('Ignore First Line');
Line 3935  sub upcsvScores_form { Line 4100  sub upcsvScores_form {
 <input type="hidden" name="probTitle" value="$env{'form.probTitle'}" />  <input type="hidden" name="probTitle" value="$env{'form.probTitle'}" />
 <input type="hidden" name="saveState"  value="$env{'form.saveState'}" />  <input type="hidden" name="saveState"  value="$env{'form.saveState'}" />
 $upfile_select  $upfile_select
 <br /><input type="button" onClick="javascript:checkUpload(this.form);" value="$upload" />  <br /><input type="button" onclick="javascript:checkUpload(this.form);" value="$upload" />
 <label><input type="checkbox" name="noFirstLine" />$ignore</label>  <label><input type="checkbox" name="noFirstLine" />$ignore</label>
 </form>  </form>
 ENDUPFORM  ENDUPFORM
Line 4071  sub csvuploadassign { Line 4236  sub csvuploadassign {
     my ($classlist) = &getclasslist('all',0);      my ($classlist) = &getclasslist('all',0);
     my @notallowed;      my @notallowed;
     my @skipped;      my @skipped;
       my @warnings;
     my $countdone=0;      my $countdone=0;
     foreach my $grade (@gradedata) {      foreach my $grade (@gradedata) {
  my %entries=&Apache::loncommon::record_sep($grade);   my %entries=&Apache::loncommon::record_sep($grade);
Line 4119  sub csvuploadassign { Line 4285  sub csvuploadassign {
                     my $pcr=$entries{$fields{$dest}} / $wgt;                      my $pcr=$entries{$fields{$dest}} / $wgt;
                     my $award=($pcr == 0) ? 'incorrect_by_override'                      my $award=($pcr == 0) ? 'incorrect_by_override'
                                           : 'correct_by_override';                                            : 'correct_by_override';
                       if ($pcr>1) {
                           push(@warnings,&mt("[_1]: point value larger than weight","$username:$domain"));
                       }
                     $grades{"resource.$part.awarded"}=$pcr;                      $grades{"resource.$part.awarded"}=$pcr;
                     $grades{"resource.$part.solved"}=$award;                      $grades{"resource.$part.solved"}=$award;
                     $points{$part}=1;                      $points{$part}=1;
Line 4147  sub csvuploadassign { Line 4316  sub csvuploadassign {
    $domain,$username);     $domain,$username);
    if ($result eq 'ok') {     if ($result eq 'ok') {
       $request->print('.');        $request->print('.');
   # Remove from grading queue
                 &Apache::bridgetask::remove_from_queue('gradingqueue',$symb,
                                                $env{'course.'.$env{'request.course.id'}.'.domain'},
                                                $env{'course.'.$env{'request.course.id'}.'.num'},
                                                $domain,$username);
    } else {     } else {
       $request->print("<p><span class=\"LC_error\">".        $request->print("<p><span class=\"LC_error\">".
                               &mt("Failed to save data for student [_1]. Message when trying to save was: [_2]",                                &mt("Failed to save data for student [_1]. Message when trying to save was: [_2]",
Line 4157  sub csvuploadassign { Line 4331  sub csvuploadassign {
         }          }
     }      }
     $request->print('<br />'.&Apache::lonhtmlcommon::confirm_success(&mt("Saved scores for [quant,_1,student]",$countdone),$countdone==0));      $request->print('<br />'.&Apache::lonhtmlcommon::confirm_success(&mt("Saved scores for [quant,_1,student]",$countdone),$countdone==0));
       if (@warnings) {
           $request->print('<br />'.&Apache::lonhtmlcommon::confirm_success(&mt('Warnings generated for the following saved scores:'),1).'<br />');
           $request->print(join(', ',@warnings));
       }
     if (@skipped) {      if (@skipped) {
  $request->print('<br />'.&Apache::lonhtmlcommon::confirm_success(&mt('No scores stored for the following username(s):'),1).'<br />');   $request->print('<br />'.&Apache::lonhtmlcommon::confirm_success(&mt('No scores stored for the following username(s):'),1).'<br />');
         $request->print(join(', ',@skipped));          $request->print(join(', ',@skipped));
Line 4258  LISTJAVASCRIPT Line 4436  LISTJAVASCRIPT
     $result.='&nbsp;<b>'.&mt('Use CODE').': </b> <input type="text" name="CODE" value="" /> <br />'."\n";      $result.='&nbsp;<b>'.&mt('Use CODE').': </b> <input type="text" name="CODE" value="" /> <br />'."\n";
   
     $result.='&nbsp;<input type="button" '.      $result.='&nbsp;<input type="button" '.
  'onClick="javascript:checkPickOne(this.form);" value="'.&mt('Next').' &rarr;" /><br />'."\n";               'onclick="javascript:checkPickOne(this.form);" value="'.&mt('Next').' &rarr;" /><br />'."\n";
   
     $request->print($result);      $request->print($result);
   
Line 4297  LISTJAVASCRIPT Line 4475  LISTJAVASCRIPT
     }      }
     $studentTable.=&Apache::loncommon::end_data_table()."\n";      $studentTable.=&Apache::loncommon::end_data_table()."\n";
     $studentTable.='<input type="button" '.      $studentTable.='<input type="button" '.
  'onClick="javascript:checkPickOne(this.form);" value="'.&mt('Next').' &rarr;" /></form>'."\n";                     'onclick="javascript:checkPickOne(this.form);" value="'.&mt('Next').' &rarr;" /></form>'."\n";
   
     $studentTable.=&show_grading_menu_form($symb);      $studentTable.=&show_grading_menu_form($symb);
     $request->print($studentTable);      $request->print($studentTable);
Line 4404  sub displayPage { Line 4582  sub displayPage {
     my $checkIcon = '<img alt="'.&mt('Check Mark').      my $checkIcon = '<img alt="'.&mt('Check Mark').
  '" src="'.&Apache::loncommon::lonhttpdurl($request->dir_config('lonIconsURL').'/check.gif').'" height="16" border="0" />';   '" src="'.&Apache::loncommon::lonhttpdurl($request->dir_config('lonIconsURL').'/check.gif').'" height="16" border="0" />';
   
     $studentTable.='&nbsp;'.&mt('<b>Note:</b> Problems graded correct by the computer are marked with a [_1] symbol.',$checkIcon)."\n".      $studentTable.='&nbsp;<span class="LC_info">'.
           &mt('Problems graded correct by the computer are marked with a [_1] symbol.',$checkIcon).
           '</span>'."\n".
  &Apache::loncommon::start_data_table().   &Apache::loncommon::start_data_table().
  &Apache::loncommon::start_data_table_header_row().   &Apache::loncommon::start_data_table_header_row().
  '<th align="center">&nbsp;Prob.&nbsp;</th>'.   '<th align="center">&nbsp;Prob.&nbsp;</th>'.
Line 4427  sub displayPage { Line 4607  sub displayPage {
  &Apache::loncommon::start_data_table_row().   &Apache::loncommon::start_data_table_row().
  '<td align="center" valign="top" >'.$prob.   '<td align="center" valign="top" >'.$prob.
  (scalar(@{$parts}) == 1 ? ''    (scalar(@{$parts}) == 1 ? '' 
                         : '<br />('.&mt('[_1]&nbsp;parts)',                          : '<br />('.&mt('[_1]parts)',
  scalar(@{$parts}))   scalar(@{$parts}).'&nbsp;')
  ).   ).
  '</td>';   '</td>';
     $studentTable.='<td valign="top">';      $studentTable.='<td valign="top">';
Line 4475  sub displayPage { Line 4655  sub displayPage {
     
     }      }
     if (&canmodify($usec)) {      if (&canmodify($usec)) {
               $studentTable.=&gradeBox_start();
  foreach my $partid (@{$parts}) {   foreach my $partid (@{$parts}) {
     $studentTable.=&gradeBox($request,$symbx,$uname,$udom,$question,$partid,\%record);      $studentTable.=&gradeBox($request,$symbx,$uname,$udom,$question,$partid,\%record);
     $studentTable.='<input type="hidden" name="q_'.$question.'" value="'.$partid.'" />'."\n";      $studentTable.='<input type="hidden" name="q_'.$question.'" value="'.$partid.'" />'."\n";
     $question++;      $question++;
  }   }
               $studentTable.=&gradeBox_end();
  $prob++;   $prob++;
     }      }
     $studentTable.='</td></tr>';      $studentTable.='</td></tr>';
Line 4488  sub displayPage { Line 4670  sub displayPage {
         $curRes = $iterator->next();          $curRes = $iterator->next();
     }      }
   
     $studentTable.='</table>'."\n".      $studentTable.=
  '<input type="button" value="'.&mt('Save').'" '.          '</table>'."\n".
  'onClick="javascript:checkSubmitPage(this.form,'.$question.');" />'.          '<input type="button" value="'.&mt('Save').'" '.
  '</form>'."\n";          'onclick="javascript:checkSubmitPage(this.form,'.$question.');" />'.
           '</form>'."\n";
     $studentTable.=&show_grading_menu_form($symb);      $studentTable.=&show_grading_menu_form($symb);
     $request->print($studentTable);      $request->print($studentTable);
   
Line 4520  sub displaySubByDates { Line 4703  sub displaySubByDates {
   
     my $interaction;      my $interaction;
     my $no_increment = 1;      my $no_increment = 1;
       my %lastrndseed;
     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 4537  sub displaySubByDates { Line 4721  sub displaySubByDates {
  my @versionKeys = split(/\:/,$$record{$version.':keys'});   my @versionKeys = split(/\:/,$$record{$version.':keys'});
  my @displaySub = ();   my @displaySub = ();
  foreach my $partid (@{$parts}) {   foreach my $partid (@{$parts}) {
               my ($hidden,$type);
               $type = $$record{$version.':resource.'.$partid.'.type'};
               if (($type eq 'anonsurvey') || ($type eq 'anonsurveycred')) {
                   $hidden = 1;
               }
     my @matchKey = ($isTask ? sort(grep /^resource\.\d+\.\Q$partid\E\.award$/,@versionKeys)      my @matchKey = ($isTask ? sort(grep /^resource\.\d+\.\Q$partid\E\.award$/,@versionKeys)
             : sort(grep /^resource\.\Q$partid\E\..*?\.submission$/,@versionKeys));              : sort(grep /^resource\.\Q$partid\E\..*?\.submission$/,@versionKeys));
           
   
 #    next if ($$record{"$version:resource.$partid.solved"} eq '');  #    next if ($$record{"$version:resource.$partid.solved"} eq '');
     my $display_part=&get_display_part($partid,$symb);      my $display_part=&get_display_part($partid,$symb);
     foreach my $matchKey (@matchKey) {      foreach my $matchKey (@matchKey) {
  if (exists($$record{$version.':'.$matchKey}) &&   if (exists($$record{$version.':'.$matchKey}) &&
     $$record{$version.':'.$matchKey} ne '') {      $$record{$version.':'.$matchKey} ne '') {
                       
     my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/)      my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/)
                : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/));                 : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/));
                     $displaySub[0].='<span class="LC_nobreak"';                      $displaySub[0].='<span class="LC_nobreak"';
                     $displaySub[0].='<b>'.&mt('Part: [_1]',$display_part).'</b>'                      $displaySub[0].='<b>'.&mt('Part: [_1]',$display_part).'</b>'
                                    .' <span class="LC_internal_info">'                                     .' <span class="LC_internal_info">'
                                    .'('.&mt('Part ID: [_1]',$responseId).')'                                     .'('.&mt('Response ID: [_1]',$responseId).')'
                                    .'</span>'                                     .'</span>'
                                    .' <b>';                                     .' <b>';
     if ($$record{"$where.$partid.tries"} eq '') {                      if ($hidden) {
  $displaySub[0].=&mt('Trial not counted');                          $displaySub[0].= &mt('Anonymous Survey').'</b>';
     } else {                      } else {
  $displaySub[0].=&mt('Trial: [_1]',                          my ($trial,$rndseed,$newvariation);
                           if ($type eq 'randomizetry') {
                               $trial = $$record{"$where.$partid.tries"};
                               $rndseed = $$record{"$where.$partid.rndseed"};
                           }
           if ($$record{"$where.$partid.tries"} eq '') {
       $displaySub[0].=&mt('Trial not counted');
           } else {
       $displaySub[0].=&mt('Trial: [_1]',
     $$record{"$where.$partid.tries"});      $$record{"$where.$partid.tries"});
     }                              if ($rndseed || $lastrndseed{$partid}) {
     my $responseType=($isTask ? 'Task'                                  if ($rndseed ne $lastrndseed{$partid}) {
                                       $newvariation = '&nbsp;('.&mt('New variation this try').')';
                                   }
                               }
           }
           my $responseType=($isTask ? 'Task'
                                               : $responseType->{$partid}->{$responseId});                                                : $responseType->{$partid}->{$responseId});
     if (!exists($orders{$partid})) { $orders{$partid}={}; }          if (!exists($orders{$partid})) { $orders{$partid}={}; }
     if (!exists($orders{$partid}->{$responseId})) {          if ((!exists($orders{$partid}->{$responseId})) || ($trial)) {
  $orders{$partid}->{$responseId}=      $orders{$partid}->{$responseId}=
     &get_order($partid,$responseId,$symb,$uname,$udom,          &get_order($partid,$responseId,$symb,$uname,$udom,
                                        $no_increment);                                             $no_increment,$type,$trial,$rndseed);
     }          }
     $displaySub[0].='</b></span>'; # /nobreak          $displaySub[0].='</b>'.$newvariation.'</span>'; # /nobreak
     $displaySub[0].='&nbsp; '.          $displaySub[0].='&nbsp; '.
  &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:",$uname,$udom).'<br />';      &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:",$uname,$udom,$type,$trial,$rndseed).'<br />';
                       }
  }   }
     }      }
     if (exists($$record{"$where.$partid.checkedin"})) {      if (exists($$record{"$where.$partid.checkedin"})) {
Line 4672  sub updateGradeByPage { Line 4874  sub updateGradeByPage {
  &Apache::loncommon::start_data_table_row().   &Apache::loncommon::start_data_table_row().
  '<td align="center" valign="top" >'.$prob.   '<td align="center" valign="top" >'.$prob.
  (scalar(@{$parts}) == 1 ? ''    (scalar(@{$parts}) == 1 ? '' 
                                         : '<br />('.&mt('[quant,_1,&nbsp;part]',scalar(@{$parts}))                                          : '<br />('.&mt('[quant,_1,part]',scalar(@{$parts}))
  .')').'</td>';   .')').'</td>';
     $studentTable.='<td valign="top">&nbsp;<b>'.$title.'</b>&nbsp;</td>';      $studentTable.='<td valign="top">&nbsp;<b>'.$title.'</b>&nbsp;</td>';
   
Line 4795  sub updateGradeByPage { Line 4997  sub updateGradeByPage {
    from the file that we are parsing that represents one entire sheet     from the file that we are parsing that represents one entire sheet
   
    'bubble line' refers to the data     'bubble line' refers to the data
    representing the line of bubbles that are on the physical bubble sheet     representing the line of bubbles that are on the physical bubblesheet
   
   
 The overall process is that a scanned in bubble sheet data is uploaded  The overall process is that a scanned in bubblesheet data is uploaded
 into a course. When a user wants to grade, they select a  into a course. When a user wants to grade, they select a
 sequence/folder of resources, a file of bubble sheet info, and pick  sequence/folder of resources, a file of bubblesheet info, and pick
 one of the predefined configurations for what each scanline looks  one of the predefined configurations for what each scanline looks
 like.  like.
   
Line 4816  username:domain. Line 5018  username:domain.
   
 During the validation phase the instructor can choose to skip scanlines.   During the validation phase the instructor can choose to skip scanlines. 
   
 After the validation phase, there are now 3 bubble sheet files  After the validation phase, there are now 3 bubblesheet files
   
   scantron_original_filename (unmodified original file)    scantron_original_filename (unmodified original file)
   scantron_corrected_filename (file where the corrected information has replaced the original information)    scantron_corrected_filename (file where the corrected information has replaced the original information)
   scantron_skipped_filename (contains the exact text of scanlines that where skipped)    scantron_skipped_filename (contains the exact text of scanlines that where skipped)
   
 Also there is a separate hash nohist_scantrondata that contains extra  Also there is a separate hash nohist_scantrondata that contains extra
 correction information that isn't representable in the bubble sheet  correction information that isn't representable in the bubblesheet
 file (see &scantron_getfile() for more information)  file (see &scantron_getfile() for more information)
   
 After all scanlines are either valid, marked as valid or skipped, then  After all scanlines are either valid, marked as valid or skipped, then
Line 5120  sub scantron_CODEunique { Line 5322  sub scantron_CODEunique {
   
 =item scantron_selectphase  =item scantron_selectphase
   
   Generates the initial screen to start the bubble sheet process.    Generates the initial screen to start the bubblesheet process.
   Allows for - starting a grading run.    Allows for - starting a grading run.
              - downloading existing scan data (original, corrected               - downloading existing scan data (original, corrected
                                                 or skipped info)                                                  or skipped info)
Line 5153  sub scantron_selectphase { Line 5355  sub scantron_selectphase {
   
     $ssi_error = 0;      $ssi_error = 0;
   
       if (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) ||
           &Apache::lonnet::allowed('usc',$env{'request.course.id'})) {
   
           # Chunk of form to prompt for a scantron file upload.
   
           $r->print('
       <br />
       '.&Apache::loncommon::start_data_table('LC_scantron_action').'
          '.&Apache::loncommon::start_data_table_header_row().'
               <th>
                 &nbsp;'.&mt('Specify a bubblesheet data file to upload.').'
               </th>
          '.&Apache::loncommon::end_data_table_header_row().'
          '.&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) {
           if (formname.upfile.value == "") {
               alert("'.&mt('Please use the browse button to select a file from your local directory.').'");
               return false;
           }
           formname.submit();
       }
                 </script>
   
                 <form enctype="multipart/form-data" action="/adm/grades" name="rules" method="post">
                   '.$default_form_data.'
                   <input name="courseid" type="hidden" value="'.$cnum.'" />
                   <input name="domainid" type="hidden" value="'.$cdom.'" />
                   <input name="command" value="scantronupload_save" type="hidden" />
                   '.&mt('File to upload: [_1]','<input type="file" name="upfile" size="50" />').'
                   <br />
                   <input type="button" onclick="javascript:checkUpload(this.form);" value="'.&mt('Upload Bubblesheet Data').'" />
                 </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:
   
     $result.= '      $result.= '
Line 5200  sub scantron_selectphase { Line 5450  sub scantron_selectphase {
         
     $r->print($result);      $r->print($result);
   
     if (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) ||  
         &Apache::lonnet::allowed('usc',$env{'request.course.id'})) {  
   
  # Chunk of form to prompt for a scantron file upload.  
   
         $r->print('  
     <br />  
     '.&Apache::loncommon::start_data_table('LC_scantron_action').'  
        '.&Apache::loncommon::start_data_table_header_row().'  
             <th>  
               &nbsp;'.&mt('Specify a bubblesheet data file to upload.').'  
             </th>  
        '.&Apache::loncommon::end_data_table_header_row().'  
        '.&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) {  
  if (formname.upfile.value == "") {  
     alert("'.&mt('Please use the browse button to select a file from your local directory.').'");  
     return false;  
  }  
  formname.submit();  
     }  
               </script>  
   
               <form enctype="multipart/form-data" action="/adm/grades" name="rules" method="post">  
                 '.$default_form_data.'  
                 <input name="courseid" type="hidden" value="'.$cnum.'" />  
                 <input name="domainid" type="hidden" value="'.$cdom.'" />  
                 <input name="command" value="scantronupload_save" type="hidden" />  
                 '.&mt('File to upload: [_1]','<input type="file" name="upfile" size="50" />').'  
                 <br />  
                 <input type="button" onClick="javascript:checkUpload(this.form);" value="'.&mt('Upload Bubblesheet Data').'" />  
               </form>  
 ');  
   
         $r->print('  
             </td>  
        '.&Apache::loncommon::end_data_table_row().'  
        '.&Apache::loncommon::end_data_table().'  
 ');  
     }  
   
     # Chunk of the form that prompts to view a scoring office file,      # Chunk of the form that prompts to view a scoring office file,
     # corrected file, skipped records in a file.      # corrected file, skipped records in a file.
   
Line 5364  sub scantron_selectphase { Line 5566  sub scantron_selectphase {
     
       LastName    - column that the last name starts in        LastName    - column that the last name starts in
       LastNameLength - number of columns that the last name spans        LastNameLength - number of columns that the last name spans
         BubblesPerRow - number of bubbles available in each row used to
                         bubble an answer. (If not specified, 10 assumed).
   
 =cut  =cut
   
Line 5394  sub get_scantron_config { Line 5598  sub get_scantron_config {
  $config{'FirstNamelength'}=$config[14];   $config{'FirstNamelength'}=$config[14];
  $config{'LastName'}=$config[15];   $config{'LastName'}=$config[15];
  $config{'LastNamelength'}=$config[16];   $config{'LastNamelength'}=$config[16];
           $config{'BubblesPerRow'}=$config[17];
  last;   last;
     }      }
     return %config;      return %config;
Line 6143  sub remember_current_skipped { Line 6348  sub remember_current_skipped {
 =item check_for_error  =item check_for_error
   
     Checks if there was an error when attempting to remove a specific      Checks if there was an error when attempting to remove a specific
     scantron_.. bubble sheet data file. Prints out an error if      scantron_.. bubblesheet data file. Prints out an error if
     something went wrong.      something went wrong.
   
 =cut  =cut
Line 6214  sub scantron_do_warning { Line 6419  sub scantron_do_warning {
     if ( $env{'form.selectpage'} eq '' ||      if ( $env{'form.selectpage'} eq '' ||
  $env{'form.scantron_selectfile'} eq '' ||   $env{'form.scantron_selectfile'} eq '' ||
  $env{'form.scantron_format'} eq '' ) {   $env{'form.scantron_format'} eq '' ) {
  $r->print("<p>".&mt('You have forgetten to specify some information. Please go Back and try again.')."</p>");   $r->print("<p>".&mt('You have forgotten to specify some information. Please go Back and try again.')."</p>");
  if ( $env{'form.selectpage'} eq '') {   if ( $env{'form.selectpage'} eq '') {
     $r->print('<p><span class="LC_error">'.&mt('You have not selected a Sequence to grade').'</span></p>');      $r->print('<p><span class="LC_error">'.&mt('You have not selected a Sequence to grade').'</span></p>');
  }    } 
  if ( $env{'form.scantron_selectfile'} eq '') {   if ( $env{'form.scantron_selectfile'} eq '') {
     $r->print('<p><span class="LC_error">'.&mt('You have not selected a file that contains the student\'s response data.').'</span></p>');      $r->print('<p><span class="LC_error">'.&mt("You have not selected a file that contains the student's response data.").'</span></p>');
  }    } 
  if ( $env{'form.scantron_format'} eq '') {   if ( $env{'form.scantron_format'} eq '') {
     $r->print('<p><span class="LC_error">'.&mt('You have not selected a the format of the student\'s response data.').'</span></p>');      $r->print('<p><span class="LC_error">'.&mt("You have not selected the format of the student's response data.").'</span></p>');
  }    } 
     } else {      } else {
  my $warning=&scantron_warning_screen('Grading: Validate Records');   my $warning=&scantron_warning_screen('Grading: Validate Records');
Line 6279  SCANTRONFORM Line 6484  SCANTRONFORM
   
 =item scantron_validate_file  =item scantron_validate_file
   
     Dispatch routine for doing validation of a bubble sheet data file.      Dispatch routine for doing validation of a bubblesheet data file.
   
     Also processes any necessary information resets that need to      Also processes any necessary information resets that need to
     occur before validation begins (ignore previous corrections,      occur before validation begins (ignore previous corrections,
Line 6317  sub scantron_validate_file { Line 6522  sub scantron_validate_file {
     #get the student pick code ready      #get the student pick code ready
     $r->print(&Apache::loncommon::studentbrowser_javascript());      $r->print(&Apache::loncommon::studentbrowser_javascript());
     my $nav_error;      my $nav_error;
     my $max_bubble=&scantron_get_maxbubble(\$nav_error);      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
       my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config);
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
         return '';          return '';
Line 6390  sub scantron_validate_file { Line 6596  sub scantron_validate_file {
   
 =item scantron_remove_file  =item scantron_remove_file
   
    Removes the requested bubble sheet data file, makes sure that     Removes the requested bubblesheet data file, makes sure that
    scantron_original_<filename> is never removed     scantron_original_<filename> is never removed
   
   
Line 6415  sub scantron_remove_file { Line 6621  sub scantron_remove_file {
   
 =item scantron_remove_scan_data  =item scantron_remove_scan_data
   
    Removes all scan_data correction for the requested bubble sheet     Removes all scan_data correction for the requested bubblesheet
    data file.  (In the case that both the are doing skipped records we need     data file.  (In the case that both the are doing skipped records we need
    to remember the old skipped lines for the time being so that element     to remember the old skipped lines for the time being so that element
    persists for a while.)     persists for a while.)
Line 6452  sub scantron_remove_scan_data { Line 6658  sub scantron_remove_scan_data {
   
 =item scantron_getfile  =item scantron_getfile
   
     Fetches the requested bubble sheet data file (all 3 versions), and      Fetches the requested bubblesheet data file (all 3 versions), and
     the scan_data hash      the scan_data hash
       
   Arguments:    Arguments:
Line 6552  sub lonnet_putfile { Line 6758  sub lonnet_putfile {
   
 =item scantron_putfile  =item scantron_putfile
   
     Stores the current version of the bubble sheet data files, and the      Stores the current version of the bubblesheet data files, and the
     scan_data hash. (Does not modify the original version only the      scan_data hash. (Does not modify the original version only the
     corrected and skipped versions.      corrected and skipped versions.
   
Line 6646  sub get_todo_count { Line 6852  sub get_todo_count {
   
 =item scantron_put_line  =item scantron_put_line
   
     Updates the 'corrected' or 'skipped' versions of the bubble sheet      Updates the 'corrected' or 'skipped' versions of the bubblesheet
     data file.      data file.
   
  Arguments:   Arguments:
Line 6770  sub scantron_validate_ID { Line 6976  sub scantron_validate_ID {
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
   
     my $nav_error;      my $nav_error;
     &scantron_get_maxbubble(\$nav_error); # parse needs the bubble_lines.. array.      &scantron_get_maxbubble(\$nav_error,\%scantron_config); # parse needs the bubble_lines.. array.
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
         return(1,$currentphase);          return(1,$currentphase);
Line 6835  sub scantron_get_correction { Line 7041  sub scantron_get_correction {
 #the previous one or the current one  #the previous one or the current one
   
     if ( $$scan_record{'scantron.PaperID'} =~ /\S/) {      if ( $$scan_record{'scantron.PaperID'} =~ /\S/) {
  $r->print("<p>".&mt("<b>An error was detected ($error)</b>".          $r->print(
     " for PaperID <tt>[_1]</tt>",              '<p class="LC_warning">'
     $$scan_record{'scantron.PaperID'})."</p> \n");             .&mt('An error was detected ([_1]) for PaperID [_2]',
                   "<b>$error</b>",
                   '<tt>'.$$scan_record{'scantron.PaperID'}.'</tt>')
              ."</p> \n");
     } else {      } else {
  $r->print("<p>".&mt("<b>An error was detected ($error)</b>".          $r->print(
     " in scanline [_1] <pre>[_2]</pre>",              '<p class="LC_warning">'
     $i,$line)."</p> \n");             .&mt('An error was detected ([_1]) in scanline [_2] [_3]',
     }                  "<b>$error</b>", $i, "<pre>$line</pre>")
     my $message="<p>".&mt("The ID on the form is  <tt>[_1]</tt><br />".             ."</p> \n");
   "The name on the paper is [_2],[_3]",      }
   $$scan_record{'scantron.ID'},      my $message =
   $$scan_record{'scantron.LastName'},          '<p>'
   $$scan_record{'scantron.FirstName'})."</p>";         .&mt('The ID on the form is [_1]',
               "<tt>$$scan_record{'scantron.ID'}</tt>")
          .'<br />'
          .&mt('The name on the paper is [_1], [_2]',
               $$scan_record{'scantron.LastName'},
               $$scan_record{'scantron.FirstName'})
          .'</p>';
   
     $r->print('<input type="hidden" name="scantron_corrections" value="'.$error.'" />'."\n");      $r->print('<input type="hidden" name="scantron_corrections" value="'.$error.'" />'."\n");
     $r->print('<input type="hidden" name="scantron_line" value="'.$i.'" />'."\n");      $r->print('<input type="hidden" name="scantron_line" value="'.$i.'" />'."\n");
Line 6857  sub scantron_get_correction { Line 7072  sub scantron_get_correction {
   
     if ($error =~ /ID$/) {      if ($error =~ /ID$/) {
  if ($error eq 'incorrectID') {   if ($error eq 'incorrectID') {
     $r->print("<p>".&mt("The encoded ID is not in the classlist").      $r->print('<p class="LC_warning">'.&mt("The encoded ID is not in the classlist").
       "</p>\n");        "</p>\n");
  } elsif ($error eq 'duplicateID') {   } elsif ($error eq 'duplicateID') {
     $r->print("<p>".&mt("The encoded ID has also been used by a previous paper [_1]",$arg)."</p>\n");      $r->print('<p class="LC_warning">'.&mt("The encoded ID has also been used by a previous paper [_1]",$arg)."</p>\n");
  }   }
  $r->print($message);   $r->print($message);
  $r->print("<p>".&mt("How should I handle this?")." <br /> \n");   $r->print("<p>".&mt("How should I handle this?")." <br /> \n");
Line 6876  sub scantron_get_correction { Line 7091  sub scantron_get_correction {
  $r->print('</li>');   $r->print('</li>');
     } elsif ($error =~ /CODE$/) {      } elsif ($error =~ /CODE$/) {
  if ($error eq 'incorrectCODE') {   if ($error eq 'incorrectCODE') {
     $r->print("<p>".&mt("The encoded CODE is not in the list of possible CODEs.")."</p>\n");      $r->print('<p class="LC_warning">'.&mt("The encoded CODE is not in the list of possible CODEs.")."</p>\n");
  } elsif ($error eq 'duplicateCODE') {   } elsif ($error eq 'duplicateCODE') {
     $r->print("<p>".&mt("The encoded CODE has also been used by a previous paper [_1], and CODEs are supposed to be unique.",join(', ',@{$arg}))."</p>\n");      $r->print('<p class="LC_warning">'.&mt("The encoded CODE has also been used by a previous paper [_1], and CODEs are supposed to be unique.",join(', ',@{$arg}))."</p>\n");
  }   }
  $r->print("<p>".&mt("The CODE on the form is  <tt>'[_1]'</tt>",          $r->print("<p>".&mt('The CODE on the form is [_1]',
     $$scan_record{'scantron.CODE'})."<br />\n");                              "<tt>'$$scan_record{'scantron.CODE'}'</tt>")
                    ."</p>\n");
  $r->print($message);   $r->print($message);
  $r->print("<p>".&mt("How should I handle this?")." <br /> \n");   $r->print("<p>".&mt("How should I handle this?")."</p>\n");
  $r->print("\n<br /> ");   $r->print("\n<br /> ");
  my $i=0;   my $i=0;
  if ($error eq 'incorrectCODE'    if ($error eq 'incorrectCODE' 
Line 6910  sub scantron_get_correction { Line 7126  sub scantron_get_correction {
     $r->print("      $r->print("
     <label>      <label>
         <input type='radio' name='scantron_CODE_resolution' value='use_unfound'$checked />          <input type='radio' name='scantron_CODE_resolution' value='use_unfound'$checked />
        ".&mt("Use the CODE [_1] that is was on the paper, ignoring the error.",         ".&mt("Use the CODE [_1] that was on the paper, ignoring the error.",
      "<b><tt>".$$scan_record{'scantron.CODE'}."</tt></b>")."       "<b><tt>".$$scan_record{'scantron.CODE'}."</tt></b>")."
     </label>");      </label>");
     $r->print("\n<br />");      $r->print("\n<br />");
Line 6950  ENDSCRIPT Line 7166  ENDSCRIPT
      "</label><input type='text' size='8' name='scantron_CODE_newvalue' onfocus=\"javascript:change_radio('use_typed')\" onkeypress=\"javascript:change_radio('use_typed')\" />"));       "</label><input type='text' size='8' name='scantron_CODE_newvalue' onfocus=\"javascript:change_radio('use_typed')\" onkeypress=\"javascript:change_radio('use_typed')\" />"));
  $r->print("\n<br /><br />");   $r->print("\n<br /><br />");
     } elsif ($error eq 'doublebubble') {      } elsif ($error eq 'doublebubble') {
  $r->print("<p>".&mt("There have been multiple bubbles scanned for some question(s)")."</p>\n");   $r->print('<p class="LC_warning">'.&mt("There have been multiple bubbles scanned for some question(s)")."</p>\n");
   
  # The form field scantron_questions is acutally a list of line numbers.   # The form field scantron_questions is acutally a list of line numbers.
  # represented by this form so:   # represented by this form so:
Line 6968  ENDSCRIPT Line 7184  ENDSCRIPT
  }   }
         $r->print(&verify_bubbles_checked(@lines_to_correct));          $r->print(&verify_bubbles_checked(@lines_to_correct));
     } elsif ($error eq 'missingbubble') {      } elsif ($error eq 'missingbubble') {
  $r->print("<p>".&mt("There have been <b>no</b> bubbles scanned for some question(s)")."</p>\n");   $r->print('<p class="LC_warning">'.&mt("There have been [_1]no[_2] bubbles scanned for some question(s)",'<b>','</b>')."</p>\n");
  $r->print($message);   $r->print($message);
  $r->print("<p>".&mt("Please indicate which bubble should be used for grading.")."</p>");   $r->print("<p>".&mt("Please indicate which bubble should be used for grading.")."</p>");
  $r->print(&mt("Some questions have no scanned bubbles.")."\n");   $r->print(&mt("Some questions have no scanned bubbles.")."\n");
Line 7173  sub scantron_bubble_selector { Line 7389  sub scantron_bubble_selector {
     my $max=$$scan_config{'Qlength'};      my $max=$$scan_config{'Qlength'};
   
     my $scmode=$$scan_config{'Qon'};      my $scmode=$$scan_config{'Qon'};
     if ($scmode eq 'number' || $scmode eq 'letter') { $max=10; }           if ($scmode eq 'number' || $scmode eq 'letter') {
           if (($$scan_config{'BubblesPerRow'} =~ /^\d+$/) &&
               ($$scan_config{'BubblesPerRow'} > 0)) {
               $max=$$scan_config{'BubblesPerRow'};
               if (($scmode eq 'number') && ($max > 10)) {
                   $max = 10;
               } elsif (($scmode eq 'letter') && $max > 26) {
                   $max = 26;
               }
           } else {
               $max = 10;
           }
       }
   
     my @alphabet=('A'..'Z');      my @alphabet=('A'..'Z');
     $r->print(&Apache::loncommon::start_data_table().      $r->print(&Apache::loncommon::start_data_table().
Line 7328  sub scantron_validate_CODE { Line 7556  sub scantron_validate_CODE {
     my %allcodes=&get_codes();      my %allcodes=&get_codes();
   
     my $nav_error;      my $nav_error;
     &scantron_get_maxbubble(\$nav_error); # parse needs the lines per response array.      &scantron_get_maxbubble(\$nav_error,\%scantron_config); # parse needs the lines per response array.
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
         return(1,$currentphase);          return(1,$currentphase);
Line 7386  sub scantron_validate_doublebubble { Line 7614  sub scantron_validate_doublebubble {
     #get scantron line setup      #get scantron line setup
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
     &scantron_get_maxbubble(); # parse needs the bubble line array.      my $nav_error;
       &scantron_get_maxbubble(\$nav_error,\%scantron_config); # parse needs the bubble line array.
       if ($nav_error) {
           $r->print(&navmap_errormsg());
           return(1,$currentphase);
       }
   
     for (my $i=0;$i<=$scanlines->{'count'};$i++) {      for (my $i=0;$i<=$scanlines->{'count'};$i++) {
  my $line=&scantron_get_line($scanlines,$scan_data,$i);   my $line=&scantron_get_line($scanlines,$scan_data,$i);
Line 7404  sub scantron_validate_doublebubble { Line 7637  sub scantron_validate_doublebubble {
   
   
 sub scantron_get_maxbubble {  sub scantron_get_maxbubble {
     my ($nav_error) = @_;      my ($nav_error,$scantron_config) = @_;
     if (defined($env{'form.scantron_maxbubble'}) &&      if (defined($env{'form.scantron_maxbubble'}) &&
  $env{'form.scantron_maxbubble'}) {   $env{'form.scantron_maxbubble'}) {
  &restore_bubble_lines();   &restore_bubble_lines();
Line 7419  sub scantron_get_maxbubble { Line 7652  sub scantron_get_maxbubble {
         if (ref($nav_error)) {          if (ref($nav_error)) {
             $$nav_error = 1;              $$nav_error = 1;
         }          }
           return;
     }      }
     my $map=$navmap->getResourceByUrl($sequence);      my $map=$navmap->getResourceByUrl($sequence);
     my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);      my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
       my $bubbles_per_row = &bubblesheet_bubbles_per_row($scantron_config);
   
     &Apache::lonxml::clear_problem_counter();      &Apache::lonxml::clear_problem_counter();
   
Line 7437  sub scantron_get_maxbubble { Line 7672  sub scantron_get_maxbubble {
     my $response_number = 0;      my $response_number = 0;
     my $bubble_line     = 0;      my $bubble_line     = 0;
     foreach my $resource (@resources) {      foreach my $resource (@resources) {
         my ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname,$udom);          my ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname,
                                                             $udom,$bubbles_per_row);
         if ((ref($analysis) eq 'HASH') && (ref($parts) eq 'ARRAY')) {          if ((ref($analysis) eq 'HASH') && (ref($parts) eq 'ARRAY')) {
     foreach my $part_id (@{$parts}) {      foreach my $part_id (@{$parts}) {
                 my $lines;                  my $lines;
Line 7466  sub scantron_get_maxbubble { Line 7702  sub scantron_get_maxbubble {
                     if (ref($analysis->{$part_id.'.shown'}) eq 'ARRAY') {                      if (ref($analysis->{$part_id.'.shown'}) eq 'ARRAY') {
                         $numshown = scalar(@{$analysis->{$part_id.'.shown'}});                          $numshown = scalar(@{$analysis->{$part_id.'.shown'}});
                     }                      }
                     my $bubbles_per_line = 10;                      my $bubbles_per_row =
                     my $inner_bubble_lines = int($numbub/$bubbles_per_line);                          &bubblesheet_bubbles_per_row($scantron_config);
                     if (($numbub % $bubbles_per_line) != 0) {                      my $inner_bubble_lines = int($numbub/$bubbles_per_row);
                       if (($numbub % $bubbles_per_row) != 0) {
                         $inner_bubble_lines++;                          $inner_bubble_lines++;
                     }                      }
                     for (my $i=0; $i<$numshown; $i++) {                      for (my $i=0; $i<$numshown; $i++) {
Line 7479  sub scantron_get_maxbubble { Line 7716  sub scantron_get_maxbubble {
                     $lines = $numshown * $inner_bubble_lines;                      $lines = $numshown * $inner_bubble_lines;
                 } else {                  } else {
                     $lines = $analysis->{"$part_id.bubble_lines"};                      $lines = $analysis->{"$part_id.bubble_lines"};
                 }                   }
   
                 $first_bubble_line{$response_number} = $bubble_line;                  $first_bubble_line{$response_number} = $bubble_line;
         $bubble_lines_per_response{$response_number} = $lines;          $bubble_lines_per_response{$response_number} = $lines;
Line 7500  sub scantron_get_maxbubble { Line 7737  sub scantron_get_maxbubble {
     return $env{'form.scantron_maxbubble'};      return $env{'form.scantron_maxbubble'};
 }  }
   
   sub bubblesheet_bubbles_per_row {
       my ($scantron_config) = @_;
       my $bubbles_per_row;
       if (ref($scantron_config) eq 'HASH') {
           $bubbles_per_row = $scantron_config->{'BubblesPerRow'};
       }
       if ((!$bubbles_per_row) || ($bubbles_per_row < 1)) {
           $bubbles_per_row = 10;
       }
       return $bubbles_per_row;
   }
   
 sub scantron_validate_missingbubbles {  sub scantron_validate_missingbubbles {
     my ($r,$currentphase) = @_;      my ($r,$currentphase) = @_;
     #get student info      #get student info
Line 7510  sub scantron_validate_missingbubbles { Line 7759  sub scantron_validate_missingbubbles {
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
     my $nav_error;      my $nav_error;
     my $max_bubble=&scantron_get_maxbubble(\$nav_error);      my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config);
     if ($nav_error) {      if ($nav_error) {
         return(1,$currentphase);          return(1,$currentphase);
     }      }
Line 7582  sub scantron_process_students { Line 7831  sub scantron_process_students {
     my (%grader_partids_by_symb,%grader_randomlists_by_symb);      my (%grader_partids_by_symb,%grader_randomlists_by_symb);
     &graders_resources_pass(\@resources,\%grader_partids_by_symb,      &graders_resources_pass(\@resources,\%grader_partids_by_symb,
                             \%grader_randomlists_by_symb);                              \%grader_randomlists_by_symb);
       my $resource_error;
     foreach my $resource (@resources) {      foreach my $resource (@resources) {
         my $ressymb = $resource->symb();          my $ressymb;
           if (ref($resource)) {
               $ressymb = $resource->symb();
           } else {
               $resource_error = 1;
               last;
           }
         my ($analysis,$parts) =          my ($analysis,$parts) =
             &scantron_partids_tograde($resource,$env{'request.course.id'},              &scantron_partids_tograde($resource,$env{'request.course.id'},
                                       $env{'user.name'},$env{'user.domain'},1);                                        $env{'user.name'},$env{'user.domain'},
                                         1,$bubbles_per_row);
         $grader_partids_by_symb{$ressymb} = $parts;          $grader_partids_by_symb{$ressymb} = $parts;
         if (ref($analysis) eq 'HASH') {          if (ref($analysis) eq 'HASH') {
             if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') {              if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') {
Line 7595  sub scantron_process_students { Line 7852  sub scantron_process_students {
             }              }
         }          }
     }      }
       if ($resource_error) {
           $r->print(&navmap_errormsg());
           return '';
       }
   
     my ($uname,$udom);      my ($uname,$udom);
     my $result= <<SCANTRONFORM;      my $result= <<SCANTRONFORM;
Line 7620  SCANTRONFORM Line 7881  SCANTRONFORM
     my $started;      my $started;
   
     my $nav_error;      my $nav_error;
     &scantron_get_maxbubble(\$nav_error); # Need the bubble lines array to parse.      &scantron_get_maxbubble(\$nav_error,\%scantron_config); # Need the bubble lines array to parse.
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
         return '';          return '';
     }      }
   
     &scantron_get_maxbubble(); # Need the bubble lines array to parse.  
   
   
     # If an ssi failed in scantron_get_maxbubble, put an error message out to      # If an ssi failed in scantron_get_maxbubble, put an error message out to
     # the user and return.      # the user and return.
   
Line 7668  SCANTRONFORM Line 7926  SCANTRONFORM
   }    }
   ($uname,$udom)=split(/:/,$uname);    ($uname,$udom)=split(/:/,$uname);
   
         my %partids_by_symb;          my (%partids_by_symb,$res_error);
         foreach my $resource (@resources) {          foreach my $resource (@resources) {
             my $ressymb = $resource->symb();              my $ressymb;
               if (ref($resource)) {
                   $ressymb = $resource->symb();
               } else {
                   $res_error = 1;
                   last;
               }
             if ((exists($grader_randomlists_by_symb{$ressymb})) ||              if ((exists($grader_randomlists_by_symb{$ressymb})) ||
                 (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {                  (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {
                 my ($analysis,$parts) =                  my ($analysis,$parts) =
                     &scantron_partids_tograde($resource,$env{'request.course.id'},$uname,$udom);                      &scantron_partids_tograde($resource,$env{'request.course.id'},
                                                 $uname,$udom,undef,$bubbles_per_row);
                 $partids_by_symb{$ressymb} = $parts;                  $partids_by_symb{$ressymb} = $parts;
             } else {              } else {
                 $partids_by_symb{$ressymb} = $grader_partids_by_symb{$ressymb};                  $partids_by_symb{$ressymb} = $grader_partids_by_symb{$ressymb};
             }              }
         }          }
   
           if ($res_error) {
               &scantron_add_delay(\@delayqueue,$line,
                                   'An error occurred while grading student '.$uname,2);
               next;
           }
   
  &Apache::lonxml::clear_problem_counter();   &Apache::lonxml::clear_problem_counter();
   &Apache::lonnet::appenv($scan_record);    &Apache::lonnet::appenv($scan_record);
   
Line 7697  SCANTRONFORM Line 7968  SCANTRONFORM
         }          }
   
         if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,          if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,
                                    \@resources,\%partids_by_symb) eq 'ssi_error') {                                     \@resources,\%partids_by_symb,
                                      $bubbles_per_row) eq 'ssi_error') {
             $ssi_error = 0; # So end of handler error message does not trigger.              $ssi_error = 0; # So end of handler error message does not trigger.
             $r->print("</form>");              $r->print("</form>");
             &ssi_print_error($r);              &ssi_print_error($r);
Line 7725  SCANTRONFORM Line 7997  SCANTRONFORM
             if ($studentrecord ne $studentdata) {              if ($studentrecord ne $studentdata) {
                 &Apache::lonxml::clear_problem_counter();                  &Apache::lonxml::clear_problem_counter();
                 if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,                  if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,
                                            \@resources,\%partids_by_symb) eq 'ssi_error') {                                             \@resources,\%partids_by_symb,
                                              $bubbles_per_row) eq 'ssi_error') {
                     $ssi_error = 0; # So end of handler error message does not trigger.                      $ssi_error = 0; # So end of handler error message does not trigger.
                     $r->print("</form>");                      $r->print("</form>");
                     &ssi_print_error($r);                      &ssi_print_error($r);
Line 7745  SCANTRONFORM Line 8018  SCANTRONFORM
                     $studentrecord .= $recording;                      $studentrecord .= $recording;
                 }                  }
                 if ($studentrecord ne $studentdata) {                  if ($studentrecord ne $studentdata) {
                     $r->print('<p><span class="LC_error">');                      $r->print('<p><span class="LC_warning">');
                     if ($scancode eq '') {                      if ($scancode eq '') {
                         $r->print(&mt('Mismatch grading bubble sheet for user: [_1] with ID: [_2].',                          $r->print(&mt('Mismatch grading bubblesheet for user: [_1] with ID: [_2].',
                                   $uname.':'.$udom,$scan_record->{'scantron.ID'}));                                    $uname.':'.$udom,$scan_record->{'scantron.ID'}));
                     } else {                      } else {
                         $r->print(&mt('Mismatch grading bubble sheet for user: [_1] with ID: [_2] and CODE: [_3].',                          $r->print(&mt('Mismatch grading bubblesheet for user: [_1] with ID: [_2] and CODE: [_3].',
                                   $uname.':'.$udom,$scan_record->{'scantron.ID'},$scancode));                                    $uname.':'.$udom,$scan_record->{'scantron.ID'},$scancode));
                     }                      }
                     $r->print('</span><br />'.&Apache::loncommon::start_data_table()."\n".                      $r->print('</span><br />'.&Apache::loncommon::start_data_table()."\n".
Line 7758  SCANTRONFORM Line 8031  SCANTRONFORM
                               '<th>'.&mt('Source').'</th><th>'.&mt('Bubbled responses').'</th>'.                                '<th>'.&mt('Source').'</th><th>'.&mt('Bubbled responses').'</th>'.
                               &Apache::loncommon::end_data_table_header_row()."\n".                                &Apache::loncommon::end_data_table_header_row()."\n".
                               &Apache::loncommon::start_data_table_row().                                &Apache::loncommon::start_data_table_row().
                               '<td>'.&mt('Bubble Sheet').'</td>'.                                '<td>'.&mt('Bubblesheet').'</td>'.
                               '<td><span class="LC_nobreak">'.$studentdata.'</span></td>'.                                '<td><span class="LC_nobreak">'.$studentdata.'</span></td>'.
                               &Apache::loncommon::end_data_table_row().                                &Apache::loncommon::end_data_table_row().
                               &Apache::loncommon::start_data_table_row().                                &Apache::loncommon::start_data_table_row().
                               '<td>Stored submissions</td>'.                                '<td>'.&mt('Stored submissions').'</td>'.
                               '<td><span class="LC_nobreak">'.$studentrecord.'</span></td>'."\n".                                '<td><span class="LC_nobreak">'.$studentrecord.'</span></td>'."\n".
                               &Apache::loncommon::end_data_table_row().                                &Apache::loncommon::end_data_table_row().
                               &Apache::loncommon::end_data_table().'</p>');                                &Apache::loncommon::end_data_table().'</p>');
Line 7797  sub graders_resources_pass { Line 8070  sub graders_resources_pass {
             my $ressymb = $resource->symb();              my $ressymb = $resource->symb();
             my ($analysis,$parts) =              my ($analysis,$parts) =
                 &scantron_partids_tograde($resource,$env{'request.course.id'},                  &scantron_partids_tograde($resource,$env{'request.course.id'},
                                           $env{'user.name'},$env{'user.domain'},1);                                            $env{'user.name'},$env{'user.domain'},
                                             1,$bubbles_per_row);
             $grader_partids_by_symb->{$ressymb} = $parts;              $grader_partids_by_symb->{$ressymb} = $parts;
             if (ref($analysis) eq 'HASH') {              if (ref($analysis) eq 'HASH') {
                 if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') {                  if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') {
Line 7811  sub graders_resources_pass { Line 8085  sub graders_resources_pass {
 }  }
   
 sub grade_student_bubbles {  sub grade_student_bubbles {
     my ($r,$uname,$udom,$scan_record,$scancode,$resources,$parts) = @_;      my ($r,$uname,$udom,$scan_record,$scancode,$resources,$parts,$bubbles_per_row) = @_;
     if (ref($resources) eq 'ARRAY') {      if (ref($resources) eq 'ARRAY') {
         my $count = 0;          my $count = 0;
         foreach my $resource (@{$resources}) {          foreach my $resource (@{$resources}) {
Line 7824  sub grade_student_bubbles { Line 8098  sub grade_student_bubbles {
                         'grade_symb'     => $ressymb,                          'grade_symb'     => $ressymb,
                         'CODE'           => $scancode                          'CODE'           => $scancode
                        );                         );
               if ($bubbles_per_row ne '') {
                   $form{'bubbles_per_row'} = $bubbles_per_row;
               }
             if (ref($parts) eq 'HASH') {              if (ref($parts) eq 'HASH') {
                 if (ref($parts->{$ressymb}) eq 'ARRAY') {                  if (ref($parts->{$ressymb}) eq 'ARRAY') {
                     foreach my $part (@{$parts->{$ressymb}}) {                      foreach my $part (@{$parts->{$ressymb}}) {
Line 7884  sub scantron_upload_scantron_data { Line 8161  sub scantron_upload_scantron_data {
   
 </script>  </script>
   
 <h3>'.&mt('Send scanned 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">
 '.$default_form_data.  '.$default_form_data.
Line 7904  sub scantron_upload_scantron_data { Line 8181  sub scantron_upload_scantron_data {
   &Apache::lonhtmlcommon::end_pick_box().'<br />    &Apache::lonhtmlcommon::end_pick_box().'<br />
   
 <input name="command" value="scantronupload_save" type="hidden" />  <input name="command" value="scantronupload_save" type="hidden" />
 <input type="button" onClick="javascript:checkUpload(this.form);" value="'.&mt('Upload Bubblesheet Data').'" />  <input type="button" onclick="javascript:checkUpload(this.form);" value="'.&mt('Upload Bubblesheet Data').'" />
 </form>  </form>
 ');  ');
     return '';      return '';
Line 8134  sub checkscantron_results { Line 8411  sub checkscantron_results {
                                     'inline',undef,'checkscantron');                                      'inline',undef,'checkscantron');
     my ($username,$domain,$started);      my ($username,$domain,$started);
     my $nav_error;      my $nav_error;
     &scantron_get_maxbubble(\$nav_error); # Need the bubble lines array to parse.      &scantron_get_maxbubble(\$nav_error,\%scantron_config); # Need the bubble lines array to parse.
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
         return '';          return '';
Line 8184  sub checkscantron_results { Line 8461  sub checkscantron_results {
             if ((exists($grader_randomlists_by_symb{$ressymb})) ||              if ((exists($grader_randomlists_by_symb{$ressymb})) ||
                 (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {                  (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {
                 (my $analysis,$parts) =                  (my $analysis,$parts) =
                     &scantron_partids_tograde($resource,$env{'request.course.id'},$username,$domain);                      &scantron_partids_tograde($resource,$env{'request.course.id'},
                                                 $username,$domain,undef,
                                                 $bubbles_per_row);
             } else {              } else {
                 $parts = $grader_partids_by_symb{$ressymb};                  $parts = $grader_partids_by_symb{$ressymb};
             }              }
Line 8229  sub checkscantron_results { Line 8508  sub checkscantron_results {
             }              }
         }          }
     }      }
     $r->print('<p>'.&mt('Comparison of bubblesheet data (including corrections) with corresponding submission records (most recent submission) for <b>[quant,_1,student]</b>  ([_2] scantron lines/student).',$numstudents,$env{'form.scantron_maxbubble'}).'</p>');      $r->print('<p>'.
                 &mt('Comparison of bubblesheet data (including corrections) with corresponding submission records (most recent submission) for [_1][quant,_2,student][_3] ([quant,_4,bubblesheet line] per student).',
                     '<b>',
                     $numstudents,
                     '</b>',
                     $env{'form.scantron_maxbubble'}).
                 '</p>'
       );
     $r->print('<p>'.&mt('Exact matches for <b>[quant,_1,student]</b>.',$passed).'<br />'.&mt('Discrepancies detected for <b>[quant,_1,student]</b>.',$failed).'</p>');      $r->print('<p>'.&mt('Exact matches for <b>[quant,_1,student]</b>.',$passed).'<br />'.&mt('Discrepancies detected for <b>[quant,_1,student]</b>.',$failed).'</p>');
     if ($passed) {      if ($passed) {
         $r->print(&mt('Students with exact correspondence between bubblesheet data and submissions are as follows:').'<br /><br />');          $r->print(&mt('Students with exact correspondence between bubblesheet data and submissions are as follows:').'<br /><br />');
Line 8463  sub grading_menu { Line 8749  sub grading_menu {
                     icon => 'addClickerInfoFile.png',                      icon => 'addClickerInfoFile.png',
                     linktitle => 'Specify a file containing the clicker information for this resource.'                      linktitle => 'Specify a file containing the clicker information for this resource.'
                    },                     },
                    { linktext => 'Grade/Manage/Review Bubblesheet Forms',                     { linktext => 'Grade/Manage/Review Bubblesheets',
                     url => $url4,                      url => $url4,
                     permission => 'F',                      permission => 'F',
                     icon => 'stat.png',                      icon => 'stat.png',
                     linktitle => 'Grade scantron exams, upload/download scantron data files, and review previously graded scantron exams.'                      linktitle => 'Grade bubblesheet exams, upload/download bubblesheet data files, and review previously graded bubblesheet exams.'
                    }                     }
                     ]                      ]
             });              });
Line 8489  sub grading_menu { Line 8775  sub grading_menu {
   
     $Str .= Apache::lonhtmlcommon::generate_menu(@menu);      $Str .= Apache::lonhtmlcommon::generate_menu(@menu);
     #$menudata->{'jscript'}      #$menudata->{'jscript'}
     $Str .='<hr /><input type="button" value="'.&mt('Verify Receipt').'" '.      $Str .='<hr /><input type="button" value="'.&mt('Verify Receipt No.').'" '.
         ' onClick="javascript:checkChoice(document.forms.gradingMenu,\'5\',\'verify\')" '.          ' onclick="javascript:checkChoice(document.forms.gradingMenu,\'5\',\'verify\')" '.
         ' /> '.          ' /> '.
         &Apache::lonnet::recprefix($env{'request.course.id'}).          &Apache::lonnet::recprefix($env{'request.course.id'}).
         '-<input type="text" name="receipt" size="4" onChange="javascript:checkReceiptNo(this.form,\'OK\')" />';          '-<input type="text" name="receipt" size="4" onchange="javascript:checkReceiptNo(this.form,\'OK\')" />';
   
     $Str .="</form>\n";      $Str .="</form>\n";
     my $receiptalert = &mt("Please enter a receipt number given by a student in the receipt box.");      my $receiptalert = &mt("Please enter a receipt number given by a student in the receipt box.");
Line 8676  GRADINGMENUJS Line 8962  GRADINGMENUJS
               </label>                </label>
             </div>              </div>
             <div>              <div>
       <input type="button" onClick="javascript:checkChoice(this.form,\'2\');" value="'.&mt('Next').' &rarr;" />        <input type="button" onclick="javascript:checkChoice(this.form,\'2\');" value="'.&mt('Next').' &rarr;" />
             </div>              </div>
           </div>            </div>
   
Line 8693  GRADINGMENUJS Line 8979  GRADINGMENUJS
               </label>                </label>
             </div>              </div>
             <div>              <div>
       <input type="button" onClick="javascript:checkChoice(this.form,\'2\');" value="'.&mt('Next').' &rarr;" />        <input type="button" onclick="javascript:checkChoice(this.form,\'2\');" value="'.&mt('Next').' &rarr;" />
             </div>              </div>
         </div>          </div>
   </form>';    </form>';
Line 8796  sub process_clicker { Line 9082  sub process_clicker {
     $result.='<table width="100%" border="0"><tr bgcolor="#e6ffff"><td>'."\n";      $result.='<table width="100%" border="0"><tr bgcolor="#e6ffff"><td>'."\n";
     $result.='&nbsp;<b>'.&mt('Specify a file containing the clicker information for this resource.').      $result.='&nbsp;<b>'.&mt('Specify a file containing the clicker information for this resource.').
         '</b></td></tr>'."\n";          '</b></td></tr>'."\n";
     $result.='<tr bgcolor=#ffffe6><td>'."\n";      $result.='<tr bgcolor="#ffffe6"><td>'."\n";
 # Attempt to restore parameters from last session, set defaults if not present  # Attempt to restore parameters from last session, set defaults if not present
     my %Saveable_Parameters=&clicker_grading_parameters();      my %Saveable_Parameters=&clicker_grading_parameters();
     &Apache::loncommon::restore_course_settings('grades_clicker',      &Apache::loncommon::restore_course_settings('grades_clicker',
Line 8823  sub process_clicker { Line 9109  sub process_clicker {
     my $pcorrect=&mt("Percentage points for correct solution");      my $pcorrect=&mt("Percentage points for correct solution");
     my $pincorrect=&mt("Percentage points for incorrect solution");      my $pincorrect=&mt("Percentage points for incorrect solution");
     my $selectform=&Apache::loncommon::select_form($env{'form.upfiletype'},'upfiletype',      my $selectform=&Apache::loncommon::select_form($env{'form.upfiletype'},'upfiletype',
    ('iclicker' => 'i>clicker',                                                     {'iclicker' => 'i>clicker',
                                                     'interwrite' => 'interwrite PRS'));                                                      'interwrite' => 'interwrite PRS'});
     $symb = &Apache::lonenc::check_encrypt($symb);      $symb = &Apache::lonenc::check_encrypt($symb);
     $result.=<<ENDUPFORM;      $result.=<<ENDUPFORM;
 <script type="text/javascript">  <script type="text/javascript">
Line 8873  function sanitycheck() { Line 9159  function sanitycheck() {
 <input type="hidden" name="saveState"  value="$env{'form.saveState'}" />  <input type="hidden" name="saveState"  value="$env{'form.saveState'}" />
 <input type="file" name="upfile" size="50" />  <input type="file" name="upfile" size="50" />
 <br /><label>$type: $selectform</label>  <br /><label>$type: $selectform</label>
 <br /><label><input type="radio" name="gradingmechanism" value="attendance"$checked{'attendance'} onClick="sanitycheck()" />$attendance </label>  <br /><label><input type="radio" name="gradingmechanism" value="attendance"$checked{'attendance'} onclick="sanitycheck()" />$attendance </label>
 <br /><label><input type="radio" name="gradingmechanism" value="personnel"$checked{'personnel'} onClick="sanitycheck()" />$personnel</label>  <br /><label><input type="radio" name="gradingmechanism" value="personnel"$checked{'personnel'} onclick="sanitycheck()" />$personnel</label>
 <br /><label><input type="radio" name="gradingmechanism" value="specific"$checked{'specific'} onClick="sanitycheck()" />$specific </label>  <br /><label><input type="radio" name="gradingmechanism" value="specific"$checked{'specific'} onclick="sanitycheck()" />$specific </label>
 <input type="text" name="specificid" value="$env{'form.specificid'}" size="20" />  <input type="text" name="specificid" value="$env{'form.specificid'}" size="20" />
 <br /><label><input type="radio" name="gradingmechanism" value="given"$checked{'given'} onClick="sanitycheck()" />$given </label>  <br /><label><input type="radio" name="gradingmechanism" value="given"$checked{'given'} onclick="sanitycheck()" />$given </label>
 <br />&nbsp;&nbsp;&nbsp;  <br />&nbsp;&nbsp;&nbsp;
 <input type="text" name="givenanswer" size="50" />  <input type="text" name="givenanswer" size="50" />
 <input type="hidden" name="waschecked" value="$env{'form.gradingmechanism'}" />  <input type="hidden" name="waschecked" value="$env{'form.gradingmechanism'}" />
 <br /><label>$pcorrect: <input type="text" name="pcorrect" size="4" value="$env{'form.pcorrect'}" onChange="sanitycheck()" /></label>  <br /><label>$pcorrect: <input type="text" name="pcorrect" size="4" value="$env{'form.pcorrect'}" onchange="sanitycheck()" /></label>
 <br /><label>$pincorrect: <input type="text" name="pincorrect" size="4" value="$env{'form.pincorrect'}" onChange="sanitycheck()" /></label>  <br /><label>$pincorrect: <input type="text" name="pincorrect" size="4" value="$env{'form.pincorrect'}" onchange="sanitycheck()" /></label>
 <br /><input type="button" onClick="javascript:checkUpload(this.form);" value="$upload" />  <br /><input type="button" onclick="javascript:checkUpload(this.form);" value="$upload" />
 </form>  </form>
 ENDUPFORM  ENDUPFORM
     $result.='</td></tr></table>'."\n".      $result.='</td></tr></table>'."\n".
Line 8914  sub process_clicker_file { Line 9200  sub process_clicker_file {
     if ($env{'form.gradingmechanism'} eq 'given') {      if ($env{'form.gradingmechanism'} eq 'given') {
         $env{'form.givenanswer'}=~s/^\s*//gs;          $env{'form.givenanswer'}=~s/^\s*//gs;
         $env{'form.givenanswer'}=~s/\s*$//gs;          $env{'form.givenanswer'}=~s/\s*$//gs;
         $env{'form.givenanswer'}=~s/[^a-zA-Z0-9\.\*\-]+/\,/g;          $env{'form.givenanswer'}=~s/[^a-zA-Z0-9\.\*\-\+]+/\,/g;
         $env{'form.givenanswer'}=uc($env{'form.givenanswer'});          $env{'form.givenanswer'}=uc($env{'form.givenanswer'});
         my @answers=split(/\,/,$env{'form.givenanswer'});          my @answers=split(/\,/,$env{'form.givenanswer'});
         $foundgiven=$#answers+1;          $foundgiven=$#answers+1;
Line 8974  sub process_clicker_file { Line 9260  sub process_clicker_file {
     $result.=(<<ENDHEADER);      $result.=(<<ENDHEADER);
 <br /><table width="100%" border="0"><tr><td bgcolor="#777777">  <br /><table width="100%" border="0"><tr><td bgcolor="#777777">
 <table width="100%" border="0"><tr bgcolor="#e6ffff"><td>  <table width="100%" border="0"><tr bgcolor="#e6ffff"><td>
 <b>$heading</b></td></tr><tr bgcolor=#ffffe6><td>  <b>$heading</b></td></tr><tr bgcolor="#ffffe6"><td>
 <form method="post" action="/adm/grades" name="clickeranalysis">  <form method="post" action="/adm/grades" name="clickeranalysis">
 <input type="hidden" name="symb" value="$symb" />  <input type="hidden" name="symb" value="$symb" />
 <input type="hidden" name="command" value="assignclickergrades" />  <input type="hidden" name="command" value="assignclickergrades" />
Line 9043  ENDHEADER Line 9329  ENDHEADER
                    "\n".&mt("Username").": <input type='text' name='uname".$id."' />&nbsp;".                     "\n".&mt("Username").": <input type='text' name='uname".$id."' />&nbsp;".
                    "\n".&mt("Domain").": ".                     "\n".&mt("Domain").": ".
                    &Apache::loncommon::select_dom_form($env{'course.'.$env{'request.course.id'}.'.domain'},'udom'.$id).'&nbsp;'.                     &Apache::loncommon::select_dom_form($env{'course.'.$env{'request.course.id'}.'.domain'},'udom'.$id).'&nbsp;'.
                    &Apache::loncommon::selectstudent_link('clickeranalysis','uname'.$id,'udom'.$id);                     &Apache::loncommon::selectstudent_link('clickeranalysis','uname'.$id,'udom'.$id,0,$id);
           $unknown_count++;            $unknown_count++;
        }         }
     }      }
Line 9088  sub iclicker_eval { Line 9374  sub iclicker_eval {
     $id=~s/^[\#0]+//;      $id=~s/^[\#0]+//;
     for (my $i=0;$i<$number;$i++) {      for (my $i=0;$i<$number;$i++) {
  my $idx=3+$i*6;   my $idx=3+$i*6;
                   $entries[$idx]=~s/[^a-zA-Z0-9\.\*\-\+]+//g;
  push(@idresponses,$entries[$idx]);   push(@idresponses,$entries[$idx]);
     }      }
     $$responses{$id}=join(',',@idresponses);      $$responses{$id}=join(',',@idresponses);
Line 9142  sub assign_clicker_grades { Line 9429  sub assign_clicker_grades {
 # Start screen output  # Start screen output
     my ($result) = &showResourceInfo($symb,$env{'form.probTitle'});      my ($result) = &showResourceInfo($symb,$env{'form.probTitle'});
   
     my $heading=&mt('Assigning grades based on clicker file');      $result .= '<br />'.
     $result.=(<<ENDHEADER);                 &Apache::loncommon::start_data_table().
 <br /><table width="100%" border="0"><tr><td bgcolor="#777777">                 &Apache::loncommon::start_data_table_header_row().
 <table width="100%" border="0"><tr bgcolor="#e6ffff"><td>                 '<th>'.&mt('Assigning grades based on clicker file').'</th>'.
 <b>$heading</b></td></tr><tr bgcolor=#ffffe6><td>                 &Apache::loncommon::end_data_table_header_row().
 ENDHEADER                 &Apache::loncommon::start_data_table_row().'<td>';
   
 # Get correct result  # Get correct result
 # FIXME: Possibly need delimiter other than ":"  # FIXME: Possibly need delimiter other than ":"
     my @correct=();      my @correct=();
Line 9163  ENDHEADER Line 9451  ENDHEADER
                     $result.='<br /><span class="LC_warning">'.                      $result.='<br /><span class="LC_warning">'.
                              &mt('More than one correct result given for question "[_1]": [_2] versus [_3].',                               &mt('More than one correct result given for question "[_1]": [_2] versus [_3].',
                                  $env{'form.question:'.$i},$correct[$i],$input[$i]).'</span>';                                   $env{'form.question:'.$i},$correct[$i],$input[$i]).'</span>';
                  } elsif ($input[$i]) {                   } elsif (($input[$i]) || ($input[$i] eq '0')) {
                     $correct[$i]=$input[$i];                      $correct[$i]=$input[$i];
                  }                   }
              }               }
           }            }
        }         }
        for (my $i=0;$i<$number;$i++) {         for (my $i=0;$i<$number;$i++) {
           if (!$correct[$i]) {            if ((!$correct[$i]) && ($correct[$i] ne '0')) {
              $result.='<br /><span class="LC_error">'.               $result.='<br /><span class="LC_error">'.
                       &mt('No correct result given for question "[_1]"!',                        &mt('No correct result given for question "[_1]"!',
                           $env{'form.question:'.$i}).'</span>';                            $env{'form.question:'.$i}).'</span>';
           }            }
        }         }
        $result.='<br />'.&mt("Correct answer: [_1]",join(', ',map { ($_?$_:'-') } @correct));         $result.='<br />'.&mt("Correct answer: [_1]",join(', ',map { ((($_) || ($_ eq '0'))?$_:'-') } @correct));
     }      }
 # Start grading  # Start grading
     my $pcorrect=$env{'form.pcorrect'};      my $pcorrect=$env{'form.pcorrect'};
     my $pincorrect=$env{'form.pincorrect'};      my $pincorrect=$env{'form.pincorrect'};
     my $storecount=0;      my $storecount=0;
       my %users=();
     foreach my $key (keys(%env)) {      foreach my $key (keys(%env)) {
        my $user='';         my $user='';
        if ($key=~/^form\.student\:(.*)$/) {         if ($key=~/^form\.student\:(.*)$/) {
Line 9195  ENDHEADER Line 9484  ENDHEADER
              $user=$env{'form.multi'.$id};               $user=$env{'form.multi'.$id};
           }            }
        }         }
        if ($user) {          if ($user) {
             if ($users{$user}) {
                $result.='<br /><span class="LC_warning">'.
                         &mt("More than one entry found for <tt>[_1]</tt>!",$user).
                         '</span><br />';
             }
             $users{$user}=1;
           my @answer=split(/\,/,$env{$key});            my @answer=split(/\,/,$env{$key});
           my $sum=0;            my $sum=0;
           my $realnumber=$number;            my $realnumber=$number;
Line 9208  ENDHEADER Line 9503  ENDHEADER
                 } elsif ($correct[$i] eq '*') {                  } elsif ($correct[$i] eq '*') {
                    $sum+=$pcorrect;                     $sum+=$pcorrect;
                 } else {                  } else {
                    if ($answer[$i] eq $correct[$i]) {  # We actually grade if correct or not
                       $sum+=$pcorrect;                     my $increment=$pincorrect;
                    } else {  # Special case: numerical answer "0"
                       $sum+=$pincorrect;                     if ($correct[$i] eq '0') {
                         if ($answer[$i]=~/^[0\.]+$/) {
                            $increment=$pcorrect;
                         }
   # General numerical answer, both evaluate to something non-zero
                      } elsif ((1.0*$correct[$i]!=0) && (1.0*$answer[$i]!=0)) {
                         if (1.0*$correct[$i]==1.0*$answer[$i]) {
                            $increment=$pcorrect;
                         }
   # Must be just alphanumeric
                      } elsif ($answer[$i] eq $correct[$i]) {
                         $increment=$pcorrect;
                    }                     }
                      $sum+=$increment;
                 }                  }
              }               }
           }            }
Line 9235  ENDHEADER Line 9542  ENDHEADER
     }      }
 # We are done  # We are done
     $result.='<br />'.&mt('Successfully stored grades for [quant,_1,student].',$storecount).      $result.='<br />'.&mt('Successfully stored grades for [quant,_1,student].',$storecount).
              '</td></tr></table>'."\n".               '</td>'.
              '</td></tr></table><br /><br />'."\n";               &Apache::loncommon::end_data_table_row().
                &Apache::loncommon::end_data_table()."<br /><br />\n";
     return $result.&show_grading_menu_form($symb);      return $result.&show_grading_menu_form($symb);
 }  }
   
 sub navmap_errormsg {  sub navmap_errormsg {
     return '<div class="LC_error">'.      return '<div class="LC_error">'.
            &mt('An error occurred retrieving information about resources in the course.').'<br />'.             &mt('An error occurred retrieving information about resources in the course.').'<br />'.
            &mt('It is recommended that you [_1]re-initialize the course[_2] and then return to this grading page..','<a href="/adm/roles?selectrole=1&newrole='.$env{'request.role'}.'">','</a>').             &mt('It is recommended that you [_1]re-initialize the course[_2] and then return to this grading page.','<a href="/adm/roles?selectrole=1&newrole='.$env{'request.role'}.'">','</a>').
            '</div>';             '</div>';
 }  }
   
 sub handler {  sub handler {
     my $request=$_[0];      my $request=$_[0];
     &reset_caches();      &reset_caches();
     if ($env{'browser.mathml'}) {      if ($request->header_only) {
  &Apache::loncommon::content_type($request,'text/xml');          &Apache::loncommon::content_type($request,'text/html');
     } else {          $request->send_http_header;
  &Apache::loncommon::content_type($request,'text/html');          return OK;
     }      }
     $request->send_http_header;  
     return '' if $request->header_only;  
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
   
     my $symb=&get_symb($request,1);      my $symb=&get_symb($request,1);
     my @commands=&Apache::loncommon::get_env_multiple('form.command');      my @commands=&Apache::loncommon::get_env_multiple('form.command');
     my $command=$commands[0];      my $command=$commands[0];
Line 9268  sub handler { Line 9575  sub handler {
   
     $ssi_error = 0;      $ssi_error = 0;
     my $brcrum = [{href=>"/adm/grades",text=>"Grading"}];      my $brcrum = [{href=>"/adm/grades",text=>"Grading"}];
     $request->print(&Apache::loncommon::start_page('Grading',undef,      my $start_page = &Apache::loncommon::start_page('Grading',undef,
                                           {'bread_crumbs' => $brcrum}));                                            {'bread_crumbs' => $brcrum});
     if ($symb eq '' && $command eq '') {      if ($symb eq '' && $command eq '') {
  if ($env{'user.adv'}) {   if ($env{'user.adv'}) {
               &Apache::loncommon::content_type($request,'text/html');
               $request->send_http_header;
               $request->print($start_page);
     if (($env{'form.codeone'}) && ($env{'form.codetwo'}) &&      if (($env{'form.codeone'}) && ($env{'form.codetwo'}) &&
  ($env{'form.codethree'})) {   ($env{'form.codethree'})) {
  my $token=$env{'form.codeone'}.'*'.$env{'form.codetwo'}.'*'.   my $token=$env{'form.codeone'}.'*'.$env{'form.codetwo'}.'*'.
Line 9295  sub handler { Line 9605  sub handler {
     } else {      } else {
  $request->print(&Apache::lonxml::tokeninputfield());   $request->print(&Apache::lonxml::tokeninputfield());
     }      }
  }          } elsif ($env{'request.course.id'}) {
               &init_perm(); 
               if (!%perm) {
                   $request->internal_redirect('/adm/quickgrades');
               } else {
                   &Apache::loncommon::content_type($request,'text/html');
                   $request->send_http_header;
                   $request->print($start_page);
               }
           }
     } else {      } else {
  &init_perm();          &init_perm();
           if (!$env{'request.course.id'}) {
               unless ((&Apache::lonnet::allowed('usc',$env{'request.role.domain'})) &&
                       ($command =~ /^scantronupload/)) {
                   # Not in a course.
                   $env{'user.error.msg'}="/adm/grades::vgr:0:0:Cannot display grades page outside course context";
                   return HTTP_NOT_ACCEPTABLE;
               }
           } elsif (!%perm) {
               $request->internal_redirect('/adm/quickgrades');
           }
           &Apache::loncommon::content_type($request,'text/html');
           $request->send_http_header;
           $request->print($start_page);
  if ($command eq 'submission' && $perm{'vgr'}) {   if ($command eq 'submission' && $perm{'vgr'}) {
     ($env{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0));      ($env{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0));
  } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {   } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {
Line 9375  sub handler { Line 9707  sub handler {
     }      }
     $request->print(&Apache::loncommon::end_page());      $request->print(&Apache::loncommon::end_page());
     &reset_caches();      &reset_caches();
     return '';      return OK;
 }  }
   
 1;  1;
Line 9479  ssi_with_retries() Line 9811  ssi_with_retries()
        calling routine should trap the error condition and display the warning         calling routine should trap the error condition and display the warning
        found in &navmap_errormsg().         found in &navmap_errormsg().
   
          $scantron_config - Reference to bubblesheet format configuration hash.
   
    Returns the maximum number of bubble lines that are expected to     Returns the maximum number of bubble lines that are expected to
    occur. Does this by walking the selected sequence rendering the     occur. Does this by walking the selected sequence rendering the
    resource and then checking &Apache::lonxml::get_problem_counter()     resource and then checking &Apache::lonxml::get_problem_counter()
Line 9502  ssi_with_retries() Line 9836  ssi_with_retries()
   
 =item  scantron_process_students() :   =item  scantron_process_students() : 
   
    Routine that does the actual grading of the bubble sheet information.     Routine that does the actual grading of the bubblesheet information.
   
    The parsed scanline hash is added to %env      The parsed scanline hash is added to %env 
   
Line 9522  ssi_with_retries() Line 9856  ssi_with_retries()
   
 =item  scantron_upload_scantron_data() :  =item  scantron_upload_scantron_data() :
   
     Creates the screen for adding a new bubble sheet data file to a course.      Creates the screen for adding a new bubblesheet data file to a course.
   
 =item  scantron_upload_scantron_data_save() :   =item  scantron_upload_scantron_data_save() : 
   
Line 9536  ssi_with_retries() Line 9870  ssi_with_retries()
 =item  scantron_download_scantron_data() :   =item  scantron_download_scantron_data() : 
   
    Shows a list of the three internal files (original, corrected,     Shows a list of the three internal files (original, corrected,
    skipped) for a specific bubble sheet data file that exists in the     skipped) for a specific bubblesheet data file that exists in the
    course.     course.
   
 =item  scantron_validate_ID() :   =item  scantron_validate_ID() : 

Removed from v.1.582  
changed lines
  Added in v.1.596.2.12.2.1


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