Diff for /loncom/homework/grades.pm between versions 1.596.2.12.2.53 and 1.706

version 1.596.2.12.2.53, 2020/09/08 15:48:41 version 1.706, 2013/09/22 18:16:46
Line 44  use Apache::Constants qw(:common :http); Line 44  use Apache::Constants qw(:common :http);
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonenc;  use Apache::lonenc;
 use Apache::lonstathelpers;  use Apache::lonstathelpers;
   use Apache::lonquickgrades;
 use Apache::bridgetask();  use Apache::bridgetask();
 use Apache::lontexconvert();  
 use HTML::Parser();  
 use File::MMagic;  
 use String::Similarity;  use String::Similarity;
 use LONCAPA;  use LONCAPA;
   
Line 143  sub nameUserString { Line 141  sub nameUserString {
   
 #--- Get the partlist and the response type for a given problem. ---  #--- Get the partlist and the response type for a given problem. ---
 #--- Indicate if a response type is coded handgraded or not. ---  #--- Indicate if a response type is coded handgraded or not. ---
 #--- Count responseIDs, essayresponse items, and dropbox items ---  
 #--- Sets response_error pointer to "1" if navmaps object broken ---  #--- Sets response_error pointer to "1" if navmaps object broken ---
 sub response_type {  sub response_type {
     my ($symb,$response_error) = @_;      my ($symb,$response_error) = @_;
Line 161  sub response_type { Line 158  sub response_type {
         return;          return;
     }      }
     my $partlist = $res->parts();      my $partlist = $res->parts();
     my ($numresp,$numessay,$numdropbox) = (0,0,0);  
     my %vPart =       my %vPart = 
  map { $_ => 1 } (&Apache::loncommon::get_env_multiple('form.vPart'));   map { $_ => 1 } (&Apache::loncommon::get_env_multiple('form.vPart'));
     my (%response_types,%handgrade);      my (%response_types,%handgrade);
Line 171  sub response_type { Line 167  sub response_type {
  my @types = $res->responseType($part);   my @types = $res->responseType($part);
  my @ids = $res->responseIds($part);   my @ids = $res->responseIds($part);
  for (my $i=0; $i < scalar(@ids); $i++) {   for (my $i=0; $i < scalar(@ids); $i++) {
             $numresp ++;  
     $response_types{$part}{$ids[$i]} = $types[$i];      $response_types{$part}{$ids[$i]} = $types[$i];
             if ($types[$i] eq 'essay') {  
                 $numessay ++;  
                 if (&Apache::lonnet::EXT("resource.$part".'_'.$ids[$i].".uploadedfiletypes",$symb)) {  
                     $numdropbox ++;  
                 }  
             }  
     $handgrade{$part.'_'.$ids[$i]} =       $handgrade{$part.'_'.$ids[$i]} = 
  &Apache::lonnet::EXT('resource.'.$part.'_'.$ids[$i].   &Apache::lonnet::EXT('resource.'.$part.'_'.$ids[$i].
      '.handgrade',$symb);       '.handgrade',$symb);
  }   }
     }      }
     return ($partlist,\%handgrade,\%response_types,$numresp,$numessay,$numdropbox);      return ($partlist,\%handgrade,\%response_types);
 }  }
   
 sub flatten_responseType {  sub flatten_responseType {
Line 211  sub get_display_part { Line 200  sub get_display_part {
     return $display;      return $display;
 }  }
   
 #--- Show parts and response type  
 sub showResourceInfo {  
     my ($symb,$partlist,$responseType,$formname,$checkboxes,$uploads) = @_;  
     unless ((ref($partlist) eq 'ARRAY') && (ref($responseType) eq 'HASH')) {  
         return '<br clear="all">';  
     }  
     my $coltitle = &mt('Problem Part Shown');  
     if ($checkboxes) {  
         $coltitle = &mt('Problem Part');  
     } else {  
         my $checkedparts = 0;  
         foreach my $partid (&Apache::loncommon::get_env_multiple('form.vPart')) {  
             if (grep(/^\Q$partid\E$/,@{$partlist})) {  
                 $checkedparts ++;  
             }  
         }  
         if ($checkedparts == scalar(@{$partlist})) {  
             return '<br clear="all">';  
         }  
         if ($uploads) {  
             $coltitle = &mt('Problem Part Selected');  
         }  
     }  
     my $result = '<div class="LC_left_float" style="display:inline-block;">';  
     if ($checkboxes) {  
         my $legend = &mt('Parts to display');  
         if ($uploads) {  
             $legend = &mt('Part(s) with dropbox');  
         }  
         $result .= '<fieldset style="display:inline-block;"><legend>'.$legend.'</legend>'.  
                    '<span class="LC_nobreak">'.  
                    '<label><input type="radio" name="chooseparts" value="0" onclick="toggleParts('."'$formname'".');" checked="checked" />'.  
                    &mt('All parts').'</label>'.('&nbsp;'x2).  
                    '<label><input type="radio" name="chooseparts" value="1" onclick="toggleParts('."'$formname'".');" />'.  
                    &mt('Selected parts').'</label></span>'.  
                    '<div id="LC_partselector" style="display:none">';  
     }  
     $result .= &Apache::loncommon::start_data_table()  
               .&Apache::loncommon::start_data_table_header_row();  
     if ($checkboxes) {  
         $result .= '<th>'.&mt('Display?').'</th>';  
     }  
     $result .= '<th>'.$coltitle.'</th>'  
               .'<th>'.&mt('Res. ID').'</th>'  
               .'<th>'.&mt('Type').'</th>'  
               .&Apache::loncommon::end_data_table_header_row();  
     my %partsseen;  
     foreach my $partID (sort(keys(%$responseType))) {  
         foreach my $resID (sort(keys(%{ $responseType->{$partID} }))) {  
             my $responsetype = $responseType->{$partID}->{$resID};  
             if ($uploads) {  
                 next unless ($responsetype eq 'essay');  
                 next unless (&Apache::lonnet::EXT("resource.$partID".'_'."$resID.uploadedfiletypes",$symb));  
             }  
             my $display_part=&get_display_part($partID,$symb);  
             if (exists($partsseen{$partID})) {  
                 $result.=&Apache::loncommon::continue_data_table_row();  
             } else {  
                 $partsseen{$partID}=scalar(keys(%{$responseType->{$partID}}));  
                 $result.=&Apache::loncommon::start_data_table_row().  
                          '<td rowspan="'.$partsseen{$partID}.'" style="vertical-align:middle">';  
                 if ($checkboxes) {  
                     $result.='<input type="checkbox" name="vPart" checked="checked" value="'.$partID.'" /></td>'.  
                              '<td rowspan="'.$partsseen{$partID}.'" style="vertical-align:middle">'.$display_part.'</td>';  
                 } else {  
                     $result.=$display_part.'</td>';  
                 }  
             }  
             $result.='<td>'.'<span class="LC_internal_info">'.$resID.'</span></td>'  
                     .'<td>'.&mt($responsetype).'</td>'  
                     .&Apache::loncommon::end_data_table_row();  
         }  
     }  
     $result.=&Apache::loncommon::end_data_table();  
     if ($checkboxes) {  
         $result .= '</div></fieldset>';  
     }  
     $result .= '</div><div style="padding:0;clear:both;margin:0;border:0"></div>';  
     if (!keys(%partsseen)) {  
         $result = '';  
         if ($uploads) {  
             return '<div style="padding:0;clear:both;margin:0;border:0"></div>'.  
                    '<p class="LC_info">'.  
                     &mt('No dropbox items or essayresponse items with uploadedfiletypes set.').  
                    '</p>';  
         } else {  
             return '<br clear="all" />';  
         }  
     }    
     return $result;  
 }  
   
 sub part_selector_js {  
     my $js = <<"END";  
 function toggleParts(formname) {  
     if (document.getElementById('LC_partselector')) {  
         var index = '';  
         if (document.forms.length) {  
             for (var i=0; i<document.forms.length; i++) {  
                 if (document.forms[i].name == formname) {  
                     index = i;  
                     break;  
                 }  
             }  
         }  
         if ((index != '') && (document.forms[index].elements['chooseparts'].length > 1)) {  
             for (var i=0; i<document.forms[index].elements['chooseparts'].length; i++) {  
                 if (document.forms[index].elements['chooseparts'][i].checked) {  
                    var val = document.forms[index].elements['chooseparts'][i].value;  
                     if (document.forms[index].elements['chooseparts'][i].value == 1) {  
                         document.getElementById('LC_partselector').style.display = 'block';  
                     } else {  
                         document.getElementById('LC_partselector').style.display = 'none';  
                     }  
                 }  
             }  
         }  
     }  
 }  
 END  
     return &Apache::lonhtmlcommon::scripttag($js);  
 }  
   
 sub reset_caches {  sub reset_caches {
     &reset_analyze_cache();      &reset_analyze_cache();
     &reset_perm();      &reset_perm();
Line 427  sub reset_caches { Line 293  sub reset_caches {
     }      }
   
     sub scantron_partids_tograde {      sub scantron_partids_tograde {
         my ($resource,$cid,$uname,$udom,$check_for_randomlist,$bubbles_per_row,$scancode) = @_;          my ($resource,$cid,$uname,$udom,$check_for_randomlist,$bubbles_per_row) = @_;
         my (%analysis,@parts);          my (%analysis,@parts);
         if (ref($resource)) {          if (ref($resource)) {
             my $symb = $resource->symb();              my $symb = $resource->symb();
Line 435  sub reset_caches { Line 301  sub reset_caches {
             if ($check_for_randomlist) {              if ($check_for_randomlist) {
                 $add_to_form = { 'check_parts_withrandomlist' => 1,};                  $add_to_form = { 'check_parts_withrandomlist' => 1,};
             }              }
             if ($scancode) {              my $analyze = 
                 if (ref($add_to_form) eq 'HASH') {  
                     $add_to_form->{'code_for_randomlist'} = $scancode;  
                 } else {  
                     $add_to_form = { 'code_for_randomlist' => $scancode,};  
                 }  
             }  
             my $analyze =  
                 &get_analyze($symb,$uname,$udom,undef,$add_to_form,                  &get_analyze($symb,$uname,$udom,undef,$add_to_form,
                              undef,undef,undef,$bubbles_per_row);                               undef,undef,undef,$bubbles_per_row);
             if (ref($analyze) eq 'HASH') {              if (ref($analyze) eq 'HASH') {
Line 471  sub cleanRecord { Line 330  sub cleanRecord {
     my $grayFont = '<span class="LC_internal_info">';      my $grayFont = '<span class="LC_internal_info">';
     if ($response =~ /^(option|rank)$/) {      if ($response =~ /^(option|rank)$/) {
  my %answer=&Apache::lonnet::str2hash($answer);   my %answer=&Apache::lonnet::str2hash($answer);
         my @answer = %answer;  
         %answer = map {&HTML::Entities::encode($_, '"<>&')} @answer;  
  my %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"});   my %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"});
  my ($toprow,$bottomrow);   my ($toprow,$bottomrow);
  foreach my $foil (@$order) {   foreach my $foil (@$order) {
Line 489  sub cleanRecord { Line 346  sub cleanRecord {
     $bottomrow.'</tr></table></blockquote>';      $bottomrow.'</tr></table></blockquote>';
     } elsif ($response eq 'match') {      } elsif ($response eq 'match') {
  my %answer=&Apache::lonnet::str2hash($answer);   my %answer=&Apache::lonnet::str2hash($answer);
         my @answer = %answer;  
         %answer = map {&HTML::Entities::encode($_, '"<>&')} @answer;  
  my %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"});   my %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"});
  my @items=&Apache::lonnet::str2array($record->{$version."resource.$partid.$respid.submissionitems"});   my @items=&Apache::lonnet::str2array($record->{$version."resource.$partid.$respid.submissionitems"});
  my ($toprow,$middlerow,$bottomrow);   my ($toprow,$middlerow,$bottomrow);
Line 513  sub cleanRecord { Line 368  sub cleanRecord {
     $bottomrow.'</tr></table></blockquote>';      $bottomrow.'</tr></table></blockquote>';
     } elsif ($response eq 'radiobutton') {      } elsif ($response eq 'radiobutton') {
  my %answer=&Apache::lonnet::str2hash($answer);   my %answer=&Apache::lonnet::str2hash($answer);
         my @answer = %answer;  
         %answer = map {&HTML::Entities::encode($_, '"<>&')}  @answer;  
  my ($toprow,$bottomrow);   my ($toprow,$bottomrow);
  my $correct =    my $correct = 
     &get_radiobutton_correct_foil($partid,$respid,$symb,$uname,$udom,$type,$trial,$rndseed);      &get_radiobutton_correct_foil($partid,$respid,$symb,$uname,$udom,$type,$trial,$rndseed);
Line 547  sub cleanRecord { Line 400  sub cleanRecord {
     $env{'form.kwstyle'}  = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : '';      $env{'form.kwstyle'}  = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : '';
     $env{'form.'.$symb} = 1; # so that we don't have to read it from disk for multiple sub of the same prob.      $env{'form.'.$symb} = 1; # so that we don't have to read it from disk for multiple sub of the same prob.
  }   }
         $answer = &Apache::lontexconvert::msgtexconverted($answer);   $answer =~ s-\n-<br />-g;
  return '<br /><br /><blockquote><tt>'.&keywords_highlight($answer).'</tt></blockquote>';   return '<br /><br /><blockquote><tt>'.&keywords_highlight($answer).'</tt></blockquote>';
     } elsif ( $response eq 'organic') {      } elsif ( $response eq 'organic') {
         my $result=&mt('Smile representation: [_1]',   my $result='Smile representation: "<tt>'.$answer.'</tt>"';
                            '"<tt>'.&HTML::Entities::encode($answer, '"<>&').'</tt>"');  
  my $jme=$record->{$version."resource.$partid.$respid.molecule"};   my $jme=$record->{$version."resource.$partid.$respid.molecule"};
  $result.=&Apache::chemresponse::jme_img($jme,$answer,400);   $result.=&Apache::chemresponse::jme_img($jme,$answer,400);
  return $result;   return $result;
Line 585  sub cleanRecord { Line 437  sub cleanRecord {
     $result.='</ul>';      $result.='</ul>';
     return $result;      return $result;
  }   }
     } elsif ( $response =~ m/(?:numerical|formula|custom)/) {      } elsif ( $response =~ m/(?:numerical|formula)/) {
         # Respect multiple input fields, see Bug #5409   
  $answer =    $answer = 
     &Apache::loncommon::format_previous_attempt_value('submission',      &Apache::loncommon::format_previous_attempt_value('submission',
       $answer);        $answer);
  return $answer;  
     }      }
     return &HTML::Entities::encode($answer, '"<>&');      return $answer;
 }  }
   
 #-- A couple of common js functions  #-- A couple of common js functions
Line 632  COMMONJSFUNCTIONS Line 482  COMMONJSFUNCTIONS
 #--- Dumps the class list with usernames,list of sections,  #--- Dumps the class list with usernames,list of sections,
 #--- section, ids and fullnames for each user.  #--- section, ids and fullnames for each user.
 sub getclasslist {  sub getclasslist {
     my ($getsec,$filterbyaccstatus,$getgroup,$symb,$submitonly,$filterbysubmstatus) = @_;      my ($getsec,$filterlist,$getgroup) = @_;
     my @getsec;      my @getsec;
     my @getgroup;      my @getgroup;
     my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));      my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));
Line 660  sub getclasslist { Line 510  sub getclasslist {
     #      #
     my %sections;      my %sections;
     my %fullnames;      my %fullnames;
     my ($cdom,$cnum,$partlist);  
     if (($filterbysubmstatus) && ($submitonly ne 'all') && ($symb ne '')) {  
         $cdom = $env{"course.$env{'request.course.id'}.domain"};  
         $cnum = $env{"course.$env{'request.course.id'}.num"};  
         my $res_error;  
         ($partlist) = &response_type($symb,\$res_error);  
     }  
     foreach my $student (keys(%$classlist)) {      foreach my $student (keys(%$classlist)) {
         my $end      =           my $end      = 
             $classlist->{$student}->[&Apache::loncoursedata::CL_END()];              $classlist->{$student}->[&Apache::loncoursedata::CL_END()];
Line 683  sub getclasslist { Line 526  sub getclasslist {
         my $group   =           my $group   = 
             $classlist->{$student}->[&Apache::loncoursedata::CL_GROUP()];              $classlist->{$student}->[&Apache::loncoursedata::CL_GROUP()];
  # filter students according to status selected   # filter students according to status selected
  if ($filterbyaccstatus && (!($stu_status =~ /Any/))) {   if ($filterlist && (!($stu_status =~ /Any/))) {
     if (!($stu_status =~ $status)) {      if (!($stu_status =~ $status)) {
  delete($classlist->{$student});   delete($classlist->{$student});
  next;   next;
Line 700  sub getclasslist { Line 543  sub getclasslist {
                }                  } 
         }          }
            if (($grp eq 'none') && !$group) {             if (($grp eq 'none') && !$group) {
            $exclude = 0;                 $exclude = 0;
         }          }
     }      }
     if ($exclude) {      if ($exclude) {
         delete($classlist->{$student});          delete($classlist->{$student});
  next;  
     }      }
  }   }
         if (($filterbysubmstatus) && ($submitonly ne 'all') && ($symb ne '')) {  
             my $udom =  
                 $classlist->{$student}->[&Apache::loncoursedata::CL_SDOM()];  
             my $uname =  
                 $classlist->{$student}->[&Apache::loncoursedata::CL_SNAME()];  
             if (($symb ne '') && ($udom ne '') && ($uname ne '')) {  
                 if ($submitonly eq 'queued') {  
                     my %queue_status =  
                         &Apache::bridgetask::get_student_status($symb,$cdom,$cnum,  
                                                                 $udom,$uname);  
                     if (!defined($queue_status{'gradingqueue'})) {  
                         delete($classlist->{$student});  
                         next;  
                     }  
                 } else {  
                     my (%status) =&student_gradeStatus($symb,$udom,$uname,$partlist);  
                     my $submitted = 0;  
                     my $graded = 0;  
                     my $incorrect = 0;  
                     foreach (keys(%status)) {  
                         $submitted = 1 if ($status{$_} ne 'nothing');  
                         $graded = 1 if ($status{$_} =~ /^ungraded/);  
                         $incorrect = 1 if ($status{$_} =~ /^incorrect/);  
   
                         my ($foo,$partid,$foo1) = split(/\./,$_);  
                         if ($status{'resource.'.$partid.'.submitted_by'} ne '') {  
                             $submitted = 0;  
                         }  
                     }  
                     if (!$submitted && ($submitonly eq 'yes' ||  
                                         $submitonly eq 'incorrect' ||  
                                         $submitonly eq 'graded')) {  
                         delete($classlist->{$student});  
                         next;  
                     } elsif (!$graded && ($submitonly eq 'graded')) {  
                         delete($classlist->{$student});  
                         next;  
                     } elsif (!$incorrect && $submitonly eq 'incorrect') {  
                         delete($classlist->{$student});  
                         next;  
                     }  
                 }  
             }  
         }  
  $section = ($section ne '' ? $section : 'none');   $section = ($section ne '' ? $section : 'none');
  if (&canview($section)) {   if (&canview($section)) {
     if (!@getsec || grep(/^\Q$section\E$/,@getsec)) {      if (!@getsec || grep(/^\Q$section\E$/,@getsec)) {
Line 766  sub getclasslist { Line 564  sub getclasslist {
     delete($classlist->{$student});      delete($classlist->{$student});
  }   }
     }      }
       my %seen = ();
     my @sections = sort(keys(%sections));      my @sections = sort(keys(%sections));
     return ($classlist,\@sections,\%fullnames);      return ($classlist,\@sections,\%fullnames);
 }  }
Line 781  sub canmodify { Line 580  sub canmodify {
  #can modify the requested section   #can modify the requested section
  return 1;   return 1;
     } else {      } else {
  # can't modify the requested section   # can't modify the request section
  return 0;   return 0;
     }      }
  }   }
Line 794  sub canview { Line 593  sub canview {
     my ($sec)=@_;      my ($sec)=@_;
     if ($perm{'vgr'}) {      if ($perm{'vgr'}) {
  if (!defined($perm{'vgr_section'})) {   if (!defined($perm{'vgr_section'})) {
     # can view whole class      # can modify whole class
     return 1;      return 1;
  } else {   } else {
     if ($sec eq $perm{'vgr_section'}) {      if ($sec eq $perm{'vgr_section'}) {
  #can view the requested section   #can modify the requested section
  return 1;   return 1;
     } else {      } else {
  # can't view the requested section   # can't modify the request section
  return 0;   return 0;
     }      }
  }   }
     }      }
     #can't view      #can't modify
     return 0;      return 0;
 }  }
   
Line 947  sub initialverifyreceipt { Line 746  sub initialverifyreceipt {
   
 #--- Check whether a receipt number is valid.---  #--- Check whether a receipt number is valid.---
 sub verifyreceipt {  sub verifyreceipt {
     my ($request,$symb) = @_;      my ($request,$symb)  = @_;
   
     my $courseid = $env{'request.course.id'};      my $courseid = $env{'request.course.id'};
     my $receipt  = &Apache::lonnet::recprefix($courseid).'-'.      my $receipt  = &Apache::lonnet::recprefix($courseid).'-'.
  $env{'form.receipt'};   $env{'form.receipt'};
     $receipt     =~ s/[^\-\d]//g;      $receipt     =~ s/[^\-\d]//g;
   
     my $title =      my $title.=
  '<h3><span class="LC_info">'.   '<h3><span class="LC_info">'.
  &mt('Verifying Receipt Number [_1]',$receipt).   &mt('Verifying Receipt Number [_1]',$receipt).
  '</span></h3>'."\n";   '</span></h3>'."\n";
Line 1035  sub verifyreceipt { Line 834  sub verifyreceipt {
 #--- Also called directly when one clicks on the subm button   #--- Also called directly when one clicks on the subm button 
 #    on the problem page.  #    on the problem page.
 sub listStudents {  sub listStudents {
     my ($request,$symb,$submitonly,$divforres) = @_;      my ($request,$symb,$submitonly) = @_;
   
     my $cdom      = $env{"course.$env{'request.course.id'}.domain"};      my $cdom      = $env{"course.$env{'request.course.id'}.domain"};
     my $cnum      = $env{"course.$env{'request.course.id'}.num"};      my $cnum      = $env{"course.$env{'request.course.id'}.num"};
     my $getsec    = $env{'form.section'} eq '' ? 'all' : $env{'form.section'};      my $getsec    = $env{'form.section'} eq '' ? 'all' : $env{'form.section'};
     my $getgroup  = $env{'form.group'} eq '' ? 'all' : $env{'form.group'};      my $getgroup  = $env{'form.group'} eq '' ? 'all' : $env{'form.group'};
     unless ($submitonly) {      unless ($submitonly) {
         $submitonly = $env{'form.submitonly'} eq '' ? 'all' : $env{'form.submitonly'};         $submitonly= $env{'form.submitonly'} eq '' ? 'all' : $env{'form.submitonly'};
     }      }
   
     my $result='';      my $result='';
     my $res_error;      my $res_error;
     my ($partlist,$handgrade,$responseType,$numresp,$numessay) = &response_type($symb,\$res_error);      my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error);
   
     my $table;  
     if (ref($partlist) eq 'ARRAY') {  
         if (scalar(@$partlist) > 1 ) {  
             $table = &showResourceInfo($symb,$partlist,$responseType,'gradesub',1);  
         } elsif ($divforres) {  
             $table = '<div style="padding:0;clear:both;margin:0;border:0"></div>';  
         } else {  
             $table = '<br clear="all" />';  
         }  
     }  
   
     my %js_lt = &Apache::lonlocal::texthash (      my %lt = &Apache::lonlocal::texthash (
  'multiple' => 'Please select a student or group of students before clicking on the Next button.',   'multiple' => 'Please select a student or group of students before clicking on the Next button.',
  'single'   => 'Please select the student before clicking on the Next button.',   'single'   => 'Please select the student before clicking on the Next button.',
      );       );
     &js_escape(\%js_lt);  
     $request->print(&Apache::lonhtmlcommon::scripttag(<<LISTJAVASCRIPT));      $request->print(&Apache::lonhtmlcommon::scripttag(<<LISTJAVASCRIPT));
     function checkSelect(checkBox) {      function checkSelect(checkBox) {
  var ctr=0;   var ctr=0;
Line 1075  sub listStudents { Line 862  sub listStudents {
     ctr++;      ctr++;
  }   }
     }      }
     sense = '$js_lt{'multiple'}';      sense = '$lt{'multiple'}';
  } else {   } else {
     if (checkBox.checked) {      if (checkBox.checked) {
  ctr = 1;   ctr = 1;
     }      }
     sense = '$js_lt{'single'}';      sense = '$lt{'single'}';
  }   }
  if (ctr == 0) {   if (ctr == 0) {
     alert(sense);      alert(sense);
Line 1100  LISTJAVASCRIPT Line 887  LISTJAVASCRIPT
     $request->print($result);      $request->print($result);
   
     my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'.      my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'.
  "\n".$table;   "\n";
   
     $gradeTable .= &Apache::lonhtmlcommon::start_pick_box();      $gradeTable .= &Apache::lonhtmlcommon::start_pick_box();
     $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Problem Text'))      $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"
Line 1114  LISTJAVASCRIPT Line 901  LISTJAVASCRIPT
                   .'<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();                    .&Apache::lonhtmlcommon::row_closure();
   
       my $submission_options;
     my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));      my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));
     my $saveStatus = $stu_status eq '' ? 'Active' : $stu_status;      my $saveStatus = $stu_status eq '' ? 'Active' : $stu_status;
     $env{'form.Status'} = $saveStatus;      $env{'form.Status'} = $saveStatus;
     my %optiontext = &Apache::lonlocal::texthash (      $submission_options.=
                           lastonly => 'last submission',  
                           last     => 'last submission with details',  
                           datesub  => 'all submissions',  
                           all      => 'all submissions with details',  
                       );  
     my $submission_options =  
         '<span class="LC_nobreak">'.          '<span class="LC_nobreak">'.
         '<label><input type="radio" name="lastSub" value="lastonly" /> '.          '<label><input type="radio" name="lastSub" value="lastonly" /> '.
         $optiontext{'lastonly'}.' </label></span>'."\n".          &mt('last submission').' </label></span>'."\n".
         '<span class="LC_nobreak">'.          '<span class="LC_nobreak">'.
         '<label><input type="radio" name="lastSub" value="last" /> '.          '<label><input type="radio" name="lastSub" value="last" /> '.
         $optiontext{'last'}.' </label></span>'."\n".          &mt('last submission with details').' </label></span>'."\n".
         '<span class="LC_nobreak">'.          '<span class="LC_nobreak">'.
         '<label><input type="radio" name="lastSub" value="datesub" checked="checked" /> '.          '<label><input type="radio" name="lastSub" value="datesub" checked="checked" /> '.
         $optiontext{'datesub'}.'</label></span>'."\n".          &mt('all submissions').'</label></span>'."\n".
         '<span class="LC_nobreak">'.          '<span class="LC_nobreak">'.
         '<label><input type="radio" name="lastSub" value="all" /> '.          '<label><input type="radio" name="lastSub" value="all" /> '.
         $optiontext{'all'}.'</label></span>';          &mt('all submissions with details').'</label></span>';
     my ($compmsg,$nocompmsg);      $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Submissions'))
     $nocompmsg = ' checked="checked"';  
     if ($numessay) {  
         $compmsg = $nocompmsg;  
         $nocompmsg = '';  
     }  
     $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Submissions'))  
                   .$submission_options                    .$submission_options
                   .&Apache::lonhtmlcommon::row_closure()  
                   .&Apache::lonhtmlcommon::row_title(&mt('Send Messages'))  
                   .'<span class="LC_nobreak">'  
                   .'<label><input type="radio" name="compmsg" value="0"'.$nocompmsg.' />'  
                   .&mt('No').('&nbsp;'x2).'</label>'  
                   .'<label><input type="radio" name="compmsg" value="1"'.$compmsg.' />'  
                   .&mt('Yes').('&nbsp;'x2).'</label>'  
                   .&Apache::lonhtmlcommon::row_closure();                    .&Apache::lonhtmlcommon::row_closure();
   
     $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Grading Increments'))      $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Grading Increments'))
Line 1159  LISTJAVASCRIPT Line 928  LISTJAVASCRIPT
                   .'<option value=".5">'.&mt('Half Points').'</option>'                    .'<option value=".5">'.&mt('Half Points').'</option>'
                   .'<option value=".25">'.&mt('Quarter Points').'</option>'                    .'<option value=".25">'.&mt('Quarter Points').'</option>'
                   .'<option value=".1">'.&mt('Tenths of a Point').'</option>'                    .'<option value=".1">'.&mt('Tenths of a Point').'</option>'
                   .'</select>';                    .'</select>'
                     .&Apache::lonhtmlcommon::row_closure();
   
     $gradeTable .=       $gradeTable .= 
         &build_section_inputs().          &build_section_inputs().
  '<input type="hidden" name="submitonly"  value="'.$submitonly.'" />'."\n".   '<input type="hidden" name="submitonly"  value="'.$submitonly.'" />'."\n".
  '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n".   '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n".
  '<input type="hidden" name="saveStatusOld" value="'.$saveStatus.'" />'."\n";   '<input type="hidden" name="saveStatusOld" value="'.$saveStatus.'" />'."\n";
   
     if (exists($env{'form.Status'})) {      if (exists($env{'form.Status'})) {
  $gradeTable .= '<input type="hidden" name="Status" value="'.$stu_status.'" />'."\n";   $gradeTable .= '<input type="hidden" name="Status" value="'.$stu_status.'" />'."\n";
     } else {      } else {
         $gradeTable .= &Apache::lonhtmlcommon::row_closure()          $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Student Status'))
                       .&Apache::lonhtmlcommon::row_title(&mt('Student Status'))  
                       .&Apache::lonhtmlcommon::StatusOptions(                        .&Apache::lonhtmlcommon::StatusOptions(
                            $saveStatus,undef,1,'javascript:reLoadList(this.form);');                             $saveStatus,undef,1,'javascript:reLoadList(this.form);')
     }                        .&Apache::lonhtmlcommon::row_closure();
     if ($numessay) {  
         $gradeTable .= &Apache::lonhtmlcommon::row_closure()  
                       .&Apache::lonhtmlcommon::row_title(&mt('Check For Plagiarism'))  
                       .'<input type="checkbox" name="checkPlag" checked="checked" />';  
     }      }
     $gradeTable .= &Apache::lonhtmlcommon::row_closure(1)  
       $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Check For Plagiarism'))
                     .'<input type="checkbox" name="checkPlag" checked="checked" />'
                     .&Apache::lonhtmlcommon::row_closure(1)
                   .&Apache::lonhtmlcommon::end_pick_box();                    .&Apache::lonhtmlcommon::end_pick_box();
   
     $gradeTable .= '<p>'      $gradeTable .= '<p>'
Line 1314  LISTJAVASCRIPT Line 1084  LISTJAVASCRIPT
     if ($submitonly eq 'graded'   ) { $submissions = 'ungraded submissions'; }      if ($submitonly eq 'graded'   ) { $submissions = 'ungraded submissions'; }
     if ($submitonly eq 'queued'   ) { $submissions = 'queued submissions'; }      if ($submitonly eq 'queued'   ) { $submissions = 'queued submissions'; }
     $gradeTable='<br />&nbsp;<span class="LC_warning">'.      $gradeTable='<br />&nbsp;<span class="LC_warning">'.
  &mt('No '.$submissions.' found for this resource for any students. ([quant,_1,student] checked for '.$submissions.')',   &mt('No '.$submissions.' found for this resource for any students. ([_1] students checked for '.$submissions.')',
     $num_students).      $num_students).
  '</span><br />';   '</span><br />';
  }   }
Line 1328  LISTJAVASCRIPT Line 1098  LISTJAVASCRIPT
 #---- Called from the listStudents routine  #---- Called from the listStudents routine
   
 sub check_script {  sub check_script {
     my ($form,$type) = @_;      my ($form, $type)=@_;
     my $chkallscript = &Apache::lonhtmlcommon::scripttag('      my $chkallscript= &Apache::lonhtmlcommon::scripttag('
     function checkall() {      function checkall() {
         for (i=0; i<document.forms.'.$form.'.elements.length; i++) {          for (i=0; i<document.forms.'.$form.'.elements.length; i++) {
             ele = document.forms.'.$form.'.elements[i];              ele = document.forms.'.$form.'.elements[i];
Line 1374  sub check_buttons { Line 1144  sub check_buttons {
   
 #     Displays the submissions for one student or a group of students  #     Displays the submissions for one student or a group of students
 sub processGroup {  sub processGroup {
     my ($request,$symb) = @_;      my ($request,$symb)  = @_;
     my $ctr        = 0;      my $ctr        = 0;
     my @stuchecked = &Apache::loncommon::get_env_multiple('form.stuinfo');      my @stuchecked = &Apache::loncommon::get_env_multiple('form.stuinfo');
     my $total      = scalar(@stuchecked)-1;      my $total      = scalar(@stuchecked)-1;
Line 1398  sub processGroup { Line 1168  sub processGroup {
 #--- Javascript to handle the submission page functionality ---  #--- Javascript to handle the submission page functionality ---
 sub sub_page_js {  sub sub_page_js {
     my $request = shift;      my $request = shift;
     my $alertmsg = &mt('A number equal or greater than 0 is expected. Entered value = ');      my $alertmsg = &mt('A number equal or greater than 0 is expected. Entered value = ');
     &js_escape(\$alertmsg);  
     $request->print(&Apache::lonhtmlcommon::scripttag(<<SUBJAVASCRIPT));      $request->print(&Apache::lonhtmlcommon::scripttag(<<SUBJAVASCRIPT));
     function updateRadio(formname,id,weight) {      function updateRadio(formname,id,weight) {
  var gradeBox = formname["GD_BOX"+id];   var gradeBox = formname["GD_BOX"+id];
Line 1517  sub sub_page_js { Line 1286  sub sub_page_js {
     }      }
  }   }
     }      }
       
  }   }
     }      }
       
  }   }
  formname.submit();   formname.submit();
     }      }
Line 1562  sub sub_page_js { Line 1333  sub sub_page_js {
 SUBJAVASCRIPT  SUBJAVASCRIPT
 }  }
   
 #--- javascript for grading message center  #--- javascript for essay type problem --
 sub sub_grademessage_js {  sub sub_page_kw_js {
     my $request = shift;      my $request = shift;
     my $iconpath = $request->dir_config('lonIconsURL');      my $iconpath = $request->dir_config('lonIconsURL');
     &commonJSfunctions($request);      &commonJSfunctions($request);
Line 1609  sub sub_grademessage_js { Line 1380  sub sub_grademessage_js {
 </script>  </script>
 INNERJS  INNERJS
   
     my $start_page_msg_central =      my $inner_js_highlight_central= (<<INNERJS);
   <script type="text/javascript">
       function updateChoice(flag) {
         opener.document.SCORE.kwclr.value = opener.radioSelection(document.hlCenter.kwdclr);
         opener.document.SCORE.kwsize.value = opener.radioSelection(document.hlCenter.kwdsize);
         opener.document.SCORE.kwstyle.value = opener.radioSelection(document.hlCenter.kwdstyle);
         opener.document.SCORE.refresh.value = "on";
         if (opener.document.SCORE.keywords.value!=""){
            opener.document.SCORE.submit();
         }
         self.close()
       }
   </script>
   INNERJS
   
       my $start_page_msg_central = 
         &Apache::loncommon::start_page('Message Central',$inner_js_msg_central,          &Apache::loncommon::start_page('Message Central',$inner_js_msg_central,
        {'js_ready'  => 1,         {'js_ready'  => 1,
  'only_body' => 1,   'only_body' => 1,
  'bgcolor'   =>'#FFFFFF',});   'bgcolor'   =>'#FFFFFF',});
     my $end_page_msg_central =      my $end_page_msg_central = 
  &Apache::loncommon::end_page({'js_ready' => 1});   &Apache::loncommon::end_page({'js_ready' => 1});
   
   
       my $start_page_highlight_central = 
           &Apache::loncommon::start_page('Highlight Central',
          $inner_js_highlight_central,
          {'js_ready'  => 1,
    'only_body' => 1,
    'bgcolor'   =>'#FFFFFF',});
       my $end_page_highlight_central = 
    &Apache::loncommon::end_page({'js_ready' => 1});
   
     my $docopen=&Apache::lonhtmlcommon::javascript_docopen();      my $docopen=&Apache::lonhtmlcommon::javascript_docopen();
     $docopen=~s/^document\.//;      $docopen=~s/^document\.//;
       my %lt = &Apache::lonlocal::texthash(
     my %html_js_lt = &Apache::lonlocal::texthash(                  keyw => 'Keywords list, separated by a space. Add/delete to list if desired.',
                   plse => 'Please select a word or group of words from document and then click this link.',
                   adds => 'Add selection to keyword list? Edit if desired.',
                 comp => 'Compose Message for: ',                  comp => 'Compose Message for: ',
                 incl => 'Include',                  incl => 'Include',
                 type => 'Type',                  type => 'Type',
Line 1630  INNERJS Line 1427  INNERJS
                 new  => 'New',                  new  => 'New',
                 save => 'Save',                  save => 'Save',
                 canc => 'Cancel',                  canc => 'Cancel',
                   kehi => 'Keyword Highlight Options',
                   txtc => 'Text Color',
                   font => 'Font Size',
                   fnst => 'Font Style',
              );               );
     &html_escape(\%html_js_lt);  
     &js_escape(\%html_js_lt);  
     $request->print(&Apache::lonhtmlcommon::scripttag(<<SUBJAVASCRIPT));      $request->print(&Apache::lonhtmlcommon::scripttag(<<SUBJAVASCRIPT));
   
   //===================== Show list of keywords ====================
     function keywords(formname) {
       var nret = prompt("$lt{'keyw'}",formname.keywords.value);
       if (nret==null) return;
       formname.keywords.value = nret;
   
       if (formname.keywords.value != "") {
    formname.refresh.value = "on";
    formname.submit();
       }
       return;
     }
   
 //===================== Script to view submitted by ==================  //===================== Script to view submitted by ==================
   function viewSubmitter(submitter) {    function viewSubmitter(submitter) {
     document.SCORE.refresh.value = "on";      document.SCORE.refresh.value = "on";
Line 1644  INNERJS Line 1456  INNERJS
     return;      return;
   }    }
   
   //===================== Script to add keyword(s) ==================
     function getSel() {
       if (document.getSelection) txt = document.getSelection();
       else if (document.selection) txt = document.selection.createRange().text;
       else return;
       var cleantxt = txt.replace(new RegExp('([\\f\\n\\r\\t\\v ])+', 'g')," ");
       if (cleantxt=="") {
    alert("$lt{'plse'}");
    return;
       }
       var nret = prompt("$lt{'adds'}",cleantxt);
       if (nret==null) return;
       document.SCORE.keywords.value = document.SCORE.keywords.value+" "+nret;
       if (document.SCORE.keywords.value != "") {
    document.SCORE.refresh.value = "on";
    document.SCORE.submit();
       }
       return;
     }
   
 //====================== Script for composing message ==============  //====================== Script for composing message ==============
    // preload images     // preload images
    img1 = new Image();     img1 = new Image();
Line 1714  INNERJS Line 1546  INNERJS
   
     pDoc.write("<form action=\\"inactive\\" name=\\"msgcenter\\">");      pDoc.write("<form action=\\"inactive\\" name=\\"msgcenter\\">");
     pDoc.write("<input value=\\""+usrctr+"\\" name=\\"usrctr\\" type=\\"hidden\\">");      pDoc.write("<input value=\\""+usrctr+"\\" name=\\"usrctr\\" type=\\"hidden\\">");
     pDoc.write("<h1>&nbsp;$html_js_lt{'comp'}\"+fullname+\"<\\/h1>");      pDoc.write("<h1>&nbsp;$lt{'comp'}\"+fullname+\"<\\/h1>");
   
     pDoc.write('<table style="border:1px solid black;"><tr>');      pDoc.write('<table style="border:1px solid black;"><tr>');
     pDoc.write("<td><b>$html_js_lt{'incl'}<\\/b><\\/td><td><b>$html_js_lt{'type'}<\\/b><\\/td><td><b>$html_js_lt{'mesa'}<\\/td><\\/tr>");      pDoc.write("<td><b>$lt{'incl'}<\\/b><\\/td><td><b>$lt{'type'}<\\/b><\\/td><td><b>$lt{'mesa'}<\\/td><\\/tr>");
 }  }
     function displaySubject(msg,shwsel) {      function displaySubject(msg,shwsel) {
     pDoc = pWin.document;      pDoc = pWin.document;
     pDoc.write("<tr>");      pDoc.write("<tr>");
     pDoc.write("<td align=\\"center\\"><input name=\\"subchk\\" type=\\"checkbox\\"" +shwsel+"><\\/td>");      pDoc.write("<td align=\\"center\\"><input name=\\"subchk\\" type=\\"checkbox\\"" +shwsel+"><\\/td>");
     pDoc.write("<td>$html_js_lt{'subj'}<\\/td>");      pDoc.write("<td>$lt{'subj'}<\\/td>");
     pDoc.write("<td><input name=\\"msgsub\\" type=\\"text\\" value=\\""+msg+"\\"size=\\"40\\" maxlength=\\"80\\"><\\/td><\\/tr>");      pDoc.write("<td><input name=\\"msgsub\\" type=\\"text\\" value=\\""+msg+"\\"size=\\"40\\" maxlength=\\"80\\"><\\/td><\\/tr>");
 }  }
   
Line 1739  INNERJS Line 1571  INNERJS
     pDoc = pWin.document;      pDoc = pWin.document;
     pDoc.write("<tr>");      pDoc.write("<tr>");
     pDoc.write("<td align=\\"center\\"><input name=\\"newmsgchk\\" type=\\"checkbox\\"" +shwsel+"><\\/td>");      pDoc.write("<td align=\\"center\\"><input name=\\"newmsgchk\\" type=\\"checkbox\\"" +shwsel+"><\\/td>");
     pDoc.write("<td align=\\"center\\">$html_js_lt{'new'}<\\/td>");      pDoc.write("<td align=\\"center\\">$lt{'new'}<\\/td>");
     pDoc.write("<td><textarea name=\\"newmsg\\" cols=\\"60\\" rows=\\"3\\" onchange=\\"javascript:this.form.newmsgchk.checked=true\\" >"+newmsg+"<\\/textarea><\\/td><\\/tr>");      pDoc.write("<td><textarea name=\\"newmsg\\" cols=\\"60\\" rows=\\"3\\" onchange=\\"javascript:this.form.newmsgchk.checked=true\\" >"+newmsg+"<\\/textarea><\\/td><\\/tr>");
 }  }
   
   function msgTail() {    function msgTail() {
     pDoc = pWin.document;      pDoc = pWin.document;
       //pDoc.write("<\\/table>");
     pDoc.write("<\\/td><\\/tr><\\/table>&nbsp;");      pDoc.write("<\\/td><\\/tr><\\/table>&nbsp;");
     pDoc.write("<input type=\\"button\\" value=\\"$html_js_lt{'save'}\\" onclick=\\"javascript:checkInput()\\">&nbsp;&nbsp;");      pDoc.write("<input type=\\"button\\" value=\\"$lt{'save'}\\" onclick=\\"javascript:checkInput()\\">&nbsp;&nbsp;");
     pDoc.write("<input type=\\"button\\" value=\\"$html_js_lt{'canc'}\\" onclick=\\"self.close()\\"><br /><br />");      pDoc.write("<input type=\\"button\\" value=\\"$lt{'canc'}\\" onclick=\\"self.close()\\"><br /><br />");
     pDoc.write("<\\/form>");      pDoc.write("<\\/form>");
     pDoc.write('$end_page_msg_central');      pDoc.write('$end_page_msg_central');
     pDoc.close();      pDoc.close();
 }  }
   
 SUBJAVASCRIPT  
 }  
   
 #--- javascript for essay type problem --  
 sub sub_page_kw_js {  
     my $request = shift;  
   
     unless ($env{'form.compmsg'}) {  
         &commonJSfunctions($request);  
     }  
   
     my $inner_js_highlight_central= (<<INNERJS);  
 <script type="text/javascript">  
     function updateChoice(flag) {  
       opener.document.SCORE.kwclr.value = opener.radioSelection(document.hlCenter.kwdclr);  
       opener.document.SCORE.kwsize.value = opener.radioSelection(document.hlCenter.kwdsize);  
       opener.document.SCORE.kwstyle.value = opener.radioSelection(document.hlCenter.kwdstyle);  
       opener.document.SCORE.refresh.value = "on";  
       if (opener.document.SCORE.keywords.value!=""){  
          opener.document.SCORE.submit();  
       }  
       self.close()  
     }  
 </script>  
 INNERJS  
   
     my $start_page_highlight_central =  
         &Apache::loncommon::start_page('Highlight Central',  
                                        $inner_js_highlight_central,  
                                        {'js_ready'  => 1,  
                                         'only_body' => 1,  
                                         'bgcolor'   =>'#FFFFFF',});  
     my $end_page_highlight_central =  
         &Apache::loncommon::end_page({'js_ready' => 1});  
   
     my $docopen=&Apache::lonhtmlcommon::javascript_docopen();  
     $docopen=~s/^document\.//;  
   
     my %js_lt = &Apache::lonlocal::texthash(  
                 keyw => 'Keywords list, separated by a space. Add/delete to list if desired.',  
                 plse => 'Please select a word or group of words from document and then click this link.',  
                 adds => 'Add selection to keyword list? Edit if desired.',  
                 col1 => 'red',  
                 col2 => 'green',  
                 col3 => 'blue',  
                 siz1 => 'normal',  
                 siz2 => '+1',  
                 siz3 => '+2',  
                 sty1 => 'normal',  
                 sty2 => 'italic',  
                 sty3 => 'bold',  
              );  
     my %html_js_lt = &Apache::lonlocal::texthash(  
                 save => 'Save',  
                 canc => 'Cancel',  
                 kehi => 'Keyword Highlight Options',  
                 txtc => 'Text Color',  
                 font => 'Font Size',  
                 fnst => 'Font Style',  
              );  
     &js_escape(\%js_lt);  
     &html_escape(\%html_js_lt);  
     &js_escape(\%html_js_lt);  
     $request->print(&Apache::lonhtmlcommon::scripttag(<<SUBJAVASCRIPT));  
   
 //===================== Show list of keywords ====================  
   function keywords(formname) {  
     var nret = prompt("$js_lt{'keyw'}",formname.keywords.value);  
     if (nret==null) return;  
     formname.keywords.value = nret;  
   
     if (formname.keywords.value != "") {  
         formname.refresh.value = "on";  
         formname.submit();  
     }  
     return;  
   }  
   
 //===================== Script to add keyword(s) ==================  
   function getSel() {  
     if (document.getSelection) txt = document.getSelection();  
     else if (document.selection) txt = document.selection.createRange().text;  
     else return;  
     if (typeof(txt) != 'string') {  
         txt = String(txt);  
     }  
     var cleantxt = txt.replace(new RegExp('([\\f\\n\\r\\t\\v ])+', 'g')," ");  
     if (cleantxt=="") {  
         alert("$js_lt{'plse'}");  
         return;  
     }  
     var nret = prompt("$js_lt{'adds'}",cleantxt);  
     if (nret==null) return;  
     document.SCORE.keywords.value = document.SCORE.keywords.value+" "+nret;  
     if (document.SCORE.keywords.value != "") {  
         document.SCORE.refresh.value = "on";  
         document.SCORE.submit();  
     }  
     return;  
   }  
   
 //====================== Script for keyword highlight options ==============  //====================== Script for keyword highlight options ==============
   function kwhighlight() {    function kwhighlight() {
     var kwclr    = document.SCORE.kwclr.value;      var kwclr    = document.SCORE.kwclr.value;
Line 1862  INNERJS Line 1594  INNERJS
     var redsel = "";      var redsel = "";
     var grnsel = "";      var grnsel = "";
     var blusel = "";      var blusel = "";
     var txtcol1 = "$js_lt{'col1'}";      if (kwclr=="red")   {var redsel="checked"};
     var txtcol2 = "$js_lt{'col2'}";      if (kwclr=="green") {var grnsel="checked"};
     var txtcol3 = "$js_lt{'col3'}";      if (kwclr=="blue")  {var blusel="checked"};
     var txtsiz1 = "$js_lt{'siz1'}";  
     var txtsiz2 = "$js_lt{'siz2'}";  
     var txtsiz3 = "$js_lt{'siz3'}";  
     var txtsty1 = "$js_lt{'sty1'}";  
     var txtsty2 = "$js_lt{'sty2'}";  
     var txtsty3 = "$js_lt{'sty3'}";  
     if (kwclr=="red")   {var redsel="checked='checked'"};  
     if (kwclr=="green") {var grnsel="checked='checked'"};  
     if (kwclr=="blue")  {var blusel="checked='checked'"};  
     var sznsel = "";      var sznsel = "";
     var sz1sel = "";      var sz1sel = "";
     var sz2sel = "";      var sz2sel = "";
     if (kwsize=="0")  {var sznsel="checked='checked'"};      if (kwsize=="0")  {var sznsel="checked"};
     if (kwsize=="+1") {var sz1sel="checked='checked'"};      if (kwsize=="+1") {var sz1sel="checked"};
     if (kwsize=="+2") {var sz2sel="checked='checked'"};      if (kwsize=="+2") {var sz2sel="checked"};
     var synsel = "";      var synsel = "";
     var syisel = "";      var syisel = "";
     var sybsel = "";      var sybsel = "";
     if (kwstyle=="")    {var synsel="checked='checked'"};      if (kwstyle=="")    {var synsel="checked"};
     if (kwstyle=="<i>") {var syisel="checked='checked'"};      if (kwstyle=="<i>") {var syisel="checked"};
     if (kwstyle=="<b>") {var sybsel="checked='checked'"};      if (kwstyle=="<b>") {var sybsel="checked"};
     highlightCentral();      highlightCentral();
     highlightbody('red',txtcol1,redsel,'0',txtsiz1,sznsel,'',txtsty1,synsel);      highlightbody('red','red',redsel,'0','normal',sznsel,'','normal',synsel);
     highlightbody('green',txtcol2,grnsel,'+1',txtsiz2,sz1sel,'<i>',txtsty2,syisel);      highlightbody('green','green',grnsel,'+1','+1',sz1sel,'<i>','italic',syisel);
     highlightbody('blue',txtcol3,blusel,'+2',txtsiz3,sz2sel,'<b>',txtsty3,sybsel);      highlightbody('blue','blue',blusel,'+2','+2',sz2sel,'<b>','bold',sybsel);
     highlightend();      highlightend();
     return;      return;
   }    }
Line 1907  INNERJS Line 1630  INNERJS
     hDoc.$docopen;      hDoc.$docopen;
     hDoc.write('$start_page_highlight_central');      hDoc.write('$start_page_highlight_central');
     hDoc.write("<form action=\\"inactive\\" name=\\"hlCenter\\">");      hDoc.write("<form action=\\"inactive\\" name=\\"hlCenter\\">");
     hDoc.write("<h1>$html_js_lt{'kehi'}<\\/h1>");      hDoc.write("<h3><span class=\\"LC_info\\">&nbsp;$lt{'kehi'}<\\/span><\\/h3><br /><br />");
   
     hDoc.write('<table border="0" width="100%"><tr style="background-color:#A1D676">');      hDoc.write('<table border="0" width="100%"><tr><td bgcolor="#777777">');
     hDoc.write("<th>$html_js_lt{'txtc'}<\\/th><th>$html_js_lt{'font'}<\\/th><th>$html_js_lt{'fnst'}<\\/th><\\/tr>");      hDoc.write('<table border="0" width="100%"><tr bgcolor="#DDFFFF">');
       hDoc.write("<td><b>$lt{'txtc'}<\\/b><\\/td><td><b>$lt{'font'}<\\/b><\\/td><td><b>$lt{'fnst'}<\\/td><\\/tr>");
   }    }
   
   function highlightbody(clrval,clrtxt,clrsel,szval,sztxt,szsel,syval,sytxt,sysel) {     function highlightbody(clrval,clrtxt,clrsel,szval,sztxt,szsel,syval,sytxt,sysel) { 
     var hDoc = hwdWin.document;      var hDoc = hwdWin.document;
     hDoc.write("<tr>");      hDoc.write("<tr bgcolor=\\"#ffffdd\\">");
     hDoc.write("<td align=\\"left\\">");      hDoc.write("<td align=\\"left\\">");
     hDoc.write("<input name=\\"kwdclr\\" type=\\"radio\\" value=\\""+clrval+"\\" "+clrsel+" \\/>&nbsp;"+clrtxt+"<\\/td>");      hDoc.write("<input name=\\"kwdclr\\" type=\\"radio\\" value=\\""+clrval+"\\" "+clrsel+">&nbsp;"+clrtxt+"<\\/td>");
     hDoc.write("<td align=\\"left\\">");      hDoc.write("<td align=\\"left\\">");
     hDoc.write("<input name=\\"kwdsize\\" type=\\"radio\\" value=\\""+szval+"\\" "+szsel+" \\/>&nbsp;"+sztxt+"<\\/td>");      hDoc.write("<input name=\\"kwdsize\\" type=\\"radio\\" value=\\""+szval+"\\" "+szsel+">&nbsp;"+sztxt+"<\\/td>");
     hDoc.write("<td align=\\"left\\">");      hDoc.write("<td align=\\"left\\">");
     hDoc.write("<input name=\\"kwdstyle\\" type=\\"radio\\" value=\\""+syval+"\\" "+sysel+" \\/>&nbsp;"+sytxt+"<\\/td>");      hDoc.write("<input name=\\"kwdstyle\\" type=\\"radio\\" value=\\""+syval+"\\" "+sysel+">&nbsp;"+sytxt+"<\\/td>");
     hDoc.write("<\\/tr>");      hDoc.write("<\\/tr>");
   }    }
   
   function highlightend() {     function highlightend() { 
     var hDoc = hwdWin.document;      var hDoc = hwdWin.document;
     hDoc.write("<\\/table><br \\/>");      hDoc.write("<\\/table>");
     hDoc.write("<input type=\\"button\\" value=\\"$html_js_lt{'save'}\\" onclick=\\"javascript:updateChoice(1)\\" \\/>&nbsp;&nbsp;");      hDoc.write("<\\/td><\\/tr><\\/table>&nbsp;");
     hDoc.write("<input type=\\"button\\" value=\\"$html_js_lt{'canc'}\\" onclick=\\"self.close()\\" \\/><br /><br />");      hDoc.write("<input type=\\"button\\" value=\\"$lt{'save'}\\" onclick=\\"javascript:updateChoice(1)\\">&nbsp;&nbsp;");
       hDoc.write("<input type=\\"button\\" value=\\"$lt{'canc'}\\" onclick=\\"self.close()\\"><br /><br />");
     hDoc.write("<\\/form>");      hDoc.write("<\\/form>");
     hDoc.write('$end_page_highlight_central');      hDoc.write('$end_page_highlight_central');
     hDoc.close();      hDoc.close();
Line 2044  sub gradeBox { Line 1769  sub gradeBox {
   
 sub handback_box {  sub handback_box {
     my ($symb,$uname,$udom,$counter,$partid,$record,$res_error_pointer) = @_;      my ($symb,$uname,$udom,$counter,$partid,$record,$res_error_pointer) = @_;
     my ($partlist,$handgrade,$responseType,$numresp,$numessay) = &response_type($symb,$res_error_pointer);      my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error_pointer);
     return unless ($numessay);  
     my (@respids);      my (@respids);
     my @part_response_id = &flatten_responseType($responseType);      my @part_response_id = &flatten_responseType($responseType);
     foreach my $part_response_id (@part_response_id) {      foreach my $part_response_id (@part_response_id) {
Line 2147  sub show_problem { Line 1871  sub show_problem {
 sub files_exist {  sub files_exist {
     my ($r, $symb) = @_;      my ($r, $symb) = @_;
     my @students = &Apache::loncommon::get_env_multiple('form.stuinfo');      my @students = &Apache::loncommon::get_env_multiple('form.stuinfo');
   
     foreach my $student (@students) {      foreach my $student (@students) {
         my ($uname,$udom,$fullname) = split(/:/,$student);          my ($uname,$udom,$fullname) = split(/:/,$student);
         my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},          my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},
Line 2166  sub files_exist { Line 1891  sub files_exist {
 sub download_all_link {  sub download_all_link {
     my ($r,$symb) = @_;      my ($r,$symb) = @_;
     unless (&files_exist($r, $symb)) {      unless (&files_exist($r, $symb)) {
         $r->print(&mt('There are currently no submitted documents.'));         $r->print(&mt('There are currently no submitted documents.'));
         return;         return;
     }      }
   
     my $all_students =       my $all_students = 
  join("\n", &Apache::loncommon::get_env_multiple('form.stuinfo'));   join("\n", &Apache::loncommon::get_env_multiple('form.stuinfo'));
   
Line 2187  sub download_all_link { Line 1913  sub download_all_link {
 sub submit_download_link {  sub submit_download_link {
     my ($request,$symb) = @_;      my ($request,$symb) = @_;
     if (!$symb) { return ''; }      if (!$symb) { return ''; }
     my $res_error;  #FIXME: Figure out which type of problem this is and provide appropriate download
     my ($partlist,$handgrade,$responseType,$numresp,$numessay,$numdropbox) =      &download_all_link($request,$symb);
         &response_type($symb,\$res_error);  
     if ($res_error) {  
         $request->print(&mt('An error occurred retrieving response types'));  
         return;  
     }  
     unless ($numessay) {  
         $request->print(&mt('No essayresponse items found'));  
         return;  
     }  
     my @chosenparts = &Apache::loncommon::get_env_multiple('form.vPart');  
     if (@chosenparts) {  
         $request->print(&showResourceInfo($symb,$partlist,$responseType,  
                                           undef,undef,1));  
     }  
     if ($numessay) {  
         my $submitonly= $env{'form.submitonly'} eq '' ? 'all' : $env{'form.submitonly'};  
         my $getsec    = $env{'form.section'} eq '' ? 'all' : $env{'form.section'};  
         my $getgroup  = $env{'form.group'} eq '' ? 'all' : $env{'form.group'};  
         (undef,undef,my $fullname) = &getclasslist($getsec,1,$getgroup,$symb,$submitonly,1);  
         if (ref($fullname) eq 'HASH') {  
             my @students = map { $_.':'.$fullname->{$_} } (keys(%{$fullname}));  
             if (@students) {  
                 @{$env{'form.stuinfo'}} = @students;  
                 if ($numdropbox) {  
                     &download_all_link($request,$symb);  
                 } else {  
                     $request->print(&mt('No essayrespose items with dropbox found'));  
                 }  
 # FIXME Need a mechanism to download essays, i.e., if $numessay > $numdropbox  
 # Needs to omit user's identity if resource instance is for an anonymous survey.  
             } else {  
                 $request->print(&mt('No students match the criteria you selected'));  
             }  
         } else {  
             $request->print(&mt('Could not retrieve student information'));  
         }  
     } else {  
         $request->print(&mt('No essayresponse items found'));  
     }  
     return;  
 }  }
   
 sub build_section_inputs {  sub build_section_inputs {
Line 2246  sub build_section_inputs { Line 1932  sub build_section_inputs {
   
 # --------------------------- show submissions of a student, option to grade   # --------------------------- show submissions of a student, option to grade 
 sub submission {  sub submission {
     my ($request,$counter,$total,$symb,$divforres,$calledby) = @_;      my ($request,$counter,$total,$symb) = @_;
     my ($uname,$udom)     = ($env{'form.student'},$env{'form.userdom'});      my ($uname,$udom)     = ($env{'form.student'},$env{'form.userdom'});
     $udom = ($udom eq '' ? $env{'user.domain'} : $udom); #has form.userdom changed for a student?      $udom = ($udom eq '' ? $env{'user.domain'} : $udom); #has form.userdom changed for a student?
     my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'});      my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'});
     $env{'form.fullname'} = &Apache::loncommon::plainname($uname,$udom,'lastname') if $env{'form.fullname'} eq '';      $env{'form.fullname'} = &Apache::loncommon::plainname($uname,$udom,'lastname') if $env{'form.fullname'} eq '';
   
       my $probtitle=&Apache::lonnet::gettitle($symb); 
     if ($symb eq '') { $request->print("Unable to handle ambiguous references:."); return ''; }      if ($symb eq '') { $request->print("Unable to handle ambiguous references:."); return ''; }
     my $probtitle=&Apache::lonnet::gettitle($symb);  
     my ($essayurl,%coursedesc_by_cid);  
   
     if (!&canview($usec)) {      if (!&canview($usec)) {
         $request->print(   $request->print('<span class="LC_warning">Unable to view requested student.('.
             '<span class="LC_warning">'.   $uname.':'.$udom.' in section '.$usec.' in course id '.
             &mt('Unable to view requested student.').   $env{'request.course.id'}.')</span>');
             ' '.&mt('([_1] in section [_2] in course id [_3])',  
                         $uname.':'.$udom,$usec,$env{'request.course.id'}).  
             '</span>');  
  return;   return;
     }      }
   
     my $res_error;  
     my ($partlist,$handgrade,$responseType,$numresp,$numessay) =  
         &response_type($symb,\$res_error);  
     if ($res_error) {  
         $request->print(&navmap_errormsg());  
         return;  
     }  
   
     if (!$env{'form.lastSub'}) { $env{'form.lastSub'} = 'datesub'; }      if (!$env{'form.lastSub'}) { $env{'form.lastSub'} = 'datesub'; }
     if (!$env{'form.vProb'}) { $env{'form.vProb'} = 'yes'; }      if (!$env{'form.vProb'}) { $env{'form.vProb'} = 'yes'; }
     if (!$env{'form.vAns'}) { $env{'form.vAns'} = 'yes'; }      if (!$env{'form.vAns'}) { $env{'form.vAns'} = 'yes'; }
     if (($numessay) && ($calledby eq 'submission') && (!exists($env{'form.compmsg'}))) {  
         $env{'form.compmsg'} = 1;  
     }  
     my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : '');      my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : '');
     my $checkIcon = '<img alt="'.&mt('Check Mark').      my $checkIcon = '<img alt="'.&mt('Check Mark').
  '" src="'.$request->dir_config('lonIconsURL').   '" src="'.$request->dir_config('lonIconsURL').
Line 2287  sub submission { Line 1958  sub submission {
   
     # header info      # header info
     if ($counter == 0) {      if ($counter == 0) {
         my @chosenparts = &Apache::loncommon::get_env_multiple('form.vPart');  
         if (@chosenparts) {  
             $request->print(&showResourceInfo($symb,$partlist,$responseType,'gradesub'));  
         } elsif ($divforres) {  
             $request->print('<div style="padding:0;clear:both;margin:0;border:0"></div>');  
         } else {  
             $request->print('<br clear="all" />');  
         }  
  &sub_page_js($request);   &sub_page_js($request);
         &sub_grademessage_js($request) if ($env{'form.compmsg'});   &sub_page_kw_js($request);
  &sub_page_kw_js($request) if ($numessay);  
   
  # option to display problem, only once else it cause problems    # option to display problem, only once else it cause problems 
         # with the form later since the problem has a form.          # with the form later since the problem has a form.
Line 2314  sub submission { Line 1976  sub submission {
     $request->print(&show_problem($request,$symb,$uname,$udom,0,1,$mode));      $request->print(&show_problem($request,$symb,$uname,$udom,0,1,$mode));
  }   }
   
    # kwclr is the only variable that is guaranteed not to be blank 
           # if this subroutine has been called once.
  my %keyhash = ();   my %keyhash = ();
  if (($env{'form.kwclr'} eq '' && $numessay) || ($env{'form.compmsg'})) {  # if ($env{'form.kwclr'} eq '' && $env{'form.handgrade'} eq 'yes') {
           if (1) {
     %keyhash = &Apache::lonnet::dump('nohist_handgrade',      %keyhash = &Apache::lonnet::dump('nohist_handgrade',
      $env{'course.'.$env{'request.course.id'}.'.domain'},       $env{'course.'.$env{'request.course.id'}.'.domain'},
      $env{'course.'.$env{'request.course.id'}.'.num'});       $env{'course.'.$env{'request.course.id'}.'.num'});
  }  
  # kwclr is the only variable that is guaranteed not to be blank  
  # if this subroutine has been called once.  
  if ($env{'form.kwclr'} eq '' && $numessay) {  
     my $loginuser = $env{'user.name'}.':'.$env{'user.domain'};      my $loginuser = $env{'user.name'}.':'.$env{'user.domain'};
     $env{'form.keywords'} = $keyhash{$symb.'_keywords'} ne '' ? $keyhash{$symb.'_keywords'} : '';      $env{'form.keywords'} = $keyhash{$symb.'_keywords'} ne '' ? $keyhash{$symb.'_keywords'} : '';
     $env{'form.kwclr'}    = $keyhash{$loginuser.'_kwclr'} ne '' ? $keyhash{$loginuser.'_kwclr'} : 'red';      $env{'form.kwclr'}    = $keyhash{$loginuser.'_kwclr'} ne '' ? $keyhash{$loginuser.'_kwclr'} : 'red';
     $env{'form.kwsize'}   = $keyhash{$loginuser.'_kwsize'} ne '' ? $keyhash{$loginuser.'_kwsize'} : '0';      $env{'form.kwsize'}   = $keyhash{$loginuser.'_kwsize'} ne '' ? $keyhash{$loginuser.'_kwsize'} : '0';
     $env{'form.kwstyle'}  = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : '';      $env{'form.kwstyle'}  = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : '';
  }      $env{'form.msgsub'}   = $keyhash{$symb.'_subject'} ne '' ? 
  if ($env{'form.compmsg'}) {  
     $env{'form.msgsub'}   = $keyhash{$symb.'_subject'} ne '' ?  
  $keyhash{$symb.'_subject'} : $probtitle;   $keyhash{$symb.'_subject'} : $probtitle;
     $env{'form.savemsgN'} = $keyhash{$symb.'_savemsgN'} ne '' ? $keyhash{$symb.'_savemsgN'} : '0';      $env{'form.savemsgN'} = $keyhash{$symb.'_savemsgN'} ne '' ? $keyhash{$symb.'_savemsgN'} : '0';
  }   }
   
  my $overRideScore = $env{'form.overRideScore'} eq '' ? 'no' : $env{'form.overRideScore'};   my $overRideScore = $env{'form.overRideScore'} eq '' ? 'no' : $env{'form.overRideScore'};
  my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));   my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));
  $request->print('<form action="/adm/grades" method="post" name="SCORE" enctype="multipart/form-data">'."\n".   $request->print('<form action="/adm/grades" method="post" name="SCORE" enctype="multipart/form-data">'."\n".
Line 2348  sub submission { Line 2007  sub submission {
  '<input type="hidden" name="vProb"      value="'.$env{'form.vProb'}.'" />'."\n".   '<input type="hidden" name="vProb"      value="'.$env{'form.vProb'}.'" />'."\n".
  '<input type="hidden" name="vAns"       value="'.$env{'form.vAns'}.'" />'."\n".   '<input type="hidden" name="vAns"       value="'.$env{'form.vAns'}.'" />'."\n".
  '<input type="hidden" name="lastSub"    value="'.$env{'form.lastSub'}.'" />'."\n".   '<input type="hidden" name="lastSub"    value="'.$env{'form.lastSub'}.'" />'."\n".
  '<input type="hidden" name="compmsg"    value="'.$env{'form.compmsg'}.'" />'."\n".  
  &build_section_inputs().   &build_section_inputs().
  '<input type="hidden" name="submitonly" value="'.$env{'form.submitonly'}.'" />'."\n".   '<input type="hidden" name="submitonly" value="'.$env{'form.submitonly'}.'" />'."\n".
  '<input type="hidden" name="NCT"'.   '<input type="hidden" name="NCT"'.
  ' value="'.($env{'form.NTSTU'} ne '' ? $env{'form.NTSTU'} : $total+1).'" />'."\n");   ' value="'.($env{'form.NTSTU'} ne '' ? $env{'form.NTSTU'} : $total+1).'" />'."\n");
  if ($env{'form.compmsg'}) {  # if ($env{'form.handgrade'} eq 'yes') {
     $request->print('<input type="hidden" name="msgsub"   value="'.$env{'form.msgsub'}.'" />'."\n".          if (1) {
     '<input type="hidden" name="shownSub" value="0" />'."\n".  
     '<input type="hidden" name="savemsgN" value="'.$env{'form.savemsgN'}.'" />'."\n");  
  }  
  if ($numessay) {  
     $request->print('<input type="hidden" name="keywords" value="'.$env{'form.keywords'}.'" />'."\n".      $request->print('<input type="hidden" name="keywords" value="'.$env{'form.keywords'}.'" />'."\n".
     '<input type="hidden" name="kwclr"    value="'.$env{'form.kwclr'}.'" />'."\n".      '<input type="hidden" name="kwclr"    value="'.$env{'form.kwclr'}.'" />'."\n".
     '<input type="hidden" name="kwsize"   value="'.$env{'form.kwsize'}.'" />'."\n".      '<input type="hidden" name="kwsize"   value="'.$env{'form.kwsize'}.'" />'."\n".
     '<input type="hidden" name="kwstyle"  value="'.$env{'form.kwstyle'}.'" />'."\n");      '<input type="hidden" name="kwstyle"  value="'.$env{'form.kwstyle'}.'" />'."\n".
       '<input type="hidden" name="msgsub"   value="'.$env{'form.msgsub'}.'" />'."\n".
       '<input type="hidden" name="shownSub" value="0" />'."\n".
       '<input type="hidden" name="savemsgN" value="'.$env{'form.savemsgN'}.'" />'."\n");
       foreach my $partid (&Apache::loncommon::get_env_multiple('form.vPart')) {
    $request->print('<input type="hidden" name="vPart" value="'.$partid.'" />'."\n");
       }
  }   }
   
  my ($cts,$prnmsg) = (1,'');   my ($cts,$prnmsg) = (1,'');
  while ($cts <= $env{'form.savemsgN'}) {   while ($cts <= $env{'form.savemsgN'}) {
     $prnmsg.='<input type="hidden" name="savemsg'.$cts.'" value="'.      $prnmsg.='<input type="hidden" name="savemsg'.$cts.'" value="'.
Line 2377  sub submission { Line 2037  sub submission {
  }   }
  $request->print($prnmsg);   $request->print($prnmsg);
   
  if ($numessay) {  # if ($env{'form.handgrade'} eq 'yes') {
           if (1) {
   
             my %lt = &Apache::lonlocal::texthash(              my %lt = &Apache::lonlocal::texthash(
                           keyh => 'Keyword Highlighting for Essays',  
                           keyw => 'Keyword Options',                            keyw => 'Keyword Options',
                           list => 'List',                            list => 'List',
                           past => 'Paste Selection to List',                            past => 'Paste Selection to List',
                           high => 'Highlight Attribute',                            high => 'Highlight Attribute',
                      );                       );    
 #  #
 # Print out the keyword options line  # Print out the keyword options line
 #  #
     $request->print(      $request->print(<<KEYWORDS);
                 '<div class="LC_columnSection">'  <br /><b>$lt{'keyw'}:</b>&nbsp;
                .'<fieldset><legend>'.$lt{'keyh'}.'</legend>'  <a href="javascript:keywords(document.SCORE);" target="_self">$lt{'list'}</a>&nbsp; &nbsp;
                .&Apache::lonhtmlcommon::funclist_from_array(  <a href="#" onmousedown="javascript:getSel(); return false"
                     ['<a href="javascript:keywords(document.SCORE);" target="_self">'.$lt{'list'}.'</a>',   class="page">$lt{'past'}</a>&nbsp; &nbsp;
                      '<a href="#" onmousedown="javascript:getSel(); return false"  <a href="javascript:kwhighlight();" target="_self">$lt{'high'}</a><br /><br />
  class="page">'.$lt{'past'}.'</a>',  KEYWORDS
                      '<a href="javascript:kwhighlight();" target="_self">'.$lt{'high'}.'</a>'],  
                     {legend => $lt{'keyw'}})  
                .'</fieldset></div>'  
             );  
   
 #  #
 # Load the other essays for similarity check  # Load the other essays for similarity check
 #  #
             (undef,undef,$essayurl) = &Apache::lonnet::decode_symb($symb);              my (undef,undef,$essayurl) = &Apache::lonnet::decode_symb($symb);
             if ($essayurl eq 'lib/templates/simpleproblem.problem') {      my ($adom,$aname,$apath)=($essayurl=~/^($LONCAPA::domain_re)\/($LONCAPA::username_re)\/(.*)$/);
                 my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};      $apath=&escape($apath);
                 my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};      $apath=~s/\W/\_/gs;
                 if ($cdom ne '' && $cnum ne '') {              &init_old_essays($symb,$apath,$adom,$aname);
                     my ($map,$id,$res) = &Apache::lonnet::decode_symb($symb);  
                     if ($map =~ m{^\Quploaded/$cdom/$cnum/\E(default(?:|_\d+)\.(?:sequence|page))$}) {  
                         my $apath = $1.'_'.$id;  
                         $apath=~s/\W/\_/gs;  
                         &init_old_essays($symb,$apath,$cdom,$cnum);  
                     }  
                 }  
             } else {  
         my ($adom,$aname,$apath)=($essayurl=~/^($LONCAPA::domain_re)\/($LONCAPA::username_re)\/(.*)$/);  
         $apath=&escape($apath);  
         $apath=~s/\W/\_/gs;  
                 &init_old_essays($symb,$apath,$adom,$aname);  
             }  
         }          }
     }      }
   
Line 2438  sub submission { Line 2080  sub submission {
     if ($perm{'vgr'}) {      if ($perm{'vgr'}) {
         $request->print(          $request->print(
             &Apache::loncommon::track_student_link(              &Apache::loncommon::track_student_link(
                 'View recent activity',                  &mt('View recent activity'),
                 $uname,$udom,'check')                  $uname,$udom,'check')
            .' '             .' '
         );          );
Line 2465  sub submission { Line 2107  sub submission {
     }      }
   
     my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname);      my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname);
       my $res_error;
       my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error);
       if ($res_error) {
           $request->print(&navmap_errormsg());
           return;
       }
   
     # Display student info      # Display student info
     $request->print(($counter == 0 ? '' : '<br />'));      $request->print(($counter == 0 ? '' : '<br />'));
Line 2473  sub submission { Line 2121  sub submission {
               .'<h3 class="LC_hcell">'.&mt('Submissions').'</h3>';                .'<h3 class="LC_hcell">'.&mt('Submissions').'</h3>';
     $result.='<input type="hidden" name="name'.$counter.      $result.='<input type="hidden" name="name'.$counter.
              '" value="'.$env{'form.fullname'}.'" />'."\n";               '" value="'.$env{'form.fullname'}.'" />'."\n";
     if ($numresp > $numessay) {  #    if ($env{'form.handgrade'} eq 'no') {
       if (1) {
         $result.='<p class="LC_info">'          $result.='<p class="LC_info">'
                 .&mt('Part(s) graded correct by the computer is marked with a [_1] symbol.',$checkIcon)                  .&mt('Part(s) graded correct by the computer is marked with a [_1] symbol.',$checkIcon)
                 ."</p>\n";                  ."</p>\n";
     }      }
   
     # If any part of the problem is an essayresponse, then check for collaborators      # If any part of the problem is an essay-response (handgraded), then check for collaborators
     my $fullname;      my $fullname;
     my $col_fullnames = [];      my $col_fullnames = [];
     if ($numessay) {  #    if ($env{'form.handgrade'} eq 'yes') {
       if (1) {
  (my $sub_result,$fullname,$col_fullnames)=   (my $sub_result,$fullname,$col_fullnames)=
     &check_collaborators($symb,$uname,$udom,\%record,$handgrade,      &check_collaborators($symb,$uname,$udom,\%record,$handgrade,
  $counter);   $counter);
  $result.=$sub_result;   $result.=$sub_result;
     }      }
     $request->print($result."\n");      $request->print($result."\n");
       
     # print student answer/submission      # print student answer/submission
     # Options are (1) Last submission only      # Options are (1) Handgraded submission only
     #             (2) Last submission (with detailed information for that submission)      #             (2) Last submission, includes submission that is not handgraded 
     #             (3) All transactions (by date)      #                  (for multi-response type part)
     #             (4) The whole record (with detailed information for all transactions)      #             (3) Last submission plus the parts info
       #             (4) The whole record for this student
       
     my ($string,$timestamp)= &get_last_submission(\%record);      my ($string,$timestamp)= &get_last_submission(\%record);
   
     my $lastsubonly;      my $lastsubonly;
   
     if ($$timestamp eq '') {      if ($$timestamp eq '') {
Line 2510  sub submission { Line 2161  sub submission {
  my %seenparts;   my %seenparts;
  my @part_response_id = &flatten_responseType($responseType);   my @part_response_id = &flatten_responseType($responseType);
  foreach my $part (@part_response_id) {   foreach my $part (@part_response_id) {
       next if ($env{'form.lastSub'} eq 'hdgrade' 
    && $$handgrade{$$part[0].'_'.$$part[1]} ne 'yes');
   
     my ($partid,$respid) = @{ $part };      my ($partid,$respid) = @{ $part };
     my $display_part=&get_display_part($partid,$symb);      my $display_part=&get_display_part($partid,$symb);
     if ($env{"form.$uname:$udom:$partid:submitted_by"}) {      if ($env{"form.$uname:$udom:$partid:submitted_by"}) {
Line 2524  sub submission { Line 2178  sub submission {
                                $$fullname{$env{"form.$uname:$udom:$partid:submitted_by"}}.'</a>').                                 $$fullname{$env{"form.$uname:$udom:$partid:submitted_by"}}.'</a>').
                     '<br />');                      '<br />');
  next;   next;
     }   }
     my $responsetype = $responseType->{$partid}->{$respid};      my $responsetype = $responseType->{$partid}->{$respid};
     if (!exists($record{"resource.$partid.$respid.submission"})) {      if (!exists($record{"resource.$partid.$respid.submission"})) {
                 $lastsubonly.="\n".'<div class="LC_grade_submission_part">'.                  $lastsubonly.="\n".'<div class="LC_grade_submission_part">'.
Line 2532  sub submission { Line 2186  sub submission {
                     ' <span class="LC_internal_info">'.                      ' <span class="LC_internal_info">'.
                     '('.&mt('Response ID: [_1]',$respid).')'.                      '('.&mt('Response ID: [_1]',$respid).')'.
                     '</span>&nbsp; &nbsp;'.                      '</span>&nbsp; &nbsp;'.
             '<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br /><br /></div>';            '<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br /><br /></div>';
  next;   next;
     }      }
     foreach my $submission (@$string) {      foreach my $submission (@$string) {
  my ($partid,$respid) = ($submission =~ /^resource\.([^\.]*)\.([^\.]*)\.submission/);   my ($partid,$respid) = ($submission =~ /^resource\.([^\.]*)\.([^\.]*)\.submission/);
  if (join('_',@{$part}) ne ($partid.'_'.$respid)) { next; }   if (join('_',@{$part}) ne ($partid.'_'.$respid)) { next; }
  my ($ressub,$hide,$draft,$subval) = split(/:/,$submission,4);   my ($ressub,$hide,$subval) = split(/:/,$submission,3);
  # Similarity check   # Similarity check
                 my $similar='';                  my $similar='';
                 my ($type,$trial,$rndseed);                  my ($type,$trial,$rndseed);
Line 2547  sub submission { Line 2201  sub submission {
                     $trial = $record{"resource.$partid.tries"};                      $trial = $record{"resource.$partid.tries"};
                     $rndseed = $record{"resource.$partid.rndseed"};                      $rndseed = $record{"resource.$partid.rndseed"};
                 }                  }
  if ($env{'form.checkPlag'}) {          if ($env{'form.checkPlag'}) {
     my ($oname,$odom,$ocrsid,$oessay,$osim)=         my ($oname,$odom,$ocrsid,$oessay,$osim)=
         &most_similar($uname,$udom,$symb,$subval);          &most_similar($uname,$udom,$symb,$subval);
     if ($osim) {      if ($osim) {
         $osim=int($osim*100.0);   $osim=int($osim*100.0);
    my %old_course_desc = 
       &Apache::lonnet::coursedescription($ocrsid,
    {'one_time' => 1});
   
                         if ($hide eq 'anon') {                          if ($hide eq 'anon') {
                             $similar='<hr /><span class="LC_warning">'.&mt("Essay was found to be similar to another essay submitted for this assignment.").'<br />'.                              $similar='<hr /><span class="LC_warning">'.&mt("Essay was found to be similar to another essay submitted for this assignment.").'<br />'.
                                      &mt('As the current submission is for an anonymous survey, no other details are available.').'</span><hr />';                                       &mt('As the current submission is for an anonymous survey, no other details are available.').'</span><hr />';
                         } else {                          } else {
     $similar='<hr />';      $similar="<hr /><h3><span class=\"LC_warning\">".
                             if ($essayurl eq 'lib/templates/simpleproblem.problem') {   &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',
                                 $similar .= '<h3><span class="LC_warning">'.      $osim,
                                             &mt('Essay is [_1]% similar to an essay by [_2]',      &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',
                                                 $osim,  
                                                 &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').  
                                             '</span></h3>';  
                             } elsif ($ocrsid ne '') {  
                                 my %old_course_desc;  
                                 if (ref($coursedesc_by_cid{$ocrsid}) eq 'HASH') {  
                                     %old_course_desc = %{$coursedesc_by_cid{$ocrsid}};  
                                 } else {  
                                     my $args;  
                                     if ($ocrsid ne $env{'request.course.id'}) {  
                                         $args = {'one_time' => 1};  
                                     }  
                                     %old_course_desc =  
                                         &Apache::lonnet::coursedescription($ocrsid,$args);  
                                     $coursedesc_by_cid{$ocrsid} = \%old_course_desc;  
                                 }  
                                 $similar .=  
                                     '<h3><span class="LC_warning">'.  
     &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',  
         $osim,  
         &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',  
         $old_course_desc{'description'},          $old_course_desc{'description'},
         $old_course_desc{'num'},          $old_course_desc{'num'},
         $old_course_desc{'domain'}).          $old_course_desc{'domain'}).
     '</span></h3>';      '</span></h3><blockquote><i>'.
                             } else {      &keywords_highlight($oessay).
                                 $similar .=      '</i></blockquote><hr />';
                                     '<h3><span class="LC_warning">'.                          }
                                     &mt('Essay is [_1]% similar to an essay by [_2] in an unknown course',              }
                                         $osim,   }
                                         &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').  
                                     '</span></h3>';  
                             }  
                             $similar .= '<blockquote><i>'.  
                                         &keywords_highlight($oessay).  
                                         '</i></blockquote><hr />';  
         }  
                     }  
                 }  
  my $order=&get_order($partid,$respid,$symb,$uname,$udom,   my $order=&get_order($partid,$respid,$symb,$uname,$udom,
                                      undef,$type,$trial,$rndseed);                                       undef,$type,$trial,$rndseed);
                 if (($env{'form.lastSub'} eq 'lastonly') ||                  if ($env{'form.lastSub'} eq 'lastonly' || $env{'form.lastSub'} eq 'datesub' || $env{'form.lastSub'} =~ /^(last|all)$/ || ($env{'form.lastSub'} eq 'hdgrade' && 
                     ($env{'form.lastSub'} eq 'datesub')  ||   $$handgrade{$$part[0].'_'.$$part[1]} eq 'yes')) {
                     ($env{'form.lastSub'} =~ /^(last|all)$/)) {  
     my $display_part=&get_display_part($partid,$symb);      my $display_part=&get_display_part($partid,$symb);
                     $lastsubonly.='<div class="LC_grade_submission_part">'.                      $lastsubonly.='<div class="LC_grade_submission_part">'.
                         '<b>'.&mt('Part: [_1]',$display_part).'</b>'.                          '<b>'.&mt('Part: [_1]',$display_part).'</b>'.
Line 2611  sub submission { Line 2238  sub submission {
                         '('.&mt('Response ID: [_1]',$respid).')'.                          '('.&mt('Response ID: [_1]',$respid).')'.
                         '</span>&nbsp; &nbsp;';                          '</span>&nbsp; &nbsp;';
     my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record);      my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record);
                           
     if (@$files) {      if (@$files) {
                         if ($hide eq 'anon') {                          if ($hide eq 'anon') {
                             $lastsubonly.='<br />'.&mt('[quant,_1,file] uploaded to this anonymous survey',scalar(@{$files}));                              $lastsubonly.='<br />'.&mt('[quant,_1,file] uploaded to this anonymous survey',scalar(@{$files}));
                         } else {                          } else {
                             $lastsubonly.='<br /><br />'.'<b>'.&mt('Submitted Files:').'</b>'                              $lastsubonly.='<br /><br />'.'<b>'.&mt('Submitted Files:').'</b>'
                                          .'<br /><span class="LC_warning">';                                          .'<br /><span class="LC_warning">';
                             if(@$files == 1) {                              if(@$files == 1) {
                                 $lastsubonly .= &mt('Like all files provided by users, this file may contain viruses!');                                  $lastsubonly .= &mt('Like all files provided by users, this file may contain viruses!');
                             } else {                              } else {
                                 $lastsubonly .= &mt('Like all files provided by users, these files may contain viruses!');                                  $lastsubonly .= &mt('Like all files provided by users, these files may contain viruses!');
                             }                              }
                             $lastsubonly .= '</span>';                              $lastsubonly .= '</span>';                         
                             foreach my $file (@$files) {                              foreach my $file (@$files) {
                                 &Apache::lonnet::allowuploaded('/adm/grades',$file);                                  &Apache::lonnet::allowuploaded('/adm/grades',$file);
                                 $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0" alt="" /> '.$file.'</a>';                                  $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0" alt="" /> '.$file.'</a>';
                             }                              }
                         }                          }
  $lastsubonly.='<br />';   $lastsubonly.='<br />';
     }                      }
                     if ($hide eq 'anon') {                      if ($hide eq 'anon') {
                         $lastsubonly.='<br /><b>'.&mt('Anonymous Survey').'</b>';                           $lastsubonly.='<br /><b>'.&mt('Anonymous Survey').'</b>'; 
                     } else {                      } else {
                         $lastsubonly.='<br /><b>'.&mt('Submitted Answer:').' </b>';                       $lastsubonly.='<br /><b>'.&mt('Submitted Answer:').' </b>'.
                         if ($draft) {  
                             $lastsubonly.= ' <span class="LC_warning">'.&mt('Draft Copy').'</span>';  
                         }  
                         $subval =  
     &cleanRecord($subval,$responsetype,$symb,$partid,      &cleanRecord($subval,$responsetype,$symb,$partid,
  $respid,\%record,$order,undef,$uname,$udom,$type,$trial,$rndseed);   $respid,\%record,$order,undef,$uname,$udom,$type,$trial,$rndseed);
                         if ($responsetype eq 'essay') {  
                             $subval =~ s{\n}{<br />}g;  
                         }  
                         $lastsubonly.=$subval."\n";  
                     }                      }
                     if ($similar) {$lastsubonly.="<br /><br />$similar\n";}              if ($similar) {$lastsubonly.="<br /><br />$similar\n";}
     $lastsubonly.='</div>';      $lastsubonly.='</div>';
  }   }
     }              }
  }   }
  $lastsubonly.='</div>'."\n"; # End: LC_grade_submissions_body   $lastsubonly.='</div>'."\n"; # End: LC_grade_submissions_body
     }      }
Line 2656  sub submission { Line 2276  sub submission {
     if ($env{'form.lastSub'} eq 'datesub') {      if ($env{'form.lastSub'} eq 'datesub') {
         my ($parts,$handgrade,$responseType) = &response_type($symb,\$res_error);          my ($parts,$handgrade,$responseType) = &response_type($symb,\$res_error);
  $request->print(&displaySubByDates($symb,\%record,$parts,$responseType,$checkIcon,$uname,$udom));   $request->print(&displaySubByDates($symb,\%record,$parts,$responseType,$checkIcon,$uname,$udom));
     }      } 
     if ($env{'form.lastSub'} =~ /^(last|all)$/) {      if ($env{'form.lastSub'} =~ /^(last|all)$/) {
         my $identifier = (&canmodify($usec)? $counter : '');          $request->print(&Apache::loncommon::get_previous_attempt($symb,$uname,$udom,
  $request->print(&Apache::loncommon::get_previous_attempt($symb,$uname,$udom,  
  $env{'request.course.id'},   $env{'request.course.id'},
  $last,'.submission',   $last,'.submission',
  'Apache::grades::keywords_highlight',   'Apache::grades::keywords_highlight'));
                                                                  $usec,$identifier));  
     }      }
     $request->print('<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':'      $request->print('<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':'
  .$udom.'" />'."\n");   .$udom.'" />'."\n");
     # return if view submission with no grading option      # return if view submission with no grading option
     if (!&canmodify($usec)) {      if (!&canmodify($usec)) {
         $request->print('<p><span class="LC_warning">'.&mt('No grading privileges').'</span></p></div>');   $request->print('<p><span class="LC_warning">'.&mt('No grading privileges').'</span></p></div>');
         return;   return;
     } else {      } else {
  $request->print('</div>'."\n");   $request->print('</div>'."\n");
     }      }
   
     # grading message center      # essay grading message center
   #    if ($env{'form.handgrade'} eq 'yes') {
     if ($env{'form.compmsg'}) {      if (1) {
         my $result='<div class="LC_Box">'.   my $result='<div class="LC_grade_message_center">';
                    '<h3 class="LC_hcell">'.&mt('Send Message').'</h3>'.      
                    '<div class="LC_grade_message_center_body">';   $result.='<div class="LC_grade_message_center_header">'.
         my ($lastname,$givenn) = split(/,/,$env{'form.fullname'});      &mt('Send Message').'</div><div class="LC_grade_message_center_body">';
         my $msgfor = $givenn.' '.$lastname;   my ($lastname,$givenn) = split(/,/,$env{'form.fullname'});
         if (scalar(@$col_fullnames) > 0) {   my $msgfor = $givenn.' '.$lastname;
             my $lastone = pop(@$col_fullnames);   if (scalar(@$col_fullnames) > 0) {
             $msgfor .= ', '.(join ', ',@$col_fullnames).' and '.$lastone.'.';      my $lastone = pop(@$col_fullnames);
         }      $msgfor .= ', '.(join ', ',@$col_fullnames).' and '.$lastone.'.';
         $msgfor =~ s/\'/\\'/g; #' stupid emacs - no! javascript   }
         $result.='<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n".   $msgfor =~ s/\'/\\'/g; #' stupid emacs - no! javascript
                  '<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n".   $result.='<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n".
          '&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.      '<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n";
                  ',\''.$msgfor.'\');" target="_self">'.   $result.='&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.
                  &mt('Compose message to student'.(scalar(@$col_fullnames) >= 1 ? 's' : '')).'</a><label> ('.      ',\''.$msgfor.'\');" target="_self">'.
                  &mt('incl. grades').' <input type="checkbox" name="withgrades'.$counter.'" /></label>)'.      &mt('Compose message to student'.(scalar(@$col_fullnames) >= 1 ? 's' : '')).'</a><label> ('.
                  ' <img src="'.$request->dir_config('lonIconsURL').      &mt('incl. grades').' <input type="checkbox" name="withgrades'.$counter.'" /></label>)'.
                  '/mailbkgrd.gif" width="14" height="10" alt="" name="mailicon'.$counter.'" />'."\n".      ' <img src="'.$request->dir_config('lonIconsURL').
                  '<br />&nbsp;('.      '/mailbkgrd.gif" width="14" height="10" alt="" name="mailicon'.$counter.'" />'."\n".
                  &mt('Message will be sent when you click on Save &amp; Next below.').")\n".      '<br />&nbsp;('.
          '</div></div>';      &mt('Message will be sent when you click on Save &amp; Next below.').")\n";
         $request->print($result);   $result.='</div></div>';
    $request->print($result);
     }      }
   
     my %seen = ();      my %seen = ();
Line 2716  sub submission { Line 2335  sub submission {
  my $part_resp = join('_',@{ $part_response_id });   my $part_resp = join('_',@{ $part_response_id });
  next if ($seen{$partid} > 0);   next if ($seen{$partid} > 0);
  $seen{$partid}++;   $seen{$partid}++;
    next if ($$handgrade{$part_resp} ne 'yes' 
    && $env{'form.lastSub'} eq 'hdgrade');
  push(@partlist,$partid);   push(@partlist,$partid);
  push(@gradePartRespid,$partid.'.'.$respid);   push(@gradePartRespid,$partid.'.'.$respid);
  $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record));   $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record));
Line 2879  sub get_last_submission { Line 2500  sub get_last_submission {
             }              }
             unless ($hide) {              unless ($hide) {
                 if (@randomize) {                  if (@randomize) {
                     foreach my $id (@randomize) {                      foreach my $id (@hidden) {
                         if ($key =~ /^\Q$id\E/) {                          if ($key =~ /^\Q$id\E/) {
                             $hide = 'rand';                              $hide = 'rand';
                             last;                              last;
Line 2888  sub get_last_submission { Line 2509  sub get_last_submission {
                 }                  }
             }              }
     my ($partid,$foo) = split(/submission$/,$key);      my ($partid,$foo) = split(/submission$/,$key);
     my $draft  = $lasthash{$partid.'awarddetail'} eq 'DRAFT' ? 1 : 0;      my $draft  = $lasthash{$partid.'awarddetail'} eq 'DRAFT' ?
             push(@string, join(':', $key, $hide, $draft, (   '<span class="LC_warning">Draft Copy</span> ' : '';
                 ref($lasthash{$key}) eq 'ARRAY' ?      push(@string, join(':', $key, $hide, $draft.$lasthash{$key}));
                     join(',', @{$lasthash{$key}}) : $lasthash{$key}) ));  
  }   }
     }      }
     if (!@string) {      if (!@string) {
Line 2919  sub keywords_highlight { Line 2539  sub keywords_highlight {
 sub show_previous_task_version {  sub show_previous_task_version {
     my ($request,$symb) = @_;      my ($request,$symb) = @_;
     if ($symb eq '') {      if ($symb eq '') {
         $request->print(          $request->print("Unable to handle ambiguous references.");
             '<span class="LC_error">'.  
             &mt('Unable to handle ambiguous references.').  
             '</span>');  
         return '';          return '';
     }      }
     my ($uname,$udom) = ($env{'form.student'},$env{'form.userdom'});      my ($uname,$udom) = ($env{'form.student'},$env{'form.userdom'});
     my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'});      my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'});
     if (!&canview($usec)) {      if (!&canview($usec)) {
         $request->print('<span class="LC_warning">'.          $request->print('<span class="LC_warning">Unable to view previous version for requested student.('.
                         &mt('Unable to view previous version for requested student.').                          $uname.':'.$udom.' in section '.$usec.' in course id '.
                         ' '.&mt('([_1] in section [_2] in course id [_3])',                          $env{'request.course.id'}.')</span>');
                                 $uname.':'.$udom,$usec,$env{'request.course.id'}).  
                         '</span>');  
         return;          return;
     }      }
     my $mode = 'both';      my $mode = 'both';
Line 3109  sub processHandGrade { Line 2725  sub processHandGrade {
  my $ctr = 0;   my $ctr = 0;
  while ($ctr < $ngrade) {   while ($ctr < $ngrade) {
     my ($uname,$udom) = split(/:/,$env{'form.unamedom'.$ctr});      my ($uname,$udom) = split(/:/,$env{'form.unamedom'.$ctr});
     my ($errorflag,$pts,$wgt,$numhidden) =       my ($errorflag,$pts,$wgt) = &saveHandGrade($request,$symb,$uname,$udom,$ctr);
                 &saveHandGrade($request,$symb,$uname,$udom,$ctr);  
     if ($errorflag eq 'no_score') {      if ($errorflag eq 'no_score') {
  $ctr++;   $ctr++;
  next;   next;
     }      }
     if ($errorflag eq 'not_allowed') {      if ($errorflag eq 'not_allowed') {
                 $request->print(   $request->print("<span class=\"LC_warning\">Not allowed to modify grades for $uname:$udom</span>");
                     '<span class="LC_error">'  
                    .&mt('Not allowed to modify grades for [_1]',"$uname:$udom")  
                    .'</span>');  
  $ctr++;   $ctr++;
  next;   next;
     }      }
             if ($numhidden) {  
                 $request->print(  
                     '<span class="LC_info">'  
                    .&mt('For [_1]: [quant,_2,transaction] hidden',"$uname:$udom",$numhidden)  
                    .'</span><br />');  
             }  
     my $includemsg = $env{'form.includemsg'.$ctr};      my $includemsg = $env{'form.includemsg'.$ctr};
     my ($subject,$message,$msgstatus) = ('','','');      my ($subject,$message,$msgstatus) = ('','','');
     my $restitle = &Apache::lonnet::gettitle($symb);      my $restitle = &Apache::lonnet::gettitle($symb);
Line 3187  sub processHandGrade { Line 2793  sub processHandGrade {
  }   }
     }      }
   
     my $res_error;  #    if ($env{'form.handgrade'} eq 'yes') {
     my ($partlist,$handgrade,$responseType,$numresp,$numessay) = &response_type($symb,\$res_error);      if (1) {
     if ($res_error) {  
         $request->print(&navmap_errormsg());  
         return;  
     }  
   
     my %keyhash = ();  
     if ($numessay) {  
  # Keywords sorted in alphabatical order   # Keywords sorted in alphabatical order
  my $loginuser = $env{'user.name'}.':'.$env{'user.domain'};   my $loginuser = $env{'user.name'}.':'.$env{'user.domain'};
    my %keyhash = ();
  $env{'form.keywords'}           =~ s/,\s{0,}|\s+/ /g;   $env{'form.keywords'}           =~ s/,\s{0,}|\s+/ /g;
  $env{'form.keywords'}           =~ s/^\s+|\s+$//g;   $env{'form.keywords'}           =~ s/^\s+|\s+$//;
  my (@keywords) = sort(split(/\s+/,$env{'form.keywords'}));   my (@keywords) = sort(split(/\s+/,$env{'form.keywords'}));
  $env{'form.keywords'} = join(' ',@keywords);   $env{'form.keywords'} = join(' ',@keywords);
  $keyhash{$symb.'_keywords'}     = $env{'form.keywords'};   $keyhash{$symb.'_keywords'}     = $env{'form.keywords'};
Line 3207  sub processHandGrade { Line 2807  sub processHandGrade {
  $keyhash{$loginuser.'_kwclr'}   = $env{'form.kwclr'};   $keyhash{$loginuser.'_kwclr'}   = $env{'form.kwclr'};
  $keyhash{$loginuser.'_kwsize'}  = $env{'form.kwsize'};   $keyhash{$loginuser.'_kwsize'}  = $env{'form.kwsize'};
  $keyhash{$loginuser.'_kwstyle'} = $env{'form.kwstyle'};   $keyhash{$loginuser.'_kwstyle'} = $env{'form.kwstyle'};
     }  
   
     if ($env{'form.compmsg'}) {  
  # message center - Order of message gets changed. Blank line is eliminated.   # message center - Order of message gets changed. Blank line is eliminated.
  # New messages are saved in env for the next student.   # New messages are saved in env for the next student.
  # All messages are saved in nohist_handgrade.db   # All messages are saved in nohist_handgrade.db
Line 3232  sub processHandGrade { Line 2830  sub processHandGrade {
  }   }
  $env{'form.savemsgN'} = --$idx;   $env{'form.savemsgN'} = --$idx;
  $keyhash{$symb.'_savemsgN'} = $env{'form.savemsgN'};   $keyhash{$symb.'_savemsgN'} = $env{'form.savemsgN'};
     }  
     if (($numessay) || ($env{'form.compmsg'})) {  
  my $putresult = &Apache::lonnet::put   my $putresult = &Apache::lonnet::put
     ('nohist_handgrade',\%keyhash,$cdom,$cnum);      ('nohist_handgrade',\%keyhash,$cdom,$cnum);
     }      }
   
     # Called by Save & Refresh from Highlight Attribute Window      # Called by Save & Refresh from Highlight Attribute Window
     my (undef,undef,$fullname) = &getclasslist($env{'form.section'},'1');      my (undef,undef,$fullname) = &getclasslist($env{'form.section'},'1');
     if ($env{'form.refresh'} eq 'on') {      if ($env{'form.refresh'} eq 'on') {
Line 3277  sub processHandGrade { Line 2872  sub processHandGrade {
  }   }
  return $a cmp $b;   return $a cmp $b;
      } (keys(%$fullname))) {       } (keys(%$fullname))) {
   # FIXME: this is fishy, looks like the button label
  if ($nextflg == 1 && $button =~ /Next$/) {   if ($nextflg == 1 && $button =~ /Next$/) {
     push(@parsedlist,$item);      push(@parsedlist,$item);
  }   }
Line 3287  sub processHandGrade { Line 2883  sub processHandGrade {
  }   }
     }      }
     $ctr = 0;      $ctr = 0;
   # FIXME: this is fishy, looks like the button label
     @parsedlist = reverse @parsedlist if ($button eq 'Previous');      @parsedlist = reverse @parsedlist if ($button eq 'Previous');
       my $res_error;
       my ($partlist) = &response_type($symb,\$res_error);
       if ($res_error) {
           $request->print(&navmap_errormsg());
           return;
       }
     foreach my $student (@parsedlist) {      foreach my $student (@parsedlist) {
  my $submitonly=$env{'form.submitonly'};   my $submitonly=$env{'form.submitonly'};
  my ($uname,$udom) = split(/:/,$student);   my ($uname,$udom) = split(/:/,$student);
Line 3337  sub processHandGrade { Line 2940  sub processHandGrade {
  $ctr++;   $ctr++;
     }      }
     if ($total < 0) {      if ($total < 0) {
         my $the_end.='<p>'.&mt('[_1]Message:[_2] No more students for this section or class.','<b>','</b>').'</p>'."\n";   my $the_end.='<p>'.&mt('[_1]Message:[_2] No more students for this section or class.','<b>','</b>').'</p>'."\n";
  $request->print($the_end);   $request->print($the_end);
     }      }
     return '';      return '';
Line 3353  sub saveHandGrade { Line 2956  sub saveHandGrade {
     my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$domain,$stuname);      my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$domain,$stuname);
     my @parts_graded;      my @parts_graded;
     my %newrecord  = ();      my %newrecord  = ();
     my ($pts,$wgt,$totchg) = ('','',0);      my ($pts,$wgt) = ('','');
     my %aggregate = ();      my %aggregate = ();
     my $aggregateflag = 0;      my $aggregateflag = 0;
     if ($env{'form.HIDE'.$newflg}) {  
         my ($version,$parts) = split(/:/,$env{'form.HIDE'.$newflg},2);  
         my $numchgs = &makehidden($version,$parts,\%record,$symb,$domain,$stuname,1);  
         $totchg += $numchgs;  
     }  
     my @parts = split(/:/,$env{'form.partlist'.$newflg});      my @parts = split(/:/,$env{'form.partlist'.$newflg});
     foreach my $new_part (@parts) {      foreach my $new_part (@parts) {
  #collaborator ($submi may vary for different parts   #collaborator ($submi may vary for different parts
Line 3463  sub saveHandGrade { Line 3061  sub saveHandGrade {
         &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate,          &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate,
       $cdom,$cnum);        $cdom,$cnum);
     }      }
     return ('',$pts,$wgt,$totchg);      return ('',$pts,$wgt);
 }  
   
 sub makehidden {  
     my ($version,$parts,$record,$symb,$domain,$stuname,$tolog) = @_;  
     return unless (ref($record) eq 'HASH');  
     my %modified;  
     my $numchanged = 0;  
     if (exists($record->{$version.':keys'})) {  
         my $partsregexp = $parts;  
         $partsregexp =~ s/,/|/g;  
         foreach my $key (split(/\:/,$record->{$version.':keys'})) {  
             if ($key =~ /^resource\.(?:$partsregexp)\.([^\.]+)$/) {  
                  my $item = $1;  
                  unless (($item eq 'solved') || ($item =~ /^award(|msg|ed)$/)) {  
                      $modified{$key} = $record->{$version.':'.$key};  
                  }  
             } elsif ($key =~ m{^(resource\.(?:$partsregexp)\.[^\.]+\.)(.+)$}) {  
                 $modified{$1.'hidden'.$2} = $record->{$version.':'.$key};  
             } elsif ($key =~ /^(ip|timestamp|host)$/) {  
                 $modified{$key} = $record->{$version.':'.$key};  
             }  
         }  
         if (keys(%modified)) {  
             if (&Apache::lonnet::putstore($env{'request.course.id'},$symb,$version,\%modified,  
                                           $domain,$stuname,$tolog) eq 'ok') {  
                 $numchanged ++;  
             }  
         }  
     }  
     return $numchanged;  
 }  }
   
 sub check_and_remove_from_queue {  sub check_and_remove_from_queue {
Line 3531  sub handback_files { Line 3099  sub handback_files {
  my $part_resp = join('_',@{ $part_response_id });   my $part_resp = join('_',@{ $part_response_id });
         if (($env{'form.'.$newflg.'_'.$part_resp.'_countreturndoc'} =~ /^\d+$/) & ($new_part eq $part_id)) {          if (($env{'form.'.$newflg.'_'.$part_resp.'_countreturndoc'} =~ /^\d+$/) & ($new_part eq $part_id)) {
             for (my $counter=1; $counter<=$env{'form.'.$newflg.'_'.$part_resp.'_countreturndoc'}; $counter++) {              for (my $counter=1; $counter<=$env{'form.'.$newflg.'_'.$part_resp.'_countreturndoc'}; $counter++) {
                 # if multiple files are uploaded names will be 'returndoc2','returndoc3'                  # if multiple files are uploaded names will be 'returndoc2','returndoc3' 
  if ($env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter}) {                  if ($env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter}) {
                     my $fname=$env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter.'.filename'};                      my $fname=$env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter.'.filename'};
                     my ($directory,$answer_file) =                       my ($directory,$answer_file) = 
                         ($env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter} =~ /^(.*?)([^\/]*)$/);                          ($env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter} =~ /^(.*?)([^\/]*)$/);
Line 3540  sub handback_files { Line 3108  sub handback_files {
         &file_name_version_ext($answer_file);          &file_name_version_ext($answer_file);
     my ($portfolio_path) = ($directory =~ /^.+$stuname\/portfolio(.*)/);      my ($portfolio_path) = ($directory =~ /^.+$stuname\/portfolio(.*)/);
                     my $getpropath = 1;                      my $getpropath = 1;
                     my ($dir_list,$listerror) =                      my ($dir_list,$listerror) = 
                         &Apache::lonnet::dirlist($portfolio_root.$portfolio_path,                          &Apache::lonnet::dirlist($portfolio_root.$portfolio_path,
                                                  $domain,$stuname,$getpropath);                                                   $domain,$stuname,$getpropath);
     my $version = &get_next_version($answer_name,$answer_ext,$dir_list);      my $version = &get_next_version($answer_name,$answer_ext,$dir_list);
Line 3561  sub handback_files { Line 3129  sub handback_files {
     $$newrecord{"resource.$new_part.$resp_id.handback"}.=',';      $$newrecord{"resource.$new_part.$resp_id.handback"}.=',';
  }   }
                         $$newrecord{"resource.$new_part.$resp_id.handback"} .= $save_file_name;                          $$newrecord{"resource.$new_part.$resp_id.handback"} .= $save_file_name;
  $file_msg.='<span class="LC_filename"><a href="/uploaded/'."$domain/$stuname/".$save_file_name.'">'.$save_file_name."</a></span> <br />";   $file_msg.= '<span class="LC_filename"><a href="/uploaded/'."$domain/$stuname/".$save_file_name.'">'.$save_file_name."</a></span> <br />";
   
                     }                      }
                     $request->print('<br />'.&mt('[_1] will be the uploaded filename [_2]','<span class="LC_info">'.$fname.'</span>','<span class="LC_filename">'.$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter}.'</span>'));                      $request->print('<br />'.&mt('[_1] will be the uploaded filename [_2]','<span class="LC_info">'.$fname.'</span>','<span class="LC_filename">'.$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter}.'</span>'));
                 }                  }
Line 3573  sub handback_files { Line 3140  sub handback_files {
         $request->print('<br />');          $request->print('<br />');
         my @what = ($symb,$env{'request.course.id'},'handback');          my @what = ($symb,$env{'request.course.id'},'handback');
         &Apache::lonnet::mark_as_readonly($domain,$stuname,\@handedback,\@what);          &Apache::lonnet::mark_as_readonly($domain,$stuname,\@handedback,\@what);
         my $user_lh = &Apache::loncommon::user_lang($stuname,$domain,$env{'request.course.id'});          my $user_lh = &Apache::loncommon::user_lang($stuname,$domain,$env{'request.course.id'});    
         my ($subject,$message);          my ($subject,$message);
         if (scalar(@handedback) == 1) {          if (scalar(@handedback) == 1) {
             $subject = &mt_user($user_lh,'File Handed Back by Instructor');              $subject = &mt_user($user_lh,'File Handed Back by Instructor');
Line 3704  sub version_portfiles { Line 3271  sub version_portfiles {
                 my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*)$/);                  my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*)$/);
  my ($answer_name,$answer_ver,$answer_ext) =   my ($answer_name,$answer_ver,$answer_ext) =
     &file_name_version_ext($answer_file);      &file_name_version_ext($answer_file);
                 my $getpropath = 1;                  my $getpropath = 1;    
                 my ($dir_list,$listerror) =                  my ($dir_list,$listerror) = 
                     &Apache::lonnet::dirlist($portfolio_root.$directory,$domain,                      &Apache::lonnet::dirlist($portfolio_root.$directory,$domain,
                                              $stu_name,$getpropath);                                               $stu_name,$getpropath);
                 my $version = &get_next_version($answer_name,$answer_ext,$dir_list);                  my $version = &get_next_version($answer_name,$answer_ext,$dir_list);
Line 3734  sub get_next_version { Line 3301  sub get_next_version {
         &file_name_version_ext($file);          &file_name_version_ext($file);
             if (($file_name eq $answer_name) &&               if (($file_name eq $answer_name) && 
         ($file_ext eq $answer_ext)) {          ($file_ext eq $answer_ext)) {
                 # gets here if filename and extension match,                        # gets here if filename and extension match, 
                 # regardless of version                       # regardless of version
                 if ($file_version ne '') {                  if ($file_version ne '') {
                     # a versioned file is found  so save it for later                      # a versioned file is found  so save it for later
                     if ($file_version > $version) {                      if ($file_version > $version) {
         $version = $file_version;          $version = $file_version;
                     }              }
         }                  }
             }              }
         }          }
     }      }
Line 3791  sub viewgrades_js { Line 3358  sub viewgrades_js {
     my ($request) = shift;      my ($request) = shift;
   
     my $alertmsg = &mt('A number equal or greater than 0 is expected. Entered value = ');      my $alertmsg = &mt('A number equal or greater than 0 is expected. Entered value = ');
     &js_escape(\$alertmsg);  
     $request->print(&Apache::lonhtmlcommon::scripttag(<<VIEWJAVASCRIPT));      $request->print(&Apache::lonhtmlcommon::scripttag(<<VIEWJAVASCRIPT));
    function writePoint(partid,weight,point) {     function writePoint(partid,weight,point) {
  var radioButton = document.classgrade["RADVAL_"+partid];   var radioButton = document.classgrade["RADVAL_"+partid];
Line 3981  sub viewgrades { Line 3547  sub viewgrades {
  &build_section_inputs().   &build_section_inputs().
  '<input type="hidden" name="Status" value="'.$env{'stu_status'}.'" />'."\n".   '<input type="hidden" name="Status" value="'.$env{'stu_status'}.'" />'."\n".
   
     #retrieve selected groups      my ($common_header,$specific_header);
     my (@groups,$group_display);      if ($env{'form.section'} eq 'all') {
     @groups = &Apache::loncommon::get_env_multiple('form.group');   $common_header = &mt('Assign Common Grade to Class');
     if (grep(/^all$/,@groups)) {          $specific_header = &mt('Assign Grade to Specific Students in Class');
         @groups = ('all');      } elsif ($env{'form.section'} eq 'none') {
     } elsif (grep(/^none$/,@groups)) {          $common_header = &mt('Assign Common Grade to Students in no Section');
         @groups = ('none');   $specific_header = &mt('Assign Grade to Specific Students in no Section');
     } elsif (@groups > 0) {      } else {
         $group_display = join(', ',@groups);          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);
     my ($common_header,$specific_header,@sections,$section_display);  
     @sections = &Apache::loncommon::get_env_multiple('form.section');  
     if (grep(/^all$/,@sections)) {  
         @sections = ('all');  
         if ($group_display) {  
             $common_header = &mt('Assign Common Grade to Students in Group(s) [_1]',$group_display);  
             $specific_header = &mt('Assign Grade to Specific Students in Group(s) [_1]',$group_display);  
         } elsif (grep(/^none$/,@groups)) {  
             $common_header = &mt('Assign Common Grade to Students not assigned to any groups');  
             $specific_header = &mt('Assign Grade to Specific Students not assigned to any groups');  
         } else {  
             $common_header = &mt('Assign Common Grade to Class');  
             $specific_header = &mt('Assign Grade to Specific Students in Class');  
         }  
     } elsif (grep(/^none$/,@sections)) {  
         @sections = ('none');  
         if ($group_display) {  
             $common_header = &mt('Assign Common Grade to Students in no Section and in Group(s) [_1]',$group_display);  
             $specific_header = &mt('Assign Grade to Specific Students in no Section and in Group(s)',$group_display);  
         } elsif (grep(/^none$/,@groups)) {  
             $common_header = &mt('Assign Common Grade to Students in no Section and in no Group');  
             $specific_header = &mt('Assign Grade to Specific Students in no Section and in no Group');  
         } else {  
             $common_header = &mt('Assign Common Grade to Students in no Section');  
             $specific_header = &mt('Assign Grade to Specific Students in no Section');  
         }  
     } else {  
         $section_display = join (", ",@sections);  
         if ($group_display) {  
             $common_header = &mt('Assign Common Grade to Students in Section(s) [_1], and in Group(s) [_2]',  
                                  $section_display,$group_display);  
             $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1], and in Group(s) [_2]',  
                                    $section_display,$group_display);  
         } elsif (grep(/^none$/,@groups)) {  
             $common_header = &mt('Assign Common Grade to Students in Section(s) [_1] and no Group',$section_display);  
             $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1] and no Group',$section_display);  
         } else {  
             $common_header = &mt('Assign Common Grade to Students in Section(s) [_1]',$section_display);  
             $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1]',$section_display);  
         }  
     }      }
     my %submit_types = &substatus_options();      $result.= '<h3>'.$common_header.'</h3>'.&Apache::loncommon::start_data_table();
     my $submission_status = $submit_types{$env{'form.submitonly'}};  
   
     if ($env{'form.submitonly'} eq 'all') {  
         $result.= '<h3>'.$common_header.'</h3>';  
     } else {  
         $result.= '<h3>'.$common_header.'&nbsp;'.&mt('(submission status: "[_1]")',$submission_status).'</h3>';   
     }  
     $result .= &Apache::loncommon::start_data_table();  
     #radio buttons/text box for assigning points for a section or class.      #radio buttons/text box for assigning points for a section or class.
     #handles different parts of a problem      #handles different parts of a problem
     my $res_error;      my $res_error;
Line 4058  sub viewgrades { Line 3576  sub viewgrades {
  my $part_resp = join('_',@{ $part_response_id });   my $part_resp = join('_',@{ $part_response_id });
  next if $seen{$partid};   next if $seen{$partid};
  $seen{$partid}++;   $seen{$partid}++;
    my $handgrade=$$handgrade{$part_resp};
  my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb);   my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb);
  $weight{$partid} = $wgt eq '' ? '1' : $wgt;   $weight{$partid} = $wgt eq '' ? '1' : $wgt;
   
Line 4076  sub viewgrades { Line 3595  sub viewgrades {
     $partid.'" size="4" '.'onchange="javascript:writePoint(\''.      $partid.'" size="4" '.'onchange="javascript:writePoint(\''.
  $partid.'\','.$weight{$partid}.',\'textval\')" /> /'.   $partid.'\','.$weight{$partid}.',\'textval\')" /> /'.
     $weight{$partid}.' '.&mt('(problem weight)').'</td>'."\n";      $weight{$partid}.' '.&mt('(problem weight)').'</td>'."\n";
  $line.= '<td><b>'.&mt('Grade Status').':</b>'.          $line.= '<td><b>'.&mt('Grade Status').':</b>'.
                 '<select name="SELVAL_'.$partid.'" '.              '<select name="SELVAL_'.$partid.'" '.
         'onchange="javascript:writeRadText(\''.$partid.'\','.              'onchange="javascript:writeRadText(\''.$partid.'\','.
  $weight{$partid}.')"> '.                  $weight{$partid}.')"> '.
     '<option selected="selected"> </option>'.      '<option selected="selected"> </option>'.
     '<option value="excused">'.&mt('excused').'</option>'.      '<option value="excused">'.&mt('excused').'</option>'.
     '<option value="reset status">'.&mt('reset status').'</option>'.      '<option value="reset status">'.&mt('reset status').'</option>'.
Line 4103  sub viewgrades { Line 3622  sub viewgrades {
   
     #table listing all the students in a section/class      #table listing all the students in a section/class
     #header of table      #header of table
     if ($env{'form.submitonly'} eq 'all') {       $result.= '<h3>'.$specific_header.'</h3>'.
         $result.= '<h3>'.$specific_header.'</h3>';                &Apache::loncommon::start_data_table().
     } else {  
         $result.= '<h3>'.$specific_header.'&nbsp;'.&mt('(submission status: "[_1]")',$submission_status).'</h3>';  
     }  
     $result.= &Apache::loncommon::start_data_table().  
       &Apache::loncommon::start_data_table_header_row().        &Apache::loncommon::start_data_table_header_row().
       '<th>'.&mt('No.').'</th>'.        '<th>'.&mt('No.').'</th>'.
       '<th>'.&nameUserString('header')."</th>\n";        '<th>'.&nameUserString('header')."</th>\n";
Line 4132  sub viewgrades { Line 3647  sub viewgrades {
  my $display_part=&get_display_part($partid,$symb);   my $display_part=&get_display_part($partid,$symb);
  if ($display =~ /^Partial Credit Factor/) {   if ($display =~ /^Partial Credit Factor/) {
     $result.='<th>'.      $result.='<th>'.
                 &mt('Score Part: [_1][_2](weight = [_3])',   &mt('Score Part: [_1][_2](weight = [_3])',
                     $display_part,'<br />',$weight{$partid}).'</th>'."\n";      $display_part,'<br />',$weight{$partid}).'</th>'."\n";
     next;      next;
           
  } else {   } else {
Line 4154  sub viewgrades { Line 3669  sub viewgrades {
   
     #get info for each student      #get info for each student
     #list all the students - with points and grade status      #list all the students - with points and grade status
     my (undef,undef,$fullname) = &getclasslist(\@sections,'1',\@groups);      my (undef,undef,$fullname) = &getclasslist($env{'form.section'},'1');
     my $ctr = 0;      my $ctr = 0;
     foreach (sort       foreach (sort 
      {       {
Line 4163  sub viewgrades { Line 3678  sub viewgrades {
  }   }
  return $a cmp $b;   return $a cmp $b;
      } (keys(%$fullname))) {       } (keys(%$fullname))) {
    $ctr++;
  $result.=&viewstudentgrade($symb,$env{'request.course.id'},   $result.=&viewstudentgrade($symb,$env{'request.course.id'},
    $_,$$fullname{$_},\@parts,\%weight,\$ctr,\%last_resets);     $_,$$fullname{$_},\@parts,\%weight,$ctr,\%last_resets);
     }      }
     $result.=&Apache::loncommon::end_data_table();      $result.=&Apache::loncommon::end_data_table();
     $result.='<input type="hidden" name="total" value="'.$ctr.'" />'."\n";      $result.='<input type="hidden" name="total" value="'.$ctr.'" />'."\n";
     $result.='<input type="button" value="'.&mt('Save').'" '.      $result.='<input type="button" value="'.&mt('Save').'" '.
  'onclick="javascript:submit();" target="_self" /></form>'."\n";   'onclick="javascript:submit();" target="_self" /></form>'."\n";
     if ($ctr == 0) {      if (scalar(%$fullname) eq 0) {
    my $colspan=3+scalar(@parts);
    my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));
         my $stu_status = join(' or ',&Apache::loncommon::get_env_multiple('form.Status'));          my $stu_status = join(' or ',&Apache::loncommon::get_env_multiple('form.Status'));
         $result='<h3><span class="LC_info">'.&mt('Manual Grading').'</span></h3>'.   $result='<span class="LC_warning">'.
                 '<span class="LC_warning">';      &mt('There are no students in section(s) [_1] with enrollment status [_2] to modify or grade.',
         if ($env{'form.submitonly'} eq 'all') {          $section_display, $stu_status).
             if (grep(/^all$/,@sections)) {      '</span>';
                 if (grep(/^all$/,@groups)) {  
                     $result .= &mt('There are no students with enrollment status [_1] to modify or grade.',  
                                    $stu_status);  
                 } elsif (grep(/^none$/,@groups)) {  
                     $result .= &mt('There are no students with no group assigned and with enrollment status [_1] to modify or grade.',  
                                    $stu_status);  
                 } else {  
                     $result .= &mt('There are no students in group(s) [_1] with enrollment status [_2] to modify or grade.',  
                                    $group_display,$stu_status);  
                 }  
             } elsif (grep(/^none$/,@sections)) {  
                 if (grep(/^all$/,@groups)) {  
                     $result .= &mt('There are no students in no section with enrollment status [_1] to modify or grade.',  
                                    $stu_status);  
                 } elsif (grep(/^none$/,@groups)) {  
                     $result .= &mt('There are no students in no section and no group with enrollment status [_1] to modify or grade.',  
                                    $stu_status);  
                 } else {  
                     $result .= &mt('There are no students in no section in group(s) [_1] with enrollment status [_2] to modify or grade.',  
                                    $group_display,$stu_status);  
                 }  
             } else {  
                 if (grep(/^all$/,@groups)) {  
                     $result .= &mt('There are no students in section(s) [_1] with enrollment status [_2] to modify or grade.',  
                                    $section_display,$stu_status);  
                 } elsif (grep(/^none$/,@groups)) {  
                     $result .= &mt('There are no students in section(s) [_1] and no group with enrollment status [_2] to modify or grade.',  
                                    $section_display,$stu_status);  
                 } else {  
                     $result .= &mt('There are no students in section(s) [_1] and group(s) [_2] with enrollment status [_3] to modify or grade.',  
                                    $section_display,$group_display,$stu_status);  
                 }  
             }  
         } else {  
             if (grep(/^all$/,@sections)) {  
                 if (grep(/^all$/,@groups)) {  
                     $result .= &mt('There are no students with enrollment status [_1] and submission status "[_2]" to modify or grade.',  
                                    $stu_status,$submission_status);  
                 } elsif (grep(/^none$/,@groups)) {  
                     $result .= &mt('There are no students with no group assigned with enrollment status [_1] and submission status "[_2]" to modify or grade.',  
                                    $stu_status,$submission_status);  
                 } else {  
                     $result .= &mt('There are no students in group(s) [_1] with enrollment status [_2] and submission status "[_3]" to modify or grade.',  
                                    $group_display,$stu_status,$submission_status);  
                 }  
             } elsif (grep(/^none$/,@sections)) {  
                 if (grep(/^all$/,@groups)) {  
                     $result .= &mt('There are no students in no section with enrollment status [_1] and submission status "[_2]" to modify or grade.',  
                                    $stu_status,$submission_status);  
                 } elsif (grep(/^none$/,@groups)) {  
                     $result .= &mt('There are no students in no section and no group with enrollment status [_1] and submission status "[_2]" to modify or grade.',  
                                    $stu_status,$submission_status);  
                 } else {  
                     $result .= &mt('There are no students in no section in group(s) [_1] with enrollment status [_2] and submission status "[_3]" to modify or grade.',  
                                    $group_display,$stu_status,$submission_status);  
                 }  
             } else {  
                 if (grep(/^all$/,@groups)) {  
                     $result .= &mt('There are no students in section(s) [_1] with enrollment status [_2] and submission status "[_3]" to modify or grade.',  
                                    $section_display,$stu_status,$submission_status);  
                 } elsif (grep(/^none$/,@groups)) {  
                     $result .= &mt('There are no students in section(s) [_1] and no group with enrollment status [_2] and submission status "[_3]" to modify or grade.',  
                                    $section_display,$stu_status,$submission_status);  
                 } else {  
                     $result .= &mt('There are no students in section(s) [_1] and group(s) [_2] with enrollment status [_3] and submission status "[_4]" to modify or grade.',  
                                    $section_display,$group_display,$stu_status,$submission_status);  
                 }  
             }  
  }  
  $result .= '</span><br />';  
     }      }
     return $result;      return $result;
 }  }
   
 #--- call by previous routine to display each student who satisfies submission filter.  #--- call by previous routine to display each student
 sub viewstudentgrade {  sub viewstudentgrade {
     my ($symb,$courseid,$student,$fullname,$parts,$weight,$ctr,$last_resets) = @_;      my ($symb,$courseid,$student,$fullname,$parts,$weight,$ctr,$last_resets) = @_;
     my ($uname,$udom) = split(/:/,$student);      my ($uname,$udom) = split(/:/,$student);
     my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname);      my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname);
     my $submitonly = $env{'form.submitonly'};      my %aggregates = (); 
     unless (($submitonly eq 'all') || ($submitonly eq 'queued')) {  
         my %partstatus = ();  
         if (ref($parts) eq 'ARRAY') {  
             foreach my $apart (@{$parts}) {  
                 my ($part,$type) = &split_part_type($apart);  
                 my ($status,undef) = split(/_/,$record{"resource.$part.solved"},2);  
                 $status = 'nothing' if ($status eq '');  
                 $partstatus{$part}      = $status;  
                 my $subkey = "resource.$part.submitted_by";  
                 $partstatus{$subkey} = $record{$subkey} if ($record{$subkey} ne '');  
             }  
             my $submitted = 0;  
             my $graded = 0;  
             my $incorrect = 0;  
             foreach my $key (keys(%partstatus)) {  
                 $submitted = 1 if ($partstatus{$key} ne 'nothing');  
                 $graded = 1 if ($partstatus{$key} =~ /^ungraded/);  
                 $incorrect = 1 if ($partstatus{$key} =~ /^incorrect/);  
   
                 my $partid = (split(/\./,$key))[1];  
                 if ($partstatus{'resource.'.$partid.'.'.$key.'.submitted_by'} ne '') {  
                     $submitted = 0;  
                 }  
             }  
             return if (!$submitted && ($submitonly eq 'yes' ||  
                                        $submitonly eq 'incorrect' ||  
                                        $submitonly eq 'graded'));  
             return if (!$graded && ($submitonly eq 'graded'));  
             return if (!$incorrect && $submitonly eq 'incorrect');  
         }  
     }  
     if ($submitonly eq 'queued') {  
         my ($cdom,$cnum) = split(/_/,$courseid);  
         my %queue_status =  
             &Apache::bridgetask::get_student_status($symb,$cdom,$cnum,  
                                                     $udom,$uname);  
         return if (!defined($queue_status{'gradingqueue'}));  
     }  
     $$ctr++;  
     my %aggregates = ();  
     my $result=&Apache::loncommon::start_data_table_row().'<td align="right">'.      my $result=&Apache::loncommon::start_data_table_row().'<td align="right">'.
  '<input type="hidden" name="ctr'.($$ctr-1).'" value="'.$student.'" />'.   '<input type="hidden" name="ctr'.($ctr-1).'" value="'.$student.'" />'.
  "\n".$$ctr.'&nbsp;</td><td>&nbsp;'.   "\n".$ctr.'&nbsp;</td><td>&nbsp;'.
  '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.   '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.
  '\');" target="_self">'.$fullname.'</a> '.   '\');" target="_self">'.$fullname.'</a> '.
  '<span class="LC_internal_info">('.$uname.($env{'user.domain'} eq $udom ? '' : ':'.$udom).')</span></td>'."\n";   '<span class="LC_internal_info">('.$uname.($env{'user.domain'} eq $udom ? '' : ':'.$udom).')</span></td>'."\n";
Line 4362  sub editgrades { Line 3770  sub editgrades {
   
     my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));      my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));
     my $title='<h2>'.&mt('Current Grade Status').'</h2>';      my $title='<h2>'.&mt('Current Grade Status').'</h2>';
     $title.='<h4><b>'.&mt('Section:').'</b> '.$section_display.'</h4>'."\n";      $title.='<h4>'.&mt('<b>Section: </b>[_1]',$section_display).'</h4>'."\n";
   
     my $result= &Apache::loncommon::start_data_table().      my $result= &Apache::loncommon::start_data_table().
  &Apache::loncommon::start_data_table_header_row().   &Apache::loncommon::start_data_table_header_row().
Line 4396  sub editgrades { Line 3804  sub editgrades {
  $ctr++;   $ctr++;
     }      }
     my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);      my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);
     my $totcolspan = 0;  
     foreach my $partid (@partid) {      foreach my $partid (@partid) {
  $header .= '<th align="center">'.&mt('Old Score').'</th>'.   $header .= '<th align="center">'.&mt('Old Score').'</th>'.
     '<th align="center">'.&mt('New Score').'</th>';      '<th align="center">'.&mt('New Score').'</th>';
Line 4413  sub editgrades { Line 3820  sub editgrades {
  '<th align="center">'.&mt('New').' '.$display.'</th>';   '<th align="center">'.&mt('New').' '.$display.'</th>';
     $columns{$partid}+=2;      $columns{$partid}+=2;
  }   }
         $totcolspan += $columns{$partid};  
     }      }
     foreach my $partid (@partid) {      foreach my $partid (@partid) {
  my $display_part=&get_display_part($partid,$symb);   my $display_part=&get_display_part($partid,$symb);
Line 4429  sub editgrades { Line 3835  sub editgrades {
     my @noupdate;      my @noupdate;
     my ($updateCtr,$noupdateCtr) = (1,1);      my ($updateCtr,$noupdateCtr) = (1,1);
     for ($i=0; $i<$env{'form.total'}; $i++) {      for ($i=0; $i<$env{'form.total'}; $i++) {
    my $line;
  my $user = $env{'form.ctr'.$i};   my $user = $env{'form.ctr'.$i};
  my ($uname,$udom)=split(/:/,$user);   my ($uname,$udom)=split(/:/,$user);
  my %newrecord;   my %newrecord;
  my $updateflag = 0;   my $updateflag = 0;
         my $usec=$classlist->{"$uname:$udom"}[5];   $line .= '<td>'.&nameUserString(undef,$$fullname{$user},$uname,$udom).'</td>';
         my $canmodify = &canmodify($usec);   my $usec=$classlist->{"$uname:$udom"}[5];
         my $line = '<td'.($canmodify?'':' colspan="2"').'>'.   if (!&canmodify($usec)) {
                    &nameUserString(undef,$$fullname{$user},$uname,$udom).'</td>';      my $numcols=scalar(@partid)*4+2;
         if (!$canmodify) {      push(@noupdate,
             push(@noupdate,   $line."<td colspan=\"$numcols\"><span class=\"LC_warning\">".
                  $line."<td colspan=\"$totcolspan\"><span class=\"LC_warning\">".   &mt('Not allowed to modify student')."</span></td></tr>");
                  &mt('Not allowed to modify student')."</span></td>");      next;
             next;   }
         }  
         my %aggregate = ();          my %aggregate = ();
         my $aggregateflag = 0;          my $aggregateflag = 0;
  $user=~s/:/_/; # colon doen't work in javascript for names   $user=~s/:/_/; # colon doen't work in javascript for names
Line 4557  sub editgrades { Line 3963  sub editgrades {
         }          }
     }      }
     if (@noupdate) {      if (@noupdate) {
         my $numcols=$totcolspan+2;  # my $numcols=(scalar(@partid)*(scalar(@parts)-1)*2)+3;
    my $numcols=scalar(@partid)*4+2;
  $result .= &Apache::loncommon::start_data_table_row('LC_empty_row').   $result .= &Apache::loncommon::start_data_table_row('LC_empty_row').
     '<td align="center" colspan="'.$numcols.'">'.      '<td align="center" colspan="'.$numcols.'">'.
     &mt('No Changes Occurred For the Students Below').      &mt('No Changes Occurred For the Students Below').
Line 4600  sub split_part_type { Line 4007  sub split_part_type {
 sub csvupload_javascript_reverse_associate {  sub csvupload_javascript_reverse_associate {
     my $error1=&mt('You need to specify the username or the student/employee ID');      my $error1=&mt('You need to specify the username or the student/employee ID');
     my $error2=&mt('You need to specify at least one grading field');      my $error2=&mt('You need to specify at least one grading field');
   &js_escape(\$error1);  
   &js_escape(\$error2);  
   return(<<ENDPICK);    return(<<ENDPICK);
   function verify(vf) {    function verify(vf) {
     var foundsomething=0;      var foundsomething=0;
Line 4642  ENDPICK Line 4047  ENDPICK
 sub csvupload_javascript_forward_associate {  sub csvupload_javascript_forward_associate {
     my $error1=&mt('You need to specify the username or the student/employee ID');      my $error1=&mt('You need to specify the username or the student/employee ID');
     my $error2=&mt('You need to specify at least one grading field');      my $error2=&mt('You need to specify at least one grading field');
   &js_escape(\$error1);  
   &js_escape(\$error2);  
   return(<<ENDPICK);    return(<<ENDPICK);
   function verify(vf) {    function verify(vf) {
     var foundsomething=0;      var foundsomething=0;
Line 4687  sub csvuploadmap_header { Line 4090  sub csvuploadmap_header {
  $javascript=&csvupload_javascript_forward_associate();   $javascript=&csvupload_javascript_forward_associate();
     }      }
   
     my $checked=(($env{'form.noFirstLine'})?' checked="checked"':'');  
     my $ignore=&mt('Ignore First Line');  
     $symb = &Apache::lonenc::check_encrypt($symb);      $symb = &Apache::lonenc::check_encrypt($symb);
     $request->print('<form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">'.      $request->print('<form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">'.
                     &mt('Total number of records found in file: [_1]',$distotal).'<hr />'.                      &mt('Total number of records found in file: [_1]',$distotal).'<hr />'.
Line 4697  sub csvuploadmap_header { Line 4098  sub csvuploadmap_header {
     $request->print(<<ENDPICK);      $request->print(<<ENDPICK);
 <br />  <br />
 <input type="button" value="$reverse" onclick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" />  <input type="button" value="$reverse" onclick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" />
 <label><input type="checkbox" name="noFirstLine" $checked />$ignore</label>  
 <input type="hidden" name="associate"  value="" />  <input type="hidden" name="associate"  value="" />
 <input type="hidden" name="phase"      value="three" />  <input type="hidden" name="phase"      value="three" />
 <input type="hidden" name="datatoken"  value="$datatoken" />  <input type="hidden" name="datatoken"  value="$datatoken" />
Line 4755  ENDPICK Line 4155  ENDPICK
   
 sub checkforfile_js {  sub checkforfile_js {
     my $alertmsg = &mt('Please use the browse button to select a file from your local directory.');      my $alertmsg = &mt('Please use the browse button to select a file from your local directory.');
     &js_escape(\$alertmsg);  
     my $result = &Apache::lonhtmlcommon::scripttag(<<CSVFORMJS);      my $result = &Apache::lonhtmlcommon::scripttag(<<CSVFORMJS);
     function checkUpload(formname) {      function checkUpload(formname) {
  if (formname.upfile.value == "") {   if (formname.upfile.value == "") {
Line 4787  sub upcsvScores_form { Line 4186  sub upcsvScores_form {
 <input type="hidden" name="command" value="csvuploadmap" />  <input type="hidden" name="command" value="csvuploadmap" />
 $upfile_select  $upfile_select
 <br /><input type="button" onclick="javascript:checkUpload(this.form);" value="$upload" />  <br /><input type="button" onclick="javascript:checkUpload(this.form);" value="$upload" />
 <label><input type="checkbox" name="noFirstLine" />$ignore</label>  
 </form>  </form>
 ENDUPFORM  ENDUPFORM
     $result.=&Apache::loncommon::help_open_topic("Course_Convert_To_CSV",      $result.=&Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
                            &mt("How do I create a CSV file from a spreadsheet")).                             &mt("How do I create a CSV file from a spreadsheet")).
             '</td>'.               '</td>'.
             &Apache::loncommon::end_data_table_row().              &Apache::loncommon::end_data_table_row().
             &Apache::loncommon::end_data_table();              &Apache::loncommon::end_data_table();
     return $result;      return $result;
Line 4800  ENDUPFORM Line 4198  ENDUPFORM
   
   
 sub csvuploadmap {  sub csvuploadmap {
     my ($request,$symb) = @_;      my ($request,$symb)= @_;
     if (!$symb) {return '';}      if (!$symb) {return '';}
   
     my $datatoken;      my $datatoken;
     if (!$env{'form.datatoken'}) {      if (!$env{'form.datatoken'}) {
  $datatoken=&Apache::loncommon::upfile_store($request);   $datatoken=&Apache::loncommon::upfile_store($request);
     } else {      } else {
         $datatoken=&Apache::loncommon::valid_datatoken($env{'form.datatoken'});   $datatoken=$env{'form.datatoken'};
         if ($datatoken ne '') {    &Apache::loncommon::load_tmp_file($request);
     &Apache::loncommon::load_tmp_file($request,$datatoken);  
         }  
     }      }
     my @records=&Apache::loncommon::upfile_record_sep();      my @records=&Apache::loncommon::upfile_record_sep();
     if ($env{'form.noFirstLine'}) { shift(@records); }  
     &csvuploadmap_header($request,$symb,$datatoken,$#records+1);      &csvuploadmap_header($request,$symb,$datatoken,$#records+1);
     my ($i,$keyfields);      my ($i,$keyfields);
     if (@records) {      if (@records) {
Line 4850  sub csvuploadmap { Line 4245  sub csvuploadmap {
 sub csvuploadoptions {  sub csvuploadoptions {
     my ($request,$symb)= @_;      my ($request,$symb)= @_;
     my $overwrite=&mt('Overwrite any existing score');      my $overwrite=&mt('Overwrite any existing score');
     my $checked=(($env{'form.noFirstLine'})?'1':'0');  
     my $ignore=&mt('Ignore First Line');  
     $request->print(<<ENDPICK);      $request->print(<<ENDPICK);
 <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">  <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
 <input type="hidden" name="command"    value="csvuploadassign" />  <input type="hidden" name="command"    value="csvuploadassign" />
Line 4865  ENDPICK Line 4258  ENDPICK
     my %fields=&get_fields();      my %fields=&get_fields();
     if (!defined($fields{'domain'})) {      if (!defined($fields{'domain'})) {
  my $domform = &Apache::loncommon::select_dom_form($env{'request.role.domain'},'default_domain');   my $domform = &Apache::loncommon::select_dom_form($env{'request.role.domain'},'default_domain');
         $request->print("\n<p>".&mt('Users are in domain: [_1]',$domform)."</p>\n");   $request->print("\n<p>".&mt('Users are in domain: [_1]',$domform)."</p>\n");
     }      }
     foreach my $key (sort(keys(%env))) {      foreach my $key (sort(keys(%env))) {
  if ($key !~ /^form\.(.*)$/) { next; }   if ($key !~ /^form\.(.*)$/) { next; }
Line 4899  sub get_fields { Line 4292  sub get_fields {
 }  }
   
 sub csvuploadassign {  sub csvuploadassign {
     my ($request,$symb) = @_;      my ($request,$symb)= @_;
     if (!$symb) {return '';}      if (!$symb) {return '';}
     my $error_msg = '';      my $error_msg = '';
     my $datatoken = &Apache::loncommon::valid_datatoken($env{'form.datatoken'});      &Apache::loncommon::load_tmp_file($request);
     if ($datatoken ne '') {  
         &Apache::loncommon::load_tmp_file($request,$datatoken);  
     }  
     my @gradedata = &Apache::loncommon::upfile_record_sep();      my @gradedata = &Apache::loncommon::upfile_record_sep();
     if ($env{'form.noFirstLine'}) { shift(@gradedata); }  
     my %fields=&get_fields();      my %fields=&get_fields();
     my $courseid=$env{'request.course.id'};      my $courseid=$env{'request.course.id'};
     my ($classlist) = &getclasslist('all',0);      my ($classlist) = &getclasslist('all',0);
Line 4963  sub csvuploadassign { Line 4352  sub csvuploadassign {
                     my $award=($pcr == 0) ? 'incorrect_by_override'                      my $award=($pcr == 0) ? 'incorrect_by_override'
                                           : 'correct_by_override';                                            : 'correct_by_override';
                     if ($pcr>1) {                      if ($pcr>1) {
                         push(@warnings,&mt("[_1]: point value larger than weight","$username:$domain"));                         push(@warnings,&mt("[_1]: point value larger than weight","$username:$domain"));
                     }                      }
                     $grades{"resource.$part.awarded"}=$pcr;                      $grades{"resource.$part.awarded"}=$pcr;
                     $grades{"resource.$part.solved"}=$award;                      $grades{"resource.$part.solved"}=$award;
Line 4984  sub csvuploadassign { Line 4373  sub csvuploadassign {
  $grades{$store_key}=$entries{$fields{$dest}};   $grades{$store_key}=$entries{$fields{$dest}};
     }      }
  }   }
  if (! %grades) {   if (! %grades) { 
            push(@skipped,&mt("[_1]: no data to save","$username:$domain"));              push(@skipped,&mt("[_1]: no data to save","$username:$domain")); 
         } else {          } else {
    $grades{"resource.regrader"}="$env{'user.name'}:$env{'user.domain'}";     $grades{"resource.regrader"}="$env{'user.name'}:$env{'user.domain'}";
Line 4999  sub csvuploadassign { Line 4388  sub csvuploadassign {
                                              $env{'course.'.$env{'request.course.id'}.'.domain'},                                               $env{'course.'.$env{'request.course.id'}.'.domain'},
                                              $env{'course.'.$env{'request.course.id'}.'.num'},                                               $env{'course.'.$env{'request.course.id'}.'.num'},
                                              $domain,$username);                                               $domain,$username);
    } else {                $countdone++;
              } else {
       $request->print("<p><span class=\"LC_error\">".        $request->print("<p><span class=\"LC_error\">".
                               &mt("Failed to save data for student [_1]. Message when trying to save was: [_2]",                                &mt("Failed to save data for student [_1]. Message when trying to save was: [_2]",
                                   "$username:$domain",$result)."</span></p>");                                    "$username:$domain",$result)."</span></p>");
    }     }
    $request->rflush();     $request->rflush();
    $countdone++;  
         }          }
     }      }
     $request->print('<br />'.&Apache::lonhtmlcommon::confirm_success(&mt("Saved scores for [quant,_1,student]",$countdone),$countdone==0));      $request->print('<br />'.&Apache::lonhtmlcommon::confirm_success(&mt("Saved scores for [quant,_1,student]",$countdone),$countdone==0));
Line 5035  sub pickStudentPage { Line 4424  sub pickStudentPage {
     my ($request,$symb) = @_;      my ($request,$symb) = @_;
   
     my $alertmsg = &mt('Please select the student you wish to grade.');      my $alertmsg = &mt('Please select the student you wish to grade.');
     &js_escape(\$alertmsg);  
     $request->print(&Apache::lonhtmlcommon::scripttag(<<LISTJAVASCRIPT));      $request->print(&Apache::lonhtmlcommon::scripttag(<<LISTJAVASCRIPT));
   
 function checkPickOne(formname) {  function checkPickOne(formname) {
Line 5055  LISTJAVASCRIPT Line 4443  LISTJAVASCRIPT
     my $cdom      = $env{"course.$env{'request.course.id'}.domain"};      my $cdom      = $env{"course.$env{'request.course.id'}.domain"};
     my $cnum      = $env{"course.$env{'request.course.id'}.num"};      my $cnum      = $env{"course.$env{'request.course.id'}.num"};
     my $getsec    = $env{'form.section'} eq '' ? 'all' : $env{'form.section'};      my $getsec    = $env{'form.section'} eq '' ? 'all' : $env{'form.section'};
     my $getgroup  = $env{'form.group'} eq '' ? 'all' : $env{'form.group'};  
   
     my $result='<h3><span class="LC_info">&nbsp;'.      my $result='<h3><span class="LC_info">&nbsp;'.
  &mt('Manual Grading by Page or Sequence').'</span></h3>';   &mt('Manual Grading by Page or Sequence').'</span></h3>';
Line 5074  LISTJAVASCRIPT Line 4461  LISTJAVASCRIPT
     # Collection of hidden fields      # Collection of hidden fields
     my $ctr=0;      my $ctr=0;
     foreach (@$titles) {      foreach (@$titles) {
  my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);          my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
  $result.='<input type="hidden" name="page'.$ctr.'" value="'.$$symbx{$_}.'" />'."\n";          $result.='<input type="hidden" name="page'.$ctr.'" value="'.$$symbx{$_}.'" />'."\n";
  $result.='<input type="hidden" name="title'.$ctr.'" value="'.$showtitle.'" />'."\n";          $result.='<input type="hidden" name="title'.$ctr.'" value="'.$showtitle.'" />'."\n";
  $ctr++;          $ctr++;
     }      }
     $result.='<input type="hidden" name="page" />'."\n".      $result.='<input type="hidden" name="page" />'."\n".
  '<input type="hidden" name="title" />'."\n";          '<input type="hidden" name="title" />'."\n";
   
     $result.=&build_section_inputs();      $result.=&build_section_inputs();
     my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));      my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));
     $result.='<input type="hidden" name="Status"  value="'.$stu_status.'" />'."\n".      $result.='<input type="hidden" name="Status"  value="'.$stu_status.'" />'."\n".
         '<input type="hidden" name="command" value="displayPage" />'."\n".   '<input type="hidden" name="command" value="displayPage" />'."\n".
         '<input type="hidden" name="symb"    value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";   '<input type="hidden" name="symb"    value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";
   
     # Show grading options      # Show grading options
     $result.=&Apache::lonhtmlcommon::start_pick_box();      $result.=&Apache::lonhtmlcommon::start_pick_box();
     my $select = '<select name="selectpage">'."\n";      my $select = '<select name="selectpage">'."\n";
     $ctr=0;      $ctr=0;
     foreach (@$titles) {      foreach (@$titles) {
         my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);   my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
         $select.='<option value="'.$ctr.'"'.   $select.='<option value="'.$ctr.'"'.
             ($$symbx{$_} =~ /$curpage$/ ? ' selected="selected"' : '').      ($$symbx{$_} =~ /$curpage$/ ? ' selected="selected"' : '').
             '>'.$showtitle.'</option>'."\n";      '>'.$showtitle.'</option>'."\n";
         $ctr++;   $ctr++;
     }      }
     $select.= '</select>';      $select.= '</select>';
   
Line 5123  LISTJAVASCRIPT Line 4510  LISTJAVASCRIPT
        .'<label><input type="radio" name="lastSub" value="all" /> '         .'<label><input type="radio" name="lastSub" value="all" /> '
            .&mt('all submissions with details').' </label>'             .&mt('all submissions with details').' </label>'
        .&Apache::lonhtmlcommon::row_closure();         .&Apache::lonhtmlcommon::row_closure();
       
     $result.=      $result.=
         &Apache::lonhtmlcommon::row_title(&mt('Use CODE'))          &Apache::lonhtmlcommon::row_title(&mt('Use CODE'))
        .'<input type="text" name="CODE" value="" />'         .'<input type="text" name="CODE" value="" />'
Line 5145  LISTJAVASCRIPT Line 4532  LISTJAVASCRIPT
  '<th>'.&nameUserString('header').'</th>'.   '<th>'.&nameUserString('header').'</th>'.
  &Apache::loncommon::end_data_table_header_row();   &Apache::loncommon::end_data_table_header_row();
     
     my (undef,undef,$fullname) = &getclasslist($getsec,'1',$getgroup);      my (undef,undef,$fullname) = &getclasslist($getsec,'1');
     my $ptr = 1;      my $ptr = 1;
     foreach my $student (sort       foreach my $student (sort 
  {   {
Line 5226  sub displayPage { Line 4613  sub displayPage {
     &Apache::lonnet::clear_EXT_cache_status();      &Apache::lonnet::clear_EXT_cache_status();
   
     if (!&canview($usec)) {      if (!&canview($usec)) {
  $request->print(   $request->print('<span class="LC_warning">'.&mt('Unable to view requested student. ([_1])',$env{'form.student'}).'</span>');
             '<span class="LC_warning">'.   return;
             &mt('Unable to view requested student. ([_1])',  
                 $env{'form.student'}).  
             '</span>');  
         return;  
     }      }
     my $result='<h3><span class="LC_info">&nbsp;'.$env{'form.title'}.'</span></h3>';      my $result='<h3><span class="LC_info">&nbsp;'.$env{'form.title'}.'</span></h3>';
     $result.='<h3>&nbsp;'.&mt('Student: [_1]',&nameUserString(undef,$$fullname{$env{'form.student'}},$uname,$udom)).      $result.='<h3>&nbsp;'.&mt('Student: [_1]',&nameUserString(undef,$$fullname{$env{'form.student'}},$uname,$udom)).
Line 5342  sub displayPage { Line 4725  sub displayPage {
  }   }
     } elsif ($env{'form.lastSub'} eq 'all') {      } elsif ($env{'form.lastSub'} eq 'all') {
  my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : '');   my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : '');
                 my $identifier = (&canmodify($usec)? $prob : '');  
  $studentTable.=&Apache::loncommon::get_previous_attempt($symbx,$uname,$udom,   $studentTable.=&Apache::loncommon::get_previous_attempt($symbx,$uname,$udom,
  $env{'request.course.id'},   $env{'request.course.id'},
  '','.submission',undef,   '','.submission');
                                                                         $usec,$identifier);  
     
     }      }
     if (&canmodify($usec)) {      if (&canmodify($usec)) {
Line 5398  sub displaySubByDates { Line 4779  sub displaySubByDates {
   
     my $interaction;      my $interaction;
     my $no_increment = 1;      my $no_increment = 1;
     my (%lastrndseed,%lasttype);      my %lastrndseed;
     for ($version=1;$version<=$$record{'version'};$version++) {      for ($version=1;$version<=$$record{'version'};$version++) {
  my $timestamp =    my $timestamp = 
     &Apache::lonlocal::locallocaltime($$record{$version.':timestamp'});      &Apache::lonlocal::locallocaltime($$record{$version.':timestamp'});
Line 5426  sub displaySubByDates { Line 4807  sub displaySubByDates {
             if (($type eq 'anonsurvey') || ($type eq 'anonsurveycred')) {              if (($type eq 'anonsurvey') || ($type eq 'anonsurveycred')) {
                 $hidden = 1;                  $hidden = 1;
             }              }
     my @matchKey;      my @matchKey = ($isTask ? sort(grep /^resource\.\d+\.\Q$partid\E\.award$/,@versionKeys)
             if ($isTask) {              : sort(grep /^resource\.\Q$partid\E\..*?\.submission$/,@versionKeys));
                 @matchKey = sort(grep(/^resource\.\d+\.\Q$partid\E\.award$/,@versionKeys));      
             } else {  
  @matchKey = sort(grep(/^resource\.\Q$partid\E\..*?\.submission$/,@versionKeys));  
             }  
 #    next if ($$record{"$version:resource.$partid.solved"} eq '');  #    next if ($$record{"$version:resource.$partid.solved"} eq '');
     my $display_part=&get_display_part($partid,$symb);      my $display_part=&get_display_part($partid,$symb);
     foreach my $matchKey (@matchKey) {      foreach my $matchKey (@matchKey) {
Line 5459  sub displaySubByDates { Line 4837  sub displaySubByDates {
         } else {          } else {
     $displaySub[0].=&mt('Trial: [_1]',      $displaySub[0].=&mt('Trial: [_1]',
     $$record{"$where.$partid.tries"});      $$record{"$where.$partid.tries"});
                             if (($rndseed ne '')  && ($lastrndseed{$partid} ne '')) {                              if ($rndseed || $lastrndseed{$partid}) {
                                 if (($rndseed ne $lastrndseed{$partid}) &&                                  if ($rndseed ne $lastrndseed{$partid}) {
                                     (($type eq 'randomizetry') || ($lasttype{$partid} eq 'randomizetry'))) {  
                                     $newvariation = '&nbsp;('.&mt('New variation this try').')';                                      $newvariation = '&nbsp;('.&mt('New variation this try').')';
                                 }                                  }
                             }                              }
                             $lastrndseed{$partid} = $rndseed;                              $lastrndseed{$partid} = $rndseed;
                             $lasttype{$partid} = $type;  
         }          }
         my $responseType=($isTask ? 'Task'          my $responseType=($isTask ? 'Task'
                                               : $responseType->{$partid}->{$responseId});                                                : $responseType->{$partid}->{$responseId});
Line 5564  sub updateGradeByPage { Line 4940  sub updateGradeByPage {
   
     $iterator->next(); # skip the first BEGIN_MAP      $iterator->next(); # skip the first BEGIN_MAP
     my $curRes = $iterator->next(); # for "current resource"      my $curRes = $iterator->next(); # for "current resource"
     my ($depth,$question,$prob,$changeflag,$hideflag)= (1,1,1,0,0);      my ($depth,$question,$prob,$changeflag)= (1,1,1,0);
     while ($depth > 0) {      while ($depth > 0) {
         if($curRes == $iterator->BEGIN_MAP) { $depth++; }          if($curRes == $iterator->BEGIN_MAP) { $depth++; }
         if($curRes == $iterator->END_MAP) { $depth--; }          if($curRes == $iterator->END_MAP) { $depth--; }
Line 5585  sub updateGradeByPage { Line 4961  sub updateGradeByPage {
     my @displayPts=();      my @displayPts=();
             my %aggregate = ();              my %aggregate = ();
             my $aggregateflag = 0;              my $aggregateflag = 0;
             if ($env{'form.HIDE'.$prob}) {  
                 my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname);  
                 my ($version,$parts) = split(/:/,$env{'form.HIDE'.$prob},2);  
                 my $numchgs = &makehidden($version,$parts,\%record,$symbx,$udom,$uname,1);  
                 $hideflag += $numchgs;  
             }  
     foreach my $partid (@{$parts}) {      foreach my $partid (@{$parts}) {
  my $newpts = $env{'form.GD_BOX'.$question.'_'.$partid};   my $newpts = $env{'form.GD_BOX'.$question.'_'.$partid};
  my $oldpts = $env{'form.oldpts'.$question.'_'.$partid};   my $oldpts = $env{'form.oldpts'.$question.'_'.$partid};
Line 5681  sub updateGradeByPage { Line 5051  sub updateGradeByPage {
     $studentTable.=&Apache::loncommon::end_data_table();      $studentTable.=&Apache::loncommon::end_data_table();
     my $grademsg=($changeflag == 0 ? &mt('No score was changed or updated.') :      my $grademsg=($changeflag == 0 ? &mt('No score was changed or updated.') :
   &mt('The scores were changed for [quant,_1,problem].',    &mt('The scores were changed for [quant,_1,problem].',
   $changeflag).'<br />');    $changeflag));
     my $hidemsg=($hideflag == 0 ? '' :      $request->print($grademsg.$studentTable);
                  &mt('Submissions were marked "hidden" for [quant,_1,transaction].',  
                      $hideflag).'<br />');  
     $request->print($hidemsg.$grademsg.$studentTable);  
   
     return '';      return '';
 }  }
Line 5759  the homework problem. Line 5126  the homework problem.
   
 sub defaultFormData {  sub defaultFormData {
     my ($symb)=@_;      my ($symb)=@_;
     return '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />';      return '<input type="hidden" name="symb"    value="'.&Apache::lonenc::check_encrypt($symb).'" />';
 }  }
   
   
Line 5912  sub scantron_uploads { Line 5279  sub scantron_uploads {
 sub scantron_scantab {  sub scantron_scantab {
     my $result='<select name="scantron_format">'."\n";      my $result='<select name="scantron_format">'."\n";
     $result.='<option></option>'."\n";      $result.='<option></option>'."\n";
     my @lines = &Apache::lonnet::get_scantronformat_file();      my @lines = &get_scantronformat_file();
     if (@lines > 0) {      if (@lines > 0) {
         foreach my $line (@lines) {          foreach my $line (@lines) {
             next if (($line =~ /^\#/) || ($line eq ''));              next if (($line =~ /^\#/) || ($line eq ''));
Line 5924  sub scantron_scantab { Line 5291  sub scantron_scantab {
     return $result;      return $result;
 }  }
   
   =pod
   
   =item get_scantronformat_file
   
     Returns an array containing lines from the scantron format file for
     the domain of the course.
   
     If a url for a custom.tab file is listed in domain's configuration.db, 
     lines are from this file.
   
     Otherwise, if a default.tab has been published in RES space by the 
     domainconfig user, lines are from this file.
   
     Otherwise, fall back to getting lines from the legacy file on the
     local server:  /home/httpd/lonTabs/default_scantronformat.tab    
   
   =cut
   
   sub get_scantronformat_file {
       my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'};
       my %domconfig = &Apache::lonnet::get_dom('configuration',['scantron'],$cdom);
       my $gottab = 0;
       my @lines;
       if (ref($domconfig{'scantron'}) eq 'HASH') {
           if ($domconfig{'scantron'}{'scantronformat'} ne '') {
               my $formatfile = &Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonDocRoot'}.$domconfig{'scantron'}{'scantronformat'});
               if ($formatfile ne '-1') {
                   @lines = split("\n",$formatfile,-1);
                   $gottab = 1;
               }
           }
       }
       if (!$gottab) {
           my $confname = $cdom.'-domainconfig';
           my $default = $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'.$cdom.'/'.$confname.'/default.tab';
           my $formatfile =  &Apache::lonnet::getfile($default);
           if ($formatfile ne '-1') {
               @lines = split("\n",$formatfile,-1);
               $gottab = 1;
           }
       }
       if (!$gottab) {
           my @domains = &Apache::lonnet::current_machine_domains();
           if (grep(/^\Q$cdom\E$/,@domains)) {
               my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
               @lines = <$fh>;
               close($fh);
           } else {
               my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab');
               @lines = <$fh>;
               close($fh);
           }
       }
       return @lines;
   }
   
 =pod   =pod 
   
 =item scantron_CODElist  =item scantron_CODElist
Line 6005  sub scantron_selectphase { Line 5428  sub scantron_selectphase {
     if (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) ||      if (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) ||
         &Apache::lonnet::allowed('usc',$env{'request.course.id'})) {          &Apache::lonnet::allowed('usc',$env{'request.course.id'})) {
   
         # Chunk of form to prompt for a scantron file upload.   # Chunk of form to prompt for a scantron file upload.
   
         $r->print('          $r->print('
     <br />');      <br />
         my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'};      '.&Apache::loncommon::start_data_table('LC_scantron_action').'
         my $cnum= $env{'course.'.$env{'request.course.id'}.'.num'};         '.&Apache::loncommon::start_data_table_header_row().'
         my $alertmsg = &mt('Please use the browse button to select a file from your local directory.');              <th>
         &js_escape(\$alertmsg);                &nbsp;'.&mt('Specify a bubblesheet data file to upload.').'
         my ($formatoptions,$formattitle,$formatjs) = &scantron_upload_dataformat($cdom);              </th>
         $r->print(&Apache::lonhtmlcommon::scripttag('         '.&Apache::loncommon::end_data_table_header_row().'
          '.&Apache::loncommon::start_data_table_row().'
               <td>
   ');
       my $default_form_data=&defaultFormData($symb);
       my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'};
       my $cnum= $env{'course.'.$env{'request.course.id'}.'.num'};
       $r->print(&Apache::lonhtmlcommon::scripttag('
     function checkUpload(formname) {      function checkUpload(formname) {
         if (formname.upfile.value == "") {   if (formname.upfile.value == "") {
             alert("'.$alertmsg.'");      alert("'.&mt('Please use the browse button to select a file from your local directory.').'");
             return false;      return false;
         }   }
         formname.submit();   formname.submit();
     }'."\n".$formatjs));      }'));
         $r->print('      $r->print('
               <form enctype="multipart/form-data" action="/adm/grades" name="rules" method="post">                <form enctype="multipart/form-data" action="/adm/grades" name="rules" method="post">
                 '.$default_form_data.'                  '.$default_form_data.'
                 <input name="courseid" type="hidden" value="'.$cnum.'" />                  <input name="courseid" type="hidden" value="'.$cnum.'" />
                 <input name="domainid" type="hidden" value="'.$cdom.'" />                  <input name="domainid" type="hidden" value="'.$cdom.'" />
                 <input name="command" value="scantronupload_save" type="hidden" />                  <input name="command" value="scantronupload_save" type="hidden" />
               '.&Apache::loncommon::start_data_table('LC_scantron_action').'                  '.&mt('File to upload: [_1]','<input type="file" name="upfile" size="50" />').'
               '.&Apache::loncommon::start_data_table_header_row().'                  <br />
                 <th>                  <input type="button" onclick="javascript:checkUpload(this.form);" value="'.&mt('Upload Bubblesheet Data').'" />
                 &nbsp;'.&mt('Specify a bubblesheet data file to upload.').'                </form>
                 </th>  ');
               '.&Apache::loncommon::end_data_table_header_row().'  
               '.&Apache::loncommon::start_data_table_row().'  
             <td>  
                 '.&mt('File to upload: [_1]','<input type="file" name="upfile" size="50" />').'<br />'."\n");  
         if ($formatoptions) {  
             $r->print('</td>  
                  '.&Apache::loncommon::end_data_table_row().'  
                  '.&Apache::loncommon::start_data_table_row().'  
                  <td>'.$formattitle.('&nbsp;'x2).$formatoptions.'  
                  </td>  
                  '.&Apache::loncommon::end_data_table_row().'  
                  '.&Apache::loncommon::start_data_table_row().'  
                  <td>'  
             );  
         } else {  
             $r->print(' <br />');  
         }  
         $r->print('<input type="button" onclick="javascript:checkUpload(this.form);" value="'.&mt('Upload Bubblesheet Data').'" />  
               </td>  
              '.&Apache::loncommon::end_data_table_row().'  
              '.&Apache::loncommon::end_data_table().'  
              </form>'  
         );  
   
           $r->print('
               </td>
          '.&Apache::loncommon::end_data_table_row().'
          '.&Apache::loncommon::end_data_table().'
   ');
     }      }
   
     # Chunk of form to prompt for a file to grade and how:      # Chunk of form to prompt for a file to grade and how:
Line 6106  sub scantron_selectphase { Line 5518  sub scantron_selectphase {
         
     $r->print($result);      $r->print($result);
   
   
   
     # Chunk of the form that prompts to view a scoring office file,      # Chunk of the form that prompts to view a scoring office file,
     # corrected file, skipped records in a file.      # corrected file, skipped records in a file.
   
Line 6167  sub scantron_selectphase { Line 5581  sub scantron_selectphase {
     return;      return;
 }  }
   
   =pod
   
   =item get_scantron_config
   
      Parse and return the scantron configuration line selected as a
      hash of configuration file fields.
   
    Arguments:
       which - the name of the configuration to parse from the file.
   
   
    Returns:
               If the named configuration is not in the file, an empty
               hash is returned.
       a hash with the fields
         name         - internal name for the this configuration setup
         description  - text to display to operator that describes this config
         CODElocation - if 0 or the string 'none'
                             - no CODE exists for this config
                        if -1 || the string 'letter'
                             - a CODE exists for this config and is
                               a string of letters
                        Unsupported value (but planned for future support)
                             if a positive integer
                                  - The CODE exists as the first n items from
                                    the question section of the form
                             if the string 'number'
                                  - The CODE exists for this config and is
                                    a string of numbers
         CODEstart   - (only matter if a CODE exists) column in the line where
                        the CODE starts
         CODElength  - length of the CODE
         IDstart     - column where the student/employee ID starts
         IDlength    - length of the student/employee ID info
         Qstart      - column where the information from the bubbled
                       'questions' start
         Qlength     - number of columns comprising a single bubble line from
                       the sheet. (usually either 1 or 10)
         Qon         - either a single character representing the character used
                       to signal a bubble was chosen in the positional setup, or
                       the string 'letter' if the letter of the chosen bubble is
                       in the final, or 'number' if a number representing the
                       chosen bubble is in the file (1->A 0->J)
         Qoff        - the character used to represent that a bubble was
                       left blank
         PaperID     - if the scanning process generates a unique number for each
                       sheet scanned the column that this ID number starts in
         PaperIDlength - number of columns that comprise the unique ID number
                         for the sheet of paper
         FirstName   - column that the first name starts in
         FirstNameLength - number of columns that the first name spans
    
         LastName    - column that the last name starts in
         LastNameLength - number of columns that the last name spans
         BubblesPerRow - number of bubbles available in each row used to 
                         bubble an answer. (If not specified, 10 assumed).
   
   =cut
   
   sub get_scantron_config {
       my ($which) = @_;
       my @lines = &get_scantronformat_file();
       my %config;
       #FIXME probably should move to XML it has already gotten a bit much now
       foreach my $line (@lines) {
    my ($name,$descrip)=split(/:/,$line);
    if ($name ne $which ) { next; }
    chomp($line);
    my @config=split(/:/,$line);
    $config{'name'}=$config[0];
    $config{'description'}=$config[1];
    $config{'CODElocation'}=$config[2];
    $config{'CODEstart'}=$config[3];
    $config{'CODElength'}=$config[4];
    $config{'IDstart'}=$config[5];
    $config{'IDlength'}=$config[6];
    $config{'Qstart'}=$config[7];
     $config{'Qlength'}=$config[8];
    $config{'Qoff'}=$config[9];
    $config{'Qon'}=$config[10];
    $config{'PaperID'}=$config[11];
    $config{'PaperIDlength'}=$config[12];
    $config{'FirstName'}=$config[13];
    $config{'FirstNamelength'}=$config[14];
    $config{'LastName'}=$config[15];
    $config{'LastNamelength'}=$config[16];
           $config{'BubblesPerRow'}=$config[17];
    last;
       }
       return %config;
   }
   
 =pod   =pod 
   
 =item username_to_idmap  =item username_to_idmap
Line 6190  sub username_to_idmap { Line 5696  sub username_to_idmap {
     my ($classlist)= @_;      my ($classlist)= @_;
     my %idmap;      my %idmap;
     foreach my $student (keys(%$classlist)) {      foreach my $student (keys(%$classlist)) {
         my $id = $classlist->{$student}->[&Apache::loncoursedata::CL_ID];   $idmap{$classlist->{$student}->[&Apache::loncoursedata::CL_ID]}=
         unless ($id eq '') {      $student;
             if (!exists($idmap{$id})) {  
                 $idmap{$id} = $student;  
             } else {  
                 my $status = $classlist->{$student}->[&Apache::loncoursedata::CL_STATUS];  
                 if ($status eq 'Active') {  
                     $idmap{$id} = $student;  
                 }  
             }  
         }  
     }      }
     return %idmap;      return %idmap;
 }  }
Line 6212  sub username_to_idmap { Line 5709  sub username_to_idmap {
    Process a requested correction to a scanline.     Process a requested correction to a scanline.
   
   Arguments:    Arguments:
     $scantron_config   - hash from &Apache::lonnet::get_scantron_config()      $scantron_config   - hash from &get_scantron_config()
     $scan_data         - hash of correction information       $scan_data         - hash of correction information 
                           (see &scantron_getfile())                            (see &scantron_getfile())
     $line              - existing scanline      $line              - existing scanline
Line 6402  sub digits_to_letters { Line 5899  sub digits_to_letters {
     totalref         - Ref of scalar used to score total number of bubble      totalref         - Ref of scalar used to score total number of bubble
                        lines needed for responses in a scan line (used when                         lines needed for responses in a scan line (used when
                        randompick in use.                          randompick in use. 
       
  Returns:   Returns:
    Hash containing the result of parsing the scanline     Hash containing the result of parsing the scanline
   
Line 6495  sub scantron_parse_scanline { Line 5992  sub scantron_parse_scanline {
                                          $partids_by_symb,$orderedforcode,                                           $partids_by_symb,$orderedforcode,
                                          $respnumlookup,$startline);                                           $respnumlookup,$startline);
         if ($total) {          if ($total) {
             $lastpos = $total*$$scantron_config{'Qlength'};              $lastpos = $total*$$scantron_config{'Qlength'}; 
         }          }
         if (ref($totalref)) {          if (ref($totalref)) {
             $$totalref = $total;              $$totalref = $total;
Line 6509  sub scantron_parse_scanline { Line 6006  sub scantron_parse_scanline {
         if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) {          if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) {
             $answers_needed = $bubble_lines_per_response{$respnumlookup->{$questnum}};              $answers_needed = $bubble_lines_per_response{$respnumlookup->{$questnum}};
         } else {          } else {
             $answers_needed = $bubble_lines_per_response{$questnum};      $answers_needed = $bubble_lines_per_response{$questnum};
         }          }
         my $answer_length  = ($$scantron_config{'Qlength'} * $answers_needed)          my $answer_length  = ($$scantron_config{'Qlength'} * $answers_needed)
                              || 1;                               || 1;
Line 6570  sub scantron_parse_scanline { Line 6067  sub scantron_parse_scanline {
   
 sub get_master_seq {  sub get_master_seq {
     my ($resources,$master_seq,$symb_to_resource) = @_;      my ($resources,$master_seq,$symb_to_resource) = @_;
     return unless ((ref($resources) eq 'ARRAY') && (ref($master_seq) eq 'ARRAY') &&      return unless ((ref($resources) eq 'ARRAY') && (ref($master_seq) eq 'ARRAY') && 
                    (ref($symb_to_resource) eq 'HASH'));                     (ref($symb_to_resource) eq 'HASH'));
     my $resource_error;      my $resource_error;
     foreach my $resource (@{$resources}) {      foreach my $resource (@{$resources}) {
Line 6648  sub scantron_validator_lettnum { Line 6145  sub scantron_validator_lettnum {
     my $occurrences = 0;      my $occurrences = 0;
     my $responsenum = $questnum-1;      my $responsenum = $questnum-1;
     if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) {      if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) {
        $responsenum = $respnumlookup->{$questnum-1}         $responsenum = $respnumlookup->{$questnum-1} 
     }      }
     if (($responsetype_per_response{$responsenum} eq 'essayresponse') ||      if (($responsetype_per_response{$responsenum} eq 'essayresponse') ||
         ($responsetype_per_response{$responsenum} eq 'formularesponse') ||          ($responsetype_per_response{$responsenum} eq 'formularesponse') ||
Line 6895  sub scantron_filter { Line 6392  sub scantron_filter {
   
 sub scantron_process_corrections {  sub scantron_process_corrections {
     my ($r) = @_;      my ($r) = @_;
     my %scantron_config=&Apache::lonnet::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 $classlist=&Apache::loncoursedata::get_classlist();      my $classlist=&Apache::loncoursedata::get_classlist();
     my $which=$env{'form.scantron_line'};      my $which=$env{'form.scantron_line'};
Line 6944  sub scantron_process_corrections { Line 6441  sub scantron_process_corrections {
  }   }
     }      }
     if ($err) {      if ($err) {
  $r->print(          $r->print(
             '<p class="LC_error">'              '<p class="LC_error">'
            .&mt('Unable to accept last correction, an error occurred: [_1]',             .&mt('Unable to accept last correction, an error occurred: [_1]',
                 $errmsg)                  $errmsg)
Line 7064  sub check_for_error { Line 6561  sub check_for_error {
 sub scantron_warning_screen {  sub scantron_warning_screen {
     my ($button_text,$symb)=@_;      my ($button_text,$symb)=@_;
     my $title=&Apache::lonnet::gettitle($env{'form.selectpage'});      my $title=&Apache::lonnet::gettitle($env{'form.selectpage'});
     my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
     my $CODElist;      my $CODElist;
     if ($scantron_config{'CODElocation'} &&      if ($scantron_config{'CODElocation'} &&
  $scantron_config{'CODEstart'} &&   $scantron_config{'CODEstart'} &&
  $scantron_config{'CODElength'}) {   $scantron_config{'CODElength'}) {
  $CODElist=$env{'form.scantron_CODElist'};   $CODElist=$env{'form.scantron_CODElist'};
  if ($env{'form.scantron_CODElist'} eq '') { $CODElist='<span class="LC_warning">'.&mt('None').'</span>'; }   if ($env{'form.scantron_CODElist'} eq '') { $CODElist='<span class="LC_warning">None</span>'; }
  $CODElist=   $CODElist=
     '<tr><td><b>'.&mt('List of CODES to validate against:').'</b></td><td><tt>'.      '<tr><td><b>'.&mt('List of CODES to validate against:').'</b></td><td><tt>'.
     $env{'form.scantron_CODElist'}.'</tt></td></tr>';      $env{'form.scantron_CODElist'}.'</tt></td></tr>';
Line 7220  sub scantron_validate_file { Line 6717  sub scantron_validate_file {
     #get the student pick code ready      #get the student pick code ready
     $r->print(&Apache::loncommon::studentbrowser_javascript());      $r->print(&Apache::loncommon::studentbrowser_javascript());
     my $nav_error;      my $nav_error;
     my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
     my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config);      my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config);
     if ($nav_error) {      if ($nav_error) {
         $r->print(&navmap_errormsg());          $r->print(&navmap_errormsg());
Line 7247  sub scantron_validate_file { Line 6744  sub scantron_validate_file {
     while (!$stop && $currentphase < scalar(@validate_phases)) {      while (!$stop && $currentphase < scalar(@validate_phases)) {
  $r->print(&mt('Validating '.$validate_phases[$currentphase]).'<br />');   $r->print(&mt('Validating '.$validate_phases[$currentphase]).'<br />');
  $r->rflush();   $r->rflush();
        
  my $which="scantron_validate_".$validate_phases[$currentphase];   my $which="scantron_validate_".$validate_phases[$currentphase];
  {   {
     no strict 'refs';      no strict 'refs';
Line 7277  sub scantron_validate_file { Line 6774  sub scantron_validate_file {
     $r->print('<input type="submit" name="submit" value="'.&mt('Ignore').' &rarr; " />');      $r->print('<input type="submit" name="submit" value="'.&mt('Ignore').' &rarr; " />');
     $r->print(' '.&mt('this error').' <br />');      $r->print(' '.&mt('this error').' <br />');
   
             $r->print('<p>'.&mt('Or return to [_1]Grade/Manage/Review Bubblesheets[_2] to start over.','<a href="/adm/grades?symb='.$symb.'&command=scantron_selectphase" class="LC_info">','</a>').'</p>');      $r->print('<p>'.&mt('Or return to [_1]Grade/Manage/Review Bubblesheets[_2] to start over.','<a href="/adm/grades?symb='.$symb.'&command=scantron_selectphase" class="LC_info">','</a>').'</p>');
  } else {   } else {
             if ($validate_phases[$currentphase] eq 'doublebubble' || $validate_phases[$currentphase] eq 'missingbubbles') {              if ($validate_phases[$currentphase] eq 'doublebubble' || $validate_phases[$currentphase] eq 'missingbubbles') {
         $r->print('<input type="button" name="submitbutton" value="'.&mt('Continue').' &rarr;" onclick="javascript:verify_bubble_radio(this.form)" />');          $r->print('<input type="button" name="submitbutton" value="'.&mt('Continue').' &rarr;" onclick="javascript:verify_bubble_radio(this.form)" />');
Line 7656  sub scantron_validate_sequence { Line 7153  sub scantron_validate_sequence {
  my @resources=   my @resources=
     $navmap->retrieveResources($map,\&scantron_filter_not_exam,1,0);      $navmap->retrieveResources($map,\&scantron_filter_not_exam,1,0);
  if (@resources) {   if (@resources) {
     $r->print('<p class="LC_warning">'      $r->print(
                   '<p class="LC_warning">'
                .&mt('Some resources in the sequence currently are not set to'                 .&mt('Some resources in the sequence currently are not set to'
                    .' exam mode. Grading these resources currently may not'                     .' bubblesheet exam mode. Grading these resources currently may not'
                    .' work correctly.')                     .' work correctly.')
                .'</p>'                 .'</p>'
             );              );
Line 7679  sub scantron_validate_ID { Line 7177  sub scantron_validate_ID {
     my %idmap=&username_to_idmap($classlist);      my %idmap=&username_to_idmap($classlist);
   
     #get scantron line setup      #get scantron line setup
     my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
   
     my $nav_error;      my $nav_error;
Line 7780  sub scantron_get_correction { Line 7278  sub scantron_get_correction {
   
     if ($error =~ /ID$/) {      if ($error =~ /ID$/) {
  if ($error eq 'incorrectID') {   if ($error eq 'incorrectID') {
     $r->print('<p class="LC_warning">'.&mt("The encoded ID is not in the classlist").              $r->print('<p class="LC_warning">'.&mt("The encoded ID is not in the classlist").
       "</p>\n");        "</p>\n");
  } elsif ($error eq 'duplicateID') {   } elsif ($error eq 'duplicateID') {
     $r->print('<p class="LC_warning">'.&mt("The encoded ID has also been used by a previous paper [_1]",$arg)."</p>\n");              $r->print('<p class="LC_warning">'.&mt("The encoded ID has also been used by a previous paper [_1]",$arg)."</p>\n");
  }   }
  $r->print($message);   $r->print($message);
  $r->print("<p>".&mt("How should I handle this?")." <br /> \n");   $r->print("<p>".&mt("How should I handle this?")." <br /> \n");
Line 7803  sub scantron_get_correction { Line 7301  sub scantron_get_correction {
  } elsif ($error eq 'duplicateCODE') {   } elsif ($error eq 'duplicateCODE') {
     $r->print('<p class="LC_warning">'.&mt("The encoded CODE has also been used by a previous paper [_1], and CODEs are supposed to be unique.",join(', ',@{$arg}))."</p>\n");      $r->print('<p class="LC_warning">'.&mt("The encoded CODE has also been used by a previous paper [_1], and CODEs are supposed to be unique.",join(', ',@{$arg}))."</p>\n");
  }   }
         $r->print("<p>".&mt('The CODE on the form is [_1]',   $r->print("<p>".&mt('The CODE on the form is [_1]',
                             "<tt>'$$scan_record{'scantron.CODE'}'</tt>")      "<tt>'$$scan_record{'scantron.CODE'}'</tt>")
                  ."</p>\n");                   ."</p>\n");
  $r->print($message);   $r->print($message);
  $r->print("<p>".&mt("How should I handle this?")."</p>\n");   $r->print("<p>".&mt("How should I handle this?")."</p>\n");
Line 7901  ENDSCRIPT Line 7399  ENDSCRIPT
  # The form field scantron_questions is actually a list of line numbers not   # The form field scantron_questions is actually a list of line numbers not
  # a list of question numbers. Therefore:   # a list of question numbers. Therefore:
  #   #
   
  my $line_list = &questions_to_line_list($arg,$randomorder,$randompick,   my $line_list = &questions_to_line_list($arg,$randomorder,$randompick,
                                                 $respnumlookup,$startline);                                                  $respnumlookup,$startline);
   
Line 7925  sub verify_bubbles_checked { Line 7423  sub verify_bubbles_checked {
     my (@ansnums) = @_;      my (@ansnums) = @_;
     my $ansnumstr = join('","',@ansnums);      my $ansnumstr = join('","',@ansnums);
     my $warning = &mt("A bubble or 'No bubble' selection has not been made for one or more lines.");      my $warning = &mt("A bubble or 'No bubble' selection has not been made for one or more lines.");
     &js_escape(\$warning);      my $output = &Apache::lonhtmlcommon::scripttag((<<ENDSCRIPT));
     my $output = &Apache::lonhtmlcommon::scripttag(<<ENDSCRIPT);  
 function verify_bubble_radio(form) {  function verify_bubble_radio(form) {
     var ansnumArray = new Array ("$ansnumstr");      var ansnumArray = new Array ("$ansnumstr");
     var need_bubble_count = 0;      var need_bubble_count = 0;
Line 8011  sub questions_to_line_list { Line 7508  sub questions_to_line_list {
             } else {              } else {
                 $first = $first_bubble_line{$responsenum} + 1;                  $first = $first_bubble_line{$responsenum} + 1;
             }              }
             $count   = $bubble_lines_per_response{$responsenum};      $count   = $bubble_lines_per_response{$responsenum};
         }          }
         $last = $first+$count-1;          $last = $first+$count-1;
         push(@lines, ($first..$last));          push(@lines, ($first..$last));
Line 8042  for multi and missing bubble cases). Line 7539  for multi and missing bubble cases).
                   and value is number of first bubble line for current student                    and value is number of first bubble line for current student
                   or code-based randompick and/or randomorder.                    or code-based randompick and/or randomorder.
   
   
  Implicit inputs:   Implicit inputs:
    %bubble_lines_per_response   - Starting line numbers for each question.     %bubble_lines_per_response   - Starting line numbers for each question.
                                   Numbered from 0 (but question numbers are from                                    Numbered from 0 (but question numbers are from
Line 8081  sub prompt_for_corrections { Line 7579  sub prompt_for_corrections {
             }              }
         } else {          } else {
             $responsenum = $question-1;              $responsenum = $question-1;
             $first = $first_bubble_line{$responsenum};              $first = $first_bubble_line{$responsenum} + 1;
         }          }
         $current_line = $first + 1 ;          $current_line = $first + 1 ;
         my @subans = split(/,/,$subdivided_bubble_lines{$responsenum});          my @subans = split(/,/,$subdivided_bubble_lines{$responsenum});
Line 8094  sub prompt_for_corrections { Line 7592  sub prompt_for_corrections {
     } else {      } else {
         if (($randomorder || $randompick) && (ref($respnumlookup) eq 'HASH')) {          if (($randomorder || $randompick) && (ref($respnumlookup) eq 'HASH')) {
             $responsenum = $respnumlookup->{$question-1};              $responsenum = $respnumlookup->{$question-1};
             if (ref($startline) eq 'HASH') {              if (ref($startline) eq 'HASH') { 
                 $first = $startline->{$question-1};                  $first = $startline->{$question-1};
             }              }
         } else {          } else {
Line 8112  sub prompt_for_corrections { Line 7610  sub prompt_for_corrections {
             ($responsetype_per_response{$responsenum} eq 'imageresponse') ||              ($responsetype_per_response{$responsenum} eq 'imageresponse') ||
             ($responsetype_per_response{$responsenum} eq 'reactionresponse') ||              ($responsetype_per_response{$responsenum} eq 'reactionresponse') ||
             ($responsetype_per_response{$responsenum} eq 'organicresponse')) {              ($responsetype_per_response{$responsenum} eq 'organicresponse')) {
             $r->print(&mt("Although this particular question type requires handgrading, the instructions for this question in the bubblesheet exam directed students to leave [quant,_1,line] blank on their bubblesheets.",$lines).'<br /><br />'.&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.').'<br />'.&mt('The score for this question will be a sum of the numeric values for the selected bubbles from each line, where A=1 point, B=2 points etc.').'<br />'.&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.").'<br /><br />');              $r->print(
                   &mt("Although this particular question type requires handgrading, the instructions for this question in the bubblesheet exam directed students to leave [quant,_1,line] blank on their bubblesheets.",$lines)
                  .'<br /><br />'
                  .&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.')
                  .'<br />'
                  .&mt('The score for this question will be a sum of the numeric values for the selected bubbles from each line, where A=1 point, B=2 points etc.')
                  .'<br />'
                  .&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.")
                  .'<br /><br />'
               );
         } else {          } else {
             $r->print(&mt("Select at most one bubble in a single line and select 'No Bubble' in all the other lines. ")."<br />");              $r->print(&mt("Select at most one bubble in a single line and select 'No Bubble' in all the other lines. ")."<br />");
         }          }
Line 8139  sub prompt_for_corrections { Line 7646  sub prompt_for_corrections {
   
  Arguments:   Arguments:
     $r           - Apache request object      $r           - Apache request object
     $scan_config - hash from &Apache::lonnet::get_scantron_config()      $scan_config - hash from &get_scantron_config()
     $line        - Number of the line being displayed.      $line        - Number of the line being displayed.
     $questionnum - Question number (may include subquestion)      $questionnum - Question number (may include subquestion)
     $error       - Type of error.      $error       - Type of error.
Line 8152  sub scantron_bubble_selector { Line 7659  sub scantron_bubble_selector {
     my $max=$$scan_config{'Qlength'};      my $max=$$scan_config{'Qlength'};
   
     my $scmode=$$scan_config{'Qon'};      my $scmode=$$scan_config{'Qon'};
     if ($scmode eq 'number' || $scmode eq 'letter') {      if ($scmode eq 'number' || $scmode eq 'letter') { 
         if (($$scan_config{'BubblesPerRow'} =~ /^\d+$/) &&          if (($$scan_config{'BubblesPerRow'} =~ /^\d+$/) &&
             ($$scan_config{'BubblesPerRow'} > 0)) {              ($$scan_config{'BubblesPerRow'} > 0)) {
             $max=$$scan_config{'BubblesPerRow'};              $max=$$scan_config{'BubblesPerRow'};
Line 8303  sub get_codes { Line 7810  sub get_codes {
   
 sub scantron_validate_CODE {  sub scantron_validate_CODE {
     my ($r,$currentphase) = @_;      my ($r,$currentphase) = @_;
     my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
     if ($scantron_config{'CODElocation'} &&      if ($scantron_config{'CODElocation'} &&
  $scantron_config{'CODEstart'} &&   $scantron_config{'CODEstart'} &&
  $scantron_config{'CODElength'}) {   $scantron_config{'CODElength'}) {
Line 8377  sub scantron_validate_doublebubble { Line 7884  sub scantron_validate_doublebubble {
         &Apache::lonnet::decode_symb($env{'form.selectpage'});          &Apache::lonnet::decode_symb($env{'form.selectpage'});
   
     #get scantron line setup      #get scantron line setup
     my %scantron_config=&Apache::lonnet::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 $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
Line 8471  sub scantron_get_maxbubble { Line 7978  sub scantron_get_maxbubble {
     my $response_number = 0;      my $response_number = 0;
     my $bubble_line     = 0;      my $bubble_line     = 0;
     foreach my $resource (@resources) {      foreach my $resource (@resources) {
         my $resid = $resource->id();          my $resid = $resource->id(); 
         my ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname,          my ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname,
                                                           $udom,undef,$bubbles_per_row);                                                            $udom,undef,$bubbles_per_row);
         if ((ref($analysis) eq 'HASH') && (ref($parts) eq 'ARRAY')) {          if ((ref($analysis) eq 'HASH') && (ref($parts) eq 'ARRAY')) {
Line 8522  sub scantron_get_maxbubble { Line 8029  sub scantron_get_maxbubble {
         $bubble_lines_per_response{$response_number} = $lines;          $bubble_lines_per_response{$response_number} = $lines;
                 $responsetype_per_response{$response_number} =                   $responsetype_per_response{$response_number} = 
                     $analysis->{$part_id.'.type'};                      $analysis->{$part_id.'.type'};
                 $masterseq_id_responsenum{$resid.'_'.$part_id} = $response_number;                  $masterseq_id_responsenum{$resid.'_'.$part_id} = $response_number;  
         $response_number++;          $response_number++;
   
         $bubble_line +=  $lines;          $bubble_line +=  $lines;
Line 8559  sub scantron_validate_missingbubbles { Line 8066  sub scantron_validate_missingbubbles {
         &Apache::lonnet::decode_symb($env{'form.selectpage'});          &Apache::lonnet::decode_symb($env{'form.selectpage'});
   
     #get scantron line setup      #get scantron line setup
     my %scantron_config=&Apache::lonnet::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 $navmap = Apache::lonnavmaps::navmap->new();      my $navmap = Apache::lonnavmaps::navmap->new();
Line 8603  sub scantron_validate_missingbubbles { Line 8110  sub scantron_validate_missingbubbles {
     for (my $i=0;$i<=$scanlines->{'count'};$i++) {      for (my $i=0;$i<=$scanlines->{'count'};$i++) {
  my $line=&scantron_get_line($scanlines,$scan_data,$i);   my $line=&scantron_get_line($scanlines,$scan_data,$i);
  if ($line=~/^[\s\cz]*$/) { next; }   if ($line=~/^[\s\cz]*$/) { next; }
         my $scan_record =   my $scan_record =
             &scantron_parse_scanline($line,$i,\%scantron_config,$scan_data,undef,\%idmap,              &scantron_parse_scanline($line,$i,\%scantron_config,$scan_data,undef,\%idmap,
                                      $randomorder,$randompick,$sequence,\@master_seq,       $randomorder,$randompick,$sequence,\@master_seq,
                                      \%symb_to_resource,\%grader_partids_by_symb,                                       \%symb_to_resource,\%grader_partids_by_symb,
                                      \%orderedforcode,\%respnumlookup,\%startline);                                       \%orderedforcode,\%respnumlookup,\%startline);
  if (!defined($$scan_record{'scantron.missingerror'})) { next; }   if (!defined($$scan_record{'scantron.missingerror'})) { next; }
Line 8616  sub scantron_validate_missingbubbles { Line 8123  sub scantron_validate_missingbubbles {
  foreach my $missing (@{$$scan_record{'scantron.missingerror'}}) {   foreach my $missing (@{$$scan_record{'scantron.missingerror'}}) {
             my $lastbubble;              my $lastbubble;
             if ($missing =~ /^(\d+)\.(\d+)$/) {              if ($missing =~ /^(\d+)\.(\d+)$/) {
                 my $question = $1;                 my $question = $1;
                 my $subquestion = $2;                 my $subquestion = $2;
                 my ($first,$responsenum);                 my ($first,$responsenum);
                 if ($randomorder || $randompick) {                 if ($randomorder || $randompick) {
                     $responsenum = $respnumlookup{$question-1};                     $responsenum = $respnumlookup{$question-1};
                     $first = $startline{$question-1};                     $first = $startline{$question-1};
                 } else {                 } else {
                     $responsenum = $question-1;                     $responsenum = $question-1; 
                     $first = $first_bubble_line{$responsenum};                     $first = $first_bubble_line{$responsenum};
                 }                 }
                 if (!defined($first)) { next; }                 if (!defined($first)) { next; }
                 my @subans = split(/,/,$subdivided_bubble_lines{$responsenum});                 my @subans = split(/,/,$subdivided_bubble_lines{$responsenum});
                 my $subcount = 1;                 my $subcount = 1;
                 while ($subcount<$subquestion) {                 while ($subcount<$subquestion) {
                     $first += $subans[$subcount-1];                     $first += $subans[$subcount-1];
                     $subcount ++;                     $subcount ++;
                 }                 }
                 my $count = $subans[$subquestion-1];                 my $count = $subans[$subquestion-1];
                 $lastbubble = $first + $count;                 $lastbubble = $first + $count;
             } else {              } else {
                 my ($first,$responsenum);                 my ($first,$responsenum);
                 if ($randomorder || $randompick) {                 if ($randomorder || $randompick) {
                     $responsenum = $respnumlookup{$missing-1};                     $responsenum = $respnumlookup{$missing-1};
                     $first = $startline{$missing-1};                     $first = $startline{$missing-1};
                 } else {                 } else {
                     $responsenum = $missing-1;                     $responsenum = $missing-1;
                     $first = $first_bubble_line{$responsenum};                     $first = $first_bubble_line{$responsenum};
                 }                 }
                 if (!defined($first)) { next; }                 if (!defined($first)) { next; }
                 $lastbubble = $first + $bubble_lines_per_response{$responsenum};                 $lastbubble = $first + $bubble_lines_per_response{$responsenum};
             }              }
             if ($lastbubble > $max_bubble) { next; }              if ($lastbubble > $max_bubble) { next; }
     push(@to_correct,$missing);      push(@to_correct,$missing);
Line 8688  sub hand_bubble_option { Line 8195  sub hand_bubble_option {
         }          }
     }      }
     if ($needs_hand_bubbles) {      if ($needs_hand_bubbles) {
         my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});          my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
         my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config);          my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config);
         return &mt('The sequence to be graded contains response types which are handgraded.').'<p>'.          return &mt('The sequence to be graded contains response types which are handgraded.').'<p>'.
                &mt('If you have already graded these by bubbling sheets to indicate points awarded, [_1]what point value is assigned to a filled last bubble in each row?','<br />').                 &mt('If you have already graded these by bubbling sheets to indicate points awarded, [_1]what point value is assigned to a filled last bubble in each row?','<br />').
                '<label><input type="radio" name="scantron_lastbubblepoints" value="'.$bubbles_per_row.'" checked="checked" />'.&mt('[quant,_1,point]',$bubbles_per_row).'</label>&nbsp;'.&mt('or').'&nbsp;'.                 '<label><input type="radio" name="scantron_lastbubblepoints" value="'.$bubbles_per_row.'" checked="checked" />'.&mt('[quant,_1,point]',$bubbles_per_row).'</label>&nbsp;'.&mt('or').'&nbsp;'.
                '<label><input type="radio" name="scantron_lastbubblepoints" value="0" />'.&mt('0 points').'</label></p>';                 '<label><input type="radio" name="scantron_lastbubblepoints" value="0"/>0 points</label></p>';
     }      }
     return;      return;
 }  }
Line 8707  sub scantron_process_students { Line 8214  sub scantron_process_students {
     }      }
     my $default_form_data=&defaultFormData($symb);      my $default_form_data=&defaultFormData($symb);
   
     my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
     my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config);      my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config); 
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
     my $classlist=&Apache::loncoursedata::get_classlist();      my $classlist=&Apache::loncoursedata::get_classlist();
     my %idmap=&username_to_idmap($classlist);      my %idmap=&username_to_idmap($classlist);
Line 8775  SCANTRONFORM Line 8282  SCANTRONFORM
  return ''; # Dunno why the other returns return '' rather than just returning.   return ''; # Dunno why the other returns return '' rather than just returning.
     }      }
   
     my %lettdig = &Apache::lonnet::letter_to_digits();      my %lettdig = &letter_to_digits();
     my $numletts = scalar(keys(%lettdig));      my $numletts = scalar(keys(%lettdig));
     my %orderedforcode;      my %orderedforcode;
   
Line 8792  SCANTRONFORM Line 8299  SCANTRONFORM
         my %startline = ();          my %startline = ();
         my $total;          my $total;
   my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,    my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,
   $scan_data,undef,\%idmap,$randomorder,                                                   $scan_data,undef,\%idmap,$randomorder,
                                                  $randompick,$sequence,\@master_seq,                                                   $randompick,$sequence,\@master_seq,
                                                  \%symb_to_resource,\%grader_partids_by_symb,                                                   \%symb_to_resource,\%grader_partids_by_symb,
                                                  \%orderedforcode,\%respnumlookup,\%startline,                                                   \%orderedforcode,\%respnumlookup,\%startline,
Line 8822  SCANTRONFORM Line 8329  SCANTRONFORM
   
         my @mapresources = @resources;          my @mapresources = @resources;
         if ($randomorder || $randompick) {          if ($randomorder || $randompick) {
             @mapresources =              @mapresources = 
                 &users_order($user,$scancode,$sequence,\@master_seq,\%symb_to_resource,                  &users_order($user,$scancode,$sequence,\@master_seq,\%symb_to_resource,
                              \%orderedforcode);                               \%orderedforcode);
         }          }
Line 8837  SCANTRONFORM Line 8344  SCANTRONFORM
             }              }
             if ((exists($grader_randomlists_by_symb{$ressymb})) ||              if ((exists($grader_randomlists_by_symb{$ressymb})) ||
                 (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {                  (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {
                 my $currcode;  
                 if (exists($grader_randomlists_by_symb{$ressymb})) {  
                     $currcode = $scancode;  
                 }  
                 my ($analysis,$parts) =                  my ($analysis,$parts) =
                     &scantron_partids_tograde($resource,$env{'request.course.id'},                      &scantron_partids_tograde($resource,$env{'request.course.id'},
                                               $uname,$udom,undef,$bubbles_per_row,                                                $uname,$udom,undef,$bubbles_per_row);
                                               $currcode);  
                 $partids_by_symb{$ressymb} = $parts;                  $partids_by_symb{$ressymb} = $parts;
             } else {              } else {
                 $partids_by_symb{$ressymb} = $grader_partids_by_symb{$ressymb};                  $partids_by_symb{$ressymb} = $grader_partids_by_symb{$ressymb};
Line 8911  SCANTRONFORM Line 8413  SCANTRONFORM
                 if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,                  if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,
                                            \@mapresources,\%partids_by_symb,                                             \@mapresources,\%partids_by_symb,
                                            $bubbles_per_row,$randomorder,$randompick,                                             $bubbles_per_row,$randomorder,$randompick,
                                            \%respnumlookup,\%startline)                                             \%respnumlookup,\%startline) 
                     eq 'ssi_error') {                      eq 'ssi_error') {
                     $ssi_error = 0; # So end of handler error message does not trigger.                      $ssi_error = 0; # So end of handler error message does not trigger.
                     $r->print("</form>");                      $r->print("</form>");
Line 8947  SCANTRONFORM Line 8449  SCANTRONFORM
                               &Apache::loncommon::end_data_table_header_row()."\n".                                &Apache::loncommon::end_data_table_header_row()."\n".
                               &Apache::loncommon::start_data_table_row().                                &Apache::loncommon::start_data_table_row().
                               '<td>'.&mt('Bubblesheet').'</td>'.                                '<td>'.&mt('Bubblesheet').'</td>'.
                               '<td><span class="LC_nobreak" style="white-space: pre;"><tt>'.$studentdata.'</tt></span></td>'.                                '<td><span class="LC_nobreak"><tt>'.$studentdata.'</tt></span></td>'.
                               &Apache::loncommon::end_data_table_row().                                &Apache::loncommon::end_data_table_row().
                               &Apache::loncommon::start_data_table_row().                                &Apache::loncommon::start_data_table_row().
                               '<td>'.&mt('Stored submissions').'</td>'.                                '<td>'.&mt('Stored submissions').'</td>'.
                               '<td><span class="LC_nobreak" style="white-space: pre;"><tt>'.$studentrecord.'</tt></span></td>'."\n".                                '<td><span class="LC_nobreak"><tt>'.$studentrecord.'</tt></span></td>'."\n".
                               &Apache::loncommon::end_data_table_row().                                &Apache::loncommon::end_data_table_row().
                               &Apache::loncommon::end_data_table().'</p>');                                &Apache::loncommon::end_data_table().'</p>');
                 } else {                  } else {
Line 9004  sub graders_resources_pass { Line 8506  sub graders_resources_pass {
 =item users_order  =item users_order
   
   Returns array of resources in current map, ordered based on either CODE,    Returns array of resources in current map, ordered based on either CODE,
   if this is a CODEd exam, or based on student's identity if this is a    if this is a CODEd exam, or based on student's identity if this is a 
   "NAMEd" exam.    "NAMEd" exam.
   
   Should be used when randomorder and/or randompick applied when the     Should be used when randomorder and/or randompick applied when the 
Line 9031  sub users_order  { Line 8533  sub users_order  {
             if (ref($actual_seq) eq 'ARRAY') {              if (ref($actual_seq) eq 'ARRAY') {
                 @mapresources = map { $symb_to_resource->{$_}; } @{$actual_seq};                  @mapresources = map { $symb_to_resource->{$_}; } @{$actual_seq};
                 if (ref($orderedforcode) eq 'HASH') {                  if (ref($orderedforcode) eq 'HASH') {
                     if (@mapresources > 0) {                      if (@mapresources > 0) { 
                         $orderedforcode->{$scancode} = \@mapresources;                          $orderedforcode->{$scancode} = \@mapresources;
                     }                      }
                 }                  }
Line 9044  sub users_order  { Line 8546  sub users_order  {
                                                            $master_seq,                                                             $master_seq,
                                                            $user,undef,1);                                                             $user,undef,1);
         if (ref($actual_seq) eq 'ARRAY') {          if (ref($actual_seq) eq 'ARRAY') {
             @mapresources =              @mapresources = 
                 map { $symb_to_resource->{$_}; } @{$actual_seq};                  map { $symb_to_resource->{$_}; } @{$actual_seq};
         }          }
     }      }
Line 9100  sub grade_student_bubbles { Line 8602  sub grade_student_bubbles {
 }  }
   
 sub scantron_upload_scantron_data {  sub scantron_upload_scantron_data {
     my ($r,$symb) = @_;      my ($r,$symb)=@_;
     my $dom = $env{'request.role.domain'};      my $dom = $env{'request.role.domain'};
     my ($formatoptions,$formattitle,$formatjs) = &scantron_upload_dataformat($dom);  
     my $domdesc = &Apache::lonnet::domain($dom,'description');      my $domdesc = &Apache::lonnet::domain($dom,'description');
     $r->print(&Apache::loncommon::coursebrowser_javascript($dom));      $r->print(&Apache::loncommon::coursebrowser_javascript($dom));
     my $select_link=&Apache::loncommon::selectcourse_link('rules','courseid',      my $select_link=&Apache::loncommon::selectcourse_link('rules','courseid',
   'domainid',    'domainid',
   'coursename',$dom);    'coursename',$dom);
     my $syllabuslink = '<a href="javascript:ToSyllabus();">'.&mt('Syllabus').'</a>'.      my $syllabuslink = '<a href="javascript:ToSyllabus();">'.&mt('Syllabus').'</a>'.
                        ('&nbsp'x2).&mt('(shows course personnel)');                         ('&nbsp'x2).&mt('(shows course personnel)'); 
     my $default_form_data=&defaultFormData($symb);      my $default_form_data=&defaultFormData($symb);
     my $nofile_alert = &mt('Please use the browse button to select a file from your local directory.');      my $nofile_alert = &mt('Please use the browse button to select a file from your local directory.');
     &js_escape(\$nofile_alert);  
     my $nocourseid_alert = &mt("Please use the 'Select Course' link to open a separate window where you can search for a course to which a file can be uploaded.");      my $nocourseid_alert = &mt("Please use the 'Select Course' link to open a separate window where you can search for a course to which a file can be uploaded.");
     &js_escape(\$nocourseid_alert);  
     $r->print(&Apache::lonhtmlcommon::scripttag('      $r->print(&Apache::lonhtmlcommon::scripttag('
     function checkUpload(formname) {      function checkUpload(formname) {
  if (formname.upfile.value == "") {   if (formname.upfile.value == "") {
Line 9142  sub scantron_upload_scantron_data { Line 8641  sub scantron_upload_scantron_data {
         return;          return;
     }      }
   
     '.$formatjs.'  
 '));  '));
     $r->print('      $r->print('
 <h3>'.&mt('Send bubblesheet data to a course').'</h3>  <h3>'.&mt('Send bubblesheet data to a course').'</h3>
Line 9158  sub scantron_upload_scantron_data { Line 8656  sub scantron_upload_scantron_data {
   &Apache::lonhtmlcommon::row_closure().    &Apache::lonhtmlcommon::row_closure().
   &Apache::lonhtmlcommon::row_title(&mt('Domain')).    &Apache::lonhtmlcommon::row_title(&mt('Domain')).
   '<input name="domainid" type="hidden" />'.$domdesc.    '<input name="domainid" type="hidden" />'.$domdesc.
   &Apache::lonhtmlcommon::row_closure());    &Apache::lonhtmlcommon::row_closure().
     if ($formatoptions) {  
         $r->print(&Apache::lonhtmlcommon::row_title($formattitle).$formatoptions.  
                   &Apache::lonhtmlcommon::row_closure());  
     }  
     $r->print(  
   &Apache::lonhtmlcommon::row_title(&mt('File to upload')).    &Apache::lonhtmlcommon::row_title(&mt('File to upload')).
   '<input type="file" name="upfile" size="50" />'.    '<input type="file" name="upfile" size="50" />'.
   &Apache::lonhtmlcommon::row_closure(1).    &Apache::lonhtmlcommon::row_closure(1).
Line 9176  sub scantron_upload_scantron_data { Line 8669  sub scantron_upload_scantron_data {
     return '';      return '';
 }  }
   
 sub scantron_upload_dataformat {  
     my ($dom) = @_;  
     my ($formatoptions,$formattitle,$formatjs);  
     $formatjs = <<'END';  
 function toggleScantab(form) {  
    return;  
 }  
 END  
     my %domconfig = &Apache::lonnet::get_dom('configuration',['scantron'],$dom);  
     if (ref($domconfig{'scantron'}) eq 'HASH') {  
         if (ref($domconfig{'scantron'}{'config'}) eq 'HASH') {  
             if (keys(%{$domconfig{'scantron'}{'config'}}) > 1) {  
                 if (($domconfig{'scantron'}{'config'}{'dat'}) &&  
                     (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH')) {  
                     if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {  
                         if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}})) {  
                             my ($onclick,$formatextra,$singleline);  
                             my @lines = &Apache::lonnet::get_scantronformat_file();  
                             my $count = 0;  
                             foreach my $line (@lines) {  
                                 next if ($line =~ /^#/);  
                                 $singleline = $line;  
                                 $count ++;  
                             }  
                             if ($count > 1) {  
                                 $formatextra = '<div style="display:none" id="bubbletype">'.  
                                                '<span class="LC_nobreak">'.  
                                                &mt('Bubblesheet type:').'&nbsp;'.  
                                                &scantron_scantab().'</span></div>';  
                                 $onclick = ' onclick="toggleScantab(this.form);"';  
                                 $formatjs = <<"END";  
 function toggleScantab(form) {  
     var divid = 'bubbletype';  
     if (document.getElementById(divid)) {  
         var radioname = 'fileformat';  
         var num = form.elements[radioname].length;  
         if (num) {  
             for (var i=0; i<num; i++) {  
                 if (form.elements[radioname][i].checked) {  
                     var chosen = form.elements[radioname][i].value;  
                     if (chosen == 'dat') {  
                         document.getElementById(divid).style.display = 'none';  
                     } else if (chosen == 'csv') {  
                         document.getElementById(divid).style.display = 'block';  
                     }  
                 }  
             }  
         }  
     }  
     return;  
 }  
   
 END  
                             } elsif ($count == 1) {  
                                 my $formatname = (split(/:/,$singleline,2))[0];  
                                 $formatextra = '<input type="hidden" name="scantron_format" value="'.$formatname.'" />';  
                             }  
                             $formattitle = &mt('File format');  
                             $formatoptions = '<label><input name="fileformat" type="radio" value="dat" checked="checked"'.$onclick.' />'.  
                                              &mt('Plain Text (no delimiters)').  
                                              '</label>'.('&nbsp;'x2).  
                                              '<label><input name="fileformat" type="radio" value="csv"'.$onclick.' />'.  
                                              &mt('Comma separated values').'</label>'.$formatextra;  
                         }  
                     }  
                 }  
             } elsif (keys(%{$domconfig{'scantron'}{'config'}}) == 1) {  
                 if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {  
                     if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}})) {  
                         $formattitle = &mt('Bubblesheet type');  
                         $formatoptions = &scantron_scantab();  
                     }  
                 }  
             }  
         }  
     }  
     return ($formatoptions,$formattitle,$formatjs);  
 }  
   
 sub scantron_upload_scantron_data_save {  sub scantron_upload_scantron_data_save {
     my ($r,$symb) = @_;      my($r,$symb)=@_;
     my $doanotherupload=      my $doanotherupload=
  '<br /><form action="/adm/grades" method="post">'."\n".   '<br /><form action="/adm/grades" method="post">'."\n".
  '<input type="hidden" name="command" value="scantronupload" />'."\n".   '<input type="hidden" name="command" value="scantronupload" />'."\n".
Line 9266  sub scantron_upload_scantron_data_save { Line 8681  sub scantron_upload_scantron_data_save {
  !&Apache::lonnet::allowed('usc',   !&Apache::lonnet::allowed('usc',
     $env{'form.domainid'}.'_'.$env{'form.courseid'})) {      $env{'form.domainid'}.'_'.$env{'form.courseid'})) {
  $r->print(&mt("You are not allowed to upload bubblesheet data to the requested course.")."<br />");   $r->print(&mt("You are not allowed to upload bubblesheet data to the requested course.")."<br />");
         unless ($symb) {   unless ($symb) {
     $r->print($doanotherupload);      $r->print($doanotherupload);
  }   }
  return '';   return '';
     }      }
     my %coursedata=&Apache::lonnet::coursedescription($env{'form.domainid'}.'_'.$env{'form.courseid'});      my %coursedata=&Apache::lonnet::coursedescription($env{'form.domainid'}.'_'.$env{'form.courseid'});
     my $uploadedfile;      my $uploadedfile;
     $r->print('<p>'.&mt("Uploading file to [_1]",$coursedata{'description'}).'</p>');      $r->print('<h3>'.&mt("Uploading file to [_1]",$coursedata{'description'}).'</h3>');
     if (length($env{'form.upfile'}) < 2) {      if (length($env{'form.upfile'}) < 2) {
         $r->print(          $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>'));
             &Apache::lonhtmlcommon::confirm_success(      } else {
                 &mt('The file: [_1] you attempted to upload contained no information. Please check that you entered the correct filename.',          my $result = 
                         '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'),1));              &Apache::lonnet::userfileupload('upfile','','scantron','','','',
     } else {  
         my %domconfig = &Apache::lonnet::get_dom('configuration',['scantron'],$env{'form.domainid'});  
         my $parser;  
         if (ref($domconfig{'scantron'}) eq 'HASH') {  
             if (ref($domconfig{'scantron'}{'config'}) eq 'HASH') {  
                 my $is_csv;  
                 my @possibles = keys(%{$domconfig{'scantron'}{'config'}});  
                 if (@possibles > 1) {  
                     if ($env{'form.fileformat'} eq 'csv') {  
                         if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {  
                             if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {  
                                 if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}}) > 1) {  
                                     $is_csv = 1;  
                                 }  
                             }  
                         }  
                     }  
                 } elsif (@possibles == 1) {  
                     if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {  
                         if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {  
                             if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}}) > 1) {  
                                 $is_csv = 1;  
                             }  
                         }  
                     }  
                 }  
                 if ($is_csv) {  
                    $parser = $domconfig{'scantron'}{'config'}{'csv'};  
                 }  
             }  
         }  
         my $result =  
             &Apache::lonnet::userfileupload('upfile','scantron','scantron',$parser,'','',  
                                             $env{'form.courseid'},$env{'form.domainid'});                                              $env{'form.courseid'},$env{'form.domainid'});
  if ($result =~ m{^/uploaded/}) {   if ($result =~ m{^/uploaded/}) {
             $r->print(      $r->print(&mt('[_1]Success:[_2] Successfully uploaded [_3] bytes of data into location: [_4]',
                 &Apache::lonhtmlcommon::confirm_success(&mt('Upload successful')).'<br />'.                            '<span class="LC_success">','</span>',(length($env{'form.upfile'})-1),
                 &mt('Uploaded [_1] bytes of data into location: [_2]',    '<span class="LC_filename">'.$result.'</span>'));
                         (length($env{'form.upfile'})-1),  
                         '<span class="LC_filename">'.$result.'</span>'));  
             ($uploadedfile) = ($result =~ m{/([^/]+)$});              ($uploadedfile) = ($result =~ m{/([^/]+)$});
             $r->print(&validate_uploaded_scantron_file($env{'form.domainid'},              $r->print(&validate_uploaded_scantron_file($env{'form.domainid'},
                                                        $env{'form.courseid'},$uploadedfile));                                                         $env{'form.courseid'},$uploadedfile));
  } else {   } else {
             $r->print(      $r->print(&mt('[_1]Error:[_2] An error ([_3]) occurred when attempting to upload the file, [_4]',
                 &Apache::lonhtmlcommon::confirm_success(&mt('Upload failed'),1).'<br />'.                            '<span class="LC_error">','</span>',$result,
                     &mt('An error ([_1]) occurred when attempting to upload the file: [_2]',  
                           $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>'));
  }   }
     }      }
Line 9348  sub validate_uploaded_scantron_file { Line 8726  sub validate_uploaded_scantron_file {
     my $output;      my $output;
     if (@lines) {      if (@lines) {
         my (%counts,$max_match_format);          my (%counts,$max_match_format);
         my ($found_match_count,$max_match_count,$max_match_pct) = (0,0,0);          my ($max_match_count,$max_match_pct) = (0,0);
         my $classlist = &Apache::loncoursedata::get_classlist($cdom,$cname);          my $classlist = &Apache::loncoursedata::get_classlist($cdom,$cname);
         my %idmap = &username_to_idmap($classlist);          my %idmap = &username_to_idmap($classlist);
         foreach my $key (keys(%idmap)) {          foreach my $key (keys(%idmap)) {
Line 9356  sub validate_uploaded_scantron_file { Line 8734  sub validate_uploaded_scantron_file {
             $idmap{$lckey} = $idmap{$key};              $idmap{$lckey} = $idmap{$key};
         }          }
         my %unique_formats;          my %unique_formats;
         my @formatlines = &Apache::lonnet::get_scantronformat_file();          my @formatlines = &get_scantronformat_file();
         foreach my $line (@formatlines) {          foreach my $line (@formatlines) {
             chomp($line);              chomp($line);
             my @config = split(/:/,$line);              my @config = split(/:/,$line);
Line 9391  sub validate_uploaded_scantron_file { Line 8769  sub validate_uploaded_scantron_file {
                 if (($max_match_format eq '') || ($percent_match > $max_match_pct)) {                  if (($max_match_format eq '') || ($percent_match > $max_match_pct)) {
                     $max_match_pct = $percent_match;                      $max_match_pct = $percent_match;
                     $max_match_format = $key;                      $max_match_format = $key;
                     $found_match_count = $counts{$key}{'found'};  
                     $max_match_count = $counts{$key}{'total'};                      $max_match_count = $counts{$key}{'total'};
                 }                  }
             }              }
Line 9410  sub validate_uploaded_scantron_file { Line 8787  sub validate_uploaded_scantron_file {
                 }                  }
             }              }
             my $showpct = sprintf("%.0f",$max_match_pct).'%';              my $showpct = sprintf("%.0f",$max_match_pct).'%';
             $output .= '<br />';              $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).
             if ($found_match_count == $max_match_count) {                         '<br />'.&mt('A low percentage of matches results from one of the following:').'<ul>'.
                 # 100% matching entries                         '<li>'.&mt('The file was uploaded to the wrong course').'</li>'.
                 $output .= &Apache::lonhtmlcommon::confirm_success(                         '<li>'.&mt('The data are not in the format expected for the domain: [_1]',
                      &mt('Comparison of student IDs: [_1] matching ([quant,_2,entry,entries])',                                    '<i>'.$cdom.'</i>').'</li>'.
                             '<b>'.$showpct.'</b>',$found_match_count)).'<br />'.                         '<li>'.&mt('Students did not bubble their IDs, or mis-bubbled them').'</li>'.
                 &mt('Comparison of student IDs in the uploaded file with'.                         '<li>'.&mt('The course roster is not up to date').'</li>'.
                     ' the course roster found matches for [_1] of the [_2] entries'.                         '</ul>';
                     ' in the file (for the format defined for [_3]).',  
                         '<b>'.$showpct.'</b>','<b>'.$max_match_count.'</b>',$format_descs);  
             } else {  
                 # Not all entries matching? -> Show warning and additional info  
                 $output .=  
                     &Apache::lonhtmlcommon::confirm_success(  
                         &mt('Comparison of student IDs: [_1] matching ([_2]/[quant,_3,entry,entries])',  
                                 '<b>'.$showpct.'</b>',$found_match_count,$max_match_count).'<br />'.  
                         &mt('Not all entries could be matched!'),1).'<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).  
                     '<p class="LC_info">'.  
                     &mt('A low percentage of matches results from one of the following:').  
                     '</p><ul>'.  
                     '<li>'.&mt('The file was uploaded to the wrong course.').'</li>'.  
                     '<li>'.&mt('The data is 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 {      } else {
         $output = '<p class="LC_warning">'.&mt('Uploaded file contained no data').'</p>';          $output = '<span class="LC_warning">'.&mt('Uploaded file contained no data').'</span>';
     }      }
     return $output;      return $output;
 }  }
Line 9457  sub valid_file { Line 8811  sub valid_file {
 }  }
   
 sub scantron_download_scantron_data {  sub scantron_download_scantron_data {
     my ($r,$symb) = @_;      my ($r,$symb)=@_;
     my $default_form_data=&defaultFormData($symb);      my $default_form_data=&defaultFormData($symb);
     my $cname=$env{'course.'.$env{'request.course.id'}.'.num'};      my $cname=$env{'course.'.$env{'request.course.id'}.'.num'};
     my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};      my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
Line 9478  sub scantron_download_scantron_data { Line 8832  sub scantron_download_scantron_data {
     &Apache::lonnet::allowuploaded('/adm/grades',$skipped);      &Apache::lonnet::allowuploaded('/adm/grades',$skipped);
     $r->print('      $r->print('
     <p>      <p>
  '.&mt('[_1]Original[_2] file as uploaded by the bubblesheet scanning office.',   '.&mt('[_1]Original[_2] file as uploaded by the scantron office.',
       '<a href="'.$orig.'">','</a>').'        '<a href="'.$orig.'">','</a>').'
     </p>      </p>
     <p>      <p>
Line 9497  sub checkscantron_results { Line 8851  sub checkscantron_results {
     my ($r,$symb) = @_;      my ($r,$symb) = @_;
     if (!$symb) {return '';}      if (!$symb) {return '';}
     my $cid = $env{'request.course.id'};      my $cid = $env{'request.course.id'};
     my %lettdig = &Apache::lonnet::letter_to_digits();      my %lettdig = &letter_to_digits();
     my $numletts = scalar(keys(%lettdig));      my $numletts = scalar(keys(%lettdig));
     my $cnum = $env{'course.'.$cid.'.num'};      my $cnum = $env{'course.'.$cid.'.num'};
     my $cdom = $env{'course.'.$cid.'.domain'};      my $cdom = $env{'course.'.$cid.'.domain'};
     my (undef, undef, $sequence) = &Apache::lonnet::decode_symb($env{'form.selectpage'});      my (undef, undef, $sequence) = &Apache::lonnet::decode_symb($env{'form.selectpage'});
     my %record;      my %record;
     my %scantron_config =      my %scantron_config =
         &Apache::lonnet::get_scantron_config($env{'form.scantron_format'});          &Apache::grades::get_scantron_config($env{'form.scantron_format'});
     my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config);      my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config);
     my ($scanlines,$scan_data)=&Apache::grades::scantron_getfile();      my ($scanlines,$scan_data)=&Apache::grades::scantron_getfile();
     my $classlist=&Apache::loncoursedata::get_classlist();      my $classlist=&Apache::loncoursedata::get_classlist();
Line 9517  sub checkscantron_results { Line 8871  sub checkscantron_results {
     my $map=$navmap->getResourceByUrl($sequence);      my $map=$navmap->getResourceByUrl($sequence);
     my ($randomorder,$randompick,@master_seq,%symb_to_resource,%grader_partids_by_symb,      my ($randomorder,$randompick,@master_seq,%symb_to_resource,%grader_partids_by_symb,
         %grader_randomlists_by_symb,%orderedforcode);          %grader_randomlists_by_symb,%orderedforcode);
     if (ref($map)) {      if (ref($map)) { 
         $randomorder=$map->randomorder();          $randomorder=$map->randomorder();
         $randompick=$map->randompick();          $randompick=$map->randompick();
     }      }
Line 9546  sub checkscantron_results { Line 8900  sub checkscantron_results {
         return '';          return '';
     }      }
   
     &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,      &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,'Processing first student');
                                           'Processing first student');  
     my $start=&Time::HiRes::time();      my $start=&Time::HiRes::time();
     my $i=-1;      my $i=-1;
   
Line 9557  sub checkscantron_results { Line 8910  sub checkscantron_results {
         my $line=&Apache::grades::scantron_get_line($scanlines,$scan_data,$i);          my $line=&Apache::grades::scantron_get_line($scanlines,$scan_data,$i);
         if ($line=~/^[\s\cz]*$/) { next; }          if ($line=~/^[\s\cz]*$/) { next; }
         if ($started) {          if ($started) {
             &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,              &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last student');
                                                      'last student');  
         }          }
         $started=1;          $started=1;
         my $scan_record=          my $scan_record=
Line 9616  sub checkscantron_results { Line 8968  sub checkscantron_results {
             my $ressymb = $resource->symb();              my $ressymb = $resource->symb();
             if ((exists($grader_randomlists_by_symb{$ressymb})) ||              if ((exists($grader_randomlists_by_symb{$ressymb})) ||
                 (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {                  (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {
                 my $currcode;  
                 if (exists($grader_randomlists_by_symb{$ressymb})) {  
                     $currcode = $scancode;  
                 }  
                 (my $analysis,$parts) =                  (my $analysis,$parts) =
                     &scantron_partids_tograde($resource,$env{'request.course.id'},                      &scantron_partids_tograde($resource,$env{'request.course.id'},
                                               $username,$domain,undef,                                                $username,$domain,undef,
                                               $bubbles_per_row,$currcode);                                                $bubbles_per_row);
             } else {              } else {
                 $parts = $grader_partids_by_symb{$ressymb};                  $parts = $grader_partids_by_symb{$ressymb};
             }              }
Line 9655  sub checkscantron_results { Line 9003  sub checkscantron_results {
 '<td>'.&mt('Bubblesheet').'</td><td>'.$showscandata.'</td><td rowspan="2">'.$last.'</td><td rowspan="2">'.$pid.'</td>'."\n".  '<td>'.&mt('Bubblesheet').'</td><td>'.$showscandata.'</td><td rowspan="2">'.$last.'</td><td rowspan="2">'.$pid.'</td>'."\n".
 '</tr>'."\n".  '</tr>'."\n".
 '<tr class="'.$css_class.'">'."\n".  '<tr class="'.$css_class.'">'."\n".
 '<td>'.&mt('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('Bubblesheet').'</td><td><span class="LC_nobreak">'.$scandata{$pid}.'</span></td><td rowspan="2">'.$last.'</td><td rowspan="2">'.$pid.'</td>'."\n".                      $badstudents .= '<tr class="'.$css_class.'"><td>'.&mt('Bubblesheet').'</td><td><span class="LC_nobreak">'.$scandata{$pid}.'</span></td><td rowspan="2">'.$last.'</td><td rowspan="2">'.$pid.'</td>'."\n".
 '</tr>'."\n".  '</tr>'."\n".
 '<tr class="'.$css_class.'">'."\n".  '<tr class="'.$css_class.'">'."\n".
 '<td>'.&mt('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".
 '</tr>'."\n";  '</tr>'."\n";
                     $failed ++;                      $failed ++;
                 }                  }
Line 9670  sub checkscantron_results { Line 9018  sub checkscantron_results {
             }              }
         }          }
     }      }
     $r->print('<p>'.      $r->print(
               &mt('Comparison of bubblesheet data (including corrections) with corresponding submission records (most recent submission) for [_1][quant,_2,student][_3] ([quant,_4,bubblesheet line] per student).',          '<p>'
                   '<b>',         .&mt('Comparison of bubblesheet data (including corrections) with corresponding submission records (most recent submission) for [_1][quant,_2,student][_3] ([quant,_4,bubblesheet line] per student).',
                   $numstudents,              '<b>',
                   '</b>',              $numstudents,
                   $env{'form.scantron_maxbubble'}).              '</b>',
               '</p>'              $env{'form.scantron_maxbubble'})
          .'</p>'
     );      );
     $r->print('<p>'      $r->print('<p>'
              .&mt('Exact matches for [_1][quant,_2,student][_3].','<b>',$passed,'</b>')               .&mt('Exact matches for [_1][quant,_2,student][_3].','<b>',$passed,'</b>')
              .'<br />'               .'<br />'
              .&mt('Discrepancies detected for [_1][quant,_2,student][_3].','<b>',$failed,'</b>')               .&mt('Discrepancies detected for [_1][quant,_2,student][_3].','<b>',$failed,'</b>')
              .'</p>');               .'</p>'
       );
     if ($passed) {      if ($passed) {
         $r->print(&mt('Students with exact correspondence between bubblesheet data and submissions are as follows:').'<br /><br />');          $r->print(&mt('Students with exact correspondence between bubblesheet data and submissions are as follows:').'<br /><br />');
         $r->print(&Apache::loncommon::start_data_table()."\n".          $r->print(&Apache::loncommon::start_data_table()."\n".
Line 9828  sub verify_scantron_grading { Line 9178  sub verify_scantron_grading {
     return ($counter,$record);      return ($counter,$record);
 }  }
   
   sub letter_to_digits {
       my %lettdig = (
                       A => 1,
                       B => 2,
                       C => 3,
                       D => 4,
                       E => 5,
                       F => 6,
                       G => 7,
                       H => 8,
                       I => 9,
                       J => 0,
                     );
       return %lettdig;
   }
   
   
 #-------- end of section for handling grading scantron forms -------  #-------- end of section for handling grading scantron forms -------
 #  #
 #-------------------------------------------------------------------  #-------------------------------------------------------------------
Line 9847  sub grading_menu { Line 9214  sub grading_menu {
   
     my %fields = ('symb'=>&Apache::lonenc::check_encrypt($symb),      my %fields = ('symb'=>&Apache::lonenc::check_encrypt($symb),
                   'command'=>'individual');                    'command'=>'individual');
       
     my $url1a = &Apache::lonhtmlcommon::build_url('grades/',\%fields);      my $url1a = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
   
     $fields{'command'}='ungraded';      $fields{'command'}='ungraded';
Line 9861  sub grading_menu { Line 9228  sub grading_menu {
   
     $fields{'command'}='downloadfilesselect';      $fields{'command'}='downloadfilesselect';
     my $url1e=&Apache::lonhtmlcommon::build_url('grades/',\%fields);      my $url1e=&Apache::lonhtmlcommon::build_url('grades/',\%fields);
       
     $fields{'command'} = 'csvform';      $fields{'command'} = 'csvform';
     my $url2 = &Apache::lonhtmlcommon::build_url('grades/',\%fields);      my $url2 = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
           
Line 9876  sub grading_menu { Line 9243  sub grading_menu {
           
     my @menu = ({ categorytitle=>'Hand Grading',      my @menu = ({ categorytitle=>'Hand Grading',
             items =>[              items =>[
                         {       linktext => 'Select individual students to grade',                          { linktext => 'Select individual students to grade',
                                 url => $url1a,                      url => $url1a,
                                 permission => 'F',                      permission => 'F',
                                 icon => 'grade_students.png',                      icon => 'grade_students.png',
                                 linktitle => 'Grade current resource for a selection of students.'                      linktitle => 'Grade current resource for a selection of students.'
                         },                          }, 
                         {       linktext => 'Grade ungraded submissions',                          {       linktext => 'Grade ungraded submissions.',
                                 url => $url1b,                                  url => $url1b,
                                 permission => 'F',                                  permission => 'F',
                                 icon => 'ungrade_sub.png',                                  icon => 'ungrade_sub.png',
Line 9901  sub grading_menu { Line 9268  sub grading_menu {
                                 icon => 'grade_PageFolder.png',                                  icon => 'grade_PageFolder.png',
                                 linktitle => 'Grade all resources in current page/sequence/folder for one student.'                                  linktitle => 'Grade all resources in current page/sequence/folder for one student.'
                         },                          },
                         {       linktext => 'Download submitted files',                          {       linktext => 'Download submissions',
                                 url => $url1e,                                  url => $url1e,
                                 permission => 'F',                                  permission => 'F',
                                 icon => 'download_sub.png',                                  icon => 'download_sub.png',
                                 linktitle => 'Download all files submitted by students.'                                  linktitle => 'Download all students submissions.'
                         }]},                          }]},
                          { categorytitle=>'Automated Grading',                           { categorytitle=>'Automated Grading',
                items =>[                 items =>[
Line 9948  sub grading_menu { Line 9315  sub grading_menu {
     return $Str;          return $Str;    
 }  }
   
   
 sub ungraded {  sub ungraded {
     my ($request)=@_;      my ($request)=@_;
     &submit_options($request);      &submit_options($request);
Line 9980  sub submit_options_table { Line 9348  sub submit_options_table {
     $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".      $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".
         '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";          '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";
   
     $result.=&selectfield(1).      $result.=&selectfield(0).
             '<input type="hidden" name="command" value="viewgrades" />              '<input type="hidden" name="command" value="viewgrades" />
             <div>              <div>
               <input type="submit" value="'.&mt('Next').' &rarr;" />                <input type="submit" value="'.&mt('Next').' &rarr;" />
Line 9994  sub submit_options_download { Line 9362  sub submit_options_download {
     my ($request,$symb) = @_;      my ($request,$symb) = @_;
     if (!$symb) {return '';}      if (!$symb) {return '';}
   
     my $res_error;  
     my ($partlist,$handgrade,$responseType,$numresp,$numessay,$numdropbox) =  
         &response_type($symb,\$res_error);  
     if ($res_error) {  
         $request->print(&mt('An error occurred retrieving response types'));  
         return;  
     }  
     unless ($numessay) {  
         $request->print(&mt('No essayresponse items found'));  
         return;  
     }  
     my $table;  
     if (ref($partlist) eq 'ARRAY') {  
         if (scalar(@$partlist) > 1 ) {  
             $table = &showResourceInfo($symb,$partlist,$responseType,'gradingMenu',1,1);  
         }  
     }  
   
     &commonJSfunctions($request);      &commonJSfunctions($request);
   
     my $result='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".      my $result='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".
         $table."\n".          '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";
         '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";  
     $result.='      $result.='
 <h2>  <h2>
   '.&mt('Select Students for whom to Download Submitted Files').'    '.&mt('Select Students for Which to Download Submissions').'
 </h2>'.&selectfield(1).'  </h2>'.&selectfield(1).'
                 <input type="hidden" name="command" value="downloadfileslink" />                  <input type="hidden" name="command" value="downloadfileslink" /> 
               <input type="submit" value="'.&mt('Next').' &rarr;" />                <input type="submit" value="'.&mt('Next').' &rarr;" />
             </div>              </div>
           </div>            </div>
Line 10042  sub submit_options { Line 9391  sub submit_options {
     $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".      $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".
  '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";   '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n";
     $result.=&selectfield(1).'      $result.=&selectfield(1).'
                 <input type="hidden" name="command" value="submission" />                  <input type="hidden" name="command" value="submission" /> 
               <input type="submit" value="'.&mt('Next').' &rarr;" />        <input type="submit" value="'.&mt('Next').' &rarr;" />
             </div>              </div>
           </div>            </div>
   
   
   </form>';    </form>';
     return $result;      return $result;
 }  }
   
 sub selectfield {  sub selectfield {
    my ($full)=@_;     my ($full)=@_;
    my %options =     my %options = 
        (&substatus_options,            (&Apache::lonlocal::texthash(
         'select_form_order' => ['yes','queued','graded','incorrect','all']);               'yes'       => 'with submissions',
                'queued'    => 'in grading queue',
                'graded'    => 'with ungraded submissions',
                'incorrect' => 'with incorrect submissions',
                'all'       => 'with any status'),
                'select_form_order' => ['yes','queued','graded','incorrect','all']);
    my $result='<div class="LC_columnSection">     my $result='<div class="LC_columnSection">
     
     <fieldset>      <fieldset>
       <legend>        <legend>
        '.&mt('Sections').'         '.&mt('Sections').'
       </legend>        </legend>
       '.&Apache::lonstatistics::SectionSelect('section','multiple',5).'        '.&Apache::lonstatistics::SectionSelect('section','multiple',5).'
     </fieldset>      </fieldset>
     
     <fieldset>      <fieldset>
       <legend>        <legend>
         '.&mt('Groups').'          '.&mt('Groups').'
       </legend>        </legend>
       '.&Apache::lonstatistics::GroupSelect('group','multiple',5).'        '.&Apache::lonstatistics::GroupSelect('group','multiple',5).'
     </fieldset>      </fieldset>
      
     <fieldset>      <fieldset>
       <legend>        <legend>
         '.&mt('Access Status').'          '.&mt('Access Status').'
Line 10078  sub selectfield { Line 9434  sub selectfield {
       '.&Apache::lonhtmlcommon::StatusOptions(undef,undef,5,undef,'mult').'        '.&Apache::lonhtmlcommon::StatusOptions(undef,undef,5,undef,'mult').'
     </fieldset>';      </fieldset>';
     if ($full) {      if ($full) {
         $result.='         $result.='
     <fieldset>      <fieldset>
       <legend>        <legend>
         '.&mt('Submission Status').'          '.&mt('Submission Status').'
Line 10090  sub selectfield { Line 9446  sub selectfield {
     return $result;      return $result;
 }  }
   
 sub substatus_options {  
     return &Apache::lonlocal::texthash(  
                                       'yes'       => 'with submissions',  
                                       'queued'    => 'in grading queue',  
                                       'graded'    => 'with ungraded submissions',  
                                       'incorrect' => 'with incorrect submissions',  
                                       'all'       => 'with any status',  
                                       );  
 }  
   
 sub transtatus_options {  
     return &Apache::lonlocal::texthash(  
                                        'yes'       => 'with score transactions',  
                                        'incorrect' => 'with less than full credit',  
                                        'all'       => 'with any status',  
                                       );  
 }  
   
 sub reset_perm {  sub reset_perm {
     undef(%perm);      undef(%perm);
 }  }
Line 10241  sub process_clicker { Line 9579  sub process_clicker {
     my $pcorrect=&mt("Percentage points for correct solution");      my $pcorrect=&mt("Percentage points for correct solution");
     my $pincorrect=&mt("Percentage points for incorrect solution");      my $pincorrect=&mt("Percentage points for incorrect solution");
     my $selectform=&Apache::loncommon::select_form($env{'form.upfiletype'},'upfiletype',      my $selectform=&Apache::loncommon::select_form($env{'form.upfiletype'},'upfiletype',
                                                    {'iclicker' => 'i>clicker',     {'iclicker' => 'i>clicker',
                                                     'interwrite' => 'interwrite PRS',                                                      'interwrite' => 'interwrite PRS',
                                                     'turning' => 'Turning Technologies'});                                                      'turning' => 'Turning Technologies'});
     $symb = &Apache::lonenc::check_encrypt($symb);      $symb = &Apache::lonenc::check_encrypt($symb);
Line 10302  ENDUPFORM Line 9640  ENDUPFORM
 <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'}" />
 ENDGRADINGFORM  ENDGRADINGFORM
     $result.='</td>'.&Apache::loncommon::end_data_table_row().           $result.='</td>'.&Apache::loncommon::end_data_table_row().
                      &Apache::loncommon::start_data_table_row().'<td>'.(<<ENDPERCFORM);                       &Apache::loncommon::start_data_table_row().'<td>'.(<<ENDPERCFORM);
       <label>$pcorrect: <input type="text" name="pcorrect" size="4" value="$env{'form.pcorrect'}" onchange="sanitycheck()" /></label>        <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>'
 ENDPERCFORM  ENDPERCFORM
     $result.='</td>'.      $result.='</td>'.
              &Apache::loncommon::end_data_table_row().               &Apache::loncommon::end_data_table_row().
Line 10316  ENDPERCFORM Line 9654  ENDPERCFORM
 }  }
   
 sub process_clicker_file {  sub process_clicker_file {
     my ($r,$symb) = @_;      my ($r,$symb)=@_;
     if (!$symb) {return '';}      if (!$symb) {return '';}
   
     my %Saveable_Parameters=&clicker_grading_parameters();      my %Saveable_Parameters=&clicker_grading_parameters();
Line 10374  sub process_clicker_file { Line 9712  sub process_clicker_file {
     $number++;      $number++;
  }   }
         $result.="</p>\n";          $result.="</p>\n";
         if ($number==0) {   if ($number==0) {
             $result .=      $result.='<span class="LC_error">'.&mt('No IDs found to determine correct answer').'</span>';
                  &Apache::lonhtmlcommon::confirm_success(      return $result;
                      &mt('No IDs found to determine correct answer'),1);   }
             return $result;  
         }  
     }      }
     if (length($env{'form.upfile'}) < 2) {      if (length($env{'form.upfile'}) < 2) {
         $result .=          $result.=&mt('[_1] Error: [_2] The file you attempted to upload, [_3] contained no information. Please check that you entered the correct filename.',
             &Apache::lonhtmlcommon::confirm_success(       '<span class="LC_error">',
                 &mt('The file: [_1] you attempted to upload contained no information. Please check that you entered the correct filename.',       '</span>',
                         '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'),1);       '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>');
         return $result;  
     }  
     my $mimetype;  
     if ($env{'form.upfiletype'} eq 'iclicker') {  
         my $mm = new File::MMagic;  
         $mimetype = $mm->checktype_contents($env{'form.upfile'});  
         unless (($mimetype eq 'text/plain') || ($mimetype eq 'text/html')) {  
             $result.= '<p>'.  
                 &Apache::lonhtmlcommon::confirm_success(  
                     &mt('File format is neither csv (iclicker 6) nor xml (iclicker 7)'),1).'</p>';  
             return $result;  
         }  
     } elsif (($env{'form.upfiletype'} ne 'interwrite') && ($env{'form.upfiletype'} ne 'turning')) {  
         $result .= '<p>'.  
             &Apache::lonhtmlcommon::confirm_success(  
                 &mt('Invalid clicker type: choose one of: i>clicker, Interwrite PRS, or Turning Technologies.'),1).'</p>';  
         return $result;          return $result;
     }      }
   
Line 10430  ENDHEADER Line 9750  ENDHEADER
     my $errormsg='';      my $errormsg='';
     my $number=0;      my $number=0;
     if ($env{'form.upfiletype'} eq 'iclicker') {      if ($env{'form.upfiletype'} eq 'iclicker') {
         if ($mimetype eq 'text/plain') {   ($errormsg,$number)=&iclicker_eval(\@questiontitles,\%responses);
             ($errormsg,$number)=&iclicker_eval(\@questiontitles,\%responses);      }
         } elsif ($mimetype eq 'text/html') {      if ($env{'form.upfiletype'} eq 'interwrite') {
             ($errormsg,$number)=&iclickerxml_eval(\@questiontitles,\%responses);  
         }  
     } elsif ($env{'form.upfiletype'} eq 'interwrite') {  
         ($errormsg,$number)=&interwrite_eval(\@questiontitles,\%responses);          ($errormsg,$number)=&interwrite_eval(\@questiontitles,\%responses);
     } elsif ($env{'form.upfiletype'} eq 'turning') {      }
       if ($env{'form.upfiletype'} eq 'turning') {
         ($errormsg,$number)=&turning_eval(\@questiontitles,\%responses);          ($errormsg,$number)=&turning_eval(\@questiontitles,\%responses);
     }      }
     $result.='<br />'.&mt('Found [_1] question(s)',$number).'<br />'.      $result.='<br />'.&mt('Found [_1] question(s)',$number).'<br />'.
Line 10490  ENDHEADER Line 9808  ENDHEADER
                    "\n".&mt("Username").": <input type='text' name='uname".$id."' />&nbsp;".                     "\n".&mt("Username").": <input type='text' name='uname".$id."' />&nbsp;".
                    "\n".&mt("Domain").": ".                     "\n".&mt("Domain").": ".
                    &Apache::loncommon::select_dom_form($env{'course.'.$env{'request.course.id'}.'.domain'},'udom'.$id).'&nbsp;'.                     &Apache::loncommon::select_dom_form($env{'course.'.$env{'request.course.id'}.'.domain'},'udom'.$id).'&nbsp;'.
                    &Apache::loncommon::selectstudent_link('clickeranalysis','uname'.$id,'udom'.$id,'',$id);                     &Apache::loncommon::selectstudent_link('clickeranalysis','uname'.$id,'udom'.$id,0,$id);
           $unknown_count++;            $unknown_count++;
        }         }
     }      }
Line 10545  sub iclicker_eval { Line 9863  sub iclicker_eval {
     return ($errormsg,$number);      return ($errormsg,$number);
 }  }
   
 sub iclickerxml_eval {  
     my ($questiontitles,$responses)=@_;  
     my $number=0;  
     my $errormsg='';  
     my @state;  
     my %respbyid;  
     my $p = HTML::Parser->new  
     (  
         xml_mode => 1,  
         start_h =>  
             [sub {  
                  my ($tagname,$attr) = @_;  
                  push(@state,$tagname);  
                  if ("@state" eq "ssn p") {  
                      my $title = $attr->{qn};  
                      $title =~ s/(^\s+|\s+$)//g;  
                      $questiontitles->[$number]=$title;  
                  } elsif ("@state" eq "ssn p v") {  
                      my $id = $attr->{id};  
                      my $entry = $attr->{ans};  
                      $id=~s/^[\#0]+//;  
                      $entry =~s/[^a-zA-Z0-9\.\*\-\+]+//g;  
                      $respbyid{$id}[$number] = $entry;  
                  }  
             }, "tagname, attr"],  
          end_h =>  
                [sub {  
                    my ($tagname) = @_;  
                    if ("@state" eq "ssn p") {  
                        $number++;  
                    }  
                    pop(@state);  
                 }, "tagname"],  
     );  
   
     $p->parse($env{'form.upfile'});  
     $p->eof;  
     foreach my $id (keys(%respbyid)) {  
         $responses->{$id}=join(',',@{$respbyid{$id}});  
     }  
     return ($errormsg,$number);  
 }  
   
 sub interwrite_eval {  sub interwrite_eval {
     my ($questiontitles,$responses)=@_;      my ($questiontitles,$responses)=@_;
     my $number=0;      my $number=0;
Line 10644  sub turning_eval { Line 9919  sub turning_eval {
     return ($errormsg,$number);      return ($errormsg,$number);
 }  }
   
   
 sub assign_clicker_grades {  sub assign_clicker_grades {
     my ($r,$symb) = @_;      my ($r,$symb)=@_;
     if (!$symb) {return '';}      if (!$symb) {return '';}
 # See which part we are saving to  # See which part we are saving to
     my $res_error;      my $res_error;
Line 10656  sub assign_clicker_grades { Line 9932  sub assign_clicker_grades {
 # FIXME: This should probably look for the first handgradeable part  # FIXME: This should probably look for the first handgradeable part
     my $part=$$partlist[0];      my $part=$$partlist[0];
 # Start screen output  # Start screen output
     my $result = &Apache::loncommon::start_data_table().       my $result=&Apache::loncommon::start_data_table().
                  &Apache::loncommon::start_data_table_header_row().               &Apache::loncommon::start_data_table_header_row().
                  '<th>'.&mt('Assigning grades based on clicker file').'</th>'.               '<th>'.&mt('Assigning grades based on clicker file').'</th>'.
                  &Apache::loncommon::end_data_table_header_row().               &Apache::loncommon::end_data_table_header_row().
                  &Apache::loncommon::start_data_table_row().'<td>';               &Apache::loncommon::start_data_table_row().'<td>';
 # Get correct result  # Get correct result
 # FIXME: Possibly need delimiter other than ":"  # FIXME: Possibly need delimiter other than ":"
     my @correct=();      my @correct=();
Line 10715  sub assign_clicker_grades { Line 9991  sub assign_clicker_grades {
                       &mt('More than one entry found for [_1]!','<tt>'.$user.'</tt>').                        &mt('More than one entry found for [_1]!','<tt>'.$user.'</tt>').
                       '</span><br />';                        '</span><br />';
           }            }
           $users{$user}=1;            $users{$user}=1; 
           my @answer=split(/\,/,$env{$key});            my @answer=split(/\,/,$env{$key});
           my $sum=0;            my $sum=0;
           my $realnumber=$number;            my $realnumber=$number;
           for (my $i=0;$i<$number;$i++) {            for (my $i=0;$i<$number;$i++) {
              if  ($correct[$i] eq '-') {               if  ($correct[$i] eq '-') {
                 $realnumber--;                  $realnumber--;
              } elsif (($answer[$i]) || ($answer[$i]=~/^[0\.]+$/)) {               } elsif (($answer[$i]) || ($answer[$i]=~/^[0\.]+$/))  {
                 if ($gradingmechanism eq 'attendance') {                  if ($gradingmechanism eq 'attendance') {
                    $sum+=$pcorrect;                     $sum+=$pcorrect;
                 } elsif ($correct[$i] eq '*') {                  } elsif ($correct[$i] eq '*') {
Line 10781  sub navmap_errormsg { Line 10057  sub navmap_errormsg {
 }  }
   
 sub startpage {  sub startpage {
     my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$js,$onload,$divforres) = @_;      my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$js) = @_;
     my %args;  
     if ($onload) {  
          my %loaditems = (  
                         'onload' => $onload,  
                       );  
          $args{'add_entries'} = \%loaditems;  
     }  
     if ($nomenu) {      if ($nomenu) {
         $args{'only_body'} = 1;          $r->print(&Apache::loncommon::start_page("Student's Version",$js,{'only_body' => '1'}));
         $r->print(&Apache::loncommon::start_page("Student's Version",$js,\%args));  
     } else {      } else {
         unshift(@$crumbs,{href=>&href_symb_cmd($symb,'gradingmenu'),text=>"Grading"});          unshift(@$crumbs,{href=>&href_symb_cmd($symb,'gradingmenu'),text=>"Grading"});
         $args{'bread_crumbs'} = $crumbs;          $r->print(&Apache::loncommon::start_page('Grading',$js,
         $r->print(&Apache::loncommon::start_page('Grading',$js,\%args));                                                   {'bread_crumbs' => $crumbs}));
           &Apache::lonquickgrades::startGradeScreen($r,($env{'form.symb'}?'probgrading':'grading'));
     }      }
     unless ($nodisplayflag) {      unless ($nodisplayflag) {
        $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp,$divforres));         $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp));
     }      }
 }  }
   
 sub select_problem {  sub select_problem {
     my ($r)=@_;      my ($r)=@_;
     $r->print('<h3>'.&mt('Select the problem or one of the problems you want to grade').'</h3><form action="/adm/grades">');      $r->print('<h3>'.&mt('Select the problem or one of the problems you want to grade').'</h3><form action="/adm/grades">');
     $r->print(&Apache::lonstathelpers::problem_selector('.',undef,1,undef,undef,1));      $r->print(&Apache::lonstathelpers::problem_selector('.',undef,1));
     $r->print('<input type="hidden" name="command" value="gradingmenu" />');      $r->print('<input type="hidden" name="command" value="gradingmenu" />');
     $r->print('<input type="submit" value="'.&mt('Next').' &rarr;" /></form>');      $r->print('<input type="submit" value="'.&mt('Next').' &rarr;" /></form>');
 }  }
Line 10821  sub handler { Line 10090  sub handler {
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
   
 # see what command we need to execute  # see what command we need to execute
    
     my @commands=&Apache::loncommon::get_env_multiple('form.command');      my @commands=&Apache::loncommon::get_env_multiple('form.command');
     my $command=$commands[0];      my $command=$commands[0];
   
Line 10857  sub handler { Line 10126  sub handler {
     if (($symb eq '' || $command eq '') && ($env{'request.course.id'})) {      if (($symb eq '' || $command eq '') && ($env{'request.course.id'})) {
 #  #
 # Not called from a resource, but inside a course  # Not called from a resource, but inside a course
 #  #    
         &startpage($request,undef,[],1,1);          &startpage($request,undef,[],1,1);
         &select_problem($request);          &select_problem($request);
     } else {      } else {
         if ($command eq 'submission' && $perm{'vgr'}) {   if ($command eq 'submission' && $perm{'vgr'}) {
             my ($stuvcurrent,$stuvdisp,$versionform,$js,$onload);              my ($stuvcurrent,$stuvdisp,$versionform,$js);
             if (($env{'form.student'} ne '') && ($env{'form.userdom'} ne '')) {              if (($env{'form.student'} ne '') && ($env{'form.userdom'} ne '')) {
                 ($stuvcurrent,$stuvdisp,$versionform,$js) =                  ($stuvcurrent,$stuvdisp,$versionform,$js) =
                     &choose_task_version_form($symb,$env{'form.student'},                      &choose_task_version_form($symb,$env{'form.student'},
                                               $env{'form.userdom'});                                                $env{'form.userdom'});
             }              }
             my $divforres;              &startpage($request,$symb,[{href=>"", text=>"Student Submissions"}],undef,undef,$stuvcurrent,$stuvdisp,undef,$js);
             if ($env{'form.student'} eq '') {  
                 $js .= &part_selector_js();  
                 $onload = "toggleParts('gradesub');";  
             } else {  
                 $divforres = 1;  
             }  
             &startpage($request,$symb,[{href=>"", text=>"Student Submissions"}],undef,undef,$stuvcurrent,$stuvdisp,undef,$js,$onload,$divforres);  
             if ($versionform) {              if ($versionform) {
                 if ($divforres) {  
                     $request->print('<div style="padding:0;clear:both;margin:0;border:0"></div>');  
                 }  
                 $request->print($versionform);                  $request->print($versionform);
             }              }
             ($env{'form.student'} eq '' ? &listStudents($request,$symb,'',$divforres) : &submission($request,0,0,$symb,$divforres,$command));              $request->print('<br clear="all" />');
       ($env{'form.student'} eq '' ? &listStudents($request,$symb) : &submission($request,0,0,$symb));
         } elsif ($command eq 'versionsub' && $perm{'vgr'}) {          } elsif ($command eq 'versionsub' && $perm{'vgr'}) {
             my ($stuvcurrent,$stuvdisp,$versionform,$js) =              my ($stuvcurrent,$stuvdisp,$versionform,$js) =
                 &choose_task_version_form($symb,$env{'form.student'},                  &choose_task_version_form($symb,$env{'form.student'},
Line 10894  sub handler { Line 10154  sub handler {
             }              }
             $request->print('<br clear="all" />');              $request->print('<br clear="all" />');
             $request->print(&show_previous_task_version($request,$symb));              $request->print(&show_previous_task_version($request,$symb));
         } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {   } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},              &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},
                                        {href=>'',text=>'Select student'}],1,1);                                         {href=>'',text=>'Select student'}],1,1);
             &pickStudentPage($request,$symb);      &pickStudentPage($request,$symb);
         } elsif ($command eq 'displayPage' && $perm{'vgr'}) {   } elsif ($command eq 'displayPage' && $perm{'vgr'}) {
             &startpage($request,$symb,              &startpage($request,$symb,
                                       [{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},                                        [{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},
                                        {href=>'',text=>'Select student'},                                         {href=>'',text=>'Select student'},
                                        {href=>'',text=>'Grade student'}],1,1);                                         {href=>'',text=>'Grade student'}],1,1);
             &displayPage($request,$symb);      &displayPage($request,$symb);
         } elsif ($command eq 'gradeByPage' && $perm{'mgr'}) {   } elsif ($command eq 'gradeByPage' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},              &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},
                                        {href=>'',text=>'Select student'},                                         {href=>'',text=>'Select student'},
                                        {href=>'',text=>'Grade student'},                                         {href=>'',text=>'Grade student'},
                                        {href=>'',text=>'Store grades'}],1,1);                                         {href=>'',text=>'Store grades'}],1,1);
             &updateGradeByPage($request,$symb);      &updateGradeByPage($request,$symb);
         } elsif ($command eq 'processGroup' && $perm{'vgr'}) {   } elsif ($command eq 'processGroup' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>'',text=>'...'},              &startpage($request,$symb,[{href=>'',text=>'...'},
                                        {href=>'',text=>'Modify grades'}],undef,undef,undef,undef,undef,undef,undef,1);                                         {href=>'',text=>'Modify grades'}]);
             &processGroup($request,$symb);      &processGroup($request,$symb);
         } elsif ($command eq 'gradingmenu' && $perm{'vgr'}) {   } elsif ($command eq 'gradingmenu' && $perm{'vgr'}) {
             &startpage($request,$symb);              &startpage($request,$symb);
             $request->print(&grading_menu($request,$symb));      $request->print(&grading_menu($request,$symb));
         } elsif ($command eq 'individual' && $perm{'vgr'}) {   } elsif ($command eq 'individual' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>'',text=>'Select individual students to grade'}]);              &startpage($request,$symb,[{href=>'',text=>'Select individual students to grade'}]);
             $request->print(&submit_options($request,$symb));      $request->print(&submit_options($request,$symb));
         } elsif ($command eq 'ungraded' && $perm{'vgr'}) {          } elsif ($command eq 'ungraded' && $perm{'vgr'}) {
             my $js = &part_selector_js();              &startpage($request,$symb,[{href=>'',text=>'Grade ungraded submissions'}]);
             my $onload = "toggleParts('gradesub');";  
             &startpage($request,$symb,[{href=>'',text=>'Grade ungraded submissions'}],  
                        undef,undef,undef,undef,undef,$js,$onload);  
             $request->print(&listStudents($request,$symb,'graded'));              $request->print(&listStudents($request,$symb,'graded'));
         } elsif ($command eq 'table' && $perm{'vgr'}) {          } elsif ($command eq 'table' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>"", text=>"Grading table"}]);              &startpage($request,$symb,[{href=>"", text=>"Grading table"}]);
Line 10932  sub handler { Line 10189  sub handler {
         } elsif ($command eq 'all_for_one' && $perm{'vgr'}) {          } elsif ($command eq 'all_for_one' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>'',text=>'Grade page/folder for one student'}],1,1);              &startpage($request,$symb,[{href=>'',text=>'Grade page/folder for one student'}],1,1);
             $request->print(&submit_options_sequence($request,$symb));              $request->print(&submit_options_sequence($request,$symb));
         } elsif ($command eq 'viewgrades' && $perm{'vgr'}) {   } elsif ($command eq 'viewgrades' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},{href=>'', text=>"Modify grades"}]);              &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},{href=>'', text=>"Modify grades"}]);
             $request->print(&viewgrades($request,$symb));      $request->print(&viewgrades($request,$symb));
         } elsif ($command eq 'handgrade' && $perm{'mgr'}) {   } elsif ($command eq 'handgrade' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'',text=>'...'},              &startpage($request,$symb,[{href=>'',text=>'...'},
                                        {href=>'',text=>'Store grades'}]);                                         {href=>'',text=>'Store grades'}]);
             $request->print(&processHandGrade($request,$symb));      $request->print(&processHandGrade($request,$symb));
         } elsif ($command eq 'editgrades' && $perm{'mgr'}) {   } elsif ($command eq 'editgrades' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},              &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},
                                        {href=>&href_symb_cmd($symb,'viewgrades').'&group=all&section=all&Status=Active',                                         {href=>&href_symb_cmd($symb,'viewgrades').'&group=all&section=all&Status=Active',
                                                                              text=>"Modify grades"},                                                                               text=>"Modify grades"},
                                        {href=>'', text=>"Store grades"}]);                                         {href=>'', text=>"Store grades"}]);
             $request->print(&editgrades($request,$symb));      $request->print(&editgrades($request,$symb));
         } elsif ($command eq 'initialverifyreceipt' && $perm{'vgr'}) {          } elsif ($command eq 'initialverifyreceipt' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>'',text=>'Verify Receipt Number'}]);              &startpage($request,$symb,[{href=>'',text=>'Verify Receipt Number'}]);
             $request->print(&initialverifyreceipt($request,$symb));              $request->print(&initialverifyreceipt($request,$symb));
         } elsif ($command eq 'verify' && $perm{'vgr'}) {   } elsif ($command eq 'verify' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"initialverifyreceipt"),text=>'Verify Receipt Number'},              &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"initialverifyreceipt"),text=>'Verify Receipt Number'},
                                        {href=>'',text=>'Verification Result'}]);                                         {href=>'',text=>'Verification Result'}]);
             $request->print(&verifyreceipt($request,$symb));      $request->print(&verifyreceipt($request,$symb));
         } elsif ($command eq 'processclicker' && $perm{'mgr'}) {          } elsif ($command eq 'processclicker' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Process clicker'}]);              &startpage($request,$symb,[{href=>'', text=>'Process clicker'}]);
             $request->print(&process_clicker($request,$symb));              $request->print(&process_clicker($request,$symb));
Line 10964  sub handler { Line 10221  sub handler {
                                        {href=>'', text=>'Process clicker file'},                                         {href=>'', text=>'Process clicker file'},
                                        {href=>'', text=>'Store grades'}]);                                         {href=>'', text=>'Store grades'}]);
             $request->print(&assign_clicker_grades($request,$symb));              $request->print(&assign_clicker_grades($request,$symb));
         } elsif ($command eq 'csvform' && $perm{'mgr'}) {   } elsif ($command eq 'csvform' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
             $request->print(&upcsvScores_form($request,$symb));      $request->print(&upcsvScores_form($request,$symb));
         } elsif ($command eq 'csvupload' && $perm{'mgr'}) {   } elsif ($command eq 'csvupload' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
             $request->print(&csvupload($request,$symb));      $request->print(&csvupload($request,$symb));
         } elsif ($command eq 'csvuploadmap' && $perm{'mgr'} ) {   } elsif ($command eq 'csvuploadmap' && $perm{'mgr'} ) {
             &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
             $request->print(&csvuploadmap($request,$symb));      $request->print(&csvuploadmap($request,$symb));
         } elsif ($command eq 'csvuploadoptions' && $perm{'mgr'}) {   } elsif ($command eq 'csvuploadoptions' && $perm{'mgr'}) {
             if ($env{'form.associate'} ne 'Reverse Association') {      if ($env{'form.associate'} ne 'Reverse Association') {
                 &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);                  &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
                 $request->print(&csvuploadoptions($request,$symb));   $request->print(&csvuploadoptions($request,$symb));
             } else {      } else {
                 if ( $env{'form.upfile_associate'} ne 'reverse' ) {   if ( $env{'form.upfile_associate'} ne 'reverse' ) {
                     $env{'form.upfile_associate'} = 'reverse';      $env{'form.upfile_associate'} = 'reverse';
                 } else {   } else {
                     $env{'form.upfile_associate'} = 'forward';      $env{'form.upfile_associate'} = 'forward';
                 }   }
                 &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);                  &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
                 $request->print(&csvuploadmap($request,$symb));   $request->print(&csvuploadmap($request,$symb));
             }      }
         } elsif ($command eq 'csvuploadassign' && $perm{'mgr'} ) {   } elsif ($command eq 'csvuploadassign' && $perm{'mgr'} ) {
             &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
             $request->print(&csvuploadassign($request,$symb));      $request->print(&csvuploadassign($request,$symb));
         } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) {   } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1,              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
                        undef,undef,undef,undef,'toggleScantab(document.rules);');      $request->print(&scantron_selectphase($request,undef,$symb));
             $request->print(&scantron_selectphase($request,undef,$symb));    } elsif ($command eq 'scantron_warning' && $perm{'mgr'}) {
         } elsif ($command eq 'scantron_warning' && $perm{'mgr'}) {  
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
             $request->print(&scantron_do_warning($request,$symb));       $request->print(&scantron_do_warning($request,$symb));
         } elsif ($command eq 'scantron_validate' && $perm{'mgr'}) {   } elsif ($command eq 'scantron_validate' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
             $request->print(&scantron_validate_file($request,$symb));      $request->print(&scantron_validate_file($request,$symb));
         } elsif ($command eq 'scantron_process' && $perm{'mgr'}) {   } elsif ($command eq 'scantron_process' && $perm{'mgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
             $request->print(&scantron_process_students($request,$symb));      $request->print(&scantron_process_students($request,$symb));
         } elsif ($command eq 'scantronupload' &&    } elsif ($command eq 'scantronupload' && 
                  (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})||    (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})||
                   &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) {    &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1,  
                        undef,undef,undef,undef,'toggleScantab(document.rules);');  
             $request->print(&scantron_upload_scantron_data($request,$symb));  
         } elsif ($command eq 'scantronupload_save' &&  
                  (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})||  
                   &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) {  
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
             $request->print(&scantron_upload_scantron_data_save($request,$symb));       $request->print(&scantron_upload_scantron_data($request,$symb)); 
         } elsif ($command eq 'scantron_download' &&    } elsif ($command eq 'scantronupload_save' &&
                  &Apache::lonnet::allowed('usc',$env{'request.course.id'})) {    (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})||
     &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
             $request->print(&scantron_download_scantron_data($request,$symb));       $request->print(&scantron_upload_scantron_data_save($request,$symb));
     } elsif ($command eq 'scantron_download' &&
    &Apache::lonnet::allowed('usc',$env{'request.course.id'})) {
               &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
        $request->print(&scantron_download_scantron_data($request,$symb));
         } elsif ($command eq 'checksubmissions' && $perm{'vgr'}) {          } elsif ($command eq 'checksubmissions' && $perm{'vgr'}) {
             &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);              &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
             $request->print(&checkscantron_results($request,$symb));              $request->print(&checkscantron_results($request,$symb));
         } elsif ($command eq 'downloadfilesselect' && $perm{'vgr'}) {          } elsif ($command eq 'downloadfilesselect' && $perm{'vgr'}) {
             my $js = &part_selector_js();              &startpage($request,$symb,[{href=>'', text=>'Select which submissions to download'}]);
             my $onload = "toggleParts('gradingMenu');";  
             &startpage($request,$symb,[{href=>'', text=>'Select which submissions to download'}],  
                        undef,undef,undef,undef,undef,$js,$onload);  
             $request->print(&submit_options_download($request,$symb));              $request->print(&submit_options_download($request,$symb));
          } elsif ($command eq 'downloadfileslink' && $perm{'vgr'}) {           } elsif ($command eq 'downloadfileslink' && $perm{'vgr'}) {
             &startpage($request,$symb,              &startpage($request,$symb,
    [{href=>&href_symb_cmd($symb,'downloadfilesselect'), text=>'Select which submissions to download'},     [{href=>&href_symb_cmd($symb,'downloadfilesselect'), text=>'Select which submissions to download'},
     {href=>'', text=>'Download submitted files'}],      {href=>'', text=>'Download submissions'}]);
                undef,undef,undef,undef,undef,undef,undef,1);  
             $request->print('<div style="padding:0;clear:both;margin:0;border:0"></div>');  
             &submit_download_link($request,$symb);              &submit_download_link($request,$symb);
         } elsif ($command) {   } elsif ($command) {
             &startpage($request,$symb,[{href=>'', text=>'Access denied'}]);              &startpage($request,$symb,[{href=>'', text=>'Access denied'}]);
             $request->print('<p class="LC_error">'.&mt('Access Denied ([_1])',$command).'</p>');      $request->print('<p class="LC_error">'.&mt('Access Denied ([_1])',$command).'</p>');
         }   }
     }      }
     if ($ssi_error) {      if ($ssi_error) {
  &ssi_print_error($request);   &ssi_print_error($request);
     }      }
     $request->print(&Apache::loncommon::end_page());      if ($env{'form.inhibitmenu'}) {
           $request->print(&Apache::loncommon::end_page());
       } else {
           &Apache::lonquickgrades::endGradeScreen($request);
       }
     &reset_caches();      &reset_caches();
     return OK;      return OK;
 }  }
Line 11076  At least the logic that drives this has Line 10330  At least the logic that drives this has
 ssi_with_retries - Does the server side include of a resource.  ssi_with_retries - Does the server side include of a resource.
                      if the ssi call returns an error we'll retry it up to                       if the ssi call returns an error we'll retry it up to
                      the number of times requested by the caller.                       the number of times requested by the caller.
                      If we still have a problem, no text is appended to the                       If we still have a proble, no text is appended to the
                      output and we set some global variables.                       output and we set some global variables.
                      to indicate to the caller an SSI error occurred.                         to indicate to the caller an SSI error occurred.  
                      All of this is supposed to deal with the issues described                       All of this is supposed to deal with the issues described
                      in LON-CAPA BZ 5631 see:                       in LonCAPA BZ 5631 see:
                      http://bugs.lon-capa.org/show_bug.cgi?id=5631                       http://bugs.lon-capa.org/show_bug.cgi?id=5631
                      by informing the user that this happened.                       by informing the user that this happened.
   
Line 11112  ssi_with_retries() Line 10366  ssi_with_retries()
   
 =over  =over
   
   =head1 Routines to display previous version of a Task for a specific student
   
   Tasks are graded pass/fail. Students who have yet to pass a particular Task
   can receive another opportunity. Access to tasks is slot-based. If a slot
   requires a proctor to check-in the student, a new version of the Task will
   be created when the student is checked in to the new opportunity.
   
   If a particular student has tried two or more versions of a particular task,
   the submission screen provides a user with vgr privileges (e.g., a Course
   Coordinator) the ability to display a previous version worked on by the
   student.  By default, the current version is displayed. If a previous version
   has been selected for display, submission data are only shown that pertain
   to that particular version, and the interface to submit grades is not shown.
   
   =over 4
   
   =item show_previous_task_version()
   
   Displays a specified version of a student's Task, as the student sees it.
   
   Inputs: 2
           request - request object
           symb    - unique symb for current instance of resource
   
   Output: None.
   
   Side Effects: calls &show_problem() to print version of Task, with
                 version contained in form item: $env{'form.previousversion'}
   
   =item choose_task_version_form()
   
   Displays a web form used to select which version of a student's view of a
   Task should be displayed.  Either launches a pop-up window, or replaces
   content in existing pop-up, or replaces page in main window.
   
   Inputs: 4
           symb    - unique symb for current instance of resource
           uname   - username of student
           udom    - domain of student
           nomenu  - 1 if display is in a pop-up window, and hence no menu
                     breadcrumbs etc., are displayed
   
   Output: 4
           current   - student's current version
           displayed - student's version being displayed
           result    - scalar containing HTML for web form used to switch to
                       a different version (or a link to close window, if pop-up).
           js        - javascript for processing selection in versions web form
   
   Side Effects: None.
   
   =item previous_display_javascript()
   
   Inputs: 2
           nomenu  - 1 if display is in a pop-up window, and hence no menu
                     breadcrumbs etc., are displayed.
           current - student's current version number.
   
   Output: 1
           js      - javascript for processing selection in versions web form.
   
   Side Effects: None.
   
   =back
   
   =head1 Routines to process bubblesheet data.
   
   =over 4
   
 =item scantron_get_correction() :   =item scantron_get_correction() : 
   
    Builds the interface screen to interact with the operator to fix a     Builds the interface screen to interact with the operator to fix a
Line 11121  ssi_with_retries() Line 10444  ssi_with_retries()
     $r           - Apache request object      $r           - Apache request object
     $i           - number of the current scanline      $i           - number of the current scanline
     $scan_record - hash ref as returned from &scantron_parse_scanline()      $scan_record - hash ref as returned from &scantron_parse_scanline()
     $scan_config - hash ref as returned from &Apache::lonnet::get_scantron_config()      $scan_config - hash ref as returned from &get_scantron_config()
     $line        - full contents of the current scanline      $line        - full contents of the current scanline
     $error       - error condition, valid values are      $error       - error condition, valid values are
                    'incorrectCODE', 'duplicateCODE',                     'incorrectCODE', 'duplicateCODE',
Line 11148  ssi_with_retries() Line 10471  ssi_with_retries()
                   or code-based randompick and/or randomorder.                    or code-based randompick and/or randomorder.
   
   
   
 =item  scantron_get_maxbubble() :   =item  scantron_get_maxbubble() : 
   
    Arguments:     Arguments:
Line 11227  ssi_with_retries() Line 10551  ssi_with_retries()
 =item navmap_errormsg() :  =item navmap_errormsg() :
   
    Returns HTML mark-up inside a <div></div> with a link to re-initialize the course.     Returns HTML mark-up inside a <div></div> with a link to re-initialize the course.
    Should be called whenever the request to instantiate a navmap object fails.       Should be called whenever the request to instantiate a navmap object fails.
   
   =back
   
 =back  =back
   

Removed from v.1.596.2.12.2.53  
changed lines
  Added in v.1.706


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