Diff for /loncom/homework/grades.pm between versions 1.554 and 1.595

version 1.554, 2009/03/06 16:13:29 version 1.595, 2010/02/22 23:08:16
Line 97  sub ssi_print_error { Line 97  sub ssi_print_error {
 #  #
 # --- Retrieve the parts from the metadata file.---  # --- Retrieve the parts from the metadata file.---
 sub getpartlist {  sub getpartlist {
     my ($symb) = @_;      my ($symb,$errorref) = @_;
   
     my $navmap   = Apache::lonnavmaps::navmap->new();      my $navmap   = Apache::lonnavmaps::navmap->new();
       unless (ref($navmap)) {
           if (ref($errorref)) { 
               $$errorref = 'navmap';
               return;
           }
       }
     my $res      = $navmap->getBySymb($symb);      my $res      = $navmap->getBySymb($symb);
     my $partlist = $res->parts();      my $partlist = $res->parts();
     my $url      = $res->src();      my $url      = $res->src();
Line 144  sub nameUserString { Line 150  sub nameUserString {
 #--- Get the partlist and the response type for a given problem. ---  #--- Get the partlist and the response type for a given problem. ---
 #--- Indicate if a response type is coded handgraded or not. ---  #--- Indicate if a response type is coded handgraded or not. ---
 sub response_type {  sub response_type {
     my ($symb) = shift;      my ($symb,$response_error) = @_;
   
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
       unless (ref($navmap)) {
           if (ref($response_error)) {
               $$response_error = 1;
           }
           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 183  sub get_display_part { Line 199  sub get_display_part {
     my ($partID,$symb)=@_;      my ($partID,$symb)=@_;
     my $display=&Apache::lonnet::EXT('resource.'.$partID.'.display',$symb);      my $display=&Apache::lonnet::EXT('resource.'.$partID.'.display',$symb);
     if (defined($display) and $display ne '') {      if (defined($display) and $display ne '') {
  $display.= " (<span class=\"LC_internal_info\">id $partID</span>)";          $display.= ' (<span class="LC_internal_info">'
                     .&mt('Part ID: [_1]',$partID).'</span>)';
     } else {      } else {
  $display=$partID;   $display=$partID;
     }      }
Line 193  sub get_display_part { Line 210  sub get_display_part {
 #--- Show resource title  #--- Show resource title
 #--- and parts and response type  #--- and parts and response type
 sub showResourceInfo {  sub showResourceInfo {
     my ($symb,$probTitle,$checkboxes) = @_;      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";
     $result .='<table border="0">';      my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error);
     my ($partlist,$handgrade,$responseType) = &response_type($symb);      if (ref($res_error)) {
           if ($$res_error) {
               return;
           }
       }
       $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').': </b>'.$display_part.              $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').': </b>'.$responsetype.'</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 234  sub reset_caches { Line 263  sub reset_caches {
   
 {  {
     my %analyze_cache;      my %analyze_cache;
       my %analyze_cache_formkeys;
   
     sub reset_analyze_cache {      sub reset_analyze_cache {
  undef(%analyze_cache);   undef(%analyze_cache);
           undef(%analyze_cache_formkeys);
     }      }
   
     sub get_analyze {      sub get_analyze {
  my ($symb,$uname,$udom,$no_increment)=@_;   my ($symb,$uname,$udom,$no_increment,$add_to_hash)=@_;
  my $key = "$symb\0$uname\0$udom";   my $key = "$symb\0$uname\0$udom";
  return $analyze_cache{$key} if (exists($analyze_cache{$key}));   if (exists($analyze_cache{$key})) {
               my $getupdate = 0;
               if (ref($add_to_hash) eq 'HASH') {
                   foreach my $item (keys(%{$add_to_hash})) {
                       if (ref($analyze_cache_formkeys{$key}) eq 'HASH') {
                           if (!exists($analyze_cache_formkeys{$key}{$item})) {
                               $getupdate = 1;
                               last;
                           }
                       } else {
                           $getupdate = 1;
                       }
                   }
               }
               if (!$getupdate) {
                   return $analyze_cache{$key};
               }
           }
   
  my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);   my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
  $url=&Apache::lonnet::clutter($url);   $url=&Apache::lonnet::clutter($url);
  my $subresult=&ssi_with_retries($url, $ssi_retries,          my %form = ('grade_target'      => 'analyze',
    ('grade_target' => 'analyze',                      'grade_domain'      => $udom,
     'grade_domain' => $udom,                      'grade_symb'        => $symb,
     'grade_symb' => $symb,                      'grade_courseid'    =>  $env{'request.course.id'},
     'grade_courseid' =>                       'grade_username'    => $uname,
     $env{'request.course.id'},                      'grade_noincrement' => $no_increment);
     'grade_username' => $uname,          if (ref($add_to_hash)) {
                                             'grade_noincrement' => $no_increment));              %form = (%form,%{$add_to_hash});
           } 
    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);
           if (ref($add_to_hash) eq 'HASH') {
               $analyze_cache_formkeys{$key} = $add_to_hash;
           } else {
               $analyze_cache_formkeys{$key} = {};
           }
  return $analyze_cache{$key} = \%analyze;   return $analyze_cache{$key} = \%analyze;
     }      }
   
Line 268  sub reset_caches { Line 323  sub reset_caches {
     sub get_radiobutton_correct_foil {      sub get_radiobutton_correct_foil {
  my ($partid,$respid,$symb,$uname,$udom)=@_;   my ($partid,$respid,$symb,$uname,$udom)=@_;
  my $analyze = &get_analyze($symb,$uname,$udom);   my $analyze = &get_analyze($symb,$uname,$udom);
  foreach my $foil (@{&get_order($partid,$respid,$symb,$uname,$udom)}) {          my $foils = &get_order($partid,$respid,$symb,$uname,$udom);
     if ($analyze->{"$partid.$respid.foil.value.$foil"} eq 'true') {          if (ref($foils) eq 'ARRAY') {
  return $foil;      foreach my $foil (@{$foils}) {
           if ($analyze->{"$partid.$respid.foil.value.$foil"} eq 'true') {
       return $foil;
           }
     }      }
  }   }
     }      }
   
     sub scantron_partids_tograde {      sub scantron_partids_tograde {
         my ($resource,$cid,$uname,$udom) = @_;          my ($resource,$cid,$uname,$udom,$check_for_randomlist) = @_;
         my (%analysis,@parts);          my (%analysis,@parts);
         if (ref($resource)) {          if (ref($resource)) {
             my $symb = $resource->symb();              my $symb = $resource->symb();
             my $analyze = &get_analyze($symb,$uname,$udom);              my $add_to_form;
               if ($check_for_randomlist) {
                   $add_to_form = { 'check_parts_withrandomlist' => 1,};
               }
               my $analyze = &get_analyze($symb,$uname,$udom,undef,$add_to_form);
             if (ref($analyze) eq 'HASH') {              if (ref($analyze) eq 'HASH') {
                 %analysis = %{$analyze};                  %analysis = %{$analyze};
             }              }
Line 721  sub verifyreceipt { Line 783  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 733  sub verifyreceipt { Line 795  sub verifyreceipt {
     if ($env{"course.$courseid.receiptalg"} eq 'receipt2' ||      if ($env{"course.$courseid.receiptalg"} eq 'receipt2' ||
  $env{"course.$courseid.receiptalg"} eq 'receipt3') { $receiptparts=1; }   $env{"course.$courseid.receiptalg"} eq 'receipt3') { $receiptparts=1; }
     my $parts=['0'];      my $parts=['0'];
     if ($receiptparts) { ($parts)=&response_type($symb); }      if ($receiptparts) {
           my $res_error; 
           ($parts)=&response_type($symb,\$res_error);
           if ($res_error) {
               return &navmap_errormsg();
           } 
       }
           
     my $header =       my $header = 
  &Apache::loncommon::start_data_table().   &Apache::loncommon::start_data_table().
Line 775  sub verifyreceipt { Line 843  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 811  sub listStudents { Line 882  sub listStudents {
   
     my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($symb,$env{'form.probTitle'},($env{'form.showgrading'} eq 'yes'));      my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($symb,$env{'form.probTitle'},($env{'form.showgrading'} eq 'yes'));
   
     my %lt = ( 'multiple' =>      my %lt = &Apache::lonlocal::texthash (
        &mt("Please select a student or group of students before clicking on the Next button."),   'multiple' => 'Please select a student or group of students before clicking on the Next button.',
        'single'   =>   'single'   => 'Please select the student before clicking on the Next button.',
        &mt("Please select the student before clicking on the Next button."),       );
        );  
     %lt = &Apache::lonlocal::texthash(%lt);  
     $request->print(<<LISTJAVASCRIPT);      $request->print(<<LISTJAVASCRIPT);
 <script type="text/javascript" language="javascript">  <script type="text/javascript" language="javascript">
     function checkSelect(checkBox) {      function checkSelect(checkBox) {
Line 858  LISTJAVASCRIPT Line 927  LISTJAVASCRIPT
     my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'.      my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'.
  "\n".$table;   "\n".$table;
   
     $gradeTable .=       $gradeTable .= &Apache::lonhtmlcommon::start_pick_box();
  '&nbsp;<b>'.&mt('View Problem Text').': </b>'.      $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Problem Text'))
     '<label><input type="radio" name="vProb" value="no" checked="checked" /> '.&mt('no').' </label>'."\n".                    .'<label><input type="radio" name="vProb" value="no" checked="checked" /> '.&mt('no').' </label>'."\n"
     '<label><input type="radio" name="vProb" value="yes" /> '.&mt('one student').' </label>'."\n".                    .'<label><input type="radio" name="vProb" value="yes" /> '.&mt('one student').' </label>'."\n"
     '<label><input type="radio" name="vProb" value="all" /> '.&mt('all students').' </label><br />'."\n";                    .'<label><input type="radio" name="vProb" value="all" /> '.&mt('all students').' </label><br />'."\n"
     $gradeTable .=                     .&Apache::lonhtmlcommon::row_closure();
  '&nbsp;<b>'.&mt('View Answer').': </b>'.      $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Answer'))
     '<label><input type="radio" name="vAns" value="no"  /> '.&mt('no').' </label>'."\n".                    .'<label><input type="radio" name="vAns" value="no"  /> '.&mt('no').' </label>'."\n"
     '<label><input type="radio" name="vAns" value="yes" /> '.&mt('one student').' </label>'."\n".                    .'<label><input type="radio" name="vAns" value="yes" /> '.&mt('one student').' </label>'."\n"
     '<label><input type="radio" name="vAns" value="all" checked="checked" /> '.&mt('all students').' </label><br />'."\n";                    .'<label><input type="radio" name="vAns" value="all" checked="checked" /> '.&mt('all students').' </label><br />'."\n"
                     .&Apache::lonhtmlcommon::row_closure();
   
     my $submission_options;      my $submission_options;
     if ($env{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1) {      if ($env{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1) {
Line 878  LISTJAVASCRIPT Line 948  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">'.
     $gradeTable .=           '<label><input type="radio" name="lastSub" value="last" /> '.
  '&nbsp;<b>'.&mt('Submissions').': </b>'.$submission_options.'<br />'."\n";          &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'))
                     .$submission_options
                     .&Apache::lonhtmlcommon::row_closure();
   
       $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Grading Increments'))
                     .'<select name="increment">'
                     .'<option value="1">'.&mt('Whole Points').'</option>'
                     .'<option value=".5">'.&mt('Half Points').'</option>'
                     .'<option value=".25">'.&mt('Quarter Points').'</option>'
                     .'<option value=".1">'.&mt('Tenths of a Point').'</option>'
                     .'</select>'
                     .&Apache::lonhtmlcommon::row_closure();
   
     $gradeTable .=       $gradeTable .= 
         '&nbsp;<b>'.&mt('Grading Increments').': </b>'.  
     '<select name="increment">'.  
     '<option value="1">'.&mt('Whole Points').'</option>'.  
     '<option value=".5">'.&mt('Half Points').'</option>'.  
     '<option value=".25">'.&mt('Quarter Points').'</option>'.  
     '<option value=".1">'.&mt('Tenths of a Point').'</option>'.  
     '</select>';  
       
     $gradeTable .=   
         &build_section_inputs().          &build_section_inputs().
  '<input type="hidden" name="submitonly"  value="'.$submitonly.'" />'."\n".   '<input type="hidden" name="submitonly"  value="'.$submitonly.'" />'."\n".
  '<input type="hidden" name="handgrade"   value="'.$env{'form.handgrade'}.'" /><br />'."\n".   '<input type="hidden" name="handgrade"   value="'.$env{'form.handgrade'}.'" /><br />'."\n".
Line 905  LISTJAVASCRIPT Line 984  LISTJAVASCRIPT
  '<input type="hidden" name="saveStatusOld" value="'.$saveStatus.'" />'."\n";   '<input type="hidden" name="saveStatusOld" value="'.$saveStatus.'" />'."\n";
   
     if (exists($env{'form.gradingMenu'}) && exists($env{'form.Status'})) {      if (exists($env{'form.gradingMenu'}) && exists($env{'form.Status'})) {
  $gradeTable.='<input type="hidden" name="Status"   value="'.$stu_status.'" />'."\n";   $gradeTable .= '<input type="hidden" name="Status" value="'.$stu_status.'" />'."\n";
     } else {      } else {
  $gradeTable.=&mt('<b>Student Status:</b> [_1]',          $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Student Status'))
  &Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,'javascript:reLoadList(this.form);')).'<br />';                        .&Apache::lonhtmlcommon::StatusOptions(
                              $saveStatus,undef,1,'javascript:reLoadList(this.form);')
                         .&Apache::lonhtmlcommon::row_closure();
     }      }
   
     $gradeTable.=&mt('To '.lc($viewgrade)." a submission or a group of submissions, click on the check box(es) next to the student's name(s). Then click on the Next button.").'<br />'."\n".      $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Check For Plagiarism'))
  '<input type="hidden" name="command" value="processGroup" />'."\n";                    .'<input type="checkbox" name="checkPlag" checked="checked" />'
                     .&Apache::lonhtmlcommon::row_closure(1)
                     .&Apache::lonhtmlcommon::end_pick_box();
   
       $gradeTable .= '<p>'
                     .&mt('To '.lc($viewgrade)." a submission or a group of submissions, click on the check box(es) next to the student's name(s). Then click on the Next button.")."\n"
                     .'<input type="hidden" name="command" value="processGroup" />'
                     .'</p>';
   
 # 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();
     $gradeTable.='<label><input type="checkbox" name="checkPlag" checked="checked" />'.&mt('Check For Plagiarism').'</label>';  
     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().
  &Apache::loncommon::start_data_table_header_row();   &Apache::loncommon::start_data_table_header_row();
Line 1003  LISTJAVASCRIPT Line 1090  LISTJAVASCRIPT
  $gradeTable.= &Apache::loncommon::start_data_table_row();   $gradeTable.= &Apache::loncommon::start_data_table_row();
     }      }
     $gradeTable.='<td align="right">'.$ctr.'&nbsp;</td>'.      $gradeTable.='<td align="right">'.$ctr.'&nbsp;</td>'.
                '<td align="center"><label><input type=checkbox name="stuinfo" value="'.                 '<td align="center"><label><input type="checkbox" name="stuinfo" value="'.
                $student.':'.$$fullname{$student}.':::SECTION'.$section.                 $student.':'.$$fullname{$student}.':::SECTION'.$section.
        ')&nbsp;" />&nbsp;&nbsp;</label></td>'."\n".'<td>'.         ')&nbsp;" />&nbsp;&nbsp;</label></td>'."\n".'<td>'.
        &nameUserString(undef,$$fullname{$student},$uname,$udom).         &nameUserString(undef,$$fullname{$student},$uname,$udom).
Line 1036  LISTJAVASCRIPT Line 1123  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 1510  INNERJS Line 1597  INNERJS
     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;Compose Message for \"+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>Type<\\/b><\\/td><td><b>Include<\\/b><\\/td><td><b>Message<\\/td><\\/tr>");
 }  }
     function displaySubject(msg,shwsel) {      function displaySubject(msg,shwsel) {
Line 1542  INNERJS Line 1629  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=\\"Save\\" onclick=\\"javascript:checkInput()\\">&nbsp;&nbsp;");
     pDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br /><br />");      pDoc.write("<input type=\\"button\\" value=\\"Cancel\\" 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 1595  INNERJS Line 1682  INNERJS
     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;Keyword Highlight Options<\\/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>Text Color<\\/b><\\/td><td><b>Font Size<\\/b><\\/td><td><b>Font Style<\\/td><\\/tr>");
   }    }
   
Line 1616  INNERJS Line 1703  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=\\"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=\\"Cancel\\" 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 1636  sub get_increment { Line 1723  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 1655  sub gradeBox { Line 1761  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 1663  sub gradeBox { Line 1769  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 1674  sub gradeBox { Line 1780  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 1693  sub gradeBox { Line 1799  sub gradeBox {
   
  #&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);   #&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.=&Apache::loncommon::end_data_table_row();
     $result.='</tr></table>'."\n";  
     $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 1704  sub gradeBox { Line 1809  sub gradeBox {
         $$record{'resource.'.$partid.'.tries'}.'" />'."\n".          $$record{'resource.'.$partid.'.tries'}.'" />'."\n".
         '<input type="hidden" name="aggtries'.$counter.'_'.$partid.'" value="'.          '<input type="hidden" name="aggtries'.$counter.'_'.$partid.'" value="'.
         $aggtries.'" />'."\n";          $aggtries.'" />'."\n";
     $result.=&handback_box($symb,$uname,$udom,$counter,$partid,$record);      my $res_error;
       $result.=&handback_box($symb,$uname,$udom,$counter,$partid,$record,\$res_error);
       if ($res_error) {
           return &navmap_errormsg();
       }
     return $result;      return $result;
 }  }
   
 sub handback_box {  sub handback_box {
     my ($symb,$uname,$udom,$counter,$partid,$record) = @_;      my ($symb,$uname,$udom,$counter,$partid,$record,$res_error) = @_;
     my ($partlist,$handgrade,$responseType) = &response_type($symb);      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) {
Line 1772  sub show_problem { Line 1881  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 1969  sub submission { Line 2075  sub submission {
     $request->print(<<KEYWORDS);      $request->print(<<KEYWORDS);
 &nbsp;<b>Keyword Options:</b>&nbsp;  &nbsp;<b>Keyword Options:</b>&nbsp;
 <a href="javascript:keywords(document.SCORE);" target="_self">List</a>&nbsp; &nbsp;  <a href="javascript:keywords(document.SCORE);" target="_self">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">Paste Selection to List</a>&nbsp; &nbsp;
 <a href="javascript:kwhighlight();" target="_self">Highlight Attribute</a><br /><br />  <a href="javascript:kwhighlight();" target="_self">Highlight Attribute</a><br /><br />
 KEYWORDS  KEYWORDS
Line 1985  KEYWORDS Line 2091  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 2005  KEYWORDS Line 2130  KEYWORDS
     }      }
   
     my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname);      my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname);
     my ($partlist,$handgrade,$responseType) = &response_type($symb);      my $res_error;
       my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error);
       if ($res_error) {
           $request->print(&navmap_errormsg());
           return;
       }
   
     # Display student info      # Display student info
     $request->print(($counter == 0 ? '' : '<br />'));      $request->print(($counter == 0 ? '' : '<br />'));
     my $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 2033  KEYWORDS Line 2160  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 2045  KEYWORDS Line 2172  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 2072  KEYWORDS Line 2201  KEYWORDS
  }   }
  my $responsetype = $responseType->{$partid}->{$respid};   my $responsetype = $responseType->{$partid}->{$respid};
  if (!exists($record{"resource.$partid.$respid.submission"})) {   if (!exists($record{"resource.$partid.$respid.submission"})) {
     $lastsubonly.="\n".'<div class="LC_grade_submission_part"><b>Part:</b> '.                      $lastsubonly.="\n".'<div class="LC_grade_submission_part">'.
  $display_part.' <span class="LC_internal_info">( ID '.$respid.                          '<b>'.&mt('Part: [_1]',$display_part).'</b>'.
  ' )</span>&nbsp; &nbsp;'.                          ' <span class="LC_internal_info">'.
                           '('.&mt('Part ID: [_1]',$respid).')</b>'.
                           '</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 2094  KEYWORDS Line 2225  KEYWORDS
    {'one_time' => 1});     {'one_time' => 1});
   
     $similar="<hr /><h3><span class=\"LC_warning\">".      $similar="<hr /><h3><span class=\"LC_warning\">".
  &mt('Essay is [_1]% similar to an essay by [_2] ([_3]:[_4]) in course [_5] (course id [_6]:[_7])',   &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',
     $osim,      $osim,
     &Apache::loncommon::plainname($oname,$odom),      &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',
     $oname,$odom,  
     $old_course_desc{'description'},      $old_course_desc{'description'},
     $old_course_desc{'num'},      $old_course_desc{'num'},
     $old_course_desc{'domain'}).      $old_course_desc{'domain'}).
Line 2111  KEYWORDS Line 2241  KEYWORDS
  ($env{'form.lastSub'} eq 'hdgrade' &&    ($env{'form.lastSub'} eq 'hdgrade' && 
  $$handgrade{$$part[0].'_'.$$part[1]} eq 'yes')) {   $$handgrade{$$part[0].'_'.$$part[1]} eq 'yes')) {
  my $display_part=&get_display_part($partid,$symb);   my $display_part=&get_display_part($partid,$symb);
  $lastsubonly.='<div class="LC_grade_submission_part"><b>Part:</b> '.                          $lastsubonly.='<div class="LC_grade_submission_part">'.
     $display_part.' <span class="LC_internal_info">( ID '.$respid.                              '<b>'.&mt('Part: [_1]',$display_part).'</b>'.
     ' )</span>&nbsp; &nbsp;';                              ' <span class="LC_internal_info">'.
                               '('.&mt('Part ID: [_1]',$respid).')'.
                               '</b></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 />';      $lastsubonly.='<br /><span class="LC_warning">'.&mt('Like all files provided by users, this file may contain viruses').'</span><br />';
Line 2121  KEYWORDS Line 2253  KEYWORDS
     foreach my $file (@$files) {      foreach my $file (@$files) {
         $file_counter++;          $file_counter++;
  &Apache::lonnet::allowuploaded('/adm/grades',$file);   &Apache::lonnet::allowuploaded('/adm/grades',$file);
  $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border=0"> '.$file.'</a>';   $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>'.   $lastsubonly.='<b>'.&mt('Submitted Answer:').' </b>'.
     &cleanRecord($subval,$responsetype,$symb,$partid,      &cleanRecord($subval,$responsetype,$symb,$partid,
  $respid,\%record,$order);   $respid,\%record,$order,undef,$uname,$udom);
  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 2151  KEYWORDS Line 2283  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 2195  KEYWORDS Line 2327  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 2211  KEYWORDS Line 2343  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 2240  KEYWORDS Line 2363  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 2256  KEYWORDS Line 2378  KEYWORDS
     '<option>7</option><option>10</option></select>'."\n";      '<option>7</option><option>10</option></select>'."\n";
  my $nsel = ($env{'form.NTSTU'} ne '' ? $env{'form.NTSTU'} : '1');   my $nsel = ($env{'form.NTSTU'} ne '' ? $env{'form.NTSTU'} : '1');
  $ntstu =~ s/<option>$nsel</<option selected="selected">$nsel</;   $ntstu =~ s/<option>$nsel</<option selected="selected">$nsel</;
  $endform.=&mt('[quant,_1,student]',$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 2422  sub processHandGrade { Line 2546  sub processHandGrade {
                                                      undef,$feedurl,undef,                                                       undef,$feedurl,undef,
                                                      undef,undef,$showsymb,                                                       undef,undef,$showsymb,
                                                      $restitle);                                                       $restitle);
  $request->print('<br />'.&mt('Sending message to [_1]:[_2]',$uname,$udom).': '.   $request->print('<br />'.&mt('Sending message to [_1]',$uname.':'.$udom).': '.
  $msgstatus);   $msgstatus);
     }      }
     if ($env{'form.collaborator'.$ctr}) {      if ($env{'form.collaborator'.$ctr}) {
Line 2553  sub processHandGrade { Line 2677  sub processHandGrade {
     }      }
     $ctr = 0;      $ctr = 0;
     @parsedlist = reverse @parsedlist if ($button eq 'Previous');      @parsedlist = reverse @parsedlist if ($button eq 'Previous');
     my ($partlist) = &response_type($symb);      my $res_error;
       my ($partlist) = &response_type($symb,\$res_error);
       if ($res_error) {
           $request->print(&navmap_errormsg());
           return;
       }
     foreach my $student (@parsedlist) {      foreach my $student (@parsedlist) {
  my $submitonly=$env{'form.submitonly'};   my $submitonly=$env{'form.submitonly'};
  my ($uname,$udom) = split(/:/,$student);   my ($uname,$udom) = split(/:/,$student);
Line 2751  sub check_and_remove_from_queue { Line 2880  sub check_and_remove_from_queue {
 sub handback_files {  sub handback_files {
     my ($request,$symb,$stuname,$domain,$newflg,$new_part,$newrecord) = @_;      my ($request,$symb,$stuname,$domain,$newflg,$new_part,$newrecord) = @_;
     my $portfolio_root = '/userfiles/portfolio';      my $portfolio_root = '/userfiles/portfolio';
     my ($partlist,$handgrade,$responseType) = &response_type($symb);      my $res_error;
       my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error);
       if ($res_error) {
           $request->print('<br />'.&navmap_errormsg().'<br />');
           return;
       }
     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 };
Line 3195  sub viewgrades { Line 3328  sub viewgrades {
  '<input type="hidden" name="Status" value="'.$env{'stu_status'}.'" />'."\n".   '<input type="hidden" name="Status" value="'.$env{'stu_status'}.'" />'."\n".
  '<input type="hidden" name="probTitle" value="'.$env{'form.probTitle'}.'" />'."\n";   '<input type="hidden" name="probTitle" value="'.$env{'form.probTitle'}.'" />'."\n";
   
     my $sectionClass;      my ($common_header,$specific_header);
     my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));  
     if ($env{'form.section'} eq 'all') {      if ($env{'form.section'} eq 'all') {
  $sectionClass=&mt('Class');   $common_header = &mt('Assign Common Grade to Class');
           $specific_header = &mt('Assign Grade to Specific Students in Class');
     } elsif ($env{'form.section'} eq 'none') {      } elsif ($env{'form.section'} eq 'none') {
  $sectionClass=&mt('Students in no Section');          $common_header = &mt('Assign Common Grade to Students in no Section');
    $specific_header = &mt('Assign Grade to Specific Students in no Section');
     } else {      } else {
  $sectionClass=&mt('Students in Section(s) [_1]');          my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));
           $common_header = &mt('Assign Common Grade to Students in Section(s) [_1]',$section_display);
    $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1]',$section_display);
     }      }
     $result.=      $result.= '<h3>'.$common_header.'</h3>'.&Apache::loncommon::start_data_table();
  '<h3>'.  
  &mt("Assign Common Grade to [_1]",$sectionClass,$section_display).'</h3>';  
     $result.= &Apache::loncommon::start_data_table();  
     #radio buttons/text box for assigning points for a section or class.      #radio buttons/text box for assigning points for a section or class.
     #handles different parts of a problem      #handles different parts of a problem
     my ($partlist,$handgrade,$responseType) = &response_type($symb);      my $res_error;
       my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error);
       if ($res_error) {
           return &navmap_errormsg();
       }
     my %weight = ();      my %weight = ();
     my $ctsparts = 0;      my $ctsparts = 0;
     my %seen = ();      my %seen = ();
Line 3236  sub viewgrades { Line 3373  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 3254  sub viewgrades { Line 3391  sub viewgrades {
   
  $result.=   $result.=
     &Apache::loncommon::start_data_table_row()."\n".      &Apache::loncommon::start_data_table_row()."\n".
     '<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><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>'.
     &Apache::loncommon::end_data_table_row()."\n";      &Apache::loncommon::end_data_table_row()."\n";
  $ctsparts++;   $ctsparts++;
     }      }
     $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
     $result.= '<h3>'.&mt('Assign Grade to Specific Students in ').$sectionClass,      $result.= '<h3>'.$specific_header.'</h3>'.
  $section_display.'</h3>';                &Apache::loncommon::start_data_table().
     $result.= &Apache::loncommon::start_data_table().        &Apache::loncommon::start_data_table_header_row().
  &Apache::loncommon::start_data_table_header_row().        '<th>'.&mt('No.').'</th>'.
  '<th>'.&mt('No.').'</th>'.        '<th>'.&nameUserString('header')."</th>\n";
  '<th>'.&nameUserString('header')."</th>\n";      my $partserror;
     my (@parts) = sort(&getpartlist($symb));      my (@parts) = sort(&getpartlist($symb,\$partserror));
       if ($partserror) {
           return &navmap_errormsg();
       }
     my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);      my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
     my @partids = ();      my @partids = ();
     foreach my $part (@parts) {      foreach my $part (@parts) {
Line 3322  sub viewgrades { Line 3462  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 3374  sub viewstudentgrade { Line 3514  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 3383  sub viewstudentgrade { Line 3523  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 3430  sub editgrades { Line 3570  sub editgrades {
     my %columns = ();      my %columns = ();
     my ($i,$ctr,$count,$rec_update) = (0,0,0,0);      my ($i,$ctr,$count,$rec_update) = (0,0,0,0);
   
     my (@parts) = sort(&getpartlist($symb));      my $partserror;
       my (@parts) = sort(&getpartlist($symb,\$partserror));
       if ($partserror) {
           return &navmap_errormsg();
       }
     my $header;      my $header;
     while ($ctr < $env{'form.totalparts'}) {      while ($ctr < $env{'form.totalparts'}) {
  my $partid = $env{'form.partid_'.$ctr};   my $partid = $env{'form.partid_'.$ctr};
Line 3641  sub split_part_type { Line 3785  sub split_part_type {
 #  #
 #--- Javascript to handle csv upload  #--- Javascript to handle csv upload
 sub csvupload_javascript_reverse_associate {  sub csvupload_javascript_reverse_associate {
     my $error1=&mt('You need to specify the username or ID');      my $error1=&mt('You need to specify the username or the student/employee ID');
     my $error2=&mt('You need to specify at least one grading field');      my $error2=&mt('You need to specify at least one grading field');
   return(<<ENDPICK);    return(<<ENDPICK);
   function verify(vf) {    function verify(vf) {
Line 3681  ENDPICK Line 3825  ENDPICK
 }  }
   
 sub csvupload_javascript_forward_associate {  sub csvupload_javascript_forward_associate {
     my $error1=&mt('You need to specify the username or ID');      my $error1=&mt('You need to specify the username or the student/employee ID');
     my $error2=&mt('You need to specify at least one grading field');      my $error2=&mt('You need to specify at least one grading field');
   return(<<ENDPICK);    return(<<ENDPICK);
   function verify(vf) {    function verify(vf) {
Line 3739  $result Line 3883  $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 3762  ENDPICK Line 3906  ENDPICK
 }  }
   
 sub csvupload_fields {  sub csvupload_fields {
     my ($symb) = @_;      my ($symb,$errorref) = @_;
     my (@parts) = &getpartlist($symb);      my (@parts) = &getpartlist($symb,$errorref);
     my @fields=(['ID','Student ID'],      if (ref($errorref)) {
           if ($$errorref) {
               return;
           }
       }
   
       my @fields=(['ID','Student/Employee ID'],
  ['username','Student Username'],   ['username','Student Username'],
  ['domain','Student Domain']);   ['domain','Student Domain']);
     my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);      my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);
Line 3788  sub csvuploadmap_footer { Line 3938  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 3833  sub upcsvScores_form { Line 3983  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 3863  sub csvuploadmap { Line 4013  sub csvuploadmap {
     &csvuploadmap_header($request,$symb,$datatoken,$#records+1);      &csvuploadmap_header($request,$symb,$datatoken,$#records+1);
     my ($i,$keyfields);      my ($i,$keyfields);
     if (@records) {      if (@records) {
  my @fields=&csvupload_fields($symb);          my $fieldserror;
    my @fields=&csvupload_fields($symb,\$fieldserror);
           if ($fieldserror) {
               $request->print(&navmap_errormsg());
               return;
           }
  if ($env{'form.upfile_associate'} eq 'reverse') {   if ($env{'form.upfile_associate'} eq 'reverse') {
     &Apache::loncommon::csv_print_samples($request,\@records);      &Apache::loncommon::csv_print_samples($request,\@records);
     $i=&Apache::loncommon::csv_print_select_table($request,\@records,      $i=&Apache::loncommon::csv_print_select_table($request,\@records,
Line 4050  sub csvuploadassign { Line 4204  sub csvuploadassign {
    $countdone++;     $countdone++;
         }          }
     }      }
     $request->print('<br /><span class="LC_info">'.&mt("Saved [_1] students",$countdone)."</span>\n");      $request->print('<br />'.&Apache::lonhtmlcommon::confirm_success(&mt("Saved scores for [quant,_1,student]",$countdone),$countdone==0));
     if (@skipped) {      if (@skipped) {
  $request->print('<p><span class="LC_warning">'.&mt('Skipped Students').'</span></p>');   $request->print('<br />'.&Apache::lonhtmlcommon::confirm_success(&mt('No scores stored for the following username(s):'),1).'<br />');
  foreach my $student (@skipped) { $request->print("$student<br />\n"); }          $request->print(join(', ',@skipped));
     }      }
     if (@notallowed) {      if (@notallowed) {
  $request->print('<p><span class="LC_error">'.&mt('Students Not Allowed to Modify').'</span></p>');   $request->print('<br />'.&Apache::lonhtmlcommon::confirm_success(&mt('Modification of scores not allowed for the following username(s):'),1).'<br />');
  foreach my $student (@notallowed) { $request->print("$student<br />\n"); }   $request->print(join(', ',@notallowed));
     }      }
     $request->print("<br />\n");      $request->print("<br />\n");
     $request->print(&show_grading_menu_form($symb));      $request->print(&show_grading_menu_form($symb));
Line 4100  LISTJAVASCRIPT Line 4254  LISTJAVASCRIPT
  &mt('Manual Grading by Page or Sequence').'</span></h3>';   &mt('Manual Grading by Page or Sequence').'</span></h3>';
   
     $result.='<form action="/adm/grades" method="post" name="displayPage">'."\n";      $result.='<form action="/adm/grades" method="post" name="displayPage">'."\n";
     my ($titles,$symbx) = &getSymbMap();      my $map_error;
       my ($titles,$symbx) = &getSymbMap($map_error);
       if ($map_error) {
           $request->print(&navmap_errormsg());
           return; 
       }
     my ($curpage) =&Apache::lonnet::decode_symb($symb);       my ($curpage) =&Apache::lonnet::decode_symb($symb); 
 #    my ($curpage,$mapId) =&Apache::lonnet::decode_symb($symb);   #    my ($curpage,$mapId) =&Apache::lonnet::decode_symb($symb); 
 #    my $type=($curpage =~ /\.(page|sequence)/);  #    my $type=($curpage =~ /\.(page|sequence)/);
Line 4147  LISTJAVASCRIPT Line 4306  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 4186  LISTJAVASCRIPT Line 4345  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 4195  LISTJAVASCRIPT Line 4354  LISTJAVASCRIPT
 }  }
   
 sub getSymbMap {  sub getSymbMap {
       my ($map_error) = @_;
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
       unless (ref($navmap)) {
           if (ref($map_error)) {
               $$map_error = 'navmap';
           }
           return;
       }
     my %symbx = ();      my %symbx = ();
     my @titles = ();      my @titles = ();
     my $minder = 0;      my $minder = 0;
Line 4255  sub displayPage { Line 4420  sub displayPage {
     $request->print($result);      $request->print($result);
   
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
       unless (ref($navmap)) {
           $request->print(&navmap_errormsg());
           $request->print(&show_grading_menu_form($symb));
           return;
       }
     my ($mapUrl, $id, $resUrl)=&Apache::lonnet::decode_symb($env{'form.page'});      my ($mapUrl, $id, $resUrl)=&Apache::lonnet::decode_symb($env{'form.page'});
     my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps      my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps
     if (!$map) {      if (!$map) {
Line 4282  sub displayPage { Line 4452  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 4353  sub displayPage { Line 4525  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 4366  sub displayPage { Line 4540  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 4427  sub displaySubByDates { Line 4602  sub displaySubByDates {
   
     my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/)      my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/)
                : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/));                 : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/));
     $displaySub[0].='<b>'.&mt('Part:').'</b>&nbsp;'.$display_part.'&nbsp;';                      $displaySub[0].='<span class="LC_nobreak"';
     $displaySub[0].='<span class="LC_internal_info">('.&mt('ID').'&nbsp;'.                      $displaySub[0].='<b>'.&mt('Part: [_1]',$display_part).'</b>'
  $responseId.')</span>&nbsp;<b>';                                     .' <span class="LC_internal_info">'
                                      .'('.&mt('Part ID: [_1]',$responseId).')'
                                      .'</span>'
                                      .' <b>';
     if ($$record{"$where.$partid.tries"} eq '') {      if ($$record{"$where.$partid.tries"} eq '') {
  $displaySub[0].=&mt('Trial&nbsp;not&nbsp;counted');   $displaySub[0].=&mt('Trial not counted');
     } else {      } else {
  $displaySub[0].=&mt('Trial&nbsp;[_1]',   $displaySub[0].=&mt('Trial: [_1]',
     $$record{"$where.$partid.tries"});      $$record{"$where.$partid.tries"});
     }      }
     my $responseType=($isTask ? 'Task'      my $responseType=($isTask ? 'Task'
Line 4444  sub displaySubByDates { Line 4622  sub displaySubByDates {
     &get_order($partid,$responseId,$symb,$uname,$udom,      &get_order($partid,$responseId,$symb,$uname,$udom,
                                        $no_increment);                                         $no_increment);
     }      }
     $displaySub[0].='</b>&nbsp; '.      $displaySub[0].='</b></span>'; # /nobreak
       $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).'<br />';
  }   }
     }      }
Line 4505  sub updateGradeByPage { Line 4684  sub updateGradeByPage {
   
     $request->print($result);      $request->print($result);
   
   
     my $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
       unless (ref($navmap)) {
           $request->print(&navmap_errormsg());
           return;
       }
     my ($mapUrl, $id, $resUrl) = &Apache::lonnet::decode_symb( $env{'form.page'});      my ($mapUrl, $id, $resUrl) = &Apache::lonnet::decode_symb( $env{'form.page'});
     my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps      my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps
     if (!$map) {      if (!$map) {
Line 4650  sub updateGradeByPage { Line 4834  sub updateGradeByPage {
 #  #
 #-------------------------------------------------------------------  #-------------------------------------------------------------------
   
 #--------------------Scantron Grading-----------------------------------  #-------------------- Bubblesheet (Scantron) Grading -------------------
 #  #
 #------ start of section for handling grading by page/sequence ---------  #------ start of section for handling grading by page/sequence ---------
   
Line 4677  Next each scanline is checked for any er Line 4861  Next each scanline is checked for any er
 bubbles' (it's an error because it may have been mis-scanned  bubbles' (it's an error because it may have been mis-scanned
 because too light bubbling), 'double bubble' (each bubble line should  because too light bubbling), 'double bubble' (each bubble line should
 have no more that one letter picked), invalid or duplicated CODE,  have no more that one letter picked), invalid or duplicated CODE,
 invalid student ID  invalid student/employee ID
   
 If the CODE option is used that determines the randomization of the  If the CODE option is used that determines the randomization of the
 homework problems, either way the student ID is looked up into a  homework problems, either way the student/employee ID is looked up into a
 username:domain.  username:domain.
   
 During the validation phase the instructor can choose to skip scanlines.   During the validation phase the instructor can choose to skip scanlines. 
Line 4728  sub defaultFormData { Line 4912  sub defaultFormData {
    Return html dropdown of possible sequences to grade     Return html dropdown of possible sequences to grade
     
  Arguments:   Arguments:
    $symb - $symb of the current resource      $symb - $symb of the current resource
      $map_error - ref to scalar which will container error if
                   $navmap object is unavailable in &getSymbMap().
   
 =cut  =cut
   
 sub getSequenceDropDown {  sub getSequenceDropDown {
     my ($symb)=@_;      my ($symb,$map_error)=@_;
     my $result='<select name="selectpage">'."\n";      my $result='<select name="selectpage">'."\n";
     my ($titles,$symbx) = &getSymbMap();      my ($titles,$symbx) = &getSymbMap($map_error);
       if (ref($map_error)) {
           return if ($$map_error);
       }
     my ($curpage)=&Apache::lonnet::decode_symb($symb);       my ($curpage)=&Apache::lonnet::decode_symb($symb); 
     my $ctr=0;      my $ctr=0;
     foreach (@$titles) {      foreach (@$titles) {
Line 5001  sub scantron_selectphase { Line 5190  sub scantron_selectphase {
     my ($r,$file2grade) = @_;      my ($r,$file2grade) = @_;
     my ($symb)=&get_symb($r);      my ($symb)=&get_symb($r);
     if (!$symb) {return '';}      if (!$symb) {return '';}
     my $sequence_selector=&getSequenceDropDown($symb);      my $map_error;
       my $sequence_selector=&getSequenceDropDown($symb,\$map_error);
       if ($map_error) {
           $r->print('<br />'.&navmap_errormsg().'<br />');
           return;
       }
     my $default_form_data=&defaultFormData($symb);      my $default_form_data=&defaultFormData($symb);
     my $grading_menu_button=&show_grading_menu_form($symb);      my $grading_menu_button=&show_grading_menu_form($symb);
     my $file_selector=&scantron_uploads($file2grade);      my $file_selector=&scantron_uploads($file2grade);
Line 5029  sub scantron_selectphase { Line 5223  sub scantron_selectphase {
             <td> '.&mt('Sequence to grade:').' </td><td> '.$sequence_selector.' </td>              <td> '.&mt('Sequence to grade:').' </td><td> '.$sequence_selector.' </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> '.&mt('Filename of scoring office file:').' </td><td> '.$file_selector.' </td>              <td> '.&mt('Filename of bubblesheet data file:').' </td><td> '.$file_selector.' </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> '.&mt('Format of data file:').' </td><td> '.$format_selector.' </td>              <td> '.&mt('Format of bubblesheet data file:').' </td><td> '.$format_selector.' </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> '.&mt('Saved CODEs to validate against:').' </td><td> '.$CODE_selector.' </td>              <td> '.&mt('Saved CODEs to validate against:').' </td><td> '.$CODE_selector.' </td>
Line 5050  sub scantron_selectphase { Line 5244  sub scantron_selectphase {
        '.&Apache::loncommon::end_data_table_row().'         '.&Apache::loncommon::end_data_table_row().'
        '.&Apache::loncommon::start_data_table_row().'         '.&Apache::loncommon::start_data_table_row().'
             <td colspan="2">              <td colspan="2">
               <input type="submit" value="'.&mt('Grading: Validate Scantron Records').'" />                <input type="submit" value="'.&mt('Grading: Validate Bubblesheet Records').'" />
             </td>              </td>
        '.&Apache::loncommon::end_data_table_row().'         '.&Apache::loncommon::end_data_table_row().'
     '.&Apache::loncommon::end_data_table().'      '.&Apache::loncommon::end_data_table().'
Line 5069  sub scantron_selectphase { Line 5263  sub scantron_selectphase {
     '.&Apache::loncommon::start_data_table('LC_scantron_action').'      '.&Apache::loncommon::start_data_table('LC_scantron_action').'
        '.&Apache::loncommon::start_data_table_header_row().'         '.&Apache::loncommon::start_data_table_header_row().'
             <th>              <th>
               &nbsp;'.&mt('Specify a Scantron data file to upload.').'                &nbsp;'.&mt('Specify a bubblesheet data file to upload.').'
             </th>              </th>
        '.&Apache::loncommon::end_data_table_header_row().'         '.&Apache::loncommon::end_data_table_header_row().'
        '.&Apache::loncommon::start_data_table_row().'         '.&Apache::loncommon::start_data_table_row().'
Line 5096  sub scantron_selectphase { Line 5290  sub scantron_selectphase {
                 <input name="command" value="scantronupload_save" type="hidden" />                  <input name="command" value="scantronupload_save" type="hidden" />
                 '.&mt('File to upload: [_1]','<input type="file" name="upfile" size="50" />').'                  '.&mt('File to upload: [_1]','<input type="file" name="upfile" size="50" />').'
                 <br />                  <br />
                 <input type="button" onClick="javascript:checkUpload(this.form);" value="'.&mt('Upload Scantron Data').'" />                  <input type="button" onclick="javascript:checkUpload(this.form);" value="'.&mt('Upload Bubblesheet Data').'" />
               </form>                </form>
 ');  ');
   
Line 5138  sub scantron_selectphase { Line 5332  sub scantron_selectphase {
              &Apache::loncommon::start_data_table('LC_scantron_action')."\n".               &Apache::loncommon::start_data_table('LC_scantron_action')."\n".
              &Apache::loncommon::start_data_table_header_row()."\n".               &Apache::loncommon::start_data_table_header_row()."\n".
              '<th colspan="2">               '<th colspan="2">
               &nbsp;'.&mt('Review scantron data and submissions for a previously graded folder/sequence')."\n".                &nbsp;'.&mt('Review bubblesheet data and submissions for a previously graded folder/sequence')."\n".
              '</th>'."\n".               '</th>'."\n".
               &Apache::loncommon::end_data_table_header_row()."\n".                &Apache::loncommon::end_data_table_header_row()."\n".
               &Apache::loncommon::start_data_table_row()."\n".                &Apache::loncommon::start_data_table_row()."\n".
Line 5154  sub scantron_selectphase { Line 5348  sub scantron_selectphase {
               '<td> '.$format_selector.' </td>'."\n".                '<td> '.$format_selector.' </td>'."\n".
               &Apache::loncommon::end_data_table_row()."\n".                &Apache::loncommon::end_data_table_row()."\n".
               &Apache::loncommon::start_data_table_row()."\n".                &Apache::loncommon::start_data_table_row()."\n".
                 '<td> '.&mt('Options').' </td>'."\n".
                 '<td> <label><input type="checkbox" name="scantron_options_hidden" value="ignore_hidden"/> '.&mt('Skip hidden resources').'</label></td>'.
                 &Apache::loncommon::end_data_table_row()."\n".
                 &Apache::loncommon::start_data_table_row()."\n".
               '<td colspan="2">'."\n".                '<td colspan="2">'."\n".
               '<input type="hidden" name="command" value="checksubmissions" />'."\n".                '<input type="hidden" name="command" value="checksubmissions" />'."\n".
               '<input type="submit" value="'.&mt('Review Scantron Data and Submission Records').'" />'."\n".                '<input type="submit" value="'.&mt('Review Bubblesheet Data and Submission Records').'" />'."\n".
               '</td>'."\n".                '</td>'."\n".
               &Apache::loncommon::end_data_table_row()."\n".                &Apache::loncommon::end_data_table_row()."\n".
               &Apache::loncommon::end_data_table()."\n".                &Apache::loncommon::end_data_table()."\n".
Line 5197  sub scantron_selectphase { Line 5395  sub scantron_selectphase {
       CODEstart   - (only matter if a CODE exists) column in the line where        CODEstart   - (only matter if a CODE exists) column in the line where
                      the CODE starts                       the CODE starts
       CODElength  - length of the CODE        CODElength  - length of the CODE
       IDstart     - column where the student ID number starts        IDstart     - column where the student/employee ID starts
       IDlength    - length of the student ID info        IDlength    - length of the student/employee ID info
       Qstart      - column where the information from the bubbled        Qstart      - column where the information from the bubbled
                     'questions' start                      'questions' start
       Qlength     - number of columns comprising a single bubble line from        Qlength     - number of columns comprising a single bubble line from
Line 5258  sub get_scantron_config { Line 5456  sub get_scantron_config {
   
 =item username_to_idmap  =item username_to_idmap
   
     creates a hash keyed by student id with values of the corresponding      creates a hash keyed by student/employee ID with values of the corresponding
     student username:domain.      student username:domain.
   
   Arguments:    Arguments:
Line 5297  sub username_to_idmap { Line 5495  sub username_to_idmap {
     $whichline         - line number of the passed in scanline      $whichline         - line number of the passed in scanline
     $field             - type of change to process       $field             - type of change to process 
                          (either                            (either 
                           'ID'     -> correct the student ID number                            'ID'     -> correct the student/employee ID
                           'CODE'   -> correct the CODE                            'CODE'   -> correct the CODE
                           'answer' -> fixup the submitted answers)                            'answer' -> fixup the submitted answers)
           
Line 5471  sub digits_to_letters { Line 5669  sub digits_to_letters {
        CODE_ignore_dup - 1 if the CODE is a duplicated use when unique         CODE_ignore_dup - 1 if the CODE is a duplicated use when unique
                             CODEs were selected, but the usage has been                              CODEs were selected, but the usage has been
                             forced by the operator                              forced by the operator
        ID  - student ID         ID  - student/employee ID
        PaperID - if used, the ID number printed on the sheet when the          PaperID - if used, the ID number printed on the sheet when the 
                  paper was scanned                   paper was scanned
        FirstName - first name from the sheet         FirstName - first name from the sheet
Line 6171  sub scantron_validate_file { Line 6369  sub scantron_validate_file {
     $r->print('<p>'.&mt('Gathering necessary information.').'</p>');$r->rflush();      $r->print('<p>'.&mt('Gathering necessary information.').'</p>');$r->rflush();
     #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 $max_bubble=&scantron_get_maxbubble();      my $nav_error;
       my $max_bubble=&scantron_get_maxbubble(\$nav_error);
       if ($nav_error) {
           $r->print(&navmap_errormsg());
           return '';
       }
     my $result=&scantron_form_start($max_bubble).$default_form_data;      my $result=&scantron_form_start($max_bubble).$default_form_data;
     $r->print($result);      $r->print($result);
           
Line 6207  sub scantron_validate_file { Line 6410  sub scantron_validate_file {
                   '<input type="radio" name="verifyrecord" value="0" checked="checked" />'.&mt('No').                    '<input type="radio" name="verifyrecord" value="0" checked="checked" />'.&mt('No').
                   '</label></span><br />'.                    '</label></span><br />'.
                   &mt('Grading will take longer if you use verification.').'<br />'.                    &mt('Grading will take longer if you use verification.').'<br />'.
                   &mt("Alternatively, the 'Review scantron data' utility (see grading menu) can be used for all students after grading is complete.").'<br /><br />'.                    &mt("Alternatively, the 'Review bubblesheet data' utility (see grading menu) can be used for all students after grading is complete.").'<br /><br />'.
                   '<input type="submit" name="submit" value="'.&mt('Start Grading').'" />'.                    '<input type="submit" name="submit" value="'.&mt('Start Grading').'" />'.
                   '<input type="hidden" name="command" value="scantron_process" />'."\n");                    '<input type="hidden" name="command" value="scantron_process" />'."\n");
     } else {      } else {
Line 6583  sub scantron_validate_sequence { Line 6786  sub scantron_validate_sequence {
     my ($r,$currentphase) = @_;      my ($r,$currentphase) = @_;
   
     my $navmap=Apache::lonnavmaps::navmap->new();      my $navmap=Apache::lonnavmaps::navmap->new();
       unless (ref($navmap)) {
           $r->print(&navmap_errormsg());
           return (1,$currentphase);
       }
     my (undef,undef,$sequence)=      my (undef,undef,$sequence)=
  &Apache::lonnet::decode_symb($env{'form.selectpage'});   &Apache::lonnet::decode_symb($env{'form.selectpage'});
   
Line 6614  sub scantron_validate_ID { Line 6821  sub scantron_validate_ID {
     #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_lines.. array.      my $nav_error;
       &scantron_get_maxbubble(\$nav_error); # parse needs the bubble_lines.. array.
       if ($nav_error) {
           $r->print(&navmap_errormsg());
           return(1,$currentphase);
       }
   
     my %found=('ids'=>{},'usernames'=>{});      my %found=('ids'=>{},'usernames'=>{});
     for (my $i=0;$i<=$scanlines->{'count'};$i++) {      for (my $i=0;$i<=$scanlines->{'count'};$i++) {
Line 6733  sub scantron_get_correction { Line 6945  sub scantron_get_correction {
     if ($closest > 0) {      if ($closest > 0) {
  foreach my $testcode (@{$closest}) {   foreach my $testcode (@{$closest}) {
     my $checked='';      my $checked='';
     if (!$i) { $checked=' checked="checked" '; }      if (!$i) { $checked=' checked="checked"'; }
     $r->print("      $r->print("
    <label>     <label>
        <input type='radio' name='scantron_CODE_resolution' value='use_closest_$i' $checked />         <input type='radio' name='scantron_CODE_resolution' value='use_closest_$i'$checked />
        ".&mt("Use the similar CODE [_1] instead.",         ".&mt("Use the similar CODE [_1] instead.",
     "<b><tt>".$testcode."</tt></b>")."      "<b><tt>".$testcode."</tt></b>")."
     </label>      </label>
Line 6747  sub scantron_get_correction { Line 6959  sub scantron_get_correction {
     }      }
  }   }
  if ($$scan_record{'scantron.CODE'}=~/\S/ ) {   if ($$scan_record{'scantron.CODE'}=~/\S/ ) {
     my $checked; if (!$i) { $checked=' checked="checked" '; }      my $checked; if (!$i) { $checked=' checked="checked"'; }
     $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 is 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>");
Line 6781  ENDSCRIPT Line 6993  ENDSCRIPT
        ".&mt("[_1]Select[_2] a CODE from the list of all CODEs and use it.",         ".&mt("[_1]Select[_2] a CODE from the list of all CODEs and use it.",
      "<a target='_blank' href='$href'>","</a>")."       "<a target='_blank' href='$href'>","</a>")."
     </label>       </label> 
     ".&mt("Selected CODE is [_1]","<input readonly='true' type='text' size='8' name='scantron_CODE_selectedvalue' onfocus=\"javascript:change_radio('use_found')\" onchange=\"javascript:change_radio('use_found')\" />"));      ".&mt("Selected CODE is [_1]",'<input readonly="readonly" type="text" size="8" name="scantron_CODE_selectedvalue" onfocus="javascript:change_radio(\'use_found\')" onchange="javascript:change_radio(\'use_found\')" />'));
     $r->print("\n<br />");      $r->print("\n<br />");
  }   }
  $r->print("   $r->print("
Line 6974  sub prompt_for_corrections { Line 7186  sub prompt_for_corrections {
             ($responsetype_per_response{$question-1} eq 'imageresponse') ||              ($responsetype_per_response{$question-1} eq 'imageresponse') ||
             ($responsetype_per_response{$question-1} eq 'reactionresponse') ||              ($responsetype_per_response{$question-1} eq 'reactionresponse') ||
             ($responsetype_per_response{$question-1} eq 'organicresponse')) {              ($responsetype_per_response{$question-1} eq 'organicresponse')) {
             $r->print(&mt("Although this particular question type requires handgrading, the instructions for this question in the exam directed students to leave [quant,_1,line] blank on their scantron sheets.",$lines).'<br /><br />'.&mt('A non-zero score can be assigned to the student during scantron grading by selecting a bubble in at least one line.').'<br />'.&mt('The score for this question will be a sum of the numeric values for the selected bubbles from each line, where A=1 point, B=2 points etc.').'<br />'.&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.").'<br /><br />');              $r->print(&mt("Although this particular question type requires handgrading, the instructions for this question in the exam directed students to leave [quant,_1,line] blank on their bubblesheets.",$lines).'<br /><br />'.&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.').'<br />'.&mt('The score for this question will be a sum of the numeric values for the selected bubbles from each line, where A=1 point, B=2 points etc.').'<br />'.&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.").'<br /><br />');
         } else {          } else {
             $r->print(&mt("Select at most one bubble in a single line and select 'No Bubble' in all the other lines. ")."<br />");              $r->print(&mt("Select at most one bubble in a single line and select 'No Bubble' in all the other lines. ")."<br />");
         }          }
Line 7168  sub scantron_validate_CODE { Line 7380  sub scantron_validate_CODE {
   
     my %allcodes=&get_codes();      my %allcodes=&get_codes();
   
     &scantron_get_maxbubble(); # parse needs the lines per response array.      my $nav_error;
       &scantron_get_maxbubble(\$nav_error); # parse needs the lines per response array.
       if ($nav_error) {
           $r->print(&navmap_errormsg());
           return(1,$currentphase);
       }
   
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
     for (my $i=0;$i<=$scanlines->{'count'};$i++) {      for (my $i=0;$i<=$scanlines->{'count'};$i++) {
Line 7222  sub scantron_validate_doublebubble { Line 7439  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); # 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 7240  sub scantron_validate_doublebubble { Line 7462  sub scantron_validate_doublebubble {
   
   
 sub scantron_get_maxbubble {  sub scantron_get_maxbubble {
       my ($nav_error) = @_;
     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 7250  sub scantron_get_maxbubble { Line 7473  sub scantron_get_maxbubble {
  &Apache::lonnet::decode_symb($env{'form.selectpage'});   &Apache::lonnet::decode_symb($env{'form.selectpage'});
   
     my $navmap=Apache::lonnavmaps::navmap->new();      my $navmap=Apache::lonnavmaps::navmap->new();
       unless (ref($navmap)) {
           if (ref($nav_error)) {
               $$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);
   
     &Apache::lonxml::clear_problem_counter();      &Apache::lonxml::clear_problem_counter();
   
     my $uname       = $env{'form.student'};      my $uname       = $env{'user.name'};
     my $udom        = $env{'form.userdom'};      my $udom        = $env{'user.domain'};
     my $cid         = $env{'request.course.id'};      my $cid         = $env{'request.course.id'};
     my $total_lines = 0;      my $total_lines = 0;
     %bubble_lines_per_response = ();      %bubble_lines_per_response = ();
Line 7339  sub scantron_validate_missingbubbles { Line 7568  sub scantron_validate_missingbubbles {
     #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();
     my $max_bubble=&scantron_get_maxbubble();      my $nav_error;
       my $max_bubble=&scantron_get_maxbubble(\$nav_error);
       if ($nav_error) {
           return(1,$currentphase);
       }
     if (!$max_bubble) { $max_bubble=2**31; }      if (!$max_bubble) { $max_bubble=2**31; }
     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 7399  sub scantron_process_students { Line 7632  sub scantron_process_students {
     my $classlist=&Apache::loncoursedata::get_classlist();      my $classlist=&Apache::loncoursedata::get_classlist();
     my %idmap=&username_to_idmap($classlist);      my %idmap=&username_to_idmap($classlist);
     my $navmap=Apache::lonnavmaps::navmap->new();      my $navmap=Apache::lonnavmaps::navmap->new();
       unless (ref($navmap)) {
           $r->print(&navmap_errormsg());
           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);
 #    $r->print("geto ".scalar(@resources)."<br />");      my (%grader_partids_by_symb,%grader_randomlists_by_symb);
       &graders_resources_pass(\@resources,\%grader_partids_by_symb,
                               \%grader_randomlists_by_symb);
       my $resource_error;
       foreach my $resource (@resources) {
           my $ressymb;
           if (ref($resource)) {
               $ressymb = $resource->symb();
           } else {
               $resource_error = 1;
               last;
           }
           my ($analysis,$parts) =
               &scantron_partids_tograde($resource,$env{'request.course.id'},
                                         $env{'user.name'},$env{'user.domain'},1);
           $grader_partids_by_symb{$ressymb} = $parts;
           if (ref($analysis) eq 'HASH') {
               if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') {
                   $grader_randomlists_by_symb{$ressymb} = 
                       $analysis->{'parts_withrandomlist'};
               }
           }
       }
       if ($resource_error) {
           $r->print(&navmap_errormsg());
           return '';
       }
   
     my ($uname,$udom);      my ($uname,$udom);
     my $result= <<SCANTRONFORM;      my $result= <<SCANTRONFORM;
 <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantronupload">  <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantronupload">
Line 7415  SCANTRONFORM Line 7679  SCANTRONFORM
           
     my $lock=&Apache::lonnet::set_lock(&mt('Grading bubblesheet exam'));      my $lock=&Apache::lonnet::set_lock(&mt('Grading bubblesheet exam'));
     my $count=&get_todo_count($scanlines,$scan_data);      my $count=&get_todo_count($scanlines,$scan_data);
     my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Scantron Status',      my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Bubblesheet Status',
      'Scantron Progress',$count,       'Bubblesheet Progress',$count,
     'inline',undef,'scantronupload');      'inline',undef,'scantronupload');
     &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,      &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,
   'Processing first student');    'Processing first student');
Line 7425  SCANTRONFORM Line 7689  SCANTRONFORM
     my $i=-1;      my $i=-1;
     my $started;      my $started;
   
     &scantron_get_maxbubble(); # Need the bubble lines array to parse.      my $nav_error;
       &scantron_get_maxbubble(\$nav_error); # Need the bubble lines array to parse.
       if ($nav_error) {
           $r->print(&navmap_errormsg());
           return '';
       }
   
     # 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 7466  SCANTRONFORM Line 7735  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;
             my ($analysis,$parts) =              if (ref($resource)) {
                 &scantron_partids_tograde($resource,$env{'request.course.id'},$uname,$udom);            $partids_by_symb{$ressymb} = $parts;                  $ressymb = $resource->symb();
               } else {
                   $res_error = 1;
                   last;
               }
               if ((exists($grader_randomlists_by_symb{$ressymb})) ||
                   (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {
                   my ($analysis,$parts) =
                       &scantron_partids_tograde($resource,$env{'request.course.id'},$uname,$udom);
                   $partids_by_symb{$ressymb} = $parts;
               } else {
                   $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();
Line 7581  SCANTRONFORM Line 7868  SCANTRONFORM
     return '';      return '';
 }  }
   
   sub graders_resources_pass {
       my ($resources,$grader_partids_by_symb,$grader_randomlists_by_symb) = @_;
       if ((ref($resources) eq 'ARRAY') && (ref($grader_partids_by_symb)) && 
           (ref($grader_randomlists_by_symb) eq 'HASH')) {
           foreach my $resource (@{$resources}) {
               my $ressymb = $resource->symb();
               my ($analysis,$parts) =
                   &scantron_partids_tograde($resource,$env{'request.course.id'},
                                             $env{'user.name'},$env{'user.domain'},1);
               $grader_partids_by_symb->{$ressymb} = $parts;
               if (ref($analysis) eq 'HASH') {
                   if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') {
                       $grader_randomlists_by_symb->{$ressymb} =
                           $analysis->{'parts_withrandomlist'};
                   }
               }
           }
       }
       return;
   }
   
 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) = @_;
     if (ref($resources) eq 'ARRAY') {      if (ref($resources) eq 'ARRAY') {
Line 7614  sub grade_student_bubbles { Line 7922  sub grade_student_bubbles {
   
 sub scantron_upload_scantron_data {  sub scantron_upload_scantron_data {
     my ($r)=@_;      my ($r)=@_;
     $r->print(&Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'}));      my $dom = $env{'request.role.domain'};
       my $domdesc = &Apache::lonnet::domain($dom,'description');
       $r->print(&Apache::loncommon::coursebrowser_javascript($dom));
     my $select_link=&Apache::loncommon::selectcourse_link('rules','courseid',      my $select_link=&Apache::loncommon::selectcourse_link('rules','courseid',
   'domainid',    'domainid',
   'coursename');    'coursename',$dom);
     my $domsel=&Apache::loncommon::select_dom_form($env{'request.role.domain'},      my $syllabuslink = '<a href="javascript:ToSyllabus();">'.&mt('Syllabus').'</a>'.
    'domainid');                         ('&nbsp'x2).&mt('(shows course personnel)'); 
     my $default_form_data=&defaultFormData(&get_symb($r,1));      my $default_form_data=&defaultFormData(&get_symb($r,1));
       my $nofile_alert = &mt('Please use the browse button to select a file from your local directory.');
       my $nocourseid_alert = &mt("Please use the 'Select Course' link to open a separate window where you can search for a course to which a file can be uploaded.");
     $r->print('      $r->print('
 <script type="text/javascript" language="javascript">  <script type="text/javascript" language="javascript">
     function checkUpload(formname) {      function checkUpload(formname) {
  if (formname.upfile.value == "") {   if (formname.upfile.value == "") {
     alert("'.&mt('Please use the browse button to select a file from your local directory.').'");      alert("'.$nofile_alert.'");
     return false;      return false;
  }   }
           if (formname.courseid.value == "") {
               alert("'.$nocourseid_alert.'");
               return false;
           }
  formname.submit();   formname.submit();
     }      }
   
       function ToSyllabus() {
           var cdom = '."'$dom'".';
           var cnum = document.rules.courseid.value;
           if (cdom == "" || cdom == null) {
               return;
           }
           if (cnum == "" || cnum == null) {
              return;
           }
           syllwin=window.open("/public/"+cdom+"/"+cnum+"/syllabus","LONCAPASyllabus",
                               "height=350,width=350,scrollbars=yes,menubar=no");
           return;
       }
   
 </script>  </script>
   
   <h3>'.&mt('Send scanned 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.
 <table>    &Apache::lonhtmlcommon::start_pick_box().
 <tr><td>'.$select_link.'                             </td></tr>    &Apache::lonhtmlcommon::row_title(&mt('Course ID')).
 <tr><td>'.&mt('Course ID:').'     </td>    '<input name="courseid" type="text" size="30" />'.$select_link.
     <td><input name="courseid"   type="text" />      </td></tr>    &Apache::lonhtmlcommon::row_closure().
 <tr><td>'.&mt('Course Name:').'   </td>    &Apache::lonhtmlcommon::row_title(&mt('Course Name')).
     <td><input name="coursename" type="text" />      </td></tr>    '<input name="coursename" type="text" size="30" />'.$syllabuslink.
 <tr><td>'.&mt('Domain:').'        </td>    &Apache::lonhtmlcommon::row_closure().
     <td>'.$domsel.'                                  </td></tr>    &Apache::lonhtmlcommon::row_title(&mt('Domain')).
 <tr><td>'.&mt('File to upload:').'</td>    '<input name="domainid" type="hidden" />'.$domdesc.
     <td><input type="file" name="upfile" size="50" /></td></tr>    &Apache::lonhtmlcommon::row_closure().
 </table>    &Apache::lonhtmlcommon::row_title(&mt('File to upload')).
     '<input type="file" name="upfile" size="50" />'.
     &Apache::lonhtmlcommon::row_closure(1).
     &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 Scantron Data').'" />  <input type="button" onclick="javascript:checkUpload(this.form);" value="'.&mt('Upload Bubblesheet Data').'" />
 </form>  </form>
 ');  ');
     return '';      return '';
Line 7664  sub scantron_upload_scantron_data_save { Line 8001  sub scantron_upload_scantron_data_save {
     if (!&Apache::lonnet::allowed('usc',$env{'form.domainid'}) &&      if (!&Apache::lonnet::allowed('usc',$env{'form.domainid'}) &&
  !&Apache::lonnet::allowed('usc',   !&Apache::lonnet::allowed('usc',
     $env{'form.domainid'}.'_'.$env{'form.courseid'})) {      $env{'form.domainid'}.'_'.$env{'form.courseid'})) {
  $r->print(&mt("You are not allowed to upload Scantron data to the requested course.")."<br />");   $r->print(&mt("You are not allowed to upload bubblesheet data to the requested course.")."<br />");
  if ($symb) {   if ($symb) {
     $r->print(&show_grading_menu_form($symb));      $r->print(&show_grading_menu_form($symb));
  } else {   } else {
Line 7673  sub scantron_upload_scantron_data_save { Line 8010  sub scantron_upload_scantron_data_save {
  return '';   return '';
     }      }
     my %coursedata=&Apache::lonnet::coursedescription($env{'form.domainid'}.'_'.$env{'form.courseid'});      my %coursedata=&Apache::lonnet::coursedescription($env{'form.domainid'}.'_'.$env{'form.courseid'});
     $r->print(&mt("Doing upload to [_1]",$coursedata{'description'})." <br />");      my $uploadedfile;
     my $fname=$env{'form.upfile.filename'};      $r->print('<h3>'.&mt("Uploading file to [_1]",$coursedata{'description'}).'</h3>');
     #FIXME  
     #copied from lonnet::userfileupload()  
     #make that function able to target a specified course  
     # Replace Windows backslashes by forward slashes  
     $fname=~s/\\/\//g;  
     # Get rid of everything but the actual filename  
     $fname=~s/^.*\/([^\/]+)$/$1/;  
     # Replace spaces by underscores  
     $fname=~s/\s+/\_/g;  
     # Replace all other weird characters by nothing  
     $fname=~s/[^\w\.\-]//g;  
     # See if there is anything left  
     unless ($fname) { return 'error: no uploaded file'; }  
     my $uploadedfile=$fname;  
     $fname='scantron_orig_'.$fname;  
     if (length($env{'form.upfile'}) < 2) {      if (length($env{'form.upfile'}) < 2) {
  $r->print(&mt("<span class=\"LC_error\">Error:</span> The file you attempted to upload, [_1]  contained no information. Please check that you entered the correct filename.",'<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"')."</span>"));          $r->print(&mt('[_1]Error:[_2] The file you attempted to upload, [_3] contained no information. Please check that you entered the correct filename.','<span class="LC_error">','</span>','<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'));
     } else {      } else {
  my $result=&Apache::lonnet::finishuserfileupload($env{'form.courseid'},$env{'form.domainid'},'upfile',$fname);          my $result = 
  if ($result =~ m|^/uploaded/|) {              &Apache::lonnet::userfileupload('upfile','','scantron','','','',
     $r->print(&mt("<span class=\"LC_success\">Success:</span> Successfully uploaded [_1] bytes of data into location [_2]",                                              $env{'form.courseid'},$env{'form.domainid'});
   (length($env{'form.upfile'})-1),   if ($result =~ m{^/uploaded/}) {
   '<span class="LC_filename">'.$result."</span>"));      $r->print(&mt('[_1]Success:[_2] Successfully uploaded [_3] bytes of data into location: [_4]',
                             '<span class="LC_success">','</span>',(length($env{'form.upfile'})-1),
     '<span class="LC_filename">'.$result.'</span>'));
               ($uploadedfile) = ($result =~ m{/([^/]+)$});
               $r->print(&validate_uploaded_scantron_file($env{'form.domainid'},
                                                          $env{'form.courseid'},$uploadedfile));
  } else {   } else {
     $r->print(&mt("<span class=\"LC_error\">Error:</span> An error ([_1]) occurred when attempting to upload the file, [_2]",      $r->print(&mt('[_1]Error:[_2] An error ([_3]) occurred when attempting to upload the file, [_4]',
   $result,                            '<span class="LC_error">','</span>',$result,
   '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"')."</span>"));    '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'));
   
  }   }
     }      }
     if ($symb) {      if ($symb) {
Line 7713  sub scantron_upload_scantron_data_save { Line 8039  sub scantron_upload_scantron_data_save {
     return '';      return '';
 }  }
   
   sub validate_uploaded_scantron_file {
       my ($cdom,$cname,$fname) = @_;
       my $scanlines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'.$fname);
       my @lines;
       if ($scanlines ne '-1') {
           @lines=split("\n",$scanlines,-1);
       }
       my $output;
       if (@lines) {
           my (%counts,$max_match_format);
           my ($max_match_count,$max_match_pct) = (0,0);
           my $classlist = &Apache::loncoursedata::get_classlist($cdom,$cname);
           my %idmap = &username_to_idmap($classlist);
           foreach my $key (keys(%idmap)) {
               my $lckey = lc($key);
               $idmap{$lckey} = $idmap{$key};
           }
           my %unique_formats;
           my @formatlines = &get_scantronformat_file();
           foreach my $line (@formatlines) {
               chomp($line);
               my @config = split(/:/,$line);
               my $idstart = $config[5];
               my $idlength = $config[6];
               if (($idstart ne '') && ($idlength > 0)) {
                   if (ref($unique_formats{$idstart.':'.$idlength}) eq 'ARRAY') {
                       push(@{$unique_formats{$idstart.':'.$idlength}},$config[0].':'.$config[1]); 
                   } else {
                       $unique_formats{$idstart.':'.$idlength} = [$config[0].':'.$config[1]];
                   }
               }
           }
           foreach my $key (keys(%unique_formats)) {
               my ($idstart,$idlength) = split(':',$key);
               %{$counts{$key}} = (
                                  'found'   => 0,
                                  'total'   => 0,
                                 );
               foreach my $line (@lines) {
                   next if ($line =~ /^#/);
                   next if ($line =~ /^[\s\cz]*$/);
                   my $id = substr($line,$idstart-1,$idlength);
                   $id = lc($id);
                   if (exists($idmap{$id})) {
                       $counts{$key}{'found'} ++;
                   }
                   $counts{$key}{'total'} ++;
               }
               if ($counts{$key}{'total'}) {
                   my $percent_match = (100*$counts{$key}{'found'})/($counts{$key}{'total'});
                   if (($max_match_format eq '') || ($percent_match > $max_match_pct)) {
                       $max_match_pct = $percent_match;
                       $max_match_format = $key;
                       $max_match_count = $counts{$key}{'total'};
                   }
               }
           }
           if (ref($unique_formats{$max_match_format}) eq 'ARRAY') {
               my $format_descs;
               my $numwithformat = @{$unique_formats{$max_match_format}};
               for (my $i=0; $i<$numwithformat; $i++) {
                   my ($name,$desc) = split(':',$unique_formats{$max_match_format}[$i]);
                   if ($i<$numwithformat-2) {
                       $format_descs .= '"<i>'.$desc.'</i>", ';
                   } elsif ($i==$numwithformat-2) {
                       $format_descs .= '"<i>'.$desc.'</i>" '.&mt('and').' ';
                   } elsif ($i==$numwithformat-1) {
                       $format_descs .= '"<i>'.$desc.'</i>"';
                   }
               }
               my $showpct = sprintf("%.0f",$max_match_pct).'%';
               $output .= '<br />'.&mt('Comparison of student IDs in the uploaded file with the course roster found matches for [_1] of the [_2] entries in the file (for the format defined for [_3]).','<b>'.$showpct.'</b>','<b>'.$max_match_count.'</b>',$format_descs).
                          '<br />'.&mt('A low percentage of matches results from one of the following:').'<ul>'.
                          '<li>'.&mt('The file was uploaded to the wrong course').'</li>'.
                          '<li>'.&mt('The data are not in the format expected for the domain: [_1]',
                                     '<i>'.$cdom.'</i>').'</li>'.
                          '<li>'.&mt('Students did not bubble their IDs, or mis-bubbled them').'</li>'.
                          '<li>'.&mt('The course roster is not up to date').'</li>'.
                          '</ul>';
           }
       } else {
           $output = '<span class="LC_warning">'.&mt('Uploaded file contained no data').'</span>';
       }
       return $output;
   }
   
 sub valid_file {  sub valid_file {
     my ($requested_file)=@_;      my ($requested_file)=@_;
     foreach my $filename (sort(&scantron_filenames())) {      foreach my $filename (sort(&scantron_filenames())) {
Line 7778  sub checkscantron_results { Line 8190  sub checkscantron_results {
     my $classlist=&Apache::loncoursedata::get_classlist();      my $classlist=&Apache::loncoursedata::get_classlist();
     my %idmap=&Apache::grades::username_to_idmap($classlist);      my %idmap=&Apache::grades::username_to_idmap($classlist);
     my $navmap=Apache::lonnavmaps::navmap->new();      my $navmap=Apache::lonnavmaps::navmap->new();
       unless (ref($navmap)) {
           $r->print(&navmap_errormsg());
           return '';
       }
     my $map=$navmap->getResourceByUrl($sequence);      my $map=$navmap->getResourceByUrl($sequence);
     my @resources=$navmap->retrieveResources($map,undef,1,0);      my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
       my (%grader_partids_by_symb,%grader_randomlists_by_symb);
       &graders_resources_pass(\@resources,\%grader_partids_by_symb,                             \%grader_randomlists_by_symb);
   
     my ($uname,$udom);      my ($uname,$udom);
     my (%scandata,%lastname,%bylast);      my (%scandata,%lastname,%bylast);
     $r->print('      $r->print('
Line 7789  sub checkscantron_results { Line 8208  sub checkscantron_results {
     my %completedstudents;      my %completedstudents;
   
     my $count=&Apache::grades::get_todo_count($scanlines,$scan_data);      my $count=&Apache::grades::get_todo_count($scanlines,$scan_data);
     my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Scantron/Submissions Comparison Status',      my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Bubblesheet/Submissions Comparison Status',
                                     'Progress of Scantron Data/Submission Records Comparison',$count,                                      'Progress of Bubblesheet Data/Submission Records Comparison',$count,
                                     'inline',undef,'checkscantron');                                      'inline',undef,'checkscantron');
     my ($username,$domain,$started);      my ($username,$domain,$started);
       my $nav_error;
     &Apache::grades::scantron_get_maxbubble();  # Need the bubble lines array to parse.      &scantron_get_maxbubble(\$nav_error); # Need the bubble lines array to parse.
       if ($nav_error) {
           $r->print(&navmap_errormsg());
           return '';
       }
   
     &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,      &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,
                                           'Processing first student');                                            'Processing first student');
Line 7835  sub checkscantron_results { Line 8258  sub checkscantron_results {
         ($username,$domain)=split(/:/,$uname);          ($username,$domain)=split(/:/,$uname);
         my $counter = -1;          my $counter = -1;
         foreach my $resource (@resources) {          foreach my $resource (@resources) {
               my $parts;
             my $ressymb = $resource->symb();              my $ressymb = $resource->symb();
             my ($analysis,$parts) =              if ((exists($grader_randomlists_by_symb{$ressymb})) ||
                 &scantron_partids_tograde($resource,$env{'request.course.id'},$username,$domain);                  (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {
                   (my $analysis,$parts) =
                       &scantron_partids_tograde($resource,$env{'request.course.id'},$username,$domain);
               } else {
                   $parts = $grader_partids_by_symb{$ressymb};
               }
             ($counter,my $recording) =              ($counter,my $recording) =
                 &verify_scantron_grading($resource,$domain,$username,$cid,$counter,                  &verify_scantron_grading($resource,$domain,$username,$cid,$counter,
                                          $scandata{$pid},$parts,                                           $scandata{$pid},$parts,
Line 7861  sub checkscantron_results { Line 8290  sub checkscantron_results {
                 if ($scandata{$pid} eq $record{$pid}) {                  if ($scandata{$pid} eq $record{$pid}) {
                     my $css_class = ($passed % 2)?'LC_odd_row':'LC_even_row';                      my $css_class = ($passed % 2)?'LC_odd_row':'LC_even_row';
                     $okstudents .= '<tr class="'.$css_class.'">'.                      $okstudents .= '<tr class="'.$css_class.'">'.
 '<td>'.&mt('Scantron').'</td><td>'.$showscandata.'</td><td rowspan="2">'.$last.'</td><td rowspan="2">'.$pid.'</td>'."\n".  '<td>'.&mt('Bubblesheet').'</td><td>'.$showscandata.'</td><td rowspan="2">'.$last.'</td><td rowspan="2">'.$pid.'</td>'."\n".
 '</tr>'."\n".  '</tr>'."\n".
 '<tr class="'.$css_class.'">'."\n".  '<tr class="'.$css_class.'">'."\n".
 '<td>Submissions</td><td>'.$showrecord.'</td></tr>'."\n";  '<td>Submissions</td><td>'.$showrecord.'</td></tr>'."\n";
                     $passed ++;                      $passed ++;
                 } else {                  } else {
                     my $css_class = ($failed % 2)?'LC_odd_row':'LC_even_row';                      my $css_class = ($failed % 2)?'LC_odd_row':'LC_even_row';
                     $badstudents .= '<tr class="'.$css_class.'"><td>'.&mt('Scantron').'</td><td><span class="LC_nobreak">'.$scandata{$pid}.'</span></td><td rowspan="2">'.$last.'</td><td rowspan="2">'.$pid.'</td>'."\n".                      $badstudents .= '<tr class="'.$css_class.'"><td>'.&mt('Bubblesheet').'</td><td><span class="LC_nobreak">'.$scandata{$pid}.'</span></td><td rowspan="2">'.$last.'</td><td rowspan="2">'.$pid.'</td>'."\n".
 '</tr>'."\n".  '</tr>'."\n".
 '<tr class="'.$css_class.'">'."\n".  '<tr class="'.$css_class.'">'."\n".
 '<td>Submissions</td><td><span class="LC_nobreak">'.$record{$pid}.'</span></td>'."\n".  '<td>Submissions</td><td><span class="LC_nobreak">'.$record{$pid}.'</span></td>'."\n".
Line 7879  sub checkscantron_results { Line 8308  sub checkscantron_results {
             }              }
         }          }
     }      }
     $r->print('<p>'.&mt('Comparison of scantron 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 <b>[quant,_1,student]</b>  ([_2] scantron lines/student).',$numstudents,$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 scantron data and submissions are as follows:').'<br /><br />');          $r->print(&mt('Students with exact correspondence between bubblesheet data and submissions are as follows:').'<br /><br />');
         $r->print(&Apache::loncommon::start_data_table()."\n".          $r->print(&Apache::loncommon::start_data_table()."\n".
                  &Apache::loncommon::start_data_table_header_row()."\n".                   &Apache::loncommon::start_data_table_header_row()."\n".
                  '<th>'.&mt('Source').'</th><th>'.&mt('Bubble records').'</th><th>'.&mt('Name').'</th><th>'.&mt('ID').'</th>'.                   '<th>'.&mt('Source').'</th><th>'.&mt('Bubble records').'</th><th>'.&mt('Name').'</th><th>'.&mt('ID').'</th>'.
Line 7891  sub checkscantron_results { Line 8320  sub checkscantron_results {
                  &Apache::loncommon::end_data_table().'<br />');                   &Apache::loncommon::end_data_table().'<br />');
     }      }
     if ($failed) {      if ($failed) {
         $r->print(&mt('Students with differences between scantron data and submissions are as follows:').'<br /><br />');          $r->print(&mt('Students with differences between bubblesheet data and submissions are as follows:').'<br /><br />');
         $r->print(&Apache::loncommon::start_data_table()."\n".          $r->print(&Apache::loncommon::start_data_table()."\n".
                  &Apache::loncommon::start_data_table_header_row()."\n".                   &Apache::loncommon::start_data_table_header_row()."\n".
                  '<th>'.&mt('Source').'</th><th>'.&mt('Bubble records').'</th><th>'.&mt('Name').'</th><th>'.&mt('ID').'</th>'.                   '<th>'.&mt('Source').'</th><th>'.&mt('Bubble records').'</th><th>'.&mt('Name').'</th><th>'.&mt('ID').'</th>'.
                  &Apache::loncommon::end_data_table_header_row()."\n".                   &Apache::loncommon::end_data_table_header_row()."\n".
                  $badstudents."\n".                   $badstudents."\n".
                  &Apache::loncommon::end_data_table()).'<br />'.                   &Apache::loncommon::end_data_table()).'<br />'.
                  &mt('Differences can occur if submissions were modified using manual grading after a scantron grading pass.').'<br />'.&mt('If unexpected discrepancies were detected, it is recommended that you inspect the original scantron sheets.');                     &mt('Differences can occur if submissions were modified using manual grading after a bubblesheet grading pass.').'<br />'.&mt('If unexpected discrepancies were detected, it is recommended that you inspect the original bubblesheets.');  
     }      }
     $r->print('</form><br />'.$grading_menu_button);      $r->print('</form><br />'.$grading_menu_button);
     return;      return;
Line 8113  sub grading_menu { Line 8542  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 Scantron Forms',                     { linktext => 'Grade/Manage/Review Bubblesheets',
                     url => $url4,                      url => $url4,
                     permission => 'F',                      permission => 'F',
                     icon => 'stat.png',                      icon => 'stat.png',
Line 8139  sub grading_menu { Line 8568  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 8326  GRADINGMENUJS Line 8755  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 8343  GRADINGMENUJS Line 8772  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 8459  sub process_clicker { Line 8888  sub process_clicker {
     my %checked;      my %checked;
     foreach my $gradingmechanism ('attendance','personnel','specific','given') {      foreach my $gradingmechanism ('attendance','personnel','specific','given') {
        if ($env{'form.gradingmechanism'} eq $gradingmechanism) {         if ($env{'form.gradingmechanism'} eq $gradingmechanism) {
           $checked{$gradingmechanism}="checked='checked'";            $checked{$gradingmechanism}=' checked="checked"';
        }         }
     }      }
   
Line 8523  function sanitycheck() { Line 8952  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 8782  sub assign_clicker_grades { Line 9211  sub assign_clicker_grades {
     my ($symb)=&get_symb($r);      my ($symb)=&get_symb($r);
     if (!$symb) {return '';}      if (!$symb) {return '';}
 # See which part we are saving to  # See which part we are saving to
     my ($partlist,$handgrade,$responseType) = &response_type($symb);      my $res_error;
       my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error);
       if ($res_error) {
           return &navmap_errormsg();
       }
 # FIXME: This should probably look for the first handgradeable part  # FIXME: This should probably look for the first handgradeable part
     my $part=$$partlist[0];      my $part=$$partlist[0];
 # Start screen output  # Start screen output
Line 8846  ENDHEADER Line 9279  ENDHEADER
           my $sum=0;            my $sum=0;
           my $realnumber=$number;            my $realnumber=$number;
           for (my $i=0;$i<$number;$i++) {            for (my $i=0;$i<$number;$i++) {
              if ($answer[$i]) {               if  ($correct[$i] eq '-') {
                   $realnumber--;
                } elsif ($answer[$i]) {
                 if ($gradingmechanism eq 'attendance') {                  if ($gradingmechanism eq 'attendance') {
                    $sum+=$pcorrect;                     $sum+=$pcorrect;
                 } elsif ($answer[$i] eq '*') {                  } elsif ($correct[$i] eq '*') {
                    $sum+=$pcorrect;                     $sum+=$pcorrect;
                 } elsif ($answer[$i] eq '-') {  
                    $realnumber--;  
                 } else {                  } else {
                    if ($answer[$i] eq $correct[$i]) {                     if ($answer[$i] eq $correct[$i]) {
                       $sum+=$pcorrect;                        $sum+=$pcorrect;
Line 8886  ENDHEADER Line 9319  ENDHEADER
     return $result.&show_grading_menu_form($symb);      return $result.&show_grading_menu_form($symb);
 }  }
   
   sub navmap_errormsg {
       return '<div class="LC_error">'.
              &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>').
              '</div>';
   }
   
 sub handler {  sub handler {
     my $request=$_[0];      my $request=$_[0];
     &reset_caches();      &reset_caches();
Line 9006  sub handler { Line 9446  sub handler {
         } elsif ($command eq 'checksubmissions' && $perm{'vgr'}) {          } elsif ($command eq 'checksubmissions' && $perm{'vgr'}) {
             $request->print(&checkscantron_results($request));                   $request->print(&checkscantron_results($request));     
  } elsif ($command) {   } elsif ($command) {
     $request->print("Access Denied ($command)");      $request->print('<p class="LC_error">'.&mt('Access Denied ([_1])',$command).'</p>');
  }   }
     }      }
     if ($ssi_error) {      if ($ssi_error) {
Line 9111  ssi_with_retries() Line 9551  ssi_with_retries()
   
 =item  scantron_get_maxbubble() :   =item  scantron_get_maxbubble() : 
   
      Arguments:
          $nav_error  - Reference to scalar which is a flag to indicate a
                         failure to retrieve a navmap object.
          if $nav_error is set to 1 by scantron_get_maxbubble(), the 
          calling routine should trap the error condition and display the warning
          found in &navmap_errormsg().
   
    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 9174  ssi_with_retries() Line 9621  ssi_with_retries()
 =item  scantron_validate_ID() :   =item  scantron_validate_ID() : 
   
    Validates all scanlines in the selected file to not have any     Validates all scanlines in the selected file to not have any
    invalid or underspecified student IDs     invalid or underspecified student/employee IDs
   
   =item navmap_errormsg() :
   
      Returns HTML mark-up inside a <div></div> with a link to re-initialize the course.
      Should be called whenever the request to instantiate a navmap object fails.  
   
 =back  =back
   

Removed from v.1.554  
changed lines
  Added in v.1.595


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