Diff for /loncom/homework/grades.pm between versions 1.125 and 1.179

version 1.125, 2003/07/25 20:35:40 version 1.179, 2004/03/04 14:09:47
Line 48  use Apache::lonhomework; Line 48  use Apache::lonhomework;
 use Apache::loncoursedata;  use Apache::loncoursedata;
 use Apache::lonmsg qw(:user_normal_msg);  use Apache::lonmsg qw(:user_normal_msg);
 use Apache::Constants qw(:common);  use Apache::Constants qw(:common);
   use Apache::lonlocal;
 use String::Similarity;  use String::Similarity;
   
 my %oldessays=();  my %oldessays=();
Line 55  my %perm=(); Line 56  my %perm=();
   
 # ----- These first few routines are general use routines.----  # ----- These first few routines are general use routines.----
 #  #
 # --- Retrieve the parts that matches stores_\d+ from the metadata file.---  # --- Retrieve the parts from the metadata file.---
 sub getpartlist {  sub getpartlist {
     my ($url) = @_;      my ($url,$symb) = @_;
     my @parts =();      my $partorder = &Apache::lonnet::metadata($url, 'partorder');
     my (@metakeys) = split(/,/,&Apache::lonnet::metadata($url,'keys'));      my @parts;
     foreach my $key (@metakeys) {      if ($partorder) {
  if ( $key =~ m/stores_(\w+)_.*/) {   for my $part (split (/,/,$partorder)) {
     push(@parts,$key);      if (!&Apache::loncommon::check_if_partid_hidden($part,$symb)) {
    push(@parts, $part);
       }
    }    
       } else {
    my $metadata = &Apache::lonnet::metadata($url, 'packages');
    foreach (split(/\,/,$metadata)) {
       if ($_ =~ /^part_(.*)$/) {
    if (!&Apache::loncommon::check_if_partid_hidden($1,$symb)) {
       push(@parts, $1);
    }
       }
  }   }
     }      }
     return @parts;      my @stores;
       foreach my $part (@parts) {
    my (@metakeys) = split(/,/,&Apache::lonnet::metadata($url,'keys'));
    foreach my $key (@metakeys) {
       if ($key =~ m/^stores_\Q$part\E_/) { push(@stores,$key); }
    }
       }
       return @stores;
 }  }
   
 # --- Get the symbolic name of a problem and the url  # --- Get the symbolic name of a problem and the url
 sub get_symb_and_url {  sub get_symb_and_url {
     my ($request) = @_;      my ($request,$silent) = @_;
     (my $url=$ENV{'form.url'}) =~ s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;      (my $url=$ENV{'form.url'}) =~ s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
     my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));      my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));
     if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }      if ($symb eq '') { 
    if (!$silent) {
       $request->print("Unable to handle ambiguous references:$url:.");
       return ();
    }
       }
     return ($symb,$url);      return ($symb,$url);
 }  }
   
Line 96  sub get_fullname { Line 120  sub get_fullname {
     return $fullname;      return $fullname;
 }  }
   
   #--- Format fullname, username:domain if different for display
   #--- Use anywhere where the student names are listed
   sub nameUserString {
       my ($type,$fullname,$uname,$udom) = @_;
       if ($type eq 'header') {
    return '<b>&nbsp;Fullname&nbsp;</b><font color="#999999">(Username)</font>&nbsp;';
       } else {
    return '&nbsp;'.$fullname.'<font color="#999999">&nbsp;('.$uname.
       ($ENV{'user.domain'} eq $udom ? '' : ' ('.$udom.')').')</font>';
       }
   }
   
 #--- Get the partlist and the response type for a given problem. ---  #--- Get the partlist and the response type for a given problem. ---
 #--- Indicate if a response type is coded handgraded or not. ---  #--- Indicate if a response type is coded handgraded or not. ---
 sub response_type {  sub response_type {
     my ($url,$symb) = shift;      my ($url,$symb) = shift;
     $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url))) if ($symb eq '');      $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url))) if ($symb eq '');
     my $allkeys = &Apache::lonnet::metadata($url,'keys');      my $allkeys = &Apache::lonnet::metadata($url,'keys');
       my %vPart;
       foreach my $partid (&Apache::loncommon::get_env_multiple('form.vPart')) {
    $vPart{$partid}=1;
       }
     my %seen = ();      my %seen = ();
     my (@partlist,%handgrade);      my (@partlist,%handgrade,%responseType);
     foreach (split(/,/,&Apache::lonnet::metadata($url,'packages'))) {      foreach (split(/,/,&Apache::lonnet::metadata($url,'packages'))) {
  if (/^\w+response_\w+.*/) {   if (/^\w+response_.*/) {
     my ($responsetype,$part) = split(/_/,$_,2);      my ($responsetype,$part) = split(/_/,$_,2);
     my ($partid,$respid) = split(/_/,$part);      my ($partid,$respid) = split(/_/,$part);
       if (&Apache::loncommon::check_if_partid_hidden($partid,$symb)) {
    next;
       }
       if (%vPart && !exists($vPart{$partid})) {
    next;
       }
     $responsetype =~ s/response$//; # make it compatible w/ navmaps - should move to that!!      $responsetype =~ s/response$//; # make it compatible w/ navmaps - should move to that!!
 #    my ($value) = &Apache::lonnet::EXT('resource.'.$part.'.handgrade',$symb);      my ($value) = &Apache::lonnet::EXT('resource.'.$part.'.handgrade',$symb);
 #    $handgrade{$part} = $responsetype.':'.($value eq 'yes' ? 'yes' : 'no'); #a bug $value is 'yes' regardless      $handgrade{$part} = ($value eq 'yes' ? 'yes' : 'no'); 
     $handgrade{$part} = $responsetype.':'.(($allkeys =~ /parameter_$part\_handgrade/) ? 'yes' : 'no');      if (!exists($responseType{$partid})) { $responseType{$partid}={}; }
       $responseType{$partid}->{$respid}=$responsetype;
     next if ($seen{$partid} > 0);      next if ($seen{$partid} > 0);
     $seen{$partid}++;      $seen{$partid}++;
     push @partlist,$partid;      push @partlist,$partid;
  }   }
     }      }
     return \@partlist,\%handgrade;      return \@partlist,\%handgrade,\%responseType;
 }  }
   
 #--- Show resource title  #--- Show resource title
 #--- and parts and response type  #--- and parts and response type
 sub showResourceInfo {  sub showResourceInfo {
     my ($url,$probTitle) = @_;      my ($url,$probTitle,$checkboxes) = @_;
       my $col=3;
       if ($checkboxes) { $col=4; }
     my $result ='<table border="0">'.      my $result ='<table border="0">'.
  '<tr><td colspan=3><font size=+1><b>Current Resource: </b>'.$probTitle.'</font></td></tr>'."\n";   '<tr><td colspan="'.$col.'"><font size="+1"><b>'.&mt('Current Resource').': </b>'.
     my ($partlist,$handgrade) = &response_type($url);   $probTitle.'</font></td></tr>'."\n";
     my %resptype = (); #,$hdgrade)=('','no');      my ($partlist,$handgrade,$responseType) = &response_type($url);
       my %resptype = ();
     my $hdgrade='no';      my $hdgrade='no';
     for (sort keys(%$handgrade)) {      my %partsseen;
  my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});      for my $part_resID (sort keys(%$handgrade)) {
  my $partID = (split(/_/))[0];   my $handgrade=$$handgrade{$part_resID};
  $resptype{$partID} = $responsetype;   my ($partID,$resID) = split(/_/,$part_resID);
    my $responsetype = $responseType->{$partID}->{$resID};
  $hdgrade = $handgrade if ($handgrade eq 'yes');   $hdgrade = $handgrade if ($handgrade eq 'yes');
  $result.='<tr><td><b>Part </b>'.$partID.'</td>'.   $result.='<tr>';
    if ($checkboxes) {
       if (exists($partsseen{$partID})) {
    $result.="<td>&nbsp;</td>";
       } else {
    $result.="<td><input type='checkbox' name='vPart' value='$partID' checked='on' /></td>";
       }
       $partsseen{$partID}=1;
    }
    $result.='<td><b>Part </b>'.$partID.' <font color="#999999">'.
       $resID.'</font></td>'.
     '<td><b>Type: </b>'.$responsetype.'</td></tr>';      '<td><b>Type: </b>'.$responsetype.'</td></tr>';
 #    '<td><b>Handgrade: </b>'.$handgrade.'</td></tr>';  #    '<td><b>Handgrade: </b>'.$handgrade.'</td></tr>';
     }      }
     $result.='</table>'."\n";      $result.='</table>'."\n";
     return $result,\%resptype,$hdgrade,$partlist,$handgrade;      return $result,$responseType,$hdgrade,$partlist,$handgrade;
 }  }
   
   
   sub get_order {
       my ($partid,$respid,$symb,$uname,$udom)=@_;
       my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
       $url=&Apache::lonnet::clutter($url);
       my $subresult=&Apache::lonnet::ssi($url,
          ('grade_target' => 'analyze'),
          ('grade_domain' => $udom),
          ('grade_symb' => $symb),
          ('grade_courseid' => 
           $ENV{'request.course.id'}),
          ('grade_username' => $uname));
       (undef,$subresult)=split(/_HASH_REF__/,$subresult,2);
       my %analyze=&Apache::lonnet::str2hash($subresult);
       return ($analyze{"$partid.$respid.shown"});
   }
 #--- Clean response type for display  #--- Clean response type for display
 #--- Currently filters option response type only.  #--- Currently filters option/rank/radiobutton/match/essay response types only.
 sub cleanRecord {  sub cleanRecord {
     my ($answer,$response,$symb) = @_;      my ($answer,$response,$symb,$partid,$respid,$record,$order,$version) = @_;
     if ($response eq 'option') {      my $grayFont = '<font color="#999999">';
  my (@IDs,@ans);      if ($response =~ /^(option|rank)$/) {
  foreach (split(/\&/,&Apache::lonnet::unescape($answer))) {   my %answer=&Apache::lonnet::str2hash($answer);
     my ($optionID,$ans) = split(/=/);   my %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"});
     push @IDs,$optionID.'</font>';   my ($toprow,$bottomrow);
     push @ans,$ans;   foreach my $foil (@$order) {
  }      if ($grading{$foil} == 1) {
  my $grayFont = '<font color="#999999">';   $toprow.='<td><b>'.$answer{$foil}.'&nbsp;</b></td>';
  return '<table border="1">'.      } else {
     '<tr valign="top"><td>Answer</td><td>'.   $toprow.='<td><i>'.$answer{$foil}.'&nbsp;</i></td>';
     (join '</td><td>',@ans).'</td></tr>'.      }
     '<tr valign="top"><td>'.$grayFont.'Option ID</font></td><td>'.$grayFont.      $bottomrow.='<td>'.$grayFont.$foil.'</font>&nbsp;</td>';
     (join '</td><td>'.$grayFont,@IDs).'</font></td></tr>'.   }
     '</table>';   return '<blockquote><table border="1">'.
     }      '<tr valign="top"><td>Answer</td>'.$toprow.'</tr>'.
     if ($response eq 'essay') {      '<tr valign="top"><td>'.$grayFont.'Option ID</font></td>'.
       $grayFont.$bottomrow.'</tr>'.'</table></blockquote>';
       } elsif ($response eq 'match') {
    my %answer=&Apache::lonnet::str2hash($answer);
    my %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"});
    my @items=&Apache::lonnet::str2array($record->{$version."resource.$partid.$respid.submissionitems"});
    my ($toprow,$middlerow,$bottomrow);
    foreach my $foil (@$order) {
       my $item=shift(@items);
       if ($grading{$foil} == 1) {
    $toprow.='<td><b>'.$item.'&nbsp;</b></td>';
    $middlerow.='<td><b>'.$grayFont.$answer{$foil}.'&nbsp;</font></b></td>';
       } else {
    $toprow.='<td><i>'.$item.'&nbsp;</i></td>';
    $middlerow.='<td><i>'.$grayFont.$answer{$foil}.'&nbsp;</font></i></td>';
       }
       $bottomrow.='<td>'.$grayFont.$foil.'</font>&nbsp;</td>';
    }
    return '<blockquote><table border="1">'.
       '<tr valign="top"><td>Answer</td>'.$toprow.'</tr>'.
       '<tr valign="top"><td>'.$grayFont.'Item ID</font></td>'.
       $middlerow.'</tr>'.
       '<tr valign="top"><td>'.$grayFont.'Option ID</font></td>'.
       $bottomrow.'</tr>'.'</table></blockquote>';
       } elsif ($response eq 'radiobutton') {
    my %answer=&Apache::lonnet::str2hash($answer);
    my ($toprow,$bottomrow);
    my $correct=($order->[0])+1;
    for (my $i=1;$i<=$#$order;$i++) {
       my $foil=$order->[$i];
       if (exists($answer{$foil})) {
    if ($i == $correct) {
       $toprow.='<td><b>true</b></td>';
    } else {
       $toprow.='<td><i>true</i></td>';
    }
       } else {
    $toprow.='<td>false</td>';
       }
       $bottomrow.='<td>'.$grayFont.$foil.'</font>&nbsp;</td>';
    }
    return '<blockquote><table border="1">'.
       '<tr valign="top"><td>Answer</td>'.$toprow.'</tr>'.
       '<tr valign="top"><td>'.$grayFont.'Option ID</font></td>'.
       $grayFont.$bottomrow.'</tr>'.'</table></blockquote>';
       } elsif ($response eq 'essay') {
  if (! exists ($ENV{'form.'.$symb})) {   if (! exists ($ENV{'form.'.$symb})) {
     my (%keyhash) = &Apache::lonnet::dump('nohist_handgrade',      my (%keyhash) = &Apache::lonnet::dump('nohist_handgrade',
   $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},    $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
Line 174  sub cleanRecord { Line 296  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.
  }   }
  return &keywords_highlight($answer);   $answer =~ s-\n-<br />-g;
    return '<br /><br /><blockquote><tt>'.&keywords_highlight($answer).'</tt></blockquote>';
     }      }
     return $answer;      return $answer;
 }  }
Line 207  sub commonJSfunctions { Line 330  sub commonJSfunctions {
  }   }
     }      }
  } else {   } else {
     if (selectOne.selected) return selectOne.value;              // only one value it must be the selected one
       return selectOne.value;
  }   }
     }      }
 </script>  </script>
Line 299  sub student_gradeStatus { Line 423  sub student_gradeStatus {
     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 %partstatus = ();      my %partstatus = ();
     foreach (@$partlist) {      foreach (@$partlist) {
  my ($status,$foo)    = split(/_/,$record{"resource.$_.solved"},2);   my ($status,undef)   = split(/_/,$record{"resource.$_.solved"},2);
  $status              = 'nothing' if ($status eq '');   $status              = 'nothing' if ($status eq '');
  $partstatus{$_}      = $status;   $partstatus{$_}      = $status;
  my $subkey           = "resource.$_.submitted_by";   my $subkey           = "resource.$_.submitted_by";
Line 402  sub verifyreceipt { Line 526  sub verifyreceipt {
   
     my ($string,$contents,$matches) = ('','',0);      my ($string,$contents,$matches) = ('','',0);
     my (undef,undef,$fullname) = &getclasslist('all','0');      my (undef,undef,$fullname) = &getclasslist('all','0');
       
       my $receiptparts=0;
       if ($ENV{"course.$courseid.receiptalg"} eq 'receipt2') { $receiptparts=1; }
       my $parts=['0'];
       if ($receiptparts) { ($parts)=&response_type($url,$symb); }
     foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {      foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {
  my ($uname,$udom)=split(/\:/);   my ($uname,$udom)=split(/\:/);
  if ($receipt eq    foreach my $part (@$parts) {
     &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb)) {      if ($receipt eq &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb,$part)) {
     $contents.='<tr bgcolor="#ffffe6"><td>&nbsp;'."\n".   $contents.='<tr bgcolor="#ffffe6"><td>&nbsp;'."\n".
  '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.      '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.
  '\')"; TARGET=_self>'.$$fullname{$_}.'</a>&nbsp;</td>'."\n".      '\')"; TARGET=_self>'.$$fullname{$_}.'</a>&nbsp;</td>'."\n".
  '<td>&nbsp;'.$uname.'&nbsp;</td>'.      '<td>&nbsp;'.$uname.'&nbsp;</td>'.
  '<td>&nbsp;'.$udom.'&nbsp;</td></tr>'."\n";      '<td>&nbsp;'.$udom.'&nbsp;</td>';
        if ($receiptparts) {
     $matches++;      $contents.='<td>&nbsp;'.$part.'&nbsp;</td>';
    }
    $contents.='</tr>'."\n";
   
    $matches++;
       }
  }   }
     }      }
     if ($matches == 0) {      if ($matches == 0) {
Line 426  sub verifyreceipt { Line 559  sub verifyreceipt {
     '<table border="0"><tr bgcolor="#e6ffff">'."\n".      '<table border="0"><tr bgcolor="#e6ffff">'."\n".
     '<td><b>&nbsp;Fullname&nbsp;</b></td>'."\n".      '<td><b>&nbsp;Fullname&nbsp;</b></td>'."\n".
     '<td><b>&nbsp;Username&nbsp;</b></td>'."\n".      '<td><b>&nbsp;Username&nbsp;</b></td>'."\n".
     '<td><b>&nbsp;Domain&nbsp;</b></td></tr>'."\n".      '<td><b>&nbsp;Domain&nbsp;</b></td>';
     $contents.   if ($receiptparts) {
       $string.='<td>&nbsp;Problem Part&nbsp;</td>';
    }
    $string.='</tr>'."\n".$contents.
     '</table></td></tr></table>'."\n";      '</table></td></tr></table>'."\n";
     }      }
     return $string.&show_grading_menu_form($symb,$url);      return $string.&show_grading_menu_form($symb,$url);
Line 453  sub listStudents { Line 589  sub listStudents {
     my $result='<h3><font color="#339933">&nbsp;'.$viewgrade.      my $result='<h3><font color="#339933">&nbsp;'.$viewgrade.
  ' Submissions for a Student or a Group of Students</font></h3>';   ' Submissions for a Student or a Group of Students</font></h3>';
   
     my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($url,$ENV{'form.probTitle'});      my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($url,$ENV{'form.probTitle'},($ENV{'form.showgrading'} eq 'yes'));
     $result.=$table;  
   
     $request->print(<<LISTJAVASCRIPT);      $request->print(<<LISTJAVASCRIPT);
 <script type="text/javascript" language="javascript">  <script type="text/javascript" language="javascript">
Line 475  sub listStudents { Line 610  sub listStudents {
     sense = "the student";      sense = "the student";
  }   }
  if (ctr == 0) {   if (ctr == 0) {
     alert("Please select "+sense+" before clicking on the $viewgrade button.");      alert("Please select "+sense+" before clicking on the Next button.");
     return false;      return false;
  }   }
  document.gradesub.submit();   document.gradesub.submit();
Line 494  LISTJAVASCRIPT Line 629  LISTJAVASCRIPT
   
     my $checkhdgrade = ($ENV{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1 ) ? 'checked' : '';      my $checkhdgrade = ($ENV{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1 ) ? 'checked' : '';
     my $checklastsub = $checkhdgrade eq '' ? 'checked' : '';      my $checklastsub = $checkhdgrade eq '' ? 'checked' : '';
     my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'."\n".      my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'.
  '&nbsp;<b>View Problem Text: </b><input type="radio" name="vProb" value="no" checked /> no '."\n".   "\n".$table.
    '&nbsp;<b>View Problem Text: </b><input type="radio" name="vProb" value="no" checked="on" /> no '."\n".
  '<input type="radio" name="vProb" value="yes" /> one student '."\n".   '<input type="radio" name="vProb" value="yes" /> one student '."\n".
  '<input type="radio" name="vProb" value="all" /> all students <br />'."\n".   '<input type="radio" name="vProb" value="all" /> all students <br />'."\n".
    '&nbsp;<b>View Answer: </b><input type="radio" name="vAns" value="no"  /> no '."\n".
    '<input type="radio" name="vAns" value="yes" /> one student '."\n".
    '<input type="radio" name="vAns" value="all" checked="on" /> all students <br />'."\n".
  '&nbsp;<b>Submissions: </b>'."\n";   '&nbsp;<b>Submissions: </b>'."\n";
     if ($ENV{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1) {      if ($ENV{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1) {
  $gradeTable.='<input type="radio" name="lastSub" value="hdgrade" '.$checkhdgrade.' /> essay part only'."\n";   $gradeTable.='<input type="radio" name="lastSub" value="hdgrade" '.$checkhdgrade.' /> essay part only'."\n";
Line 506  LISTJAVASCRIPT Line 645  LISTJAVASCRIPT
     my $saveStatus = $ENV{'form.Status'} eq '' ? 'Active' : $ENV{'form.Status'};      my $saveStatus = $ENV{'form.Status'} eq '' ? 'Active' : $ENV{'form.Status'};
     $ENV{'form.Status'} = $saveStatus;      $ENV{'form.Status'} = $saveStatus;
   
     $gradeTable.='<input type="radio" name="lastSub" value="lastonly" '.$checklastsub.' /> last sub only'."\n".      $gradeTable.='<input type="radio" name="lastSub" value="lastonly" '.$checklastsub.' /> last submission only'."\n".
  '<input type="radio" name="lastSub" value="last" /> last sub & parts info'."\n".   '<input type="radio" name="lastSub" value="last" /> last submission & parts info'."\n".
  '<input type="radio" name="lastSub" value="datesub" /> by dates and submissions'."\n".   '<input type="radio" name="lastSub" value="datesub" /> by dates and submissions'."\n".
  '<input type="radio" name="lastSub" value="all" /> all details'."\n".   '<input type="radio" name="lastSub" value="all" /> all details'."\n".
  '<input type="hidden" name="section"     value="'.$getsec.'" />'."\n".   '<input type="hidden" name="section"     value="'.$getsec.'" />'."\n".
Line 527  LISTJAVASCRIPT Line 666  LISTJAVASCRIPT
     &Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,'javascript:reLoadList(this.form);').'<br />';      &Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,'javascript:reLoadList(this.form);').'<br />';
     }      }
   
     $gradeTable.='To '.lc($viewgrade).' a submission, click on the check box next to the student\'s name. Then '."\n".      $gradeTable.='To '.lc($viewgrade).' a submission or a group of submissions, click on the check box(es) '.
  'click on the '.$viewgrade.' button. To view the submissions for a group of students, click'."\n".   'next to the student\'s name(s). Then click on the Next button.<br />'."\n".
  ' on the check boxes for the group of students.<br />'."\n".  
  '<input type="hidden" name="command" value="processGroup" />'."\n";   '<input type="hidden" name="command" value="processGroup" />'."\n";
     $gradeTable.='<input type="button" '."\n".      $gradeTable.='<input type="button" '."\n".
  'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n".   'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n".
  'value="'.$viewgrade.'" />'."\n";   'value="Next->" />'."\n";
       $gradeTable.='<input type="checkbox" name="checkPlag" checked="on">Check For Plagiarism</input>';
     my (undef, undef, $fullname) = &getclasslist($getsec,'1');        my (undef, undef, $fullname) = &getclasslist($getsec,'1');  
     $gradeTable.='<table border="0"><tr><td bgcolor="#777777">'.      $gradeTable.='<table border="0"><tr><td bgcolor="#777777">'.
  '<table border="0"><tr bgcolor="#e6ffff">';   '<table border="0"><tr bgcolor="#e6ffff">';
     my $loop = 0;      my $loop = 0;
     while ($loop < 2) {      while ($loop < 2) {
  $gradeTable.='<td><b>&nbsp;Select&nbsp;</b></td><td><b>&nbsp;Fullname&nbsp;</b>'.   $gradeTable.='<td><b>&nbsp;No.</b>&nbsp;</td><td><b>&nbsp;Select&nbsp;</b></td>'.
     '<font color="#999999">(Username)</font>&nbsp;</td>';      '<td>'.&nameUserString('header').'</td>';
  if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {   if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
     foreach (sort(@$partlist)) {      foreach (sort(@$partlist)) {
  $gradeTable.='<td><b>&nbsp;Part '.(split(/_/))[0].' Status&nbsp;</b></td>';   $gradeTable.='<td><b>&nbsp;Part '.(split(/_/))[0].' Status&nbsp;</b></td>';
     }      }
  }   }
  $loop++;   $loop++;
   # $gradeTable.='<td></td>' if ($loop%2 ==1);
     }      }
     $gradeTable.='</tr>'."\n";      $gradeTable.='</tr>'."\n";
   
Line 557  LISTJAVASCRIPT Line 696  LISTJAVASCRIPT
  my %status = ();   my %status = ();
  if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {   if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
     (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist);      (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist);
     my $statusflg = '';      my $submitted = 0;
       my $graded = 0;
     foreach (keys(%status)) {      foreach (keys(%status)) {
  $statusflg = 1 if ($status{$_} ne 'nothing');   $submitted = 1 if ($status{$_} ne 'nothing');
    $graded = 1 if ($status{$_} !~ /^correct/);
   
  my ($foo,$partid,$foo1) = split(/\./,$_);   my ($foo,$partid,$foo1) = split(/\./,$_);
  if ($status{'resource.'.$partid.'.submitted_by'} ne '') {   if ($status{'resource.'.$partid.'.submitted_by'} ne '') {
     $statusflg = '';      $submitted = 0;
       my ($part)=split(/\./,$partid);
     $gradeTable.='<input type="hidden" name="'.      $gradeTable.='<input type="hidden" name="'.
  $student.':submitted_by" value="'.   $student.':'.$part.':submitted_by" value="'.
  $status{'resource.'.$partid.'.submitted_by'}.'" />';   $status{'resource.'.$partid.'.submitted_by'}.'" />';
  }   }
     }      }
     next if ($statusflg eq '' && $submitonly eq 'yes');      next if (!$submitted && ($submitonly eq 'yes' ||
        $submitonly eq 'incorrect' ||
        $submitonly eq 'graded'));
       next if (!$graded && ($submitonly eq 'graded' ||
     $submitonly eq 'incorrect'));
  }   }
   
  $ctr++;   $ctr++;
  if ( $perm{'vgr'} eq 'F' ) {   if ( $perm{'vgr'} eq 'F' ) {
     $gradeTable.='<tr bgcolor="#ffffe6">' if ($ctr%2 ==1);      $gradeTable.='<tr bgcolor="#ffffe6">' if ($ctr%2 ==1);
     $gradeTable.='<td align="center"><input type=checkbox name="stuinfo" value="'.      $gradeTable.='<td align="right">'.$ctr.'&nbsp;</td>'.
    '<td align="center"><input type=checkbox name="stuinfo" value="'.
  $student.':'.$$fullname{$student}.'&nbsp;"></td>'."\n".   $student.':'.$$fullname{$student}.'&nbsp;"></td>'."\n".
  '<td>&nbsp;'.$$fullname{$student}.'&nbsp;'."\n".   '<td>'.&nameUserString(undef,$$fullname{$student},$uname,$udom).'</td>'."\n";
  '<font color="#999999">('.$uname.')</font></td>'."\n";  
   
     if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {      if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
  foreach (sort keys(%status)) {   foreach (sort keys(%status)) {
Line 585  LISTJAVASCRIPT Line 732  LISTJAVASCRIPT
     $gradeTable.='<td align="middle">&nbsp;'.$status{$_}.'&nbsp;</td>'."\n";      $gradeTable.='<td align="middle">&nbsp;'.$status{$_}.'&nbsp;</td>'."\n";
  }   }
     }      }
   #    $gradeTable.='<td></td>' if ($ctr%2 ==1);
     $gradeTable.='</tr>'."\n" if ($ctr%2 ==0);      $gradeTable.='</tr>'."\n" if ($ctr%2 ==0);
  }   }
     }      }
     if ($ctr%2 ==1) {      if ($ctr%2 ==1) {
  $gradeTable.='<td>&nbsp;</td><td>&nbsp;</td>';   $gradeTable.='<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>';
     if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {      if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
  foreach (@$partlist) {   foreach (@$partlist) {
     $gradeTable.='<td>&nbsp;</td>';      $gradeTable.='<td>&nbsp;</td>';
Line 601  LISTJAVASCRIPT Line 749  LISTJAVASCRIPT
     $gradeTable.='</table></td></tr></table>'.      $gradeTable.='</table></td></tr></table>'.
  '<input type="button" '.   '<input type="button" '.
  'onClick="javascript:checkSelect(this.form.stuinfo);" '.   'onClick="javascript:checkSelect(this.form.stuinfo);" '.
  'value="'.$viewgrade.'" /></form>'."\n";   'value="Next->" /></form>'."\n";
     if ($ctr == 0) {      if ($ctr == 0) {
  my $num_students=(scalar(keys(%$fullname)));   my $num_students=(scalar(keys(%$fullname)));
  if ($num_students eq 0) {   if ($num_students eq 0) {
     $gradeTable='<br />&nbsp;<font color="red">There are no students currently enrolled.</font>';      $gradeTable='<br />&nbsp;<font color="red">There are no students currently enrolled.</font>';
  } else {   } else {
       my $submissions='submissions';
       if ($submitonly eq 'incorrect') { $submissions = 'incorrect submissions'; }
       if ($submitonly eq 'graded'   ) { $submissions = 'ungraded submissions'; }
     $gradeTable='<br />&nbsp;<font color="red">'.      $gradeTable='<br />&nbsp;<font color="red">'.
  'No submissions found for this resource for any students. ('.$num_students.   'No '.$submissions.' found for this resource for any students. ('.$num_students.
  ' checked for submissions</font><br />';   ' students checked for '.$submissions.')</font><br />';
  }   }
     } elsif ($ctr == 1) {      } elsif ($ctr == 1) {
  $gradeTable =~ s/type=checkbox/type=checkbox checked/;   $gradeTable =~ s/type=checkbox/type=checkbox checked/;
Line 624  LISTJAVASCRIPT Line 775  LISTJAVASCRIPT
 sub processGroup {  sub processGroup {
     my ($request)  = shift;      my ($request)  = shift;
     my $ctr        = 0;      my $ctr        = 0;
     my @stuchecked = (ref($ENV{'form.stuinfo'}) ? @{$ENV{'form.stuinfo'}}      my @stuchecked = &Apache::loncommon::get_env_multiple('form.stuinfo');
       : ($ENV{'form.stuinfo'}));  
     my $total      = scalar(@stuchecked)-1;      my $total      = scalar(@stuchecked)-1;
   
     foreach (@stuchecked) {      foreach (@stuchecked) {
Line 752  sub sub_page_js { Line 902  sub sub_page_js {
     for (i=0;i<=total;i++) {      for (i=0;i<=total;i++) {
  for (j=0;j<parttot;j++) {   for (j=0;j<parttot;j++) {
     var partid = formname["partid"+i+"_"+j].value;      var partid = formname["partid"+i+"_"+j].value;
     var selopt = formname["GD_SEL"+i+"_"+partid];      if (formname["GD_SEL"+i+"_"+partid][0].selected) {
     if (selopt[0].selected) {  
  var points = formname["GD_BOX"+i+"_"+partid].value;   var points = formname["GD_BOX"+i+"_"+partid].value;
  if (points == "") {   if (points == "") {
     var name = formname["name"+i].value;      var name = formname["name"+i].value;
     var resp = confirm("You did not assign a score for "+name+", part "+partid+". Continue?");      var studentID = (name != '' ? name : formname["unamedom"+i].value);
       var resp = confirm("You did not assign a score for "+studentID+
          ", part "+partid+". Continue?");
     if (resp == false) {      if (resp == false) {
  formname["GD_BOX"+i+"_"+partid].focus();   formname["GD_BOX"+i+"_"+partid].focus();
  return false;   return false;
Line 785  sub sub_page_js { Line 936  sub sub_page_js {
  var ptr = 0;   var ptr = 0;
  for (i=1;i<total;i++) {   for (i=1;i<total;i++) {
     var partid = formname["q_"+i].value;      var partid = formname["q_"+i].value;
     var selopt = formname["GD_SEL"+i+"_"+partid];      if (formname["GD_SEL"+i+"_"+partid][0].selected) {
     if (selopt[0].selected) {  
  var points = formname["GD_BOX"+i+"_"+partid].value;   var points = formname["GD_BOX"+i+"_"+partid].value;
  var status = formname["solved"+i+"_"+partid].value;   var status = formname["solved"+i+"_"+partid].value;
  if (points == "" && status != "correct_by_student") {   if (points == "" && status != "correct_by_student") {
Line 834  sub sub_page_kw_js { Line 984  sub sub_page_kw_js {
     if (nret==null) return;      if (nret==null) return;
     formname.keywords.value = nret;      formname.keywords.value = nret;
   
     formname.refresh.value = "on";  
     if (formname.keywords.value != "") {      if (formname.keywords.value != "") {
    formname.refresh.value = "on";
  formname.submit();   formname.submit();
     }      }
     return;      return;
Line 862  sub sub_page_kw_js { Line 1012  sub sub_page_kw_js {
     }      }
     var nret = prompt("Add selection to keyword list? Edit if desired.",cleantxt);      var nret = prompt("Add selection to keyword list? Edit if desired.",cleantxt);
     if (nret==null) return;      if (nret==null) return;
     var curlist = document.SCORE.keywords.value;      document.SCORE.keywords.value = document.SCORE.keywords.value+" "+nret;
     document.SCORE.keywords.value = curlist+" "+nret;  
     document.SCORE.refresh.value = "on";  
     if (document.SCORE.keywords.value != "") {      if (document.SCORE.keywords.value != "") {
    document.SCORE.refresh.value = "on";
  document.SCORE.submit();   document.SCORE.submit();
     }      }
     return;      return;
Line 882  sub sub_page_kw_js { Line 1031  sub sub_page_kw_js {
     var Nmsg  = msgform.savemsgN.value;      var Nmsg  = msgform.savemsgN.value;
     savedMsgHeader(Nmsg,usrctr,fullname);      savedMsgHeader(Nmsg,usrctr,fullname);
     var subject = msgform.msgsub.value;      var subject = msgform.msgsub.value;
     var rtrchk  = document.SCORE["includemsg"+usrctr];      var msgchk = document.SCORE["includemsg"+usrctr].value;
     var msgchk = rtrchk.value;  
     re = /msgsub/;      re = /msgsub/;
     var shwsel = "";      var shwsel = "";
     if (re.test(msgchk)) { shwsel = "checked" }      if (re.test(msgchk)) { shwsel = "checked" }
Line 895  sub sub_page_kw_js { Line 1043  sub sub_page_kw_js {
  shwsel = "";   shwsel = "";
  if (re.test(msgchk)) { shwsel = "checked" }   if (re.test(msgchk)) { shwsel = "checked" }
  var message = document.SCORE["savemsg"+i].value;   var message = document.SCORE["savemsg"+i].value;
  var shownOnce = document.SCORE["shownOnce"+i].value;   message = (document.SCORE["shownOnce"+i].value == 0 ? checkEntities(message) : message);
  message = (shownOnce == 0 ? checkEntities(message) : message);  
  displaySavedMsg(i,message,shwsel); //I do not get it. w/o checkEntities on saved messages,   displaySavedMsg(i,message,shwsel); //I do not get it. w/o checkEntities on saved messages,
                                    //any &lt; is already converted to <, etc. However, only once!!                                     //any &lt; is already converted to <, etc. However, only once!!
     }      }
Line 932  sub sub_page_kw_js { Line 1079  sub sub_page_kw_js {
  height = 600;   height = 600;
  scrollbar = "yes";   scrollbar = "yes";
     }      }
 //    if (window.pWin) {window.pWin.close(); window.pWin=null}  
     var xpos = (screen.width-600)/2;      var xpos = (screen.width-600)/2;
     xpos = (xpos < 0) ? '0' : xpos;      xpos = (xpos < 0) ? '0' : xpos;
     var ypos = (screen.height-height)/2-30;      var ypos = (screen.height-height)/2-30;
Line 941  sub sub_page_kw_js { Line 1087  sub sub_page_kw_js {
     pWin = window.open('', 'MessageCenter', 'toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=600,height='+height);      pWin = window.open('', 'MessageCenter', 'toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=600,height='+height);
     pWin.focus();      pWin.focus();
     pDoc = pWin.document;      pDoc = pWin.document;
       pDoc.open('text/html','replace');
     pDoc.write("<html><head>");      pDoc.write("<html><head>");
     pDoc.write("<title>Message Central</title>");      pDoc.write("<title>Message Central</title>");
   
Line 1027  sub sub_page_kw_js { Line 1174  sub sub_page_kw_js {
     pDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>");      pDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>");
     pDoc.write("</form>");      pDoc.write("</form>");
     pDoc.write("</body></html>");      pDoc.write("</body></html>");
       pDoc.close();
 }  }
   
 //====================== Script for keyword highlight options ==============  //====================== Script for keyword highlight options ==============
Line 1070  sub sub_page_kw_js { Line 1218  sub sub_page_kw_js {
     hwdWin = window.open('', 'KeywordHighlightCentral', 'toolbar=no,location=no,scrollbars=no,width=400,height=300,screenx='+xpos+',screeny='+ypos);      hwdWin = window.open('', 'KeywordHighlightCentral', 'toolbar=no,location=no,scrollbars=no,width=400,height=300,screenx='+xpos+',screeny='+ypos);
     hwdWin.focus();      hwdWin.focus();
     var hDoc = hwdWin.document;      var hDoc = hwdWin.document;
       hDoc.open('text/html','replace');
     hDoc.write("<html><head>");      hDoc.write("<html><head>");
     hDoc.write("<title>Highlight Central</title>");      hDoc.write("<title>Highlight Central</title>");
   
Line 1118  sub sub_page_kw_js { Line 1267  sub sub_page_kw_js {
     hDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>");      hDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>");
     hDoc.write("</form>");      hDoc.write("</form>");
     hDoc.write("</body></html>");      hDoc.write("</body></html>");
       hDoc.close();
   }    }
   
 </script>  </script>
Line 1145  sub gradeBox { Line 1295  sub gradeBox {
     my $ctr = 0;      my $ctr = 0;
     $result.='<table border="0"><tr>'."\n";  # display radio buttons in a nice table 10 across      $result.='<table border="0"><tr>'."\n";  # display radio buttons in a nice table 10 across
     while ($ctr<=$wgt) {      while ($ctr<=$wgt) {
  $result.= '<td><input type="radio" name="RADVAL'.$counter.'_'.$partid.'" '.   $result.= '<td><nobr><input type="radio" name="RADVAL'.$counter.'_'.$partid.'" '.
     'onclick="javascript:writeBox(this.form,\''.$counter.'_'.$partid.'\','.      'onclick="javascript:writeBox(this.form,\''.$counter.'_'.$partid.'\','.
     $ctr.')" value="'.$ctr.'" '.      $ctr.')" value="'.$ctr.'" '.
     ($score eq $ctr ? 'checked':'').' /> '.$ctr."</td>\n";      ($score eq $ctr ? 'checked':'').' /> '.$ctr."</nobr></td>\n";
  $result.=(($ctr+1)%10 == 0 ? '</tr><tr>' : '');   $result.=(($ctr+1)%10 == 0 ? '</tr><tr>' : '');
  $ctr++;   $ctr++;
     }      }
Line 1183  sub gradeBox { Line 1333  sub gradeBox {
 }  }
   
 sub show_problem {  sub show_problem {
     my ($request,$symb,$uname,$udom,$removeform,$viewon) = @_;      my ($request,$symb,$uname,$udom,$removeform,$viewon,$mode) = @_;
     my $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom,      my $rendered;
       $ENV{'request.course.id'});      if ($mode eq 'both' or $mode eq 'text') {
    $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom,
        $ENV{'request.course.id'});
       }
     if ($removeform) {      if ($removeform) {
  $rendered=~s|<form(.*?)>||g;   $rendered=~s|<form(.*?)>||g;
  $rendered=~s|</form>||g;   $rendered=~s|</form>||g;
  $rendered=~s|name="submit"|name="would_have_been_submit"|g;   $rendered=~s|name="submit"|name="would_have_been_submit"|g;
     }      }
     my $companswer=&Apache::loncommon::get_student_answers($symb,$uname,$udom,      my $companswer;
    $ENV{'request.course.id'});      if ($mode eq 'both' or $mode eq 'answer') {
    $companswer=&Apache::loncommon::get_student_answers($symb,$uname,$udom,
       $ENV{'request.course.id'});
       }
     if ($removeform) {      if ($removeform) {
  $companswer=~s|<form(.*?)>||g;   $companswer=~s|<form(.*?)>||g;
  $companswer=~s|</form>||g;   $companswer=~s|</form>||g;
  $rendered=~s|name="submit"|name="would_have_been_submit"|g;   $companswer=~s|name="submit"|name="would_have_been_submit"|g;
     }      }
     my $result.='<table border="0" width="100%"><tr><td bgcolor="#777777">';      my $result.='<table border="0" width="100%"><tr><td bgcolor="#777777">';
     $result.='<table border="0" width="100%">';      $result.='<table border="0" width="100%">';
     $result.='<tr><td bgcolor="#e6ffff"><b> View of the problem - '.$ENV{'form.fullname'}.      if ($viewon) {
  '</b></td></tr>' if ($viewon);   $result.='<tr><td bgcolor="#e6ffff"><b> ';
     $result.='<tr><td bgcolor="#ffffff">'.$rendered.'<br />';   if ($mode eq 'both' or $mode eq 'text') {
     $result.='<b>Correct answer:</b><br />'.$companswer;      $result.='View of the problem - ';
    } else {
       $result.='Correct answer: ';
    }
    $result.=$ENV{'form.fullname'}.'</b></td></tr>';
       }
       if ($mode eq 'both') {
    $result.='<tr><td bgcolor="#ffffff">'.$rendered.'<br />';
    $result.='<b>Correct answer:</b><br />'.$companswer;
       } elsif ($mode eq 'text') {
    $result.='<tr><td bgcolor="#ffffff">'.$rendered;
       } elsif ($mode eq 'answer') {
    $result.='<tr><td bgcolor="#ffffff">'.$companswer;
       }
     $result.='</td></tr></table>';      $result.='</td></tr></table>';
     $result.='</td></tr></table><br />';      $result.='</td></tr></table><br />';
     return $result;      return $result;
Line 1229  sub submission { Line 1398  sub submission {
  return;   return;
     }      }
   
     $ENV{'form.lastSub'} = ($ENV{'form.lastSub'} eq '' ? 'datesub' : $ENV{'form.lastSub'});      if (!$ENV{'form.lastSub'}) { $ENV{'form.lastSub'} = 'datesub'; }
       if (!$ENV{'form.vProb'}) { $ENV{'form.vProb'} = 'yes'; }
       if (!$ENV{'form.vAns'}) { $ENV{'form.vAns'} = 'yes'; }
     my $last = ($ENV{'form.lastSub'} eq 'last' ? 'last' : '');      my $last = ($ENV{'form.lastSub'} eq 'last' ? 'last' : '');
     my $checkIcon = '<img src="'.$request->dir_config('lonIconsURL').      my $checkIcon = '<img src="'.$request->dir_config('lonIconsURL').
  '/check.gif" height="16" border="0" />';   '/check.gif" height="16" border="0" />';
Line 1252  sub submission { Line 1423  sub submission {
   
  # 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.
  if ($ENV{'form.vProb'} eq 'yes' or !$ENV{'form.vProb'}) {   if ($ENV{'form.vProb'} eq 'yes' or $ENV{'form.vAns'} eq 'yes') {
     $request->print(&show_problem($request,$symb,$uname,$udom,0,1));      my $mode;
       if ($ENV{'form.vProb'} eq 'yes' && $ENV{'form.vAns'} eq 'yes') {
    $mode='both';
       } elsif ($ENV{'form.vProb'} eq 'yes') {
    $mode='text';
       } elsif ($ENV{'form.vAns'} eq 'yes') {
    $mode='answer';
       }
       $request->print(&show_problem($request,$symb,$uname,$udom,0,1,$mode));
  }   }
   
  # kwclr is the only variable that is guaranteed to be non blank    # kwclr is the only variable that is guaranteed to be non blank 
Line 1288  sub submission { Line 1467  sub submission {
  '<input type="hidden" name="url"        value="'.$url.'" />'."\n".   '<input type="hidden" name="url"        value="'.$url.'" />'."\n".
  '<input type="hidden" name="showgrading" value="'.$ENV{'form.showgrading'}.'" />'."\n".   '<input type="hidden" name="showgrading" value="'.$ENV{'form.showgrading'}.'" />'."\n".
  '<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="lastSub"    value="'.$ENV{'form.lastSub'}.'" />'."\n".   '<input type="hidden" name="lastSub"    value="'.$ENV{'form.lastSub'}.'" />'."\n".
  '<input type="hidden" name="section"    value="'.$ENV{'form.section'}.'">'."\n".   '<input type="hidden" name="section"    value="'.$ENV{'form.section'}.'">'."\n".
  '<input type="hidden" name="submitonly" value="'.$ENV{'form.submitonly'}.'">'."\n".   '<input type="hidden" name="submitonly" value="'.$ENV{'form.submitonly'}.'">'."\n".
Line 1302  sub submission { Line 1482  sub submission {
     '<input type="hidden" name="msgsub"   value="'.$ENV{'form.msgsub'}.'" />'."\n".      '<input type="hidden" name="msgsub"   value="'.$ENV{'form.msgsub'}.'" />'."\n".
     '<input type="hidden" name="shownSub" value="0" />'."\n".      '<input type="hidden" name="shownSub" value="0" />'."\n".
     '<input type="hidden" name="savemsgN" value="'.$ENV{'form.savemsgN'}.'" />'."\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,'');
Line 1338  KEYWORDS Line 1521  KEYWORDS
         }          }
     }      }
   
     if ($ENV{'form.vProb'} eq 'all') {      if ($ENV{'form.vProb'} eq 'all' or $ENV{'form.vAns'} eq 'all') {
  $request->print('<br /><br /><br />') if ($counter > 0);   $request->print('<br /><br /><br />') if ($counter > 0);
  $request->print(&show_problem($request,$symb,$uname,$udom,1,1));   my $mode;
    if ($ENV{'form.vProb'} eq 'all' && $ENV{'form.vAns'} eq 'all') {
       $mode='both';
    } elsif ($ENV{'form.vProb'} eq 'all' ) {
       $mode='text';
    } elsif ($ENV{'form.vAns'} eq 'all') {
       $mode='answer';
    }
    $request->print(&show_problem($request,$symb,$uname,$udom,1,1,$mode));
     }      }
   
     my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);      my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);
   
     my ($partlist,$handgrade) = &response_type($url,$symb);      my ($partlist,$handgrade,$responseType) = &response_type($url,$symb);
   
     # Display student info      # Display student info
     $request->print(($counter == 0 ? '' : '<br />'));      $request->print(($counter == 0 ? '' : '<br />'));
     my $result='<table border="0" width=100%><tr><td bgcolor="#777777">'."\n".      my $result='<table border="0" width=100%><tr><td bgcolor="#777777">'."\n".
  '<table border="0" width=100%><tr bgcolor="#edffff"><td>'."\n";   '<table border="0" width=100%><tr bgcolor="#edffff"><td>'."\n";
   
     $result.='<b>Fullname: </b>'.$ENV{'form.fullname'}.      $result.='<b>Fullname: </b>'.&nameUserString(undef,$ENV{'form.fullname'},$uname,$udom).'<br />'."\n";
  '<font color="#999999">&nbsp; &nbsp;Username: '.$uname.  
  ($ENV{'user.domain'} eq $udom ? '' : ' ('.$udom.')').'</font><br />'."\n";  
     $result.='<input type="hidden" name="name'.$counter.      $result.='<input type="hidden" name="name'.$counter.
  '" value="'.$ENV{'form.fullname'}.'" />'."\n";   '" value="'.$ENV{'form.fullname'}.'" />'."\n";
   
Line 1393  KEYWORDS Line 1583  KEYWORDS
     $result.=$$fullname{$_}.'&nbsp; &nbsp; &nbsp;';      $result.=$$fullname{$_}.'&nbsp; &nbsp; &nbsp;';
  }   }
                 $result.='<br />'."\n";                  $result.='<br />'."\n";
    my ($part)=split(/\./,$_);
  $result.='<input type="hidden" name="collaborator'.$counter.   $result.='<input type="hidden" name="collaborator'.$counter.
     '" value="'.(join ':',@goodcollaborators).'" />'."\n";      '" value="'.$part.':'.(join ':',@goodcollaborators).'" />'.
       "\n";
     }      }
     if (scalar(@badcollaborators) > 0) {      if (scalar(@badcollaborators) > 0) {
  $result.='<table border="0"><tr bgcolor="#ffbbbb"><td>';   $result.='<table border="0"><tr bgcolor="#ffbbbb"><td>';
Line 1420  KEYWORDS Line 1612  KEYWORDS
     #             (3) Last submission plus the parts info      #             (3) Last submission plus the parts info
     #             (4) The whole record for this student      #             (4) The whole record for this student
     if ($ENV{'form.lastSub'} =~ /^(lastonly|hdgrade)$/) {      if ($ENV{'form.lastSub'} =~ /^(lastonly|hdgrade)$/) {
  if ($ENV{'form.'.$uname.':'.$udom.':submitted_by'}) {   my ($string,$timestamp)= &get_last_submission(\%record);
     my $submitby=''.   my $lastsubonly=''.
  '<b>Collaborative submission by: </b>'.      ($$timestamp eq '' ? '' : '<b>Date Submitted:</b> '.
  '<a href="javascript:viewSubmitter(\''.       $$timestamp)."</td></tr>\n";
  $ENV{'form.'.$uname.':'.$udom.':submitted_by'}.   if ($$timestamp eq '') {
  '\')"; TARGET=_self>'.      $lastsubonly.='<tr><td bgcolor="#ffffe6">'.$$string[0]; 
  $$fullname{$ENV{'form.'.$uname.':'.$udom.':submitted_by'}}.'</a>';   } else {
     $request->print($submitby);      my %seenparts;
  } else {      for my $part (sort keys(%$handgrade)) {
     my ($string,$timestamp)= &get_last_submission (\%record);   my ($partid,$respid) = split(/_/,$part);
     my $lastsubonly=''.   if ($ENV{"form.$uname:$udom:$partid:submitted_by"}) {
  ($$timestamp eq '' ? '' : '<b>Date Submitted:</b> '.      if (exists($seenparts{$partid})) { next; }
  $$timestamp)."</td></tr>\n";      $seenparts{$partid}=1;
     if ($$timestamp eq '') {      my $submitby='<b>Part '.$partid.
  $lastsubonly.='<tr><td bgcolor="#ffffe6">'.$$string[0];    ' Collaborative submission by: </b>'.
     } else {   '<a href="javascript:viewSubmitter(\''.
  for my $part (sort keys(%$handgrade)) {   $ENV{"form.$uname:$udom:$partid:submitted_by"}.
     my ($responsetype,$foo) = split(/:/,$$handgrade{$part});   '\')"; TARGET=_self>'.
     my ($partid,$respid) = split(/_/,$part);   $$fullname{$ENV{"form.$uname:$udom:$partid:submitted_by"}}.'</a><br />';
     if (!exists($record{'resource.'.$partid.'.'.$respid.'.submission'})) {      $request->print($submitby);
       next;
    }
    my $responsetype = $responseType->{$partid}->{$respid};
    if (!exists($record{"resource.$partid.$respid.submission"})) {
       $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '.
    $partid.'</b> <font color="#999999">( ID '.$respid.
    ' )</font>&nbsp; &nbsp;'.
    '<font color="red">Nothing submitted - no attempts</font><br /><br />';
       next;
    }
    foreach (@$string) {
       my ($partid,$respid) = /^resource\.([^\.]*)\.([^\.]*)\.submission/;
       if ($part ne ($partid.'_'.$respid)) { next; }
       my ($ressub,$subval) = split(/:/,$_,2);
       # Similarity check
       my $similar='';
       if($ENV{'form.checkPlag'}){
    my ($oname,$odom,$ocrsid,$oessay,$osim)=
       &most_similar($uname,$udom,$subval);
    if ($osim) {
       $osim=int($osim*100.0);
       $similar="<hr /><h3><font color=\"#FF0000\">Essay".
    " is $osim% similar to an essay by ".
    &Apache::loncommon::plainname($oname,$odom).
    '</font></h3><blockquote><i>'.
    &keywords_highlight($oessay).
    '</i></blockquote><hr />';
    }
       }
       my $order=&get_order($partid,$respid,$symb,$uname,$udom);
       if ($ENV{'form.lastSub'} eq 'lastonly' || 
    ($ENV{'form.lastSub'} eq 'hdgrade' && 
    $$handgrade{$part} eq 'yes')) {
  $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '.   $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '.
     $partid.'</b> <font color="#999999">( ID '.$respid.      $partid.'</b> <font color="#999999">( ID '.$respid.
     ' )</font>&nbsp; &nbsp;'.      ' )</font>&nbsp; &nbsp;';
     '<font color="red">Nothing submitted - no attempts</font><br /><br />';   if ($record{"resource.$partid.$respid.uploadedurl"}) {
      } else {      $lastsubonly.='<a href="'.&Apache::lonnet::tokenwrapper($record{"resource.$partid.$respid.uploadedurl"}).'" target="lonGRDs"><img src="/adm/lonIcons/unknown.gif" border=0"> File uploaded by student</a> <font color="red" size="1">Like all files provided by users, this file may contain virusses</font><br />';
  foreach (@$string) {  
     my ($partid,$respid) = /^resource\.(\w+)\.(\w+)\.submission/;  
     if ($part eq ($partid.'_'.$respid)) {  
  my ($ressub,$subval) = split(/:/,$_,2);  
                             # Similarity check  
  my $similar='';  
  my ($oname,$odom,$ocrsid,$oessay,$osim)=&most_similar($uname,$udom,$subval);  
  if ($osim) {  
     $osim=int($osim*100.0);  
     $similar='<hr /><h3><font color="#FF0000">Essay is '.$osim.  
  '% similar to an essay by '.&Apache::loncommon::plainname($oname,$odom).  
  '</font></h3><blockquote><i>'.  
  &keywords_highlight($oessay).'</i></blockquote><hr />';  
  }  
  $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '.  
     $partid.'</b> <font color="#999999">( ID '.$respid.  
     ' )</font>&nbsp; &nbsp;'.  
     ($record{"resource.$partid.$respid.uploadedurl"}?  
      '<a href="'.  
      &Apache::lonnet::tokenwrapper($record{"resource.$partid.$respid.uploadedurl"}).  
      '"><img src="/adm/lonIcons/unknown.gif" border=0"> File uploaded by student</a> '.  
      '<font color="red" size="1">Like all files provided by users, '.  
      'this file may contain virusses</font><br />':'').  
      '<b>Submitted Answer: </b>'.($responsetype =~ /^(essay|option)$/ ?   
   '<blockquote>' : '').  
      &cleanRecord($subval,$responsetype,$symb).  
      ($responsetype =~ /^(essay|option)$/ ? '</blockquote><br />' :   
       '<br /><br />').$similar."\n"  
      if ($ENV{'form.lastSub'} eq 'lastonly' ||   
  ($ENV{'form.lastSub'} eq 'hdgrade' &&   
   $$handgrade{$part} =~ /:yes$/));  
     }  
  }   }
    $lastsubonly.='<b>Submitted Answer: </b>'.
       &cleanRecord($subval,$responsetype,$symb,$partid,
    $respid,\%record,$order);
    if ($similar) {$lastsubonly.="<br /><br />$similar\n";}
     }      }
  }   }
     }      }
     $lastsubonly.='</td></tr><tr bgcolor="#ffffff"><td>'."\n";  
     $request->print($lastsubonly);  
  }   }
    $lastsubonly.='</td></tr><tr bgcolor="#ffffff"><td>'."\n";
    $request->print($lastsubonly);
     } elsif ($ENV{'form.lastSub'} eq 'datesub') {      } elsif ($ENV{'form.lastSub'} eq 'datesub') {
  my (undef,$responseType,undef,$parts) = &showResourceInfo($url);   my (undef,$responseType,undef,$parts) = &showResourceInfo($url);
  $request->print(&displaySubByDates(\$symb,\%record,$parts,$responseType,$checkIcon));   $request->print(&displaySubByDates($symb,\%record,$parts,$responseType,$checkIcon,$uname,$udom));
     } elsif ($ENV{'form.lastSub'} =~ /^(last|all)$/) {      } elsif ($ENV{'form.lastSub'} =~ /^(last|all)$/) {
  $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'},
Line 1502  KEYWORDS Line 1699  KEYWORDS
  my $toGrade.='<input type="button" value="Grade Student" '.   my $toGrade.='<input type="button" value="Grade Student" '.
     'onClick="javascript:checksubmit(this.form,\'Grade Student\',\''      'onClick="javascript:checksubmit(this.form,\'Grade Student\',\''
     .$counter.'\');" TARGET=_self> &nbsp;'."\n" if (&canmodify($usec));      .$counter.'\');" TARGET=_self> &nbsp;'."\n" if (&canmodify($usec));
  $toGrade.='</td></tr></table></td></tr></table></form>'."\n";   $toGrade.='</td></tr></table></td></tr></table>'."\n";
  $toGrade.=&show_grading_menu_form($symb,$url)    if (($ENV{'form.command'} eq 'submission') || 
     if (($ENV{'form.command'} eq 'submission') ||       ($ENV{'form.command'} eq 'processGroup' && $counter == $total)) {
  ($ENV{'form.command'} eq 'processGroup' && $counter == $total));      $toGrade.='</form>'.&show_grading_menu_form($symb,$url) 
    }
  $request = print($toGrade);   $request = print($toGrade);
  return;   return;
     }      }
Line 1519  KEYWORDS Line 1717  KEYWORDS
     $msgfor .= ', '.(join ', ',@col_fullnames).' and '.$lastone.'.';      $msgfor .= ', '.(join ', ',@col_fullnames).' and '.$lastone.'.';
  }   }
  $msgfor =~ s/\'/\\'/g; #' stupid emacs - no! javascript   $msgfor =~ s/\'/\\'/g; #' stupid emacs - no! javascript
 # $result.='<tr><td bgcolor="#ffffff">'."\n".  
  $result='<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n".   $result='<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n".
     '<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n";      '<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n";
  $result.='&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.   $result.='&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.
Line 1534  KEYWORDS Line 1731  KEYWORDS
   
     my %seen = ();      my %seen = ();
     my @partlist;      my @partlist;
       my @gradePartRespid;
     for (sort keys(%$handgrade)) {      for (sort keys(%$handgrade)) {
  my ($partid,$respid) = split(/_/);   my ($partid,$respid) = split(/_/);
  next if ($seen{$partid} > 0);   next if ($seen{$partid} > 0);
  $seen{$partid}++;   $seen{$partid}++;
  next if ($$handgrade{$_} =~ /:no$/ && $ENV{'form.lastSub'} =~ /^(hdgrade)$/);   next if ($$handgrade{$_} =~ /:no$/ && $ENV{'form.lastSub'} =~ /^(hdgrade)$/);
  push @partlist,$partid;   push @partlist,$partid;
    push @gradePartRespid,$partid.'.'.$respid;
   
  $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record));   $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record));
     }      }
     $result='<input type="hidden" name="partlist'.$counter.      $result='<input type="hidden" name="partlist'.$counter.
  '" value="'.(join ":",@partlist).'" />'."\n";   '" value="'.(join ":",@partlist).'" />'."\n";
       $result.='<input type="hidden" name="gradePartRespid'.
    '" value="'.(join ":",@gradePartRespid).'" />'."\n" if ($counter == 0);
     my $ctr = 0;      my $ctr = 0;
     while ($ctr < scalar(@partlist)) {      while ($ctr < scalar(@partlist)) {
  $result.='<input type="hidden" name="partid'.$counter.'_'.$ctr.'" value="'.   $result.='<input type="hidden" name="partid'.$counter.'_'.$ctr.'" value="'.
Line 1566  KEYWORDS Line 1767  KEYWORDS
  my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1');   my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1');
  $ntstu =~ s/<option>$nsel</<option selected="on">$nsel</;   $ntstu =~ s/<option>$nsel</<option selected="on">$nsel</;
  $endform.=$ntstu.'student(s) &nbsp;&nbsp;';   $endform.=$ntstu.'student(s) &nbsp;&nbsp;';
  $endform.='<input type="button" value="Next" '.   $endform.='<input type="button" value="Previous" '.
     'onClick="javascript:checksubmit(this.form,\'Next\');" TARGET=_self> &nbsp;'."\n".      'onClick="javascript:checksubmit(this.form,\'Previous\');" TARGET=_self> &nbsp;'."\n".
     '<input type="button" value="Previous" '.      '<input type="button" value="Next" '.
     'onClick="javascript:checksubmit(this.form,\'Previous\');" TARGET=_self> &nbsp;';      'onClick="javascript:checksubmit(this.form,\'Next\');" TARGET=_self> &nbsp;';
  $endform.='(Next and Previous do not save the scores.)'."\n" ;   $endform.='(Next and Previous (student) do not save the scores.)'."\n" ;
  $endform.='</td><tr></table></form>';   $endform.='</td><tr></table></form>';
  $endform.=&show_grading_menu_form($symb,$url);   $endform.=&show_grading_menu_form($symb,$url);
  $request->print($endform);   $request->print($endform);
Line 1656  sub processHandGrade { Line 1857  sub processHandGrade {
        $ENV{'form.msgsub'},$message);         $ENV{'form.msgsub'},$message);
     }      }
     if ($ENV{'form.collaborator'.$ctr}) {      if ($ENV{'form.collaborator'.$ctr}) {
  my (@collaborators) = split(/:/,$ENV{'form.collaborator'.$ctr});   my @collabstrs=&Apache::loncommon::get_env_multiple("form.collaborator$ctr");
  foreach (@collaborators) {   foreach my $collabstr (@collabstrs) {
     my ($errorflag,$pts,$wgt) =       my ($part,@collaborators) = split(/:/,$collabstr);
  &saveHandGrade($request,$url,$symb,$_,$udom,$ctr,$ENV{'form.unamedom'.$ctr});      foreach (@collaborators) {
     if ($errorflag eq 'not_allowed') {   my ($errorflag,$pts,$wgt) = 
  $request->print("<font color=\"red\">Not allowed to modify grades for $_:$udom</font>");      &saveHandGrade($request,$url,$symb,$_,$udom,$ctr,
  next;     $ENV{'form.unamedom'.$ctr},$part);
     } else {   if ($errorflag eq 'not_allowed') {
  if ($message ne '') {      $request->print("<font color=\"red\">Not allowed to modify grades for $_:$udom</font>");
     $msgstatus = &Apache::lonmsg::user_normal_msg ($_,$udom,      next;
    $ENV{'form.msgsub'},   } else {
    $message);      if ($message ne '') {
    $msgstatus = &Apache::lonmsg::user_normal_msg($_,$udom,$ENV{'form.msgsub'},$message);
       }
       
  }   }
     }      }
  }   }
Line 1770  sub processHandGrade { Line 1974  sub processHandGrade {
  }   }
     }      }
     $ctr = 0;      $ctr = 0;
     my ($partlist,$handgrade) = &response_type($ENV{'form.url'},$symb);  
     @parsedlist = reverse @parsedlist if ($button eq 'Previous');      @parsedlist = reverse @parsedlist if ($button eq 'Previous');
       my ($partlist) = &response_type($url);
     foreach my $student (@parsedlist) {      foreach my $student (@parsedlist) {
    my $submitonly=$ENV{'form.submitonly'};
  my ($uname,$udom) = split(/:/,$student);   my ($uname,$udom) = split(/:/,$student);
  if ($ENV{'form.submitonly'} eq 'yes') {   if ($submitonly =~ /^(yes|graded|incorrect)$/) {
     my (%status) = &student_gradeStatus($ENV{'form.url'},$symb,$udom,$uname,$partlist) ;  #    my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);
     my $statusflg = '';      my %status=&student_gradeStatus($url,$symb,$udom,$uname,$partlist);
       my $submitted = 0;
       my $graded = 1;
     foreach (keys(%status)) {      foreach (keys(%status)) {
  $statusflg = 1 if ($status{$_} ne 'nothing');   $submitted = 1 if ($status{$_} ne 'nothing');
  my ($foo,$partid,$foo1) = split(/\./);   $graded = 0 if ($status{$_} =~ /^correct/);
  $statusflg = '' if ($status{'resource.'.$partid.'.submitted_by'} ne '');   my ($foo,$partid,$foo1) = split(/\./,$_);
    if ($status{'resource.'.$partid.'.submitted_by'} ne '') {
       $submitted = 0;
    }
     }      }
     next if ($statusflg eq '');      next if (!$submitted && ($submitonly eq 'yes' ||
        $submitonly eq 'incorrect' ||
        $submitonly eq 'graded'));
       next if (!$graded && ($submitonly eq 'graded' ||
     $submitonly eq 'incorrect'));
  }   }
  push @nextlist,$student if ($ctr < $ntstu);   push @nextlist,$student if ($ctr < $ntstu);
    last if ($ctr == $ntstu);
  $ctr++;   $ctr++;
     }      }
   
Line 1811  sub processHandGrade { Line 2026  sub processHandGrade {
   
 #---- Save the score and award for each student, if changed  #---- Save the score and award for each student, if changed
 sub saveHandGrade {  sub saveHandGrade {
     my ($request,$url,$symb,$stuname,$domain,$newflg,$submitter) = @_;      my ($request,$url,$symb,$stuname,$domain,$newflg,$submitter,$part) = @_;
     my $usec = &Apache::lonnet::getsection($domain,$stuname,      my $usec = &Apache::lonnet::getsection($domain,$stuname,
    $ENV{'request.course.id'});     $ENV{'request.course.id'});
     if (!&canmodify($usec)) { return('not_allowed'); }      if (!&canmodify($usec)) { return('not_allowed'); }
Line 1819  sub saveHandGrade { Line 2034  sub saveHandGrade {
     my %newrecord  = ();      my %newrecord  = ();
     my ($pts,$wgt) = ('','');      my ($pts,$wgt) = ('','');
     foreach (split(/:/,$ENV{'form.partlist'.$newflg})) {      foreach (split(/:/,$ENV{'form.partlist'.$newflg})) {
    #collaborator may vary for different parts
    if ($submitter && $_ ne $part) { next; }
  my $dropMenu = $ENV{'form.GD_SEL'.$newflg.'_'.$_};   my $dropMenu = $ENV{'form.GD_SEL'.$newflg.'_'.$_};
  if ($dropMenu eq 'excused') {   if ($dropMenu eq 'excused') {
     if ($record{'resource.'.$_.'.solved'} ne 'excused') {      if ($record{'resource.'.$_.'.solved'} ne 'excused') {
Line 1839  sub saveHandGrade { Line 2056  sub saveHandGrade {
     $pts = ($ENV{'form.GD_BOX'.$newflg.'_'.$_} ne '' ?       $pts = ($ENV{'form.GD_BOX'.$newflg.'_'.$_} ne '' ? 
     $ENV{'form.GD_BOX'.$newflg.'_'.$_} :       $ENV{'form.GD_BOX'.$newflg.'_'.$_} : 
     $ENV{'form.RADVAL'.$newflg.'_'.$_});      $ENV{'form.RADVAL'.$newflg.'_'.$_});
     return 'no_score' if ($pts eq '' && $ENV{'form.GD_SEL'.$newflg.'_'.$_} eq '');      if ($pts eq '' && $ENV{'form.GD_SEL'.$newflg.'_'.$_} eq '') {
    next;
       }
     $wgt = $ENV{'form.WGT'.$newflg.'_'.$_} eq '' ? 1 :       $wgt = $ENV{'form.WGT'.$newflg.'_'.$_} eq '' ? 1 : 
  $ENV{'form.WGT'.$newflg.'_'.$_};   $ENV{'form.WGT'.$newflg.'_'.$_};
     my $partial= $pts/$wgt;      my $partial= $pts/$wgt;
     next if ($partial eq $record{'resource.'.$_.'.awarded'}); #do not update score for part if not changed.      if ($partial eq $record{'resource.'.$_.'.awarded'}) {
     $newrecord{'resource.'.$_.'.awarded'}  = $partial    #do not update score for part if not changed.
  if ($record{'resource.'.$_.'.awarded'} ne $partial);   next;
       }
       if ($record{'resource.'.$_.'.awarded'} ne $partial) {
    $newrecord{'resource.'.$_.'.awarded'}  = $partial;
       }
     my $reckey = 'resource.'.$_.'.solved';      my $reckey = 'resource.'.$_.'.solved';
     if ($partial == 0) {      if ($partial == 0) {
  $newrecord{$reckey} = 'incorrect_by_override'    if ($record{$reckey} ne 'incorrect_by_override') {
     if ($record{$reckey} ne 'incorrect_by_override');      $newrecord{$reckey} = 'incorrect_by_override';
    }
     } else {      } else {
  $newrecord{$reckey} = 'correct_by_override'    if ($record{$reckey} ne 'correct_by_override') {
     if ($record{$reckey} ne 'correct_by_override');      $newrecord{$reckey} = 'correct_by_override';
    }
       }    
       if ($submitter && 
    ($record{'resource.'.$_.'.submitted_by'} ne $submitter)) {
    $newrecord{'resource.'.$_.'.submitted_by'} = $submitter;
     }      }
     $newrecord{'resource.'.$_.'.submitted_by'} = $submitter       $newrecord{'resource.'.$_.'.regrader'}=
  if ($submitter && ($record{'resource.'.$_.'.submitted_by'} ne $submitter));   "$ENV{'user.name'}:$ENV{'user.domain'}";
     $newrecord{'resource.'.$_.'.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";  
  }   }
     }      }
   
     if (scalar(keys(%newrecord)) > 0) {      if (scalar(keys(%newrecord)) > 0) {
  &Apache::lonnet::cstore(\%newrecord,$symb,   &Apache::lonnet::cstore(\%newrecord,$symb,
  $ENV{'request.course.id'},$domain,$stuname);   $ENV{'request.course.id'},$domain,$stuname);
Line 2042  sub viewgrades { Line 2269  sub viewgrades {
     &viewgrades_js($request);      &viewgrades_js($request);
   
     my ($symb,$url) = ($ENV{'form.symb'},$ENV{'form.url'});       my ($symb,$url) = ($ENV{'form.symb'},$ENV{'form.url'}); 
     my $result='<h3><font color="#339933">Manual Grading</font></h3>';      #need to make sure we have the correct data for later EXT calls, 
       #thus invalidate the cache
       &Apache::lonnet::devalidatecourseresdata(
                    $ENV{'course.'.$ENV{'request.course.id'}.'.num'},
                    $ENV{'course.'.$ENV{'request.course.id'}.'.domain'});
       &Apache::lonnet::clear_EXT_cache_status();
   
       my $result='<h3><font color="#339933">'.&mt('Manual Grading').'</font></h3>';
     $result.='<font size=+1><b>Current Resource: </b>'.$ENV{'form.probTitle'}.'</font>'."\n";      $result.='<font size=+1><b>Current Resource: </b>'.$ENV{'form.probTitle'}.'</font>'."\n";
   
     #view individual student submission form - called using Javascript viewOneStudent      #view individual student submission form - called using Javascript viewOneStudent
Line 2059  sub viewgrades { Line 2292  sub viewgrades {
  '<input type="hidden" name="Status" value="'.$ENV{'form.Status'}.'" />'."\n".   '<input type="hidden" name="Status" value="'.$ENV{'form.Status'}.'" />'."\n".
  '<input type="hidden" name="probTitle" value="'.$ENV{'form.probTitle'}.'" />'."\n";   '<input type="hidden" name="probTitle" value="'.$ENV{'form.probTitle'}.'" />'."\n";
   
     $result.='<h3>Assign Common Grade To ';      my $sectionClass;
     if ($ENV{'form.section'} eq 'all') {      if ($ENV{'form.section'} eq 'all') {
  $result.='Class </h3>';   $sectionClass='Class </h3>';
     } elsif ($ENV{'form.section'} eq 'no') {      } elsif ($ENV{'form.section'} eq 'no') {
  $result.='Students in no Section </h3>';   $sectionClass='Students in no Section </h3>';
     } else {      } else {
  $result.='Students in Section '.$ENV{'form.section'}.'</h3>';   $sectionClass='Students in Section '.$ENV{'form.section'}.'</h3>';
     }      }
       $result.='<h3>Assign Common Grade To '.$sectionClass;
     $result.= '<table border=0><tr><td bgcolor="#777777">'."\n".      $result.= '<table border=0><tr><td bgcolor="#777777">'."\n".
  '<table border=0><tr bgcolor="#ffffdd"><td>';   '<table border=0><tr bgcolor="#ffffdd"><td>';
     #radio buttons/text box for assigning points for a section or class.      #radio buttons/text box for assigning points for a section or class.
Line 2080  sub viewgrades { Line 2314  sub viewgrades {
  my ($partid,$respid) = split (/_/,$_,2);   my ($partid,$respid) = split (/_/,$_,2);
  next if $seen{$partid};   next if $seen{$partid};
  $seen{$partid}++;   $seen{$partid}++;
  my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});   my $handgrade=$$handgrade{$_};
  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 2107  sub viewgrades { Line 2341  sub viewgrades {
     'onChange="javascript:writeRadText(\''.$partid.'\','.      'onChange="javascript:writeRadText(\''.$partid.'\','.
  $weight{$partid}.')"> '.   $weight{$partid}.')"> '.
     '<option selected="on"> </option>'.      '<option selected="on"> </option>'.
 #    '<option>excused</option></select></td></tr>'."\n";  
     '<option>excused</option>'.      '<option>excused</option>'.
     '<option>reset status</option></select></td></tr>'."\n";      '<option>reset status</option></select></td></tr>'."\n";
  $ctsparts++;   $ctsparts++;
Line 2119  sub viewgrades { Line 2352  sub viewgrades {
   
     #table listing all the students in a section/class      #table listing all the students in a section/class
     #header of table      #header of table
     $result.= '<h3>Assign Grade to Specific Students in ';      $result.= '<h3>Assign Grade to Specific Students in '.$sectionClass;
     if ($ENV{'form.section'} eq 'all') {  
  $result.='the Class </h3>';  
     } elsif ($ENV{'form.section'} eq 'no') {  
  $result.='no Section </h3>';  
     } else {  
  $result.='Section '.$ENV{'form.section'}.'</h3>';  
     }  
     $result.= '<table border=0><tr><td bgcolor="#777777">'."\n".      $result.= '<table border=0><tr><td bgcolor="#777777">'."\n".
  '<table border=0><tr bgcolor="#deffff">'.   '<table border=0><tr bgcolor="#deffff"><td>&nbsp;<b>No.</b>&nbsp;</td>'.
  '<td><b>Fullname</b> <font color="#999999">(Username)</font></td>'."\n";   '<td>'.&nameUserString('header')."</td>\n";
     my (@parts) = sort(&getpartlist($url));      my (@parts) = sort(&getpartlist($url,$symb));
     foreach my $part (@parts) {      foreach my $part (@parts) {
  my $display=&Apache::lonnet::metadata($url,$part.'.display');   my $display=&Apache::lonnet::metadata($url,$part.'.display');
  $display =~ s/^Number of Attempts/Tries/; # makes the column narrower   $display =~ s|^Number of Attempts|Tries<br />|; # makes the column narrower
  if  (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); }   if  (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); }
  if ($display =~ /^Partial Credit Factor/) {   if ($display =~ /^Partial Credit Factor/) {
     my ($partid) = &split_part_type($part);      my ($partid) = &split_part_type($part);
Line 2154  sub viewgrades { Line 2380  sub viewgrades {
  my $uname = $_;   my $uname = $_;
  $uname=~s/:/_/;   $uname=~s/:/_/;
  $result.='<input type="hidden" name="ctr'.$ctr.'" value="'.$uname.'" />'."\n";   $result.='<input type="hidden" name="ctr'.$ctr.'" value="'.$uname.'" />'."\n";
  $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},  
    $_,$$fullname{$_},\@parts,\%weight);  
  $ctr++;   $ctr++;
    $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},
      $_,$$fullname{$_},\@parts,\%weight,$ctr);
     }      }
     $result.='</table></td></tr></table>';      $result.='</table></td></tr></table>';
     $result.='<input type="hidden" name="total" value="'.$ctr.'" />'."\n";      $result.='<input type="hidden" name="total" value="'.$ctr.'" />'."\n";
     $result.='<input type="button" value="Submit Changes" '.      $result.='<input type="button" value="Save" '.
  'onClick="javascript:submit();" TARGET=_self /></form>'."\n";   'onClick="javascript:submit();" TARGET=_self /></form>'."\n";
     if (scalar(%$fullname) eq 0) {      if (scalar(%$fullname) eq 0) {
  my $colspan=3+scalar(@parts);   my $colspan=3+scalar(@parts);
Line 2173  sub viewgrades { Line 2399  sub viewgrades {
   
 #--- call by previous routine to display each student  #--- call by previous routine to display each student
 sub viewstudentgrade {  sub viewstudentgrade {
     my ($url,$symb,$courseid,$student,$fullname,$parts,$weight) = @_;      my ($url,$symb,$courseid,$student,$fullname,$parts,$weight,$ctr) = @_;
     my ($uname,$udom) = split(/:/,$student);      my ($uname,$udom) = split(/:/,$student);
     $student=~s/:/_/;      $student=~s/:/_/;
     my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname);      my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname);
     my $result='<tr bgcolor="#ffffdd"><td>'.      my $result='<tr bgcolor="#ffffdd"><td align="right">'.$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> '.
  '<font color="#999999">('.$uname.($ENV{'user.domain'} eq $udom ? '' : ':'.$udom).')</font></td>'."\n";   '<font color="#999999">('.$uname.($ENV{'user.domain'} eq $udom ? '' : ':'.$udom).')</font></td>'."\n";
Line 2197  sub viewstudentgrade { Line 2423  sub viewstudentgrade {
     $status = 'nothing' if ($status eq '');      $status = 'nothing' if ($status eq '');
     $result.='<input type="hidden" name="'.'GD_'.$student.'_'.      $result.='<input type="hidden" name="'.'GD_'.$student.'_'.
  $part.'_solved_s" value="'.$status.'" />'."\n";   $part.'_solved_s" value="'.$status.'" />'."\n";
     $result.='<td align="middle"><select name="'.      $result.='<td align="middle">&nbsp;<select name="'.
  'GD_'.$student.'_'.$part.'_solved" '.   'GD_'.$student.'_'.$part.'_solved" '.
  'onChange="javascript:changeOneScore(\''.$part.'\',\''.$student.'\')" >'."\n";   'onChange="javascript:changeOneScore(\''.$part.'\',\''.$student.'\')" >'."\n";
 #    my $optsel = '<option selected="on"> </option><option>excused</option>'."\n";  
 #    $optsel = '<option> </option><option selected="on">excused</option>'."\n"  
 # if ($status eq 'excused');  
 #    $result.=$optsel;  
     $result.= (($status eq 'excused') ? '<option> </option><option selected="on">excused</option>'       $result.= (($status eq 'excused') ? '<option> </option><option selected="on">excused</option>' 
  : '<option selected="on"> </option><option>excused</option>')."\n";   : '<option selected="on"> </option><option>excused</option>')."\n";
     $result.='<option>reset status</option>';      $result.='<option>reset status</option>';
     $result.="</select></td>\n";      $result.="</select>&nbsp;</td>\n";
  } else {   } else {
     $result.='<input type="hidden" name="'.      $result.='<input type="hidden" name="'.
  'GD_'.$student.'_'.$part.'_'.$type.'_s" value="'.$score.'" />'.   'GD_'.$student.'_'.$part.'_'.$type.'_s" value="'.$score.'" />'.
Line 2231  sub editgrades { Line 2453  sub editgrades {
     my $title='<h3><font color="#339933">Current Grade Status</font></h3>';      my $title='<h3><font color="#339933">Current Grade Status</font></h3>';
     $title.='<font size=+1><b>Current Resource: </b>'.$ENV{'form.probTitle'}.'</font><br />'."\n";      $title.='<font size=+1><b>Current Resource: </b>'.$ENV{'form.probTitle'}.'</font><br />'."\n";
     $title.='<font size=+1><b>Section: </b>'.$ENV{'form.section'}.'</font>'."\n";      $title.='<font size=+1><b>Section: </b>'.$ENV{'form.section'}.'</font>'."\n";
   
     my $result= '<table border="0"><tr><td bgcolor="#777777">'."\n";      my $result= '<table border="0"><tr><td bgcolor="#777777">'."\n";
     $result.= '<table border="0"><tr bgcolor="#deffff">'.      $result.= '<table border="0"><tr bgcolor="#deffff">'.
  '<td rowspan=2><b>Username</b></td><td rowspan=2><b>Domain</b></td><td rowspan=2><b>Fullname</b></td>'."\n";   '<td rowspan=2 valign="center">&nbsp;<b>No.</b>&nbsp;</td>'.
    '<td rowspan=2 valign="center">'.&nameUserString('header')."</td>\n";
   
     my %scoreptr = (      my %scoreptr = (
     'correct'  =>'correct_by_override',      'correct'  =>'correct_by_override',
Line 2249  sub editgrades { Line 2473  sub editgrades {
     my %columns = ();      my %columns = ();
     my ($i,$ctr,$count,$rec_update) = (0,0,0,0);      my ($i,$ctr,$count,$rec_update) = (0,0,0,0);
   
     my (@parts) = sort(&getpartlist($url));      my (@parts) = sort(&getpartlist($url,$symb));
     my $header;      my $header;
     while ($ctr < $ENV{'form.totalparts'}) {      while ($ctr < $ENV{'form.totalparts'}) {
  my $partid = $ENV{'form.partid_'.$ctr};   my $partid = $ENV{'form.partid_'.$ctr};
Line 2283  sub editgrades { Line 2507  sub editgrades {
     $result .= $header;      $result .= $header;
     $result .= '</tr>'."\n";      $result .= '</tr>'."\n";
     my $noupdate;      my $noupdate;
       my ($updateCtr,$noupdateCtr) = (1,1);
     for ($i=0; $i<$ENV{'form.total'}; $i++) {      for ($i=0; $i<$ENV{'form.total'}; $i++) {
  my $line;   my $line;
  my $user = $ENV{'form.ctr'.$i};   my $user = $ENV{'form.ctr'.$i};
Line 2291  sub editgrades { Line 2516  sub editgrades {
  my ($uname,$udom)=split(/_/,$user);   my ($uname,$udom)=split(/_/,$user);
  my %newrecord;   my %newrecord;
  my $updateflag = 0;   my $updateflag = 0;
  $line .= '<tr bgcolor="#ffffde"><td>'.$uname.'&nbsp;</td><td>'.   $line .= '<td>'.&nameUserString(undef,$$fullname{$usercolon},$uname,$udom).'</td>';
     $udom.'&nbsp;</td><td>'.  
  $$fullname{$usercolon}.'&nbsp;</td>';  
  my $usec=$classlist->{"$uname:$udom"}[5];   my $usec=$classlist->{"$uname:$udom"}[5];
  if (!&canmodify($usec)) {   if (!&canmodify($usec)) {
     my $numcols=scalar(@partid)*(scalar(@parts)-1)*2;      my $numcols=scalar(@partid)*4+2;
     $noupdate.=$line."<td colspan=\"$numcols\"><font color=\"red\">Not allowed to modify student</font></td></tr>";      $noupdate.=$line."<td colspan=\"$numcols\"><font color=\"red\">Not allowed to modify student</font></td></tr>";
     next;      next;
  }   }
Line 2322  sub editgrades { Line 2545  sub editgrades {
   
     if ($dropMenu eq 'reset status' &&      if ($dropMenu eq 'reset status' &&
  $old_score ne '') { # ignore if no previous attempts => nothing to reset   $old_score ne '') { # ignore if no previous attempts => nothing to reset
  print "reset status<br>";  
  $newrecord{'resource.'.$_.'.tries'} = 0;   $newrecord{'resource.'.$_.'.tries'} = 0;
  $newrecord{'resource.'.$_.'.solved'} = '';   $newrecord{'resource.'.$_.'.solved'} = '';
  $newrecord{'resource.'.$_.'.award'} = '';   $newrecord{'resource.'.$_.'.award'} = '';
  $newrecord{'resource.'.$_.'.awarded'} = 0;   $newrecord{'resource.'.$_.'.awarded'} = 0;
  $newrecord{'resource.'.$_.'.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";   $newrecord{'resource.'.$_.'.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
  $updateflag = 1;   $updateflag = 1;
       } elsif (!($old_part eq $partial && $old_score eq $score)) {
    $updateflag = 1;
    $newrecord{'resource.'.$_.'.awarded'}  = $partial if $partial ne '';
    $newrecord{'resource.'.$_.'.solved'}   = $score;
    $rec_update++;
     }      }
   
     $line .= '<td align="center">'.$old_aw.'&nbsp;</td>'.      $line .= '<td align="center">'.$old_aw.'&nbsp;</td>'.
  '<td align="center">'.$awarded.   '<td align="center">'.$awarded.
  ($score eq 'excused' ? $score : '').'&nbsp;</td>';   ($score eq 'excused' ? $score : '').'&nbsp;</td>';
   
     if (!($old_part eq $partial && $old_score eq $score)) {  
  $updateflag = 1;  
  $newrecord{'resource.'.$_.'.awarded'}  = $partial if $partial ne '';  
  $newrecord{'resource.'.$_.'.solved'}   = $score;  
  $rec_update++;  
     }  
   
     my $partid=$_;      my $partid=$_;
     foreach my $stores (@parts) {      foreach my $stores (@parts) {
Line 2363  sub editgrades { Line 2584  sub editgrades {
     $count++;      $count++;
     &Apache::lonnet::cstore(\%newrecord,$symb,$ENV{'request.course.id'},      &Apache::lonnet::cstore(\%newrecord,$symb,$ENV{'request.course.id'},
     $udom,$uname);      $udom,$uname);
     $result.=$line;      $result.='<tr bgcolor="#ffffde"><td align="right">&nbsp;'.$updateCtr.'&nbsp;</td>'.$line;
       $updateCtr++;
  } else {   } else {
     $noupdate.=$line;      $noupdate.='<tr bgcolor="#ffffde"><td align="right">&nbsp;'.$noupdateCtr.'&nbsp;</td>'.$line;
       $noupdateCtr++;
  }   }
     }      }
     if ($noupdate) {      if ($noupdate) {
  my $numcols=(scalar(@partid)*(scalar(@parts)-1)*2)+3;  # my $numcols=(scalar(@partid)*(scalar(@parts)-1)*2)+3;
  $result .= '<tr bgcolor="#ffffff"><td align="center" colspan="'.$numcols.'">No Changes Occured For the Students Below</td></tr>'.$noupdate;   my $numcols=scalar(@partid)*4+2;
    $result .= '<tr bgcolor="#ffffff"><td align="center" colspan="'.$numcols.'">No Changes Occurred For the Students Below</td></tr>'.$noupdate;
     }      }
     $result .= '</table></td></tr></table>'."\n".      $result .= '</table></td></tr></table>'."\n".
  &show_grading_menu_form ($symb,$url);   &show_grading_menu_form ($symb,$url);
Line 2509  to this page if the data selected is ins Line 2733  to this page if the data selected is ins
 $javascript  $javascript
 </script>  </script>
 ENDPICK  ENDPICK
     $request->print(&show_grading_menu_form($symb,$url));  
     return '';      return '';
   
 }  }
   
 sub csvupload_fields {  sub csvupload_fields {
     my ($url) = @_;      my ($url,$symb) = @_;
     my (@parts) = &getpartlist($url);      my (@parts) = &getpartlist($url,$symb);
     my @fields=(['username','Student Username'],['domain','Student Domain']);      my @fields=(['username','Student Username'],['domain','Student Domain']);
     foreach my $part (sort(@parts)) {      foreach my $part (sort(@parts)) {
  my @datum;   my @datum;
Line 2599  sub csvuploadmap { Line 2822  sub csvuploadmap {
     &csvuploadmap_header($request,$symb,$url,$datatoken,$#records+1);      &csvuploadmap_header($request,$symb,$url,$datatoken,$#records+1);
     my ($i,$keyfields);      my ($i,$keyfields);
     if (@records) {      if (@records) {
  my @fields=&csvupload_fields($url);   my @fields=&csvupload_fields($url,$symb);
   
  if ($ENV{'form.upfile_associate'} eq 'reverse') {   if ($ENV{'form.upfile_associate'} eq 'reverse') {
     &Apache::loncommon::csv_print_samples($request,\@records);      &Apache::loncommon::csv_print_samples($request,\@records);
Line 2649  sub csvuploadassign { Line 2872  sub csvuploadassign {
     foreach my $grade (@gradedata) {      foreach my $grade (@gradedata) {
  my %entries=&Apache::loncommon::record_sep($grade);   my %entries=&Apache::loncommon::record_sep($grade);
  my $username=$entries{$fields{'username'}};   my $username=$entries{$fields{'username'}};
    $username=~s/\s//g;
  my $domain=$entries{$fields{'domain'}};   my $domain=$entries{$fields{'domain'}};
    $domain=~s/\s//g;
  if (!exists($$classlist{"$username:$domain"})) {   if (!exists($$classlist{"$username:$domain"})) {
     push(@skipped,"$username:$domain");      push(@skipped,"$username:$domain");
     next;      next;
Line 2726  LISTJAVASCRIPT Line 2951  LISTJAVASCRIPT
     $result.='<form action="/adm/grades" method="post" name="displayPage">'."\n";      $result.='<form action="/adm/grades" method="post" name="displayPage">'."\n";
     $result.='&nbsp;<b>Problems from:</b> <select name="selectpage">'."\n";      $result.='&nbsp;<b>Problems from:</b> <select name="selectpage">'."\n";
     my ($titles,$symbx) = &getSymbMap($request);      my ($titles,$symbx) = &getSymbMap($request);
     my ($curpage,$type,$mapId) = ($symb =~ /(.*?\.(page|sequence))___(\d+)___/);       my ($curpage) =&Apache::lonnet::decode_symb($symb); 
   #    my ($curpage,$mapId) =&Apache::lonnet::decode_symb($symb); 
   #    my $type=($curpage =~ /\.(page|sequence)/);
     my $ctr=0;      my $ctr=0;
     foreach (@$titles) {      foreach (@$titles) {
  my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);   my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
Line 2746  LISTJAVASCRIPT Line 2973  LISTJAVASCRIPT
     $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.='&nbsp;<b>View Problems Text: </b><input type="radio" name="vProb" value="no" checked /> no '."\n".      $result.='&nbsp;<b>View Problems Text: </b><input type="radio" name="vProb" value="no" checked="on" /> no '."\n".
  '<input type="radio" name="vProb" value="yes" /> yes '."<br>\n";   '<input type="radio" name="vProb" value="yes" /> yes '."<br>\n";
   
     $result.='&nbsp;<b>Submission Details: </b>'.      $result.='&nbsp;<b>Submission Details: </b>'.
Line 2762  LISTJAVASCRIPT Line 2989  LISTJAVASCRIPT
  '<input type="hidden" name="saveState" value="'.$ENV{'form.saveState'}.'" />'."<br />\n";   '<input type="hidden" name="saveState" value="'.$ENV{'form.saveState'}.'" />'."<br />\n";
   
     $result.='&nbsp;<input type="button" '.      $result.='&nbsp;<input type="button" '.
  'onClick="javascript:checkPickOne(this.form);"value="Submit" /><br />'."\n";   'onClick="javascript:checkPickOne(this.form);"value="Next->" /><br />'."\n";
   
     $request->print($result);      $request->print($result);
   
     my $studentTable.='&nbsp;<b>Select a student you wish to grade</b><br>'.      my $studentTable.='&nbsp;<b>Select a student you wish to grade and then click on the Next button.</b><br>'.
  '<table border="0"><tr><td bgcolor="#777777">'.   '<table border="0"><tr><td bgcolor="#777777">'.
  '<table border="0"><tr bgcolor="#e6ffff">'.   '<table border="0"><tr bgcolor="#e6ffff">'.
  '<td><b>&nbsp;Fullname <font color="#999999">(username)</font></b></td>'.   '<td align="right">&nbsp;<b>No.</b></td>'.
  '<td><b>&nbsp;Fullname <font color="#999999">(username)</font></b></td>'.   '<td>'.&nameUserString('header').'</td>'.
  '<td><b>&nbsp;Fullname <font color="#999999">(username)</font></b></td>'.   '<td align="right">&nbsp;<b>No.</b></td>'.
  '<td><b>&nbsp;Fullname <font color="#999999">(username)</font></b></td></tr>';   '<td>'.&nameUserString('header').'</td></tr>';
     
     my (undef,undef,$fullname) = &getclasslist($getsec,'1');      my (undef,undef,$fullname) = &getclasslist($getsec,'1');
     my $ptr = 1;      my $ptr = 1;
     foreach my $student (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {      foreach my $student (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {
  my ($uname,$udom) = split(/:/,$student);   my ($uname,$udom) = split(/:/,$student);
  $studentTable.=($ptr%4 == 1 ? '<tr bgcolor="#ffffe6"><td>' : '</td><td>');   $studentTable.=($ptr%2 == 1 ? '<tr bgcolor="#ffffe6">' : '</td>');
  $studentTable.='<input type="radio" name="student" value="'.$student.'" /> '.$$fullname{$student}.   $studentTable.='<td align="right">'.$ptr.'&nbsp;</td>';
     '<font color="#999999"> ('.$uname.($udom eq $cdom ? '':':'.$udom).')</font>'."\n";   $studentTable.='<td>&nbsp;<input type="radio" name="student" value="'.$student.'" /> '
  $studentTable.=($ptr%4 == 0 ? '</td></tr>' : '');      .&nameUserString(undef,$$fullname{$student},$uname,$udom)."\n";
    $studentTable.=($ptr%2 == 0 ? '</td></tr>' : '');
  $ptr++;   $ptr++;
     }      }
     $studentTable.='</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;' if ($ptr%4 == 2);      $studentTable.='</td><td>&nbsp;</td><td>&nbsp;' if ($ptr%2 == 0);
     $studentTable.='</td><td>&nbsp;</td><td>&nbsp;' if ($ptr%4 == 3);  
     $studentTable.='</td><td>&nbsp;' if ($ptr%4 == 0);  
     $studentTable.='</td></tr></table></td></tr></table>'."\n";      $studentTable.='</td></tr></table></td></tr></table>'."\n";
     $studentTable.='<br /><input type="button" '.      $studentTable.='<input type="button" '.
  'onClick="javascript:checkPickOne(this.form);"value="Submit" /></form>'."\n";   'onClick="javascript:checkPickOne(this.form);"value="Next->" /></form>'."\n";
   
     $studentTable.=&show_grading_menu_form($symb,$url);      $studentTable.=&show_grading_menu_form($symb,$url);
     $request->print($studentTable);      $request->print($studentTable);
Line 2799  LISTJAVASCRIPT Line 3025  LISTJAVASCRIPT
   
 sub getSymbMap {  sub getSymbMap {
     my ($request) = @_;      my ($request) = @_;
     my $navmap = Apache::lonnavmaps::navmap-> new($ENV{'request.course.fn'}.'.db',      my $navmap = Apache::lonnavmaps::navmap->new();
   $ENV{'request.course.fn'}.'_parms.db');  
     $navmap->init();  
   
     my %symbx = ();      my %symbx = ();
     my @titles = ();      my @titles = ();
Line 2835  sub displayPage { Line 3059  sub displayPage {
     my ($classlist,undef,$fullname) = &getclasslist($getsec,'1');      my ($classlist,undef,$fullname) = &getclasslist($getsec,'1');
     my ($uname,$udom) = split(/:/,$ENV{'form.student'});      my ($uname,$udom) = split(/:/,$ENV{'form.student'});
     my $usec=$classlist->{$ENV{'form.student'}}[5];      my $usec=$classlist->{$ENV{'form.student'}}[5];
   
       #need to make sure we have the correct data for later EXT calls, 
       #thus invalidate the cache
       &Apache::lonnet::devalidatecourseresdata(
                    $ENV{'course.'.$ENV{'request.course.id'}.'.num'},
                    $ENV{'course.'.$ENV{'request.course.id'}.'.domain'});
       &Apache::lonnet::clear_EXT_cache_status();
   
     if (!&canview($usec)) {      if (!&canview($usec)) {
  $request->print('<font color="red">Unable to view requested student.('.$ENV{'form.student'}.')</font>');   $request->print('<font color="red">Unable to view requested student.('.$ENV{'form.student'}.')</font>');
  $request->print(&show_grading_menu_form($symb,$url));   $request->print(&show_grading_menu_form($symb,$url));
  return;   return;
     }      }
     my $result='<h3><font color="#339933">&nbsp;'.$ENV{'form.title'}.'</font></h3>';      my $result='<h3><font color="#339933">&nbsp;'.$ENV{'form.title'}.'</font></h3>';
     $result.='<h3>&nbsp;Student: '.$$fullname{$ENV{'form.student'}}.      $result.='<h3>&nbsp;Student: '.&nameUserString(undef,$$fullname{$ENV{'form.student'}},$uname,$udom).
  '<font color="#999999"> ('.$uname.($udom eq $cdom ? '':':'.$udom).')</font></h3>'."\n";   '</h3>'."\n";
   
     &sub_page_js($request);      &sub_page_js($request);
     $request->print($result);      $request->print($result);
   
     my $navmap = Apache::lonnavmaps::navmap-> new($ENV{'request.course.fn'}.'.db',      my $navmap = Apache::lonnavmaps::navmap->new();
   $ENV{'request.course.fn'}.'_parms.db',1, 1);      my ($mapUrl, $id, $resUrl)=&Apache::lonnet::decode_symb($ENV{'form.page'});
     my ($mapUrl, $id, $resUrl) = split(/___/, $ENV{'form.page'});  
     my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps      my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps
   
     my $iterator = $navmap->getIterator($map->map_start(),      my $iterator = $navmap->getIterator($map->map_start(),
Line 2883  sub displayPage { Line 3113  sub displayPage {
         if($curRes == $iterator->BEGIN_MAP) { $depth++; }          if($curRes == $iterator->BEGIN_MAP) { $depth++; }
         if($curRes == $iterator->END_MAP) { $depth--; }          if($curRes == $iterator->END_MAP) { $depth--; }
   
 #        if (ref($curRes) && $curRes->is_problem() && !$curRes->randomout) {  
         if (ref($curRes) && $curRes->is_problem()) {          if (ref($curRes) && $curRes->is_problem()) {
     my $parts = $curRes->parts();      my $parts = $curRes->parts();
             my $title = $curRes->compTitle();              my $title = $curRes->compTitle();
Line 2891  sub displayPage { Line 3120  sub displayPage {
     $studentTable.='<tr bgcolor="#ffffe6"><td align="center" valign="top" >'.$question.      $studentTable.='<tr bgcolor="#ffffe6"><td align="center" valign="top" >'.$question.
  (scalar(@{$parts}) == 1 ? '' : '<br>('.scalar(@{$parts}).'&nbsp;parts)').'</td>';   (scalar(@{$parts}) == 1 ? '' : '<br>('.scalar(@{$parts}).'&nbsp;parts)').'</td>';
     $studentTable.='<td valign="top">';      $studentTable.='<td valign="top">';
     if ($ENV{'form.vProb'} eq 'yes') {      if ($ENV{'form.vProb'} eq 'yes' ) {
  $studentTable.=&show_problem($request,$symbx,$uname,$udom,1);   $studentTable.=&show_problem($request,$symbx,$uname,$udom,1,
        undef,'both');
     } else {      } else {
  my $companswer = &Apache::loncommon::get_student_answers($symbx,$uname,$udom,$ENV{'request.course.id'});   my $companswer = &Apache::loncommon::get_student_answers($symbx,$uname,$udom,$ENV{'request.course.id'});
  $companswer =~ s|<form(.*?)>||g;   $companswer =~ s|<form(.*?)>||g;
Line 2913  sub displayPage { Line 3143  sub displayPage {
  } else {   } else {
     my %responseType = ();      my %responseType = ();
     foreach my $partid (@{$parts}) {      foreach my $partid (@{$parts}) {
  $responseType{$partid} = $curRes->responseType($partid);   my @responseIds =$curRes->responseIds($partid);
    my @responseType =$curRes->responseType($partid);
    my %responseIds;
    for (my $i=0;$i<=$#responseIds;$i++) {
       $responseIds{$responseIds[$i]}=$responseType[$i];
    }
    $responseType{$partid} = \%responseIds;
     }      }
     $studentTable.= &displaySubByDates(\$symbx,\%record,$parts,\%responseType,$checkIcon);      $studentTable.= &displaySubByDates($symbx,\%record,$parts,\%responseType,$checkIcon,$uname,$udom);
   
  }   }
     } 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' : '');
Line 2950  sub displayPage { Line 3187  sub displayPage {
 }  }
   
 sub displaySubByDates {  sub displaySubByDates {
     my ($symbx,$record,$parts,$responseType,$checkIcon) = @_;      my ($symb,$record,$parts,$responseType,$checkIcon,$uname,$udom) = @_;
     my $studentTable='<table border="0" width="100%"><tr><td bgcolor="#777777">'.      my $studentTable='<table border="0" width="100%"><tr><td bgcolor="#777777">'.
  '<table border="0" width="100%"><tr bgcolor="#e6ffff">'.   '<table border="0" width="100%"><tr bgcolor="#e6ffff">'.
  '<td><b>Date/Time</b></td>'.   '<td><b>Date/Time</b></td>'.
Line 2958  sub displaySubByDates { Line 3195  sub displaySubByDates {
  '<td><b>Status&nbsp;</b></td></tr>';   '<td><b>Status&nbsp;</b></td></tr>';
     my ($version);      my ($version);
     my %mark;      my %mark;
       my %orders;
     $mark{'correct_by_student'} = $checkIcon;      $mark{'correct_by_student'} = $checkIcon;
     return '<br />&nbsp;<font color="red">Nothing submitted - no attempts</font><br />'       if (!exists($$record{'1:timestamp'})) {
  if (!exists($$record{'1:timestamp'}));   return '<br />&nbsp;<font color="red">Nothing submitted - no attempts</font><br />';
       }
     for ($version=1;$version<=$$record{'version'};$version++) {      for ($version=1;$version<=$$record{'version'};$version++) {
  my $timestamp = scalar(localtime($$record{$version.':timestamp'}));   my $timestamp = scalar(localtime($$record{$version.':timestamp'}));
  $studentTable.='<tr bgcolor="#ffffff" valign="top"><td>'.$timestamp.'</td>';   $studentTable.='<tr bgcolor="#ffffff" valign="top"><td>'.$timestamp.'</td>';
  my @versionKeys = split(/\:/,$$record{$version.':keys'});   my @versionKeys = split(/\:/,$$record{$version.':keys'});
  my @displaySub = ();   my @displaySub = ();
  foreach my $partid (@{$parts}) {   foreach my $partid (@{$parts}) {
     my @matchKey = grep /^resource\.$partid\..*?\.submission$/,@versionKeys;      my @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 '');
     $displaySub[0].=(exists $$record{$version.':'.$matchKey[0]}) ?       foreach my $matchKey (@matchKey) {
  '<b>Part&nbsp;'.$partid.'&nbsp;'.   if (exists $$record{$version.':'.$matchKey}) {
  ($$record{"$version:resource.$partid.tries"} eq '' ? 'Trial&nbsp;not&nbsp;counted' :      my ($responseId)=($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/);
  'Trial&nbsp;'.$$record{"$version:resource.$partid.tries"}).'</b>&nbsp; '.      $displaySub[0].='<b>Part&nbsp;'.$partid.'&nbsp;';
  &cleanRecord($$record{$version.':'.$matchKey[0]},$$responseType{$partid},$$symbx).'<br />' : '';      $displaySub[0].='<font color="#999999">(ID&nbsp;'.
     $displaySub[1].=(exists $$record{"$version:resource.$partid.award"}) ?   $responseId.')</font>&nbsp;';
  '<b>Part&nbsp;'.$partid.'</b> &nbsp;'.      if ($$record{"$version:resource.$partid.tries"} eq '') {
  lc($$record{"$version:resource.$partid.award"}).' '.   $displaySub[0].='Trial&nbsp;not&nbsp;counted';
  $mark{$$record{"$version:resource.$partid.solved"}}.'<br />' : '';      } else {
     $displaySub[2].=(exists $$record{"$version:resource.$partid.regrader"}) ?   $displaySub[0].='Trial&nbsp;'.
  $$record{"$version:resource.$partid.regrader"}.' (<b>Part:</b> '.$partid.')' : '';      $$record{"$version:resource.$partid.tries"};
  }      }
  $displaySub[2].=(exists $$record{"$version:resource.regrader"}) ?      my $responseType=$responseType->{$partid}->{$responseId};
     $$record{"$version:resource.regrader"} : '';      if (!exists($orders{$partid})) { $orders{$partid}={}; }
  $studentTable.='<td>'.$displaySub[0].'&nbsp;</td><td>'.$displaySub[1].      if (!exists($orders{$partid}->{$responseId})) {
     ($displaySub[2] eq '' ? '' : 'Manually graded by '.$displaySub[2]).'&nbsp;</td></tr>';   $orders{$partid}->{$responseId}=
       &get_order($partid,$responseId,$symb,$uname,$udom);
       }
       $displaySub[0].='</b>&nbsp; '.
    &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:").'<br />';
    }
       }
       if (exists $$record{"$version:resource.$partid.award"}) {
    $displaySub[1].='<b>Part&nbsp;'.$partid.'</b> &nbsp;'.
       lc($$record{"$version:resource.$partid.award"}).' '.
       $mark{$$record{"$version:resource.$partid.solved"}}.
       '<br />';
       }
       if (exists $$record{"$version:resource.$partid.regrader"}) {
    $displaySub[2].=$$record{"$version:resource.$partid.regrader"}.
       ' (<b>'.&mt('Part').':</b> '.$partid.')';
       }
    }
    # needed because old essay regrader has not parts info
    if (exists $$record{"$version:resource.regrader"}) {
       $displaySub[2].=$$record{"$version:resource.regrader"};
    }
    $studentTable.='<td>'.$displaySub[0].'&nbsp;</td><td>'.$displaySub[1];
    if ($displaySub[2]) {
       $studentTable.='Manually graded by '.$displaySub[2];
    }
    $studentTable.='&nbsp;</td></tr>';
       
     }      }
     $studentTable.='</table></td></tr></table>';      $studentTable.='</table></td></tr></table>';
     return $studentTable;      return $studentTable;
Line 3006  sub updateGradeByPage { Line 3272  sub updateGradeByPage {
  return;   return;
     }      }
     my $result='<h3><font color="#339933">&nbsp;'.$ENV{'form.title'}.'</font></h3>';      my $result='<h3><font color="#339933">&nbsp;'.$ENV{'form.title'}.'</font></h3>';
     $result.='<h3>&nbsp;Student: '.$ENV{'form.fullname'}.      $result.='<h3>&nbsp;Student: '.&nameUserString(undef,$ENV{'form.fullname'},$uname,$udom).
  '<font color="#999999"> ('.$uname.($udom eq $cdom ? '':':'.$udom).')</font></h3>'."\n";   '</h3>'."\n";
   
     $request->print($result);      $request->print($result);
   
     my $navmap = Apache::lonnavmaps::navmap-> new($ENV{'request.course.fn'}.'.db',      my $navmap = Apache::lonnavmaps::navmap->new();
   $ENV{'request.course.fn'}.'_parms.db',1, 1);      my ($mapUrl, $id, $resUrl) = &Apache::lonnet::decode_symb( $ENV{'form.page'});
     my ($mapUrl, $id, $resUrl) = split(/___/, $ENV{'form.page'});  
     my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps      my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps
   
     my $iterator = $navmap->getIterator($map->map_start(),      my $iterator = $navmap->getIterator($map->map_start(),
Line 3062  sub updateGradeByPage { Line 3327  sub updateGradeByPage {
     $score = 'excused';      $score = 'excused';
  } elsif ($dropMenu eq 'reset status'   } elsif ($dropMenu eq 'reset status'
  && $ENV{'form.solved'.$question.'_'.$partid} ne '') { #update only if previous record exists   && $ENV{'form.solved'.$question.'_'.$partid} ne '') { #update only if previous record exists
     print "got to reset = $ENV{'form.solved'.$question.'_'.$partid}:<br>";  
     $newrecord{'resource.'.$partid.'.tries'} = 0;      $newrecord{'resource.'.$partid.'.tries'} = 0;
     $newrecord{'resource.'.$partid.'.solved'} = '';      $newrecord{'resource.'.$partid.'.solved'} = '';
     $newrecord{'resource.'.$partid.'.award'} = '';      $newrecord{'resource.'.$partid.'.award'} = '';
Line 3136  sub getSequenceDropDown { Line 3400  sub getSequenceDropDown {
     my ($request,$symb)=@_;      my ($request,$symb)=@_;
     my $result='<select name="selectpage">'."\n";      my $result='<select name="selectpage">'."\n";
     my ($titles,$symbx) = &getSymbMap($request);      my ($titles,$symbx) = &getSymbMap($request);
     my ($curpage,$type,$mapId) = ($symb =~ /(.*?\.(page|sequence))___(\d+)___/);       my ($curpage)=&Apache::lonnet::decode_symb($symb); 
     my $ctr=0;      my $ctr=0;
     foreach (@$titles) {      foreach (@$titles) {
  my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);   my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
Line 3152  sub getSequenceDropDown { Line 3416  sub getSequenceDropDown {
 sub scantron_uploads {  sub scantron_uploads {
     if (!-e $Apache::lonnet::perlvar{'lonScansDir'}) { return ''};      if (!-e $Apache::lonnet::perlvar{'lonScansDir'}) { return ''};
     my $result= '<select name="scantron_selectfile">';      my $result= '<select name="scantron_selectfile">';
     opendir(DIR,$Apache::lonnet::perlvar{'lonScansDir'});      my $cdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
     my @files=sort(readdir(DIR));      my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};
       my @files=&Apache::lonnet::dirlist('userfiles',$cdom,$cname,
       &Apache::loncommon::propath($cdom,$cname));
     foreach my $filename (@files) {      foreach my $filename (@files) {
  if ($filename eq '.' or $filename eq '..') { next; }   ($filename)=split(/&/,$filename);
    if ($filename!~/^scantron_orig_/) { next ; }
    $filename=~s/^scantron_orig_//;
  $result.="<option>$filename</option>\n";   $result.="<option>$filename</option>\n";
     }      }
     closedir(DIR);  
     $result.="</select>";      $result.="</select>";
     return $result;      return $result;
 }  }
Line 3186  sub scantron_selectphase { Line 3453  sub scantron_selectphase {
     my $file_selector=&scantron_uploads();      my $file_selector=&scantron_uploads();
     my $format_selector=&scantron_scantab();      my $format_selector=&scantron_scantab();
     my $result;      my $result;
       #FIXME allow instructor to be able to download the scantron file
       # and to upload it,
     $result.= <<SCANTRONFORM;      $result.= <<SCANTRONFORM;
 <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantro_process">      <table width="100%" border="0">
   <input type="hidden" name="command" value="scantron_process" />  
   $default_form_data  
   <table width="100%" border="0">  
     <tr>      <tr>
       <td bgcolor="#777777">        <td bgcolor="#777777">
          <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantro_process">
          <input type="hidden" name="command" value="scantron_validate" />
           $default_form_data
         <table width="100%" border="0">          <table width="100%" border="0">
           <tr bgcolor="#e6ffff">            <tr bgcolor="#e6ffff">
             <td>              <td colspan="2">
               &nbsp;<b>Specify file location and which Folder/Sequence to grade</b>                &nbsp;<b>Specify file and which Folder/Sequence to grade</b>
             </td>              </td>
           </tr>            </tr>
           <tr bgcolor="#ffffe6">            <tr bgcolor="#ffffe6">
               <td> Sequence to grade: </td><td> $sequence_selector </td>
             </tr>
             <tr bgcolor="#ffffe6">
               <td> Filename of scoring office file: </td><td> $file_selector </td>
             </tr>
             <tr bgcolor="#ffffe6">
               <td> Format of data file: </td><td> $format_selector </td>
             </tr>
             <tr bgcolor="#ffffe6">
             <td>              <td>
                Sequence to grade: $sequence_selector  <!-- FIXME this is lazy, a single parse of the set should let me know what this is -->
                 Last line to expect an answer on: </td><td>
                   <input type="text" name="scantron_maxbubble" />
     </td>      </td>
           </tr>            </tr>
           <tr bgcolor="#ffffe6">            <tr bgcolor="#ffffe6">
               <td colspan="2">
                 <input type="submit" value="Validate Scantron Records" />
               </td>
             </tr>
           </table>
          </form>
         </td>
       </tr>
   SCANTRONFORM
      
       $r->print($result);
   
       if (&Apache::lonnet::allowed('usc',$ENV{'request.role.domain'}) ||
           &Apache::lonnet::allowed('usc',$ENV{'request.course.id'})) {
   
           $r->print(<<SCANTRONFORM);
       <tr>
         <td bgcolor="#777777">
           <table width="100%" border="0">
             <tr bgcolor="#e6ffff">
             <td>              <td>
  Filename of scoring office file: $file_selector                &nbsp;<b>Specify a Scantron data file to upload.</b>
     </td>              </td>
           </tr>            </tr>
           <tr bgcolor="#ffffe6">            <tr bgcolor="#ffffe6">
             <td>              <td>
               Format of data file: $format_selector  SCANTRONFORM
     </td>      my $default_form_data=&defaultFormData(&get_symb_and_url($r,1));
       my $cdom= $ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
       my $cnum= $ENV{'course.'.$ENV{'request.course.id'}.'.num'};
       $r->print(<<UPLOAD);
                 <script type="text/javascript" language="javascript">
       function checkUpload(formname) {
    if (formname.upfile.value == "") {
       alert("Please use the browse button to select a file from your local directory.");
       return false;
    }
    formname.submit();
       }
                 </script>
   
                 <form enctype='multipart/form-data' action='/adm/grades' name='rules' method='post'>
                   $default_form_data
                   <input name='courseid' type='hidden' value='$cnum' />
                   <input name='domainid' type='hidden' value='$cdom' />
                   <input name='command' value='scantronupload_save' type='hidden' />
                   File to upload:<input type="file" name="upfile" size="50" />
                   <br />
                   <input type="button" onClick="javascript:checkUpload(this.form);" value="Upload Scantron Data" />
                 </form>
   UPLOAD
   
           $r->print(<<SCANTRONFORM);
               </td>
           </tr>            </tr>
         </table>          </table>
       </td>        </td>
     </tr>      </tr>
   SCANTRONFORM
       }
   
       $r->print(<<SCANTRONFORM);
   </table>    </table>
   <input type="submit" value="Submit" />  
 </form>  </form>
 $grading_menu_button  $grading_menu_button
 SCANTRONFORM  SCANTRONFORM
   
     return $result;      return
 }  }
   
 sub get_scantron_config {  sub get_scantron_config {
     my ($which) = @_;      my ($which) = @_;
     my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');      my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
     my %config;      my %config;
       #FIXME probably should move to XML it has already gotten a bit much now
     foreach my $line (<$fh>) {      foreach my $line (<$fh>) {
  my ($name,$descrip)=split(/:/,$line);   my ($name,$descrip)=split(/:/,$line);
  if ($name ne $which ) { next; }   if ($name ne $which ) { next; }
Line 3246  sub get_scantron_config { Line 3576  sub get_scantron_config {
  $config{'Qlength'}=$config[8];   $config{'Qlength'}=$config[8];
  $config{'Qoff'}=$config[9];   $config{'Qoff'}=$config[9];
  $config{'Qon'}=$config[10];   $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];
  last;   last;
     }      }
     return %config;      return %config;
Line 3261  sub username_to_idmap { Line 3597  sub username_to_idmap {
     return %idmap;      return %idmap;
 }  }
   
   sub scantron_fixup_scanline {
       my ($scantron_config,$scan_data,$line,$whichline,$field,$args)=@_;
       if ($field eq 'ID') {
    if (length($args->{'newid'}) > $$scantron_config{'IDlength'}) {
       return ($line,1,'New value to large');
    }
    if (length($args->{'newid'}) < $$scantron_config{'IDlength'}) {
       $args->{'newid'}=sprintf('%-'.$$scantron_config{'IDlength'}.'s',
        $args->{'newid'});
    }
    substr($line,$$scantron_config{'IDstart'}-1,
          $$scantron_config{'IDlength'})=$args->{'newid'};
    if ($args->{'newid'}=~/^\s*$/) {
       &scan_data($scan_data,"$whichline.user",
          $args->{'username'}.':'.$args->{'domain'});
    }
       } elsif ($field eq 'answer') {
    my $length=$scantron_config->{'Qlength'};
    my $off=$scantron_config->{'Qoff'};
    my $on=$scantron_config->{'Qon'};
    my $answer=${off}x$length;
    if ($args->{'response'} eq 'none') {
       &scan_data($scan_data,
          "$whichline.no_bubble.".$args->{'question'},'1');
    } else {
       substr($answer,$args->{'response'},1)=$on;
       &scan_data($scan_data,
          "$whichline.no_bubble.".$args->{'question'},undef,'1');
    }
    my $where=$length*($args->{'question'}-1)+$scantron_config->{'Qstart'};
    substr($line,$where-1,$length)=$answer;
       }
       return $line;
   }
   
   sub scan_data {
       my ($scan_data,$key,$value,$delete)=@_;
       my $filename=$ENV{'form.scantron_selectfile'};
       if (defined($value)) {
    $scan_data->{$filename.'_'.$key} = $value;
       }
       if ($delete) { delete($scan_data->{$filename.'_'.$key}); }
       return $scan_data->{$filename.'_'.$key};
   }
   
 sub scantron_parse_scanline {  sub scantron_parse_scanline {
     my ($line,$scantron_config)=@_;      my ($line,$whichline,$scantron_config,$scan_data)=@_;
     my %record;      my %record;
     my $questions=substr($line,$$scantron_config{'Qstart'}-1);      my $questions=substr($line,$$scantron_config{'Qstart'}-1);
     my $data=substr($line,0,$$scantron_config{'Qstart'}-1);      my $data=substr($line,0,$$scantron_config{'Qstart'}-1);
Line 3276  sub scantron_parse_scanline { Line 3657  sub scantron_parse_scanline {
     }      }
     $record{'scantron.ID'}=substr($data,$$scantron_config{'IDstart'}-1,      $record{'scantron.ID'}=substr($data,$$scantron_config{'IDstart'}-1,
   $$scantron_config{'IDlength'});    $$scantron_config{'IDlength'});
       $record{'scantron.PaperID'}=
    substr($data,$$scantron_config{'PaperID'}-1,
          $$scantron_config{'PaperIDlength'});
       $record{'scantron.FirstName'}=
    substr($data,$$scantron_config{'FirstName'}-1,
          $$scantron_config{'FirstNamelength'});
       $record{'scantron.LastName'}=
    substr($data,$$scantron_config{'LastName'}-1,
          $$scantron_config{'LastNamelength'});
     my @alphabet=('A'..'Z');      my @alphabet=('A'..'Z');
     my $questnum=0;      my $questnum=0;
     while ($questions) {      while ($questions) {
Line 3283  sub scantron_parse_scanline { Line 3673  sub scantron_parse_scanline {
  my $currentquest=substr($questions,0,$$scantron_config{'Qlength'});   my $currentquest=substr($questions,0,$$scantron_config{'Qlength'});
  substr($questions,0,$$scantron_config{'Qlength'})='';   substr($questions,0,$$scantron_config{'Qlength'})='';
  if (length($currentquest) < $$scantron_config{'Qlength'}) { next; }   if (length($currentquest) < $$scantron_config{'Qlength'}) { next; }
  my (@array)=split(/$$scantron_config{'Qon'}/,$currentquest);   my @array=split($$scantron_config{'Qon'},$currentquest,-1);
  if (scalar(@array) gt 2) {  
     #FIXME do something intelligent with double bubbles  
     Apache->request->print("<br ><b>Wha!!!</b> <pre>".scalar(@array).  
    '-'.$currentquest.'-'.$questnum.'</pre><br />');  
  }  
  if (length($array[0]) eq $$scantron_config{'Qlength'}) {   if (length($array[0]) eq $$scantron_config{'Qlength'}) {
     $record{"scantron.$questnum.answer"}='';      $record{"scantron.$questnum.answer"}='';
       if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) {
    push(@{$record{"scantron.missingerror"}},$questnum);
        }
  } else {   } else {
     $record{"scantron.$questnum.answer"}=$alphabet[length($array[0])];      $record{"scantron.$questnum.answer"}=$alphabet[length($array[0])];
  }   }
     if (scalar(@array) gt 2) {
        push(@{$record{'scantron.doubleerror'}},$questnum);
        my @ans=@array;
        my $i=length($ans[0]);shift(@ans);
       while ($#ans) {
     $i+=length($ans[0])+1;
     $record{"scantron.$questnum.answer"}.=$alphabet[$i];
     shift(@ans);
        }
     }
     }      }
     $record{'scantron.maxquest'}=$questnum;      $record{'scantron.maxquest'}=$questnum;
     return \%record;      return \%record;
 }  }
   
 sub scantron_add_delay {  sub scantron_add_delay {
       my ($delayqueue,$scanline,$errormessage,$errorcode)=@_;
       push(@$delayqueue,
    {'line' => $scanline, 'emsg' => $errormessage,
     'ecode' => $errorcode }
    );
 }  }
   
 sub scantron_find_student {  sub scantron_find_student {
     my ($scantron_record,$idmap)=@_;      my ($scantron_record,$scan_data,$idmap,$line)=@_;
     my $scanID=$$scantron_record{'scantron.ID'};      my $scanID=$$scantron_record{'scantron.ID'};
       if ($scanID =~ /^\s*$/) {
     return &scan_data($scan_data,"$line.user");
       }
     foreach my $id (keys(%$idmap)) {      foreach my $id (keys(%$idmap)) {
  Apache->request->print('<pre>checking studnet -'.$id.'- againt -'.$scanID.'- </pre>');    if (lc($id) eq lc($scanID)) {
  if (lc($id) eq lc($scanID)) { Apache->request->print('success');return $$idmap{$id}; }       return $$idmap{$id};
     }
     }      }
     return undef;      return undef;
 }  }
Line 3320  sub scantron_filter { Line 3727  sub scantron_filter {
     return 0;      return 0;
 }  }
   
   sub scantron_process_corrections {
       my ($r) = @_;
       my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'});
       my ($scanlines,$scan_data)=&scantron_getfile();
       my $classlist=&Apache::loncoursedata::get_classlist();
       my $which=$ENV{'form.scantron_line'};
       my $line=&scantron_get_line($scanlines,$which);
       my ($skip,$err,$errmsg);
       if ($ENV{'form.scantron_skip_record'}) {
    $skip=1;
       } elsif ($ENV{'form.scantron_corrections'} =~ /^(duplicate|incorrect)ID$/) {
    my $newstudent=$ENV{'form.scantron_username'}.':'.
       $ENV{'form.scantron_domain'};
    my $newid=$classlist->{$newstudent}->[&Apache::loncoursedata::CL_ID];
    ($line,$err,$errmsg)=
       &scantron_fixup_scanline(\%scantron_config,$scan_data,$line,$which,
        'ID',{'newid'=>$newid,
       'username'=>$ENV{'form.scantron_username'},
       'domain'=>$ENV{'form.scantron_domain'}});
       } elsif ($ENV{'form.scantron_corrections'} =~ /^(missing|double)bubble$/) {
    foreach my $question (split(',',$ENV{'form.scantron_questions'})) {
       ($line,$err,$errmsg)=
    &scantron_fixup_scanline(\%scantron_config,$scan_data,$line,
    $which,'answer',
    { 'question'=>$question,
          'response'=>$ENV{"form.scantron_correct_Q_$question"}});
       if ($err) { last; }
    }
       }
       if ($err) {
    $r->print("Unable to accept last correction, an error occurred :$errmsg:");
       } else {
    &scantron_put_line($scanlines,$which,$line,$skip);
    &scantron_putfile($scanlines,$scan_data);
       }
   }
   
   
   sub scantron_validate_file {
       my ($r) = @_;
       my ($symb,$url)=&get_symb_and_url($r);
       if (!$symb) {return '';}
       my $default_form_data=&defaultFormData($symb,$url);
   
       if ($ENV{'form.scantron_corrections'}) {
    &scantron_process_corrections($r);
       }
       #get the student pick code ready
       $r->print(&Apache::loncommon::studentbrowser_javascript());
       my $result= <<SCANTRONFORM;
   <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantronupload">
     <input type="hidden" name="selectpage" value="$ENV{'form.selectpage'}" />
     <input type="hidden" name="scantron_format" value="$ENV{'form.scantron_format'}" />
     <input type="hidden" name="scantron_selectfile" value="$ENV{'form.scantron_selectfile'}" />
     <input type="hidden" name="scantron_maxbubble" value="$ENV{'form.scantron_maxbubble'}" />
     $default_form_data
   SCANTRONFORM
       $r->print($result);
       
       my @validate_phases=( 'ID',
     'CODE',
     'doublebubble',
     'missingbubbles');
       if (!$ENV{'form.validatepass'}) {
    $ENV{'form.valiadatepass'} = 0;
       }
       my $currentphase=$ENV{'form.valiadatepass'};
   
       if ($ENV{'form.scantron_selectfile'}=~m-^/-) {
    #first pass copy file to classdir
   
       }
       my $stop=0;
       while (!$stop && $currentphase < scalar(@validate_phases)) {
    $r->print("<p> Validating ".$validate_phases[$currentphase]."</p>");
    $r->rflush();
    my $which="scantron_validate_".$validate_phases[$currentphase];
    {
       no strict 'refs';
       ($stop,$currentphase)=&$which($r,$currentphase);
    }
       }
       if (!$stop) {
    $r->print("Validation process complete.<br />");
    $r->print('<input type="submit" name="submit" value="Start Grading" />');
    $r->print('<input type="hidden" name="command" value="scantron_process" />');
       } else {
    $r->print('<input type="hidden" name="command" value="scantron_validate" />');
    $r->print("<input type='hidden' name='validatepass' value='".$currentphase."' />");
       }
       if ($stop) {
    $r->print('<input type="submit" name="submit" value="Continue ->" />');
    $r->print(' using corrected info <br />');
    $r->print("<input type='submit' value='Skip' name='scantron_skip_record' />");
    $r->print(" this scanline saving it for later.");
       }
       $r->print(" </form><br />".&show_grading_menu_form($symb,$url).
         "</body></html>");
       return '';
   }
   
   sub scantron_getfile {
       #FIXME really would prefer a scantron directory but tokenwrapper
       # doesn't allow access to subdirs of userfiles
       my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};
       my $cdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
       my $lines;
       $lines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'.
          'scantron_orig_'.$ENV{'form.scantron_selectfile'});
       my %scanlines;
       $scanlines{'orig'}=[(split("\n",$lines,-1))];
       my $temp=$scanlines{'orig'};
       $scanlines{'count'}=$#$temp;
   
       $lines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'.
          'scantron_corrected_'.$ENV{'form.scantron_selectfile'});
       if ($lines eq '-1') {
    $scanlines{'corrected'}=[];
       } else {
    $scanlines{'corrected'}=[(split("\n",$lines,-1))];
       }
       $lines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'.
          'scantron_skipped_'.$ENV{'form.scantron_selectfile'});
       if ($lines eq '-1') {
    $scanlines{'skipped'}=[];
       } else {
    $scanlines{'skipped'}=[(split("\n",$lines,-1))];
       }
       my @tmp=&Apache::lonnet::dump('nohist_scantrondata',$cdom,$cname);
       if ($tmp[0] =~ /^(error:|no_such_host)/) { @tmp=(); }
       my %scan_data = @tmp;
       return (\%scanlines,\%scan_data);
   }
   
   sub lonnet_putfile {
       my ($contents,$filename)=@_;
       my $docuname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};
       my $docudom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
       my $docuhome=$ENV{'course.'.$ENV{'request.course.id'}.'.home'};
       $ENV{'form.sillywaytopassafilearound'}=$contents;
       &Apache::lonnet::finishuserfileupload($docuname,$docudom,$docuhome,'sillywaytopassafilearound',$filename);
   
   }
   
   sub scantron_putfile {
       my ($scanlines,$scan_data) = @_;
       #FIXME really would prefer a scantron directory but tokenwrapper
       # doesn't allow access to subdirs of userfiles
       my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};
       my $cdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
       my $prefix='scantron_';
   # no need to update orig, shouldn't change
   #   &lonnet_putfile(join("\n",@{$scanlines->{'orig'}}),$prefix.'orig_'.
   #    $ENV{'form.scantron_selectfile'});
       &lonnet_putfile(join("\n",@{$scanlines->{'corrected'}}),
       $prefix.'corrected_'.
       $ENV{'form.scantron_selectfile'});
       &lonnet_putfile(join("\n",@{$scanlines->{'skipped'}}),
       $prefix.'skipped_'.
       $ENV{'form.scantron_selectfile'});
       &Apache::lonnet::put('nohist_scantrondata',$scan_data,$cdom,$cname);
   }
   
   sub scantron_get_line {
       my ($scanlines,$i)=@_;
       if ($scanlines->{'skipped'}[$i]) {return undef;}
       if ($scanlines->{'corrected'}[$i]) {return $scanlines->{'corrected'}[$i];}
       return $scanlines->{'orig'}[$i]; 
   }
   
   sub scantron_put_line {
       my ($scanlines,$i,$newline,$skip)=@_;
       if ($skip) {
    $scanlines->{'skipped'}[$i]=$newline;
    return;
       }
       $scanlines->{'corrected'}[$i]=$newline;
   }
   
   sub scantron_validate_ID {
       my ($r,$currentphase) = @_;
       
       #get student info
       my $classlist=&Apache::loncoursedata::get_classlist();
       my %idmap=&username_to_idmap($classlist);
   
       #get scantron line setup
       my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'});
       my ($scanlines,$scan_data)=&scantron_getfile();
   
       my %found=('ids'=>{},'usernames'=>{});
       for (my $i=0;$i<=$scanlines->{'count'};$i++) {
    my $line=&scantron_get_line($scanlines,$i);
    if ($line=~/^[\s\cz]*$/) { next; }
    my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,
    $scan_data);
    my $id=$$scan_record{'scantron.ID'};
    my $found;
    foreach my $checkid (keys(%idmap)) {
       if (lc($checkid) eq lc($id)) { $found=$checkid;last; }
    }
    if ($found) {
       my $username=$idmap{$found};
       if ($found{'ids'}{$found}) {
    &scantron_get_correction($r,$i,$scan_record,\%scantron_config,
    $line,'duplicateID',$found);
    return(1);
       } elsif ($found{'usernames'}{$username}) {
    &scantron_get_correction($r,$i,$scan_record,\%scantron_config,
    $line,'duplicateID',$username);
    return(1);
       }
       #FIXME store away line we prviously saw the ID on to use above
       $found{'ids'}{$found}++;
       $found{'usernames'}{$username}++;
    } else {
       if ($id =~ /^\s*$/) {
    my $username=&scan_data($scan_data,"$i.user");
    if (defined($username) && $found{'usernames'}{$username}) {
       &scantron_get_correction($r,$i,$scan_record,
        \%scantron_config,
        $line,'duplicateID',$username);
       return(1);
    } elsif (!defined($username)) {
       &scantron_get_correction($r,$i,$scan_record,
        \%scantron_config,
        $line,'incorrectID');
       return(1);
    }
    $found{'usernames'}{$username}++;
       } else {
    &scantron_get_correction($r,$i,$scan_record,\%scantron_config,
    $line,'incorrectID');
    return(1);
       }
    }
       }
   
       return (0,$currentphase+1);
   }
   
   sub scantron_get_correction {
       my ($r,$i,$scan_record,$scan_config,$line,$error,$arg)=@_;
   
   #FIXME in the case of a duplicated ID the previous line, probaly need
   #to show both the current line and the previous one and allow skipping
   #the previous one or the current one
   
       $r->print("<p><b>An error was detected ($error)</b>");
       if ( defined($$scan_record{'scantron.PaperID'}) ) {
    $r->print(" for PaperID <tt>".
     $$scan_record{'scantron.PaperID'}."</tt> \n");
       } else {
    $r->print(" in scanline $i <pre>".
     $line."</pre> \n");
       }
       $r->print('<input type="hidden" name="scantron_corrections" value="'.$error.'" />'."\n");
       $r->print('<input type="hidden" name="scantron_line" value="'.$i.'" />'."\n");
       if ($error =~ /ID$/) {
    if ($error eq 'unknownID') {
       $r->print("The encoded ID is not in the classlist</p>\n");
    } elsif ($error eq 'duplicateID') {
       $r->print("The encoded ID has also been used by a previous paper $arg</p>\n");
    }
    $r->print("<p>The ID on the form is  <tt>".
     $$scan_record{'scantron.ID'}."</tt><br />\n");
    $r->print("The name on the paper is ".
     $$scan_record{'scantron.LastName'}.",".
     $$scan_record{'scantron.FirstName'}."</p>");
    $r->print("<p>How should I handle this? <br /> \n");
    $r->print("\n<ul><li> ");
    #FIXME it would be nice if this sent back the user ID and
    #could do partial userID matches
    $r->print(&Apache::loncommon::selectstudent_link('scantronupload',
          'scantron_username','scantron_domain'));
    $r->print(": <input type='text' name='scantron_username' value='' />");
    $r->print("\n@".
    &Apache::loncommon::select_dom_form($ENV{'request.role..domain'},'scantron_domain'));
   
    $r->print('</li>');
       } elsif ($error eq 'doublebubble') {
   #FIXME Need to print out who this is along with the paper info
    $r->print("<p>There have been multiple bubbles scanned for a some question(s)</p>\n");
    $r->print('<input type="hidden" name="scantron_questions" value="'.
     join(',',@{$arg}).'" />');
    $r->print("<p>Please indicate which bubble should be used for grading</p>");
    foreach my $question (@{$arg}) {
       my $selected=$$scan_record{"scantron.$question.answer"};
       &scantron_bubble_selector($r,$scan_config,$question,split('',$selected));
    }
       } elsif ($error eq 'missingbubble') {
    $r->print("<p>There have been <b>no</b> bubbles scanned for some question(s)</p>\n");
    $r->print("<p>Please indicate which bubble should be used for grading</p>");
    $r->print("Some questions have no scanned bubbles\n");
    $r->print('<input type="hidden" name="scantron_questions" value="'.
     join(',',@{$arg}).'" />');
    foreach my $question (@{$arg}) {
       my $selected=$$scan_record{"scantron.$question.answer"};
       &scantron_bubble_selector($r,$scan_config,$question);
    }
       } else {
    $r->print("\n<ul>");
       }
       $r->print("\n</li></ul>");
   
   }
   
   sub scantron_bubble_selector {
       my ($r,$scan_config,$quest,@selected)=@_;
       my $max=$$scan_config{'Qlength'};
       my @alphabet=('A'..'Z');
       $r->print("<table border='1'><tr><td rowspan='2'>$quest</td>");
       for (my $i=0;$i<$max+1;$i++) {
    $r->print('<td align="center">');
    if ($selected[0] eq $alphabet[$i]) { $r->print('X'); shift(@selected) }
    else { $r->print('&nbsp;'); }
    $r->print('</td>');
       }
       $r->print('<td></td></tr><tr>');
       for (my $i=0;$i<$max;$i++) {
    $r->print('<td><input type="radio" name="scantron_correct_Q_'.$quest.
     '" value="'.$i.'" />'.$alphabet[$i]."</td>");
       }
       $r->print('<td><input type="radio" name="scantron_correct_Q_'.$quest.
         '" value="none" /> No bubble </td>');
       $r->print('</tr></table>');
   }
   
   sub scantron_validate_CODE {
       my ($r,$currentphase) = @_;
       #FIXME doesn't do anything yet
       return (0,$currentphase+1);
   }
   
   sub scantron_validate_doublebubble {
       my ($r,$currentphase) = @_;
       #get student info
       my $classlist=&Apache::loncoursedata::get_classlist();
       my %idmap=&username_to_idmap($classlist);
   
       #get scantron line setup
       my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'});
       my ($scanlines,$scan_data)=&scantron_getfile();
       for (my $i=0;$i<=$scanlines->{'count'};$i++) {
    my $line=&scantron_get_line($scanlines,$i);
    if ($line=~/^[\s\cz]*$/) { next; }
    my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,
    $scan_data);
    if (!defined($$scan_record{'scantron.doubleerror'})) { next; }
    &scantron_get_correction($r,$i,$scan_record,\%scantron_config,$line,
    'doublebubble',
    $$scan_record{'scantron.doubleerror'});
       return (1,$currentphase);
       }
       return (0,$currentphase+1);
   }
   
   sub scantron_validate_missingbubbles {
       my ($r,$currentphase) = @_;
       #get student info
       my $classlist=&Apache::loncoursedata::get_classlist();
       my %idmap=&username_to_idmap($classlist);
   
       #get scantron line setup
       my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'});
       my ($scanlines,$scan_data)=&scantron_getfile();
       my $max_bubble=$ENV{'form.scantron_maxbubble'};
       if (!$max_bubble) { $max_bubble=2**31; }
       for (my $i=0;$i<=$scanlines->{'count'};$i++) {
    my $line=&scantron_get_line($scanlines,$i);
    if ($line=~/^[\s\cz]*$/) { next; }
    my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,
    $scan_data);
    if (!defined($$scan_record{'scantron.missingerror'})) { next; }
    my @to_correct;
    foreach my $missing (@{$$scan_record{'scantron.missingerror'}}) {
       if ($missing > $max_bubble) { next; }
       push(@to_correct,$missing);
    }
    if (@to_correct) {
       &scantron_get_correction($r,$i,$scan_record,\%scantron_config,
        $line,'missingbubble',\@to_correct);
       return (1,$currentphase);
    }
   
       }
       return (0,$currentphase+1);
   }
   
 sub scantron_process_students {  sub scantron_process_students {
     my ($r) = @_;      my ($r) = @_;
     my (undef,undef,$sequence)=split(/___/,$ENV{'form.selectpage'});      my (undef,undef,$sequence)=&Apache::lonnet::decode_symb($ENV{'form.selectpage'});
     my ($symb,$url)=&get_symb_and_url($r);      my ($symb,$url)=&get_symb_and_url($r);
     if (!$symb) {return '';}      if (!$symb) {return '';}
     my $default_form_data=&defaultFormData($symb,$url);      my $default_form_data=&defaultFormData($symb,$url);
   
     my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'});      my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'});
     my $scanlines=Apache::File->new($Apache::lonnet::perlvar{'lonScansDir'}."/$ENV{'form.scantron_selectfile'}");      my ($scanlines,$scan_data)=&scantron_getfile();
     my @scanlines=<$scanlines>;  
     my $classlist=&Apache::loncoursedata::get_classlist();      my $classlist=&Apache::loncoursedata::get_classlist();
     my %idmap=&username_to_idmap($classlist);      my %idmap=&username_to_idmap($classlist);
     my $navmap=Apache::lonnavmaps::navmap->new($ENV{'request.course.fn'}.'.db',$ENV{'request.course.fn'}.'_parms.db',1, 1);      my $navmap=Apache::lonnavmaps::navmap->new();
     my $map=$navmap->getResourceByUrl($sequence);      my $map=$navmap->getResourceByUrl($sequence);
     my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);      my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
     $r->print("geto ".scalar(@resources)."<br />");  #    $r->print("geto ".scalar(@resources)."<br />");
     my $result= <<SCANTRONFORM;      my $result= <<SCANTRONFORM;
 <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantronupload">  <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantronupload">
   <input type="hidden" name="command" value="scantron_configphase" />    <input type="hidden" name="command" value="scantron_configphase" />
Line 3344  SCANTRONFORM Line 4139  SCANTRONFORM
     $r->print($result);      $r->print($result);
   
     my @delayqueue;      my @delayqueue;
     my $totalcorrect;      my %completedstudents;
     my $totalincorrect;      
       my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Scantron Status',
     my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,       'Scantron Progress',$scanlines->{'count'});
            'Scantron Status','Scantron Progress',scalar(@scanlines));      &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,
     foreach my $line (@scanlines) {    'Processing first student');
  my $studentcorrect;      my $start=&Time::HiRes::time();
  my $studentincorrect;      my $i=-1;
       my ($uname,$udom);
  chomp($line);      while ($i<$scanlines->{'count'}) {
  my $scan_record=&scantron_parse_scanline($line,\%scantron_config);    ($uname,$udom)=('','');
  my ($uname,$udom);    $i++;
  if ($uname=&scantron_find_student($scan_record,\%idmap)) {    my $line=&scantron_get_line($scanlines,$i);
     &scantron_add_delay(\@delayqueue,$line,    if ($line=~/^[\s\cz]*$/) { next; }
  'Unable to find a student that matches');    my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,
  }    $scan_data);
  $r->print('<pre>doing studnet'.$uname.'</pre>');    unless ($uname=&scantron_find_student($scan_record,$scan_data,
  ($uname,$udom)=split(/:/,$uname);         \%idmap,$i)) {
  &Apache::lonnet::delenv('form.counter');       &scantron_add_delay(\@delayqueue,$line,
  &Apache::lonnet::appenv(%$scan_record);    'Unable to find a student that matches',1);
 #    &Apache::lonhomework::showhash(%ENV);       next;
     $Apache::lonxml::debug=1;    }
  &Apache::lonxml::debug("line is $line");    if (exists $completedstudents{$uname}) {
        &scantron_add_delay(\@delayqueue,$line,
     'Student '.$uname.' has multiple sheets',2);
        next;
     }
     ($uname,$udom)=split(/:/,$uname);
     &Apache::lonnet::delenv('form.counter');
     &Apache::lonnet::appenv(%$scan_record);
   
     my $i=0;   my $i=0;
  foreach my $resource (@resources) {   foreach my $resource (@resources) {
     $i++;      $i++;
     my $result=&Apache::lonnet::ssi($resource->src(),      my $result=&Apache::lonnet::ssi($resource->src(),
Line 3378  SCANTRONFORM Line 4180  SCANTRONFORM
   'grade_domain'  =>$udom,    'grade_domain'  =>$udom,
   'grade_courseid'=>$ENV{'request.course.id'},    'grade_courseid'=>$ENV{'request.course.id'},
   'grade_symb'    =>$resource->symb()));    'grade_symb'    =>$resource->symb()));
     my %score=&Apache::lonnet::restore($resource->symb(),  
        $ENV{'request.course.id'},  
        $udom,$uname);  
     foreach my $part ($resource->{PARTS}) {  
  if ($score{'resource.'.$part.'.solved'} =~ /^correct/) {  
     $studentcorrect++;  
     $totalcorrect++;  
  } else {  
     $studentincorrect++;  
     $totalincorrect++;  
  }  
     }  
     $r->print('<pre>'.  
       $resource->symb().'-'.  
       $resource->src().'-'.'</pre>result is'.$result);  
     &Apache::lonhomework::showhash(%score);  
  #    if ($i eq 3) {last;}  
  }   }
    $completedstudents{$uname}={'line'=>$line};
       } continue {
  &Apache::lonnet::delenv('form.counter');   &Apache::lonnet::delenv('form.counter');
  &Apache::lonnet::delenv('scantron\.');   &Apache::lonnet::delenv('scantron\.');
  &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,   &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
              'last student Who got a '.$studentcorrect.' correct and '.   'last student');
      $studentincorrect.' incorrect. The class has gotten '.  
              $totalcorrect.' correct and '.$totalincorrect.' incorrect');  
  last;  
  #FIXME  
  #get iterator for $sequence  
  #foreach question 'submit' the students answer to the server  
  #   through grade target {  
  #   generate data to pass back that includes grade recevied  
  #}  
     }  
     $Apache::lonxml::debug=0;  
     foreach my $delay (@delayqueue) {  
  #FIXME  
  #print out each delayed student with interface to select how  
  #  to repair student provided info  
  #Expected errors include  
  #  1 bad/no stuid/username  
  #  2 invalid bubblings  
   
     }      }
     #FIXME      &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
     # if delay queue exists 2 submits one to process delayed students one  #    my $lasttime = &Time::HiRes::time()-$start;
     #     to ignore delayed students, possibly saving the delay queue for later  #    $r->print("<p>took $lasttime</p>");
       
     $navmap->untieHashes();      $navmap->untieHashes();
       $r->print("</form><p>Done</p>");
       $r->print(&show_grading_menu_form($symb,$url));
       return '';
   }
   
   sub scantron_upload_scantron_data {
       my ($r)=@_;
       $r->print(&Apache::loncommon::coursebrowser_javascript($ENV{'request.role.domain'}));
       my $select_link=&Apache::loncommon::selectcourse_link('rules','courseid',
     'domainid');
       my $domsel=&Apache::loncommon::select_dom_form($ENV{'request.role.domain'},
      'domainid');
       my $default_form_data=&defaultFormData(&get_symb_and_url($r,1));
       $r->print(<<UPLOAD);
   <script type="text/javascript" language="javascript">
       function checkUpload(formname) {
    if (formname.upfile.value == "") {
       alert("Please use the browse button to select a file from your local directory.");
       return false;
    }
    formname.submit();
       }
   </script>
   
   <form enctype='multipart/form-data' action='/adm/grades' name='rules' method='post'>
   $default_form_data
   Course: <input name='courseid' type='text' />
   Domain: $domsel $select_link
   <br />
   <input name='command' value='scantronupload_save' type='hidden' />
   File to upload:<input type="file" name="upfile" size="50" />
   <br />
   <input type="button" onClick="javascript:checkUpload(this.form);" value="Upload Scantron Data" />
   </form>
   UPLOAD
       return '';
   }
   
   sub scantron_upload_scantron_data_save {
       my($r)=@_;
       if (!&Apache::lonnet::allowed('usc',$ENV{'form.domainid'}) &&
    !&Apache::lonnet::allowed('usc',
       $ENV{'form.domainid'}.'_'.$ENV{'form.courseid'})) {
    $r->print("You are not allowed to upload Scantron data to the requested course.<br />");
    $r->print(&show_grading_menu_form(&get_symb_and_url($r)));
    return '';
       }
       $r->print("Doing upload to ".$ENV{'form.courseid'}." <br />");
       my $home=&Apache::lonnet::homeserver($ENV{'form.courseid'},
    $ENV{'form.domainid'});
       my $fname=$ENV{'form.upfile.filename'};
       #FIXME
       #copied from lonnet::userfileupload()
       #make that function able to target a specified course
       # Replace Windows backslashes by forward slashes
       $fname=~s/\\/\//g;
       # Get rid of everything but the actual filename
       $fname=~s/^.*\/([^\/]+)$/$1/;
       # Replace spaces by underscores
       $fname=~s/\s+/\_/g;
       # Replace all other weird characters by nothing
       $fname=~s/[^\w\.\-]//g;
       # See if there is anything left
       unless ($fname) { return 'error: no uploaded file'; }
       $fname='scantron_orig_'.$fname;
       $r->print(&Apache::lonnet::finishuserfileupload($ENV{'form.courseid'},
       $ENV{'form.domainid'},
       $home,'upfile',$fname));
       my ($symb,$url)=&get_symb_and_url($r);
       if ($symb) {
    $r->print(&show_grading_menu_form(&get_symb_and_url($r)));
       } else {
    $r->print('<br /><form action="/adm/grades" method="post">'."\n".
     '<input type="hidden" name="command" value="scantronupload" />'."\n".
     '<input type="submit" name="submit" value="Do Another Upload" />'."\n".
     '</form>'."\n");
       }
       return '';
 }  }
   
   
 #-------- end of section for handling grading scantron forms -------  #-------- end of section for handling grading scantron forms -------
 #  #
 #-------------------------------------------------------------------  #-------------------------------------------------------------------
Line 3477  sub gradingmenu { Line 4325  sub gradingmenu {
  }   }
  formname.command.value = cmd;   formname.command.value = cmd;
  formname.saveState.value = "saveCmd="+cmdsave+":saveSec="+pullDownSelection(formname.section)+   formname.saveState.value = "saveCmd="+cmdsave+":saveSec="+pullDownSelection(formname.section)+
     ":saveSub="+radioSelection(formname.submitonly)+":saveStatus="+pullDownSelection(formname.Status);      ":saveSub="+pullDownSelection(formname.submitonly)+":saveStatus="+pullDownSelection(formname.Status);
  if (val < 5) formname.submit();   if (val < 5) formname.submit();
  if (val == 5) {   if (val == 5) {
     if (!checkReceiptNo(formname,'notOK')) { return false;}      if (!checkReceiptNo(formname,'notOK')) { return false;}
Line 3528  GRADINGMENUJS Line 4376  GRADINGMENUJS
   
     $result.='<table width="100%" border=0>';      $result.='<table width="100%" border=0>';
     $result.='<tr bgcolor="#ffffe6" valign="top"><td>'."\n".      $result.='<tr bgcolor="#ffffe6" valign="top"><td>'."\n".
  '&nbsp;Select Section: <select name="section">'."\n";   '&nbsp;'.&mt('Select Section').': <select name="section">'."\n";
     if (ref($sections)) {      if (ref($sections)) {
  foreach (sort (@$sections)) {$result.='<option value="'.$_.'" '.   foreach (sort (@$sections)) {
  ($saveSec eq $_ ? 'selected="on"' : '').'>'.$_.'</option>'."\n";}      $result.='<option value="'.$_.'" '.
    ($saveSec eq $_ ? 'selected="on"':'').'>'.$_.'</option>'."\n";
    }
     }      }
     $result.= '<option value="all" '.($saveSec eq 'all' ? 'selected="on"' : ''). '>all</select> &nbsp; ';      $result.= '<option value="all" '.($saveSec eq 'all' ? 'selected="on"' : ''). '>all</select> &nbsp; ';
   
     $result.='Student Status:</b>'.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,undef);      $result.=&mt('Student Status').':</b>'.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,undef);
   
     if (ref($sections)) {      if (ref($sections) && (grep /no/,@$sections)) {
  $result.='&nbsp;(Section "no" implies the students were not assigned a section.)<br />'    $result.='&nbsp;(Section "no" implies the students were not assigned a section.)<br />';
     if (grep /no/,@$sections);  
     }      }
     $result.='</td></tr>';      $result.='</td></tr>';
   
     $result.='<tr bgcolor="#ffffe6"valign="top"><td>'.      $result.='<tr bgcolor="#ffffe6"valign="top"><td>'.
  '<input type="radio" name="radioChoice" value="submission" '.   '<input type="radio" name="radioChoice" value="submission" '.
  ($saveCmd eq 'submission' ? 'checked' : '').'> '.'<b>Current Resource:</b> For one or more students'.   ($saveCmd eq 'submission' ? 'checked' : '').'> '.'<b>'.&mt('Current Resource').':</b> '.&mt('For one or more students').
  '<br />&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;-->For students with '.   ' <select name="submitonly">'.
  '<input type="radio" name="submitonly" value="yes" '.   '<option value="yes" '.
  ($saveSub eq 'yes' ? 'checked' : '').' /> submissions or '.   ($saveSub eq 'yes' ? 'selected="on"' : '').'>with submissions</option>'.
  '<input type="radio" name="submitonly" value="all" '.   '<option value="graded" '.
  ($saveSub eq 'all' ? 'checked' : '').' /> for all</td></tr>'."\n";   ($saveSub eq 'graded' ? 'selected="on"' : '').'>with ungraded submissions</option>'.
    '<option value="incorrect" '.
    ($saveSub eq 'incorrect' ? 'selected="on"' : '').'>with incorrect submissions</option>'.
    '<option value="all" '.
    ($saveSub eq 'all' ? 'selected="on"' : '').'>with any status</option></select></td></tr>'."\n";
   
     $result.='<tr bgcolor="#ffffe6"valign="top"><td>'.      $result.='<tr bgcolor="#ffffe6"valign="top"><td>'.
  '<input type="radio" name="radioChoice" value="viewgrades" '.   '<input type="radio" name="radioChoice" value="viewgrades" '.
Line 3563  GRADINGMENUJS Line 4416  GRADINGMENUJS
  'The <b>complete</b> set/page/sequence: For one student</td></tr>'."\n";   'The <b>complete</b> set/page/sequence: For one student</td></tr>'."\n";
   
     $result.='<tr bgcolor="#ffffe6"><td><br />'.      $result.='<tr bgcolor="#ffffe6"><td><br />'.
  '<input type="button" onClick="javascript:checkChoice(this.form,\'2\');" value="View/Grade/Regrade" />'.   '<input type="button" onClick="javascript:checkChoice(this.form,\'2\');" value="Next->" />'.
  '</td></tr></table>'."\n";   '</td></tr></table>'."\n";
   
     $result.='</td><td valign="top">';      $result.='</td><td valign="top">';
Line 3596  sub handler { Line 4449  sub handler {
   
     undef(%perm);      undef(%perm);
     if ($ENV{'browser.mathml'}) {      if ($ENV{'browser.mathml'}) {
  $request->content_type('text/xml');   &Apache::loncommon::content_type($request,'text/xml');
     } else {      } else {
  $request->content_type('text/html');   &Apache::loncommon::content_type($request,'text/html');
     }      }
     $request->send_http_header;      $request->send_http_header;
     return '' if $request->header_only;      return '' if $request->header_only;
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
     my $url=$ENV{'form.url'};      my $url=$ENV{'form.url'};
     my $symb=$ENV{'form.symb'};      my $symb=$ENV{'form.symb'};
     my $command=$ENV{'form.command'};      my @commands=&Apache::loncommon::get_env_multiple('form.command');
       my $command=$commands[0];
       if ($#commands > 0) {
    &Apache::lonnet::logthis("grades got multiple commands ".join(':',@commands));
       }
     if (!$url) {      if (!$url) {
  my ($temp1,$temp2);   my ($temp1,$temp2);
  ($temp1,$temp2,$ENV{'form.url'})=split(/___/,$symb);   ($temp1,$temp2,$ENV{'form.url'})=&Apache::lonnet::decode_symb($symb);
  $url = $ENV{'form.url'};   $url = $ENV{'form.url'};
     }      }
     &send_header($request);      &send_header($request);
     if ($url eq '' && $symb eq '') {      if ($url eq '' && $symb eq '' && $command eq '') {
  if ($ENV{'user.adv'}) {   if ($ENV{'user.adv'}) {
     if (($ENV{'form.codeone'}) && ($ENV{'form.codetwo'}) &&      if (($ENV{'form.codeone'}) && ($ENV{'form.codetwo'}) &&
  ($ENV{'form.codethree'})) {   ($ENV{'form.codethree'})) {
Line 3621  sub handler { Line 4478  sub handler {
  my ($tsymb,$tuname,$tudom,$tcrsid)=   my ($tsymb,$tuname,$tudom,$tcrsid)=
     &Apache::lonnet::checkin($token);      &Apache::lonnet::checkin($token);
  if ($tsymb) {   if ($tsymb) {
     my ($map,$id,$url)=split(/\_\_\_/,$tsymb);      my ($map,$id,$url)=&Apache::lonnet::decode_symb($tsymb);
     if (&Apache::lonnet::allowed('mgr',$tcrsid)) {      if (&Apache::lonnet::allowed('mgr',$tcrsid)) {
  $request->print(&Apache::lonnet::ssi_body('/res/'.$url,   $request->print(&Apache::lonnet::ssi_body('/res/'.$url,
   ('grade_username' => $tuname,    ('grade_username' => $tuname,
Line 3653  sub handler { Line 4510  sub handler {
  delete($perm{'mgr'});   delete($perm{'mgr'});
     }      }
  }   }
   
  if ($command eq 'submission' && $perm{'vgr'}) {   if ($command eq 'submission' && $perm{'vgr'}) {
     ($ENV{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0));      ($ENV{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0));
  } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {   } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {
Line 3693  sub handler { Line 4549  sub handler {
     }      }
  } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) {   } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) {
     $request->print(&scantron_selectphase($request));      $request->print(&scantron_selectphase($request));
     } elsif ($command eq 'scantron_validate' && $perm{'mgr'}) {
        $request->print(&scantron_validate_file($request));
    } elsif ($command eq 'scantron_validate' && $perm{'mgr'}) {
       $request->print(&scantron_validate_file($request));
  } elsif ($command eq 'scantron_process' && $perm{'mgr'}) {   } elsif ($command eq 'scantron_process' && $perm{'mgr'}) {
     $request->print(&scantron_process_students($request));      $request->print(&scantron_process_students($request));
     } elsif ($command eq 'scantronupload' && 
     (&Apache::lonnet::allowed('usc',$ENV{'request.role.domain'})||
     &Apache::lonnet::allowed('usc',$ENV{'request.course.id'}))) {
        $request->print(&scantron_upload_scantron_data($request)); 
     } elsif ($command eq 'scantronupload_save' &&
     (&Apache::lonnet::allowed('usc',$ENV{'request.role.domain'})||
     &Apache::lonnet::allowed('usc',$ENV{'request.course.id'}))) {
        $request->print(&scantron_upload_scantron_data_save($request));
     } elsif ($command eq 'scantrondownload' &&
    &Apache::lonnet::allowed('usc',$ENV{'request.course.id'})) {
        $request->print(&scantron_download_scantron_data($request));
  } elsif ($command) {   } elsif ($command) {
     $request->print("Access Denied");      $request->print("Access Denied ($command)");
  }   }
     }      }
     &send_footer($request);      &send_footer($request);
Line 3712  sub send_header { Line 4583  sub send_header {
 #remotewindow.close();  #remotewindow.close();
 #</script>");   #</script>"); 
     $request->print(&Apache::loncommon::bodytag('Grading'));      $request->print(&Apache::loncommon::bodytag('Grading'));
       $request->rflush();
 }  }
   
 sub send_footer {  sub send_footer {

Removed from v.1.125  
changed lines
  Added in v.1.179


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.