Diff for /loncom/homework/grades.pm between versions 1.82 and 1.112

version 1.82, 2003/04/01 05:21:48 version 1.112, 2003/07/11 20:22:43
Line 41  use Apache::style; Line 41  use Apache::style;
 use Apache::lonxml;  use Apache::lonxml;
 use Apache::lonnet;  use Apache::lonnet;
 use Apache::loncommon;  use Apache::loncommon;
   use Apache::lonhtmlcommon;
 use Apache::lonnavmaps;  use Apache::lonnavmaps;
 use Apache::lonhomework;  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 String::Similarity;
   
   my %oldessays=();
   my %perm=();
   
 # ----- These first few routines are general use routines.----  # ----- These first few routines are general use routines.----
 #  #
Line 125  sub getclasslist { Line 130  sub getclasslist {
  my (undef,undef,$end,$start,$id,$section,$fullname,$status)=   my (undef,undef,$end,$start,$id,$section,$fullname,$status)=
             @{$classlist->{$_}};              @{$classlist->{$_}};
  # filter students according to status selected   # filter students according to status selected
  if ($filterlist && $ENV{'form.status'} ne 'Any') {   if ($filterlist && $ENV{'form.Status'} ne 'Any') {
     if ($ENV{'form.status'} ne $status) {      if ($ENV{'form.Status'} ne $status) {
  delete ($classlist->{$_});   delete ($classlist->{$_});
  next;   next;
     }      }
  }   }
  $section = ($section ne '' ? $section : 'no');   $section = ($section ne '' ? $section : 'no');
  if ($getsec eq 'all' || $getsec eq $section) {   if (&canview($section)) {
             $sections{$section}++;      if ($getsec eq 'all' || $getsec eq $section) {
             $fullnames{$_}=$fullname;   $sections{$section}++;
         } else {   $fullnames{$_}=$fullname;
             delete($classlist->{$_});      } else {
         }   delete($classlist->{$_});
       }
    } else {
       delete($classlist->{$_});
    }
     }      }
     my %seen = ();      my %seen = ();
     my @sections = sort(keys(%sections));      my @sections = sort(keys(%sections));
     return ($classlist,\@sections,\%fullnames);      return ($classlist,\@sections,\%fullnames);
 }  }
   
 #find user domain  sub canmodify {
 sub finduser {      my ($sec)=@_;
     my ($name) = @_;      if ($perm{'mgr'}) {
     my $domain = '';   if (!defined($perm{'mgr_section'})) {
     if ( $Apache::grades::viewgrades eq 'F' ) {      # can modify whole class
  my %classlist=&Apache::lonnet::dump('classlist',      return 1;
     $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},   } else {
     $ENV{'course.'.$ENV{'request.course.id'}.'.num'});      if ($sec eq $perm{'mgr_section'}) {
  my (@fields) = grep /^$name:/, keys %classlist;   #can modify the requested section
  ($name, $domain) = split(/:/,$fields[0]);   return 1;
  return ($name,$domain);      } else {
     } else {   # can't modify the request section
  return ($ENV{'user.name'},$ENV{'user.domain'});   return 0;
       }
    }
     }      }
       #can't modify
       return 0;
 }  }
   
 #--- Prompts a user to enter a username.  sub canview {
 sub moreinfo {      my ($sec)=@_;
     my ($request,$reason) = @_;      if ($perm{'vgr'}) {
     $request->print("Unable to process request: $reason");   if (!defined($perm{'vgr_section'})) {
     if ( $Apache::grades::viewgrades eq 'F' ) {      # can modify whole class
  $request->print('<form action="/adm/grades" method="post">'."\n");      return 1;
  if ($ENV{'form.url'}) {   } else {
     $request->print('<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />'."\n");      if ($sec eq $perm{'vgr_section'}) {
  }   #can modify the requested section
  if ($ENV{'form.symb'}) {   return 1;
     $request->print('<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />'."\n");      } else {
  }   # can't modify the request section
  $request->print('<input type="hidden" name="command" value="'.$ENV{'form.command'}.'" />'."\n");   return 0;
  $request->print("Student:".'<input type="text" name="student" value="'.$ENV{'form.student'}.'" />'."<br />\n");      }
  $request->print("Domain:".'<input type="text" name="domain" value="'.$ENV{'user.domain'}.'" />'."<br />\n");   }
  $request->print('<input type="submit" name="submit" value="ReSubmit" />'."<br />\n");  
  $request->print('</form>');  
     }      }
     return '';      #can't modify
       return 0;
 }  }
   
 #--- Retrieve the grade status of a student for all the parts  #--- Retrieve the grade status of a student for all the parts
Line 221  sub jscriptNform { Line 233  sub jscriptNform {
 }  }
   
 #------------------ End of general use routines --------------------  #------------------ End of general use routines --------------------
   
   #
   # Find most similar essay
   #
   
   sub most_similar {
       my ($uname,$udom,$uessay)=@_;
   
   # ignore spaces and punctuation
   
       $uessay=~s/\W+/ /gs;
   
   # these will be returned. Do not care if not at least 50 percent similar
       my $limit=0.6;
       my $sname='';
       my $sdom='';
       my $scrsid='';
       my $sessay='';
   # go through all essays ...
       foreach my $tkey (keys %oldessays) {
    my ($tname,$tdom,$tcrsid)=split(/\./,$tkey);
   # ... except the same student
           if (($tname ne $uname) || ($tdom ne $udom)) {
       my $tessay=$oldessays{$tkey};
               $tessay=~s/\W+/ /gs;
   # String similarity gives up if not even limit
               my $tsimilar=&String::Similarity::similarity($uessay,$tessay,$limit);
   # Found one
               if ($tsimilar>$limit) {
    $limit=$tsimilar;
                   $sname=$tname;
                   $sdom=$tdom;
                   $scrsid=$tcrsid;
                   $sessay=$oldessays{$tkey};
               }
           } 
       }
       if ($limit>0.6) {
          return ($sname,$sdom,$scrsid,$sessay,$limit);
       } else {
          return ('','','','',0);
       }
   }
   
 #-------------------------------------------------------------------  #-------------------------------------------------------------------
   
 #------------------------------------ Receipt Verification Routines  #------------------------------------ Receipt Verification Routines
Line 312  sub listStudents { Line 368  sub listStudents {
   
     $request->print(<<LISTJAVASCRIPT);      $request->print(<<LISTJAVASCRIPT);
 <script type="text/javascript" language="javascript">  <script type="text/javascript" language="javascript">
   function checkSelect(checkBox) {      function checkSelect(checkBox) {
     var ctr=0;   var ctr=0;
     var sense="";   var sense="";
     if (checkBox.length > 1) {   if (checkBox.length > 1) {
        for (var i=0; i<checkBox.length; i++) {      for (var i=0; i<checkBox.length; i++) {
   if (checkBox[i].checked) {   if (checkBox[i].checked) {
      ctr++;      ctr++;
   }   }
        }      }
        sense = "a student or group of students";      sense = "a student or group of students";
     } else {   } else {
        if (checkBox.checked) {      if (checkBox.checked) {
    ctr = 1;   ctr = 1;
        }      }
        sense = "the student";      sense = "the student";
    }
    if (ctr == 0) {
       alert("Please select "+sense+" before clicking on the $viewgrade button.");
       return false;
    }
    document.gradesub.submit();
     }      }
     if (ctr == 0) {  
        alert("Please select "+sense+" before clicking on the $viewgrade button.");      function reLoadList(formname) {
        return false;   if (formname.saveStatusOld.value == pullDownSelection(formname.Status)) {return;}
    formname.command.value = 'submission';
    formname.submit();
       }
   
       function pullDownSelection(selectOne) {
    var selection="";
    if (selectOne.length > 1) {
       for (var i=0; i<selectOne.length; i++) {
    if (selectOne[i].selected) {
       return selectOne[i].value;
    }
       }
    } else {
       if (selectOne.selected) return selectOne.value;
    }
     }      }
     document.gradesub.submit();  
   }  
 </script>  </script>
 LISTJAVASCRIPT  LISTJAVASCRIPT
   
Line 350  LISTJAVASCRIPT Line 425  LISTJAVASCRIPT
     if ($ENV{'form.handgrade'} eq 'yes') {      if ($ENV{'form.handgrade'} eq 'yes') {
  $gradeTable.='<input type="radio" name="lastSub" value="hdgrade" '.$checkhdgrade.' /> handgrade only'."\n";   $gradeTable.='<input type="radio" name="lastSub" value="hdgrade" '.$checkhdgrade.' /> handgrade only'."\n";
     }      }
   
       my $saveStatus = $ENV{'form.Status'} eq '' ? 'Active' : $ENV{'form.Status'};
       $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 sub only'."\n".
  '<input type="radio" name="lastSub" value="last" /> last sub & parts info'."\n".   '<input type="radio" name="lastSub" value="last" /> last sub & parts info'."\n".
  '<input type="radio" name="lastSub" value="all" /> all details'."\n".   '<input type="radio" name="lastSub" value="all" /> all details'."\n".
Line 362  LISTJAVASCRIPT Line 441  LISTJAVASCRIPT
  '<input type="hidden" name="probTitle"   value="'.$ENV{'form.probTitle'}.'" />'."\n".   '<input type="hidden" name="probTitle"   value="'.$ENV{'form.probTitle'}.'" />'."\n".
  '<input type="hidden" name="url"  value="'.$url.'" />'."\n".   '<input type="hidden" name="url"  value="'.$url.'" />'."\n".
  '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".   '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
  'To '.lc($viewgrade).' a submission, click on the check box next to the student\'s name. Then '."\n".   '<input type="hidden" name="saveStatusOld" value="'.$saveStatus.'" />'."\n";
   
       $gradeTable.='<b>Student Status:</b> '.
    &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".
  'click on the '.$viewgrade.' button. To view the submissions for a group of students, click'."\n".   'click on the '.$viewgrade.' button. To view the submissions for a group of students, click'."\n".
  ' on the check boxes for the group of students.<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";
  '<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="'.$viewgrade.'" />'."\n";
    
     my (undef,undef,$fullname) = &getclasslist($getsec,$ENV{'form.showgrading'} eq 'yes' ? '1' : '0');      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">';
  '<td><b>&nbsp;Select&nbsp;</b></td><td><b>&nbsp;Fullname&nbsp;</b></td>'.      my $loop = 0;
  '<td><b>&nbsp;Username&nbsp;</b></td><td><b>&nbsp;Domain&nbsp;</b></td>';      while ($loop < 2) {
     foreach (sort(@$partlist)) {   $gradeTable.='<td><b>&nbsp;Select&nbsp;</b></td><td><b>&nbsp;Fullname&nbsp;</b>'.
  $gradeTable.='<td><b>&nbsp;Part '.(split(/_/))[0].' Status&nbsp;</b></td>';      '<font color="#999999">(Username)</font>&nbsp;</td>';
    if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
       foreach (sort(@$partlist)) {
    $gradeTable.='<td><b>&nbsp;Part '.(split(/_/))[0].' Status&nbsp;</b></td>';
       }
    }
    $loop++;
     }      }
     $gradeTable.='</tr>'."\n";      $gradeTable.='</tr>'."\n";
   
     my $ctr = 0;      my $ctr = 0;
     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);
  my (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist);   my %status = ();
  my $statusflg = '';   if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
  foreach (keys(%status)) {      (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist);
     $statusflg = 1 if ($status{$_} ne 'nothing');      my $statusflg = '';
     my ($foo,$partid,$foo1) = split(/\./,$_);      foreach (keys(%status)) {
     if ($status{'resource.'.$partid.'.submitted_by'} ne '') {   $statusflg = 1 if ($status{$_} ne 'nothing');
  $statusflg = '';   my ($foo,$partid,$foo1) = split(/\./,$_);
  $gradeTable.='<input type="hidden" name="'.   if ($status{'resource.'.$partid.'.submitted_by'} ne '') {
     $student.':submitted_by" value="'.      $statusflg = '';
     $status{'resource.'.$partid.'.submitted_by'}.'" />';      $gradeTable.='<input type="hidden" name="'.
    $student.':submitted_by" value="'.
    $status{'resource.'.$partid.'.submitted_by'}.'" />';
    }
     }      }
       next if ($statusflg eq '' && $submitonly eq 'yes');
  }   }
  next if ($statusflg eq '' && $submitonly eq 'yes');  
   
  $ctr++;   $ctr++;
  if ( $Apache::grades::viewgrades eq 'F' ) {   if ( $perm{'vgr'} eq 'F' ) {
     $gradeTable.='<tr bgcolor="#ffffe6">'.      $gradeTable.='<tr bgcolor="#ffffe6">' if ($ctr%2 ==1);
  '<td align="center"><input type=checkbox name="stuinfo" value="'.      $gradeTable.='<td align="center"><input type=checkbox name="stuinfo" value="'.
  $student.':'.$$fullname{$student}.'"></td>'."\n".   $student.':'.$$fullname{$student}.'&nbsp;"></td>'."\n".
  '<td>&nbsp;'.$$fullname{$student}.'&nbsp;</td>'."\n".   '<td>&nbsp;'.$$fullname{$student}.'&nbsp;'."\n".
  '<td>&nbsp;'.$uname.'&nbsp;</td>'."\n".   '<font color="#999999">('.$uname.')</font></td>'."\n";
  '<td align="middle">&nbsp;'.$udom.'&nbsp;</td>'."\n";  
           if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
     foreach (sort keys(%status)) {   foreach (sort keys(%status)) {
  next if (/^resource.*?submitted_by$/);      next if (/^resource.*?submitted_by$/);
  $gradeTable.='<td align="middle">&nbsp;'.$status{$_}.'&nbsp;</td>'."\n";      $gradeTable.='<td align="middle">&nbsp;'.$status{$_}.'&nbsp;</td>'."\n";
    }
     }      }
     $gradeTable.='</tr>'."\n";      $gradeTable.='</tr>'."\n" if ($ctr%2 ==0);
  }   }
     }      }
       if ($ctr%2 ==1) {
    $gradeTable.='<td>&nbsp;</td><td>&nbsp;</td>';
       if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
    foreach (@$partlist) {
       $gradeTable.='<td>&nbsp;</td>';
    }
       }
    $gradeTable.='</tr>';
       }
   
     $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="'.$viewgrade.'" /></form>'."\n";
     if ($ctr == 0) {      if ($ctr == 0) {
  $gradeTable='<br />&nbsp;<font color="red">'.   my $num_students=(scalar(keys(%$fullname)));
     'No submission found for this resource.</font><br />';   if ($num_students eq 0) {
       $gradeTable='<br />&nbsp;<font color="red">There are no students currently enrolled.</font>';
    } else {
       $gradeTable='<br />&nbsp;<font color="red">'.
    'No submissions found for this resource for any students. ('.$num_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 717  sub sub_page_kw_js { Line 826  sub sub_page_kw_js {
  height = 600;   height = 600;
  scrollbar = "yes";   scrollbar = "yes";
     }      }
 //    if (window.pWin) window.pWin.close();  //    if (window.pWin) {window.pWin.close(); window.pWin=null}
     pWin = window.open('', 'MessageCenter', 'toolbar=no,location=no,scrollbars='+scrollbar+',screenx=70,screeny=75,width=600,height='+height);      pWin = window.open('', 'MessageCenter', 'toolbar=no,location=no,scrollbars='+scrollbar+',screenx=70,screeny=75,width=600,height='+height);
     pWin.focus();      pWin.focus();
     pDoc = pWin.document;      pDoc = pWin.document;
Line 752  sub sub_page_kw_js { Line 861  sub sub_page_kw_js {
     pDoc.write("     includemsg = 1;");      pDoc.write("     includemsg = 1;");
     pDoc.write("  }");      pDoc.write("  }");
     pDoc.write("  imgformname = eval(\\"opener.document.SCORE.mailicon\\"+usrctr);");      pDoc.write("  imgformname = eval(\\"opener.document.SCORE.mailicon\\"+usrctr);");
     pDoc.write("  if (includemsg) {");      pDoc.write("  imgformname.src = \\"$iconpath/\\"+((includemsg) ? \\"mailto.gif\\" : \\"mailbkgrd.gif\\");");
     pDoc.write("     imgformname.src = \\"$iconpath/mailto.gif\\";");  
     pDoc.write("  } else {");  
     pDoc.write("     imgformname.src = \\"$iconpath/mailbkgrd.gif\\";");  
     pDoc.write("  }");  
     pDoc.write("  var includemsg = eval(\\"opener.document.SCORE.includemsg\\"+usrctr);");      pDoc.write("  var includemsg = eval(\\"opener.document.SCORE.includemsg\\"+usrctr);");
     pDoc.write("  includemsg.value = msgchk;");      pDoc.write("  includemsg.value = msgchk;");
   
Line 1002  sub submission { Line 1107  sub submission {
   
     (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 ($uname,$udom)     = ($ENV{'form.student'},$ENV{'form.userdom'});      my ($uname,$udom)     = ($ENV{'form.student'},$ENV{'form.userdom'});
     ($uname,$udom)        = &finduser($uname) if $udom eq '';      my $usec = &Apache::lonnet::getsection($udom,$uname,$ENV{'request.course.id'});
     $ENV{'form.fullname'} = &get_fullname ($uname,$udom) if $ENV{'form.fullname'} eq '';      $ENV{'form.fullname'} = &get_fullname ($uname,$udom) if $ENV{'form.fullname'} eq '';
   
     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 '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }
   
       if (!&canview($usec)) {
    $request->print('<font color="red">Unable to view requested student.('.$uname.$udom.$usec.$ENV{'request.course.id'}.')</font>');
    $request->print(&show_grading_menu_form($symb,$url));
    return;
       }
   
     my $last = ($ENV{'form.lastSub'} eq 'last' ? 'last' : '');      my $last = ($ENV{'form.lastSub'} eq 'last' ? 'last' : '');
   
     # header info      # header info
Line 1079  sub submission { Line 1191  sub submission {
  $request->print($prnmsg);   $request->print($prnmsg);
   
  if ($ENV{'form.handgrade'} eq 'yes' && $ENV{'form.showgrading'} eq 'yes') {   if ($ENV{'form.handgrade'} eq 'yes' && $ENV{'form.showgrading'} eq 'yes') {
   #
   # Print out the keyword options line
   #
     $request->print(<<KEYWORDS);      $request->print(<<KEYWORDS);
 &nbsp;<b>Keyword Options:</b>&nbsp;  &nbsp;<b>Keyword Options:</b>&nbsp;
 <a href="javascript:keywords(document.SCORE.keywords)"; TARGET=_self>List</a>&nbsp; &nbsp;  <a href="javascript:keywords(document.SCORE.keywords)"; TARGET=_self>List</a>&nbsp; &nbsp;
Line 1086  sub submission { Line 1201  sub submission {
  CLASS="page">Paste Selection to List</a>&nbsp; &nbsp;   CLASS="page">Paste Selection to List</a>&nbsp; &nbsp;
 <a href="javascript:kwhighlight()"; TARGET=_self>Highlight Attribute</a><br /><br />  <a href="javascript:kwhighlight()"; TARGET=_self>Highlight Attribute</a><br /><br />
 KEYWORDS  KEYWORDS
   #
   # Load the other essays for similarity check
   #
               my $essayurl=&Apache::lonnet::declutter($url);
       my ($adom,$aname,$apath)=($essayurl=~/^(\w+)\/(\w+)\/(.*)$/);
       $apath=&Apache::lonnet::escape($apath);
       $apath=~s/\W/\_/gs;
       %oldessays=&Apache::lonnet::dump('nohist_essay_'.$apath,$adom,$aname);
         }          }
     }      }
   
Line 1112  KEYWORDS Line 1235  KEYWORDS
     my @col_fullnames;      my @col_fullnames;
     my ($classlist,$fullname);      my ($classlist,$fullname);
     if ($ENV{'form.handgrade'} eq 'yes') {      if ($ENV{'form.handgrade'} eq 'yes') {
  my @col_list;  
  ($classlist,undef,$fullname) = &getclasslist('all','0');   ($classlist,undef,$fullname) = &getclasslist('all','0');
  for (keys (%$handgrade)) {   for (keys (%$handgrade)) {
     my $ncol = &Apache::lonnet::EXT('resource.'.$_.      my $ncol = &Apache::lonnet::EXT('resource.'.$_.
Line 1121  KEYWORDS Line 1243  KEYWORDS
     next if ($ncol <= 0);      next if ($ncol <= 0);
             s/\_/\./g;              s/\_/\./g;
             next if ($record{'resource.'.$_.'.collaborators'} eq '');              next if ($record{'resource.'.$_.'.collaborators'} eq '');
             my (@colList) = split(/,?\s+/,              my @goodcollaborators = ();
                                    $record{'resource.'.$_.'.collaborators'});              my @badcollaborators  = ();
             my @collaborators = ();      foreach (split(/,?\s+/,$record{'resource.'.$_.'.collaborators'})) { 
     foreach (@colList) { #pre-filter list - throw out submitter   $_ =~ s/[\$\^\(\)]//g;
    next if ($_ eq '');
  my ($co_name,$co_dom) = split /\@|:/,$_;   my ($co_name,$co_dom) = split /\@|:/,$_;
  $co_dom = $udom if (! defined($co_dom));   $co_dom = $udom if (! defined($co_dom) || $co_dom =~ /^domain$/i);
  next if ($co_name eq $uname && $co_dom eq $udom);   next if ($co_name eq $uname && $co_dom eq $udom);
  push @collaborators, $_;   # Doing this grep allows 'fuzzy' specification
    my @Matches = grep /^$co_name:$co_dom$/i,keys %$classlist;
    if (! scalar(@Matches)) {
       push @badcollaborators,$_;
    } else {
       push @goodcollaborators, @Matches;
    }
     }      }
             my (@badcollaborators);              if (scalar(@goodcollaborators) != 0) {
             if (scalar(@collaborators) != 0) {  
                 $result.='<b>Collaborators: </b>';                  $result.='<b>Collaborators: </b>';
                 foreach my $collaborator (@collaborators) {                  foreach (@goodcollaborators) {
                     my ($co_name,$co_dom) = split /\@|:/,$collaborator;      my ($lastname,$givenn) = split(/,/,$$fullname{$_});
                     $co_dom = $udom if (! defined($co_dom));      push @col_fullnames, $givenn.' '.$lastname;
                     # Doing this grep allows 'fuzzy' specification      $result.=$$fullname{$_}.'&nbsp; &nbsp; &nbsp;';
                     my @Matches = grep /^$co_name:$co_dom$/i,   }
                     keys %$classlist;  
     if (! scalar(@Matches)) {  
                         push @badcollaborators,':'.$collaborator.':';  
                         next;  
                     }  
                     push @col_list, @Matches;  
                     foreach (@Matches) {  
                         my ($lastname,$givenn) = split(/,/,$$fullname{$_});  
                         push @col_fullnames, $givenn.' '.$lastname;  
                         $result.=$$fullname{$_}.'&nbsp; &nbsp; &nbsp;';  
                     }  
                 }  
                 $result.='<br />'."\n";                  $result.='<br />'."\n";
                 if (scalar(@badcollaborators) > 0) {   $result.='<input type="hidden" name="collaborator'.$counter.
                     $result.='<table border="0"><tr bgcolor="#ffbbbb"><td>';      '" value="'.(join ':',@goodcollaborators).'" />'."\n";
                     $result.='This student has submitted ';      }
                     if (scalar(@badcollaborators) == 1) {      if (scalar(@badcollaborators) > 0) {
                         $result .= 'an invalid collaborator';   $result.='<table border="0"><tr bgcolor="#ffbbbb"><td>';
                     } else {   $result.='This student has submitted ';
                         $result .= 'invalid collaborators';   $result.=(scalar(@badcollaborators) == 1) ? 'an invalid collaborator' : 'invalid collaborators';
                     }   $result .= ': '.join(', ',@badcollaborators);
                     $result .= ': '.join(', ',@badcollaborators);   $result .= '</td></tr></table>';
     $result .= '</td></tr></table>';                       }         
                 }      if (scalar(@badcollaborators > $ncol)) {
                 if (scalar(@collaborators > $ncol)) {   $result .= '<table border="0"><tr bgcolor="#ffbbbb"><td>';
                     $result .= '<table border="0"><tr bgcolor="#ffbbbb"><td>';   $result .= 'This student has submitted too many '.
                     $result .= 'This student has submitted too many '.      'collaborators.  Maximum is '.$ncol.'.';
                         'collaborators.  Maximum is '.$ncol;   $result .= '</td></tr></table>';
                     $result .= '</td></tr></table>';      }
                 }  
                 $result.='<input type="hidden" name="collaborator'.$counter.  
                     '" value="'.(join ':',@col_list).'" />'."\n";  
             }  
  }   }
     }      }
     $request->print($result."\n");      $request->print($result."\n");
Line 1201  KEYWORDS Line 1313  KEYWORDS
     } else {      } else {
  for my $part (sort keys(%$handgrade)) {   for my $part (sort keys(%$handgrade)) {
     foreach (@$string) {      foreach (@$string) {
  my ($partid,$respid) = /^resource\.(\d+)\.(\d+)\.submission/;   my ($partid,$respid) = /^resource\.(\w+)\.(\w+)\.submission/;
  if ($part eq ($partid.'_'.$respid)) {   if ($part eq ($partid.'_'.$respid)) {
     my ($ressub,$subval) = split(/:/,$_,2);      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 '.      $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;'.
Line 1211  KEYWORDS Line 1332  KEYWORDS
                                 '<a href="'.                                  '<a href="'.
                                 &Apache::lonnet::tokenwrapper($record{"resource.$partid.$respid.uploadedurl"}).                                  &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 />':'').     '"><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>Answer: </b>'.                                  '<b>Answer: </b><blockquote>'.
  &keywords_highlight($subval).'</td></tr>'."\n"   &keywords_highlight($subval).'</blockquote><br />&nbsp;'.$similar.'</td></tr>'."\n"
  if ($ENV{'form.lastSub'} eq 'lastonly' ||    if ($ENV{'form.lastSub'} eq 'lastonly' || 
     ($ENV{'form.lastSub'} eq 'hdgrade' &&       ($ENV{'form.lastSub'} eq 'hdgrade' && 
      $$handgrade{$part} =~ /:yes$/));       $$handgrade{$part} =~ /:yes$/));
Line 1231  KEYWORDS Line 1352  KEYWORDS
     }      }
           
     # return if view submission with no grading option      # return if view submission with no grading option
     if ($ENV{'form.showgrading'} eq '') {      if ($ENV{'form.showgrading'} eq '' || (!&canmodify($usec))) {
  $request->print('</td></tr></table></td></tr></table></form>'."\n");   $request->print('</td></tr></table></td></tr></table></form>'."\n");
  $request->print(&show_grading_menu_form($symb,$url))    $request->print(&show_grading_menu_form($symb,$url)) 
     if (($ENV{'form.command'} eq 'submission') ||       if (($ENV{'form.command'} eq 'submission') || 
Line 1250  KEYWORDS Line 1371  KEYWORDS
  my $lastone = pop @col_fullnames;   my $lastone = pop @col_fullnames;
  $msgfor .= ', '.(join ', ',@col_fullnames).' and '.$lastone.'.';   $msgfor .= ', '.(join ', ',@col_fullnames).' and '.$lastone.'.';
     }      }
       $msgfor =~ s/\'/\\'/g; #' stupid emacs - no! javascript
     $result.='<tr><td bgcolor="#ffffff">'."\n".      $result.='<tr><td bgcolor="#ffffff">'."\n".
  '&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.   '&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.
  ',\''.$msgfor.'\')"; TARGET=_self>'.   ',\''.$msgfor.'\')"; TARGET=_self>'.
Line 1374  sub processHandGrade { Line 1496  sub processHandGrade {
  $ctr++;   $ctr++;
  next;   next;
     }      }
       if ($errorflag eq 'not_allowed') {
    $request->print("<font color=\"red\">Not allowed to modify grades for $uname:$udom</font>");
    $ctr++;
    next;
       }
     my $includemsg = $ENV{'form.includemsg'.$ctr};      my $includemsg = $ENV{'form.includemsg'.$ctr};
     my ($subject,$message,$msgstatus) = ('','','');      my ($subject,$message,$msgstatus) = ('','','');
     if ($includemsg =~ /savemsg|newmsg\Q$ctr\E/) {      if ($includemsg =~ /savemsg|newmsg\Q$ctr\E/) {
Line 1393  sub processHandGrade { Line 1520  sub processHandGrade {
     if ($ENV{'form.collaborator'.$ctr}) {      if ($ENV{'form.collaborator'.$ctr}) {
  my (@collaborators) = split(/:/,$ENV{'form.collaborator'.$ctr});   my (@collaborators) = split(/:/,$ENV{'form.collaborator'.$ctr});
  foreach (@collaborators) {   foreach (@collaborators) {
     &saveHandGrade($request,$url,$symb,$_,$udom,$ctr,      my ($errorflag,$pts,$wgt) = &saveHandGrade($request,$url,$symb,$_,$udom,$ctr,$ENV{'form.unamedom'.$ctr});
    $ENV{'form.unamedom'.$ctr});      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 1447  sub processHandGrade { Line 1578  sub processHandGrade {
  $ENV{'course.'.$ENV{'request.course.id'}.'.num'});   $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
   
     # Called by Save & Refresh from Highlight Attribute Window      # Called by Save & Refresh from Highlight Attribute Window
       my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'0');
     if ($ENV{'form.refresh'} eq 'on') {      if ($ENV{'form.refresh'} eq 'on') {
  my $ctr = 0;   my ($ctr,$total) = (0,0);
  $ENV{'form.NTSTU'}=$ngrade;  
  while ($ctr < $ngrade) {   while ($ctr < $ngrade) {
     ($ENV{'form.student'},$ENV{'form.userdom'}) = split(/:/,$ENV{'form.unamedom'.$ctr});      $total++ if  $ENV{'form.unamedom'.$ctr} ne '';
     &submission($request,$ctr,$ngrade-1);      $ctr++;
    }
    $ENV{'form.NTSTU'}=$ngrade;
    $ctr = 0;
    while ($ctr < $total) {
       my $processUser = $ENV{'form.unamedom'.$ctr};
       ($ENV{'form.student'},$ENV{'form.userdom'}) = split(/:/,$processUser);
       $ENV{'form.fullname'} = $$fullname{$processUser};
       &submission($request,$ctr,$total-1);
     $ctr++;      $ctr++;
  }   }
  return '';   return '';
Line 1468  sub processHandGrade { Line 1607  sub processHandGrade {
  $laststu = $firststu if ($ctr > $ngrade);   $laststu = $firststu if ($ctr > $ngrade);
     }      }
   
     my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'0');  
     my (@parsedlist,@nextlist);      my (@parsedlist,@nextlist);
     my ($nextflg) = 0;      my ($nextflg) = 0;
     foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {      foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {
Line 1524  sub processHandGrade { Line 1662  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) = @_;
       my $usec = &Apache::lonnet::getsection($domain,$stuname,
      $ENV{'request.course.id'});
       if (!&canmodify($usec)) { return('not_allowed'); }
     my %record     = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$domain,$stuname);      my %record     = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$domain,$stuname);
     my %newrecord  = ();      my %newrecord  = ();
     my ($pts,$wgt) = ('','');      my ($pts,$wgt) = ('','');
Line 1581  sub viewgrades_js { Line 1722  sub viewgrades_js {
  var textbox = eval("document.classgrade.TEXTVAL_"+partid);   var textbox = eval("document.classgrade.TEXTVAL_"+partid);
  if (point == "textval") {   if (point == "textval") {
     var point = eval("document.classgrade.TEXTVAL_"+partid+".value");      var point = eval("document.classgrade.TEXTVAL_"+partid+".value");
     if (isNaN(point) || point < 0) {      if (isNaN(point) || parseFloat(point) < 0) {
  alert("A number equal or greater than 0 is expected. Entered value = "+point);   alert("A number equal or greater than 0 is expected. Entered value = "+parseFloat(point));
  var resetbox = false;   var resetbox = false;
  for (var i=0; i<radioButton.length; i++) {   for (var i=0; i<radioButton.length; i++) {
     if (radioButton[i].checked) {      if (radioButton[i].checked) {
Line 1595  sub viewgrades_js { Line 1736  sub viewgrades_js {
  }   }
  return;   return;
     }      }
     if (point > weight) {      if (parseFloat(point) > parseFloat(weight)) {
  var resp = confirm("You entered a value ("+point+   var resp = confirm("You entered a value ("+parseFloat(point)+
    ") greater than the weight for the part. Accept?");     ") greater than the weight for the part. Accept?");
  if (resp == false) {   if (resp == false) {
     textbox.value = "";      textbox.value = "";
Line 1605  sub viewgrades_js { Line 1746  sub viewgrades_js {
     }      }
     for (var i=0; i<radioButton.length; i++) {      for (var i=0; i<radioButton.length; i++) {
  radioButton[i].checked=false;   radioButton[i].checked=false;
  if (point == i) {   if (parseFloat(point) == i) {
     radioButton[i].checked=true;      radioButton[i].checked=true;
  }   }
     }      }
Line 1679  sub viewgrades_js { Line 1820  sub viewgrades_js {
  var point  = textbox.value;   var point  = textbox.value;
  var weight = eval("document.classgrade.weight_"+partid+".value");   var weight = eval("document.classgrade.weight_"+partid+".value");
   
  if (isNaN(point) || point < 0) {   if (isNaN(point) || parseFloat(point) < 0) {
     alert("A number equal or greater than 0 is expected. Entered value = "+point);      alert("A number equal or greater than 0 is expected. Entered value = "+parseFloat(point));
     textbox.value = "";      textbox.value = "";
     return;      return;
  }   }
  if (point > weight) {   if (parseFloat(point) > parseFloat(weight)) {
     var resp = confirm("You entered a value ("+point+      var resp = confirm("You entered a value ("+parseFloat(point)+
        ") greater than the weight of the part. Accept?");         ") greater than the weight of the part. Accept?");
     if (resp == false) {      if (resp == false) {
  textbox.value = "";   textbox.value = "";
Line 1816  sub viewgrades { Line 1957  sub viewgrades {
     $result.='</table>'.'</td></tr></table>'.'</td></tr></table>'."\n".      $result.='</table>'.'</td></tr></table>'.'</td></tr></table>'."\n".
  '<input type="hidden" name="totalparts" value="'.$ctsparts.'" />';   '<input type="hidden" name="totalparts" value="'.$ctsparts.'" />';
     $result.='<input type="button" value="Reset" '.      $result.='<input type="button" value="Reset" '.
  'onClick="javascript:resetEntry('.$ctsparts.');" TARGET=_self> &nbsp; &nbsp;';   'onClick="javascript:resetEntry('.$ctsparts.');" TARGET=_self>';
     $result.='<input type="button" value="Submit Changes" '.  #    $result.=' &nbsp; &nbsp;<input type="button" value="Submit Changes" name="subButton1'.
  'onClick="javascript:submit();" TARGET=_self />'."\n";  # 'onClick="javascript:submit();" TARGET=_self />'."\n";
   
     #table listing all the students in a section/class      #table listing all the students in a section/class
     #header of table      #header of table
Line 1832  sub viewgrades { Line 1973  sub viewgrades {
     }      }
     $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><b>Fullname</b></td><td><b>Username</b></td><td><b>Domain</b></td>'."\n";   '<td><b>Fullname</b> <font color="#999999">(Username)</font></td>'."\n";
     my (@parts) = sort(&getpartlist($url));      my (@parts) = sort(&getpartlist($url));
     foreach my $part (@parts) {      foreach my $part (@parts) {
  my $display=&Apache::lonnet::metadata($url,$part.'.display');   my $display=&Apache::lonnet::metadata($url,$part.'.display');
Line 1853  sub viewgrades { Line 1994  sub viewgrades {
     my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'1');      my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'1');
     my $ctr = 0;      my $ctr = 0;
     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 = $_;
    $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'},   $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},
    $_,$$fullname{$_},\@parts,\%weight);     $_,$$fullname{$_},\@parts,\%weight);
Line 1863  sub viewgrades { Line 2005  sub viewgrades {
     $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="Submit Changes" '.
  'onClick="javascript:submit();" TARGET=_self /></form>'."\n";   'onClick="javascript:submit();" TARGET=_self /></form>'."\n";
       if (scalar(%$fullname) eq 0) {
    my $colspan=3+scalar(@parts);
    $result='<font color="red">There are no students in section "'.$ENV{'form.section'}.'" with enrollment status "'.$ENV{'form.Status'}.'" to modify or grade.</font>';
       }
     $result.=&show_grading_menu_form($symb,$url);      $result.=&show_grading_menu_form($symb,$url);
     return $result;      return $result;
 }  }
Line 1871  sub viewgrades { Line 2017  sub viewgrades {
 sub viewstudentgrade {  sub viewstudentgrade {
     my ($url,$symb,$courseid,$student,$fullname,$parts,$weight) = @_;      my ($url,$symb,$courseid,$student,$fullname,$parts,$weight) = @_;
     my ($uname,$udom) = split(/:/,$student);      my ($uname,$udom) = split(/:/,$student);
       $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>'.
  '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.   '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.
  '\')"; TARGET=_self>'.$fullname.'</a>'.   '\')"; TARGET=_self>'.$fullname.'</a> '.
  '</td><td>'.$uname.'</td><td align="middle">'.$udom.'</td>'."\n";   '<font color="#999999">('.$uname.($ENV{'user.domain'} eq $udom ? '' : ':'.$udom).')</font></td>'."\n";
     foreach my $apart (@$parts) {      foreach my $apart (@$parts) {
  my ($part,$type) = &split_part_type($apart);   my ($part,$type) = &split_part_type($apart);
  my $score=$record{"resource.$part.$type"};   my $score=$record{"resource.$part.$type"};
  if ($type eq 'awarded') {   if ($type eq 'awarded') {
     my $pts = $score eq '' ? '' : $score*$$weight{$part};      my $pts = $score eq '' ? '' : $score*$$weight{$part};
     $result.='<input type="hidden" name="'.      $result.='<input type="hidden" name="'.
  'GD_'.$uname.'_'.$part.'_awarded_s" value="'.$pts.'" />'."\n";   'GD_'.$student.'_'.$part.'_awarded_s" value="'.$pts.'" />'."\n";
     $result.='<td align="middle"><input type="text" name="'.      $result.='<td align="middle"><input type="text" name="'.
  'GD_'.$uname.'_'.$part.'_awarded" '.   'GD_'.$student.'_'.$part.'_awarded" '.
  'onChange="javascript:changeSelect(\''.$part.'\',\''.$uname.   'onChange="javascript:changeSelect(\''.$part.'\',\''.$student.
  '\')" value="'.$pts.'" size="4" /></td>'."\n";   '\')" value="'.$pts.'" size="4" /></td>'."\n";
  } elsif ($type eq 'solved') {   } elsif ($type eq 'solved') {
     my ($status,$foo)=split(/_/,$score,2);      my ($status,$foo)=split(/_/,$score,2);
     $status = 'nothing' if ($status eq '');      $status = 'nothing' if ($status eq '');
     $result.='<input type="hidden" name="'.'GD_'.$uname.'_'.      $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"><select name="'.
  'GD_'.$uname.'_'.$part.'_solved" '.   'GD_'.$student.'_'.$part.'_solved" '.
  'onChange="javascript:changeOneScore(\''.$part.'\',\''.$uname.'\')" >'."\n";   'onChange="javascript:changeOneScore(\''.$part.'\',\''.$student.'\')" >'."\n";
     my $optsel = '<option selected="on"> </option><option>excused</option>'."\n";      my $optsel = '<option selected="on"> </option><option>excused</option>'."\n";
     $optsel = '<option> </option><option selected="on">excused</option>'."\n"      $optsel = '<option> </option><option selected="on">excused</option>'."\n"
  if ($status eq 'excused');   if ($status eq 'excused');
Line 1902  sub viewstudentgrade { Line 2049  sub viewstudentgrade {
     $result.="</select></td>\n";      $result.="</select></td>\n";
  } else {   } else {
     $result.='<input type="hidden" name="'.      $result.='<input type="hidden" name="'.
  'GD_'.$uname.'_'.$part.'_'.$type.'_s" value="'.$score.'" />'.   'GD_'.$student.'_'.$part.'_'.$type.'_s" value="'.$score.'" />'.
     "\n";      "\n";
     $result.='<td align="middle"><input type="text" name="'.      $result.='<td align="middle"><input type="text" name="'.
  'GD_'.$uname.'_'.$part.'_'.$type.'" '.   'GD_'.$student.'_'.$part.'_'.$type.'" '.
  'value="'.$score.'" size="4" /></td>'."\n";   'value="'.$score.'" size="4" /></td>'."\n";
  }   }
     }      }
Line 1925  sub editgrades { Line 2072  sub editgrades {
     $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>Fullname</b></td>'."\n";   '<td rowspan=2><b>Username</b></td><td rowspan=2><b>Domain</b></td><td rowspan=2><b>Fullname</b></td>'."\n";
   
     my %scoreptr = (      my %scoreptr = (
     'correct'  =>'correct_by_override',      'correct'  =>'correct_by_override',
Line 1973  sub editgrades { Line 2120  sub editgrades {
     $result .= '</tr><tr bgcolor="#deffff">';      $result .= '</tr><tr bgcolor="#deffff">';
     $result .= $header;      $result .= $header;
     $result .= '</tr>'."\n";      $result .= '</tr>'."\n";
       my $noupdate;
     for ($i=0; $i<$ENV{'form.total'}; $i++) {      for ($i=0; $i<$ENV{'form.total'}; $i++) {
    my $line;
  my $user = $ENV{'form.ctr'.$i};   my $user = $ENV{'form.ctr'.$i};
    my $usercolon = $user;
    $usercolon =~s/_/:/;
    my ($uname,$udom)=split(/_/,$user);
  my %newrecord;   my %newrecord;
  my $updateflag = 0;   my $updateflag = 0;
  my @userdom = grep /^$user:/,keys %$classlist;   $line .= '<tr bgcolor="#ffffde"><td>'.$uname.'&nbsp;</td><td>'.
  my (undef,$udom) = split(/:/,$userdom[0]);      $udom.'&nbsp;</td><td>'.
    $$fullname{$usercolon}.'&nbsp;</td>';
  $result .= '<tr bgcolor="#ffffde"><td>'.$user.'&nbsp;</td><td>'.   my $usec=$classlist->{"$uname:$udom"}[5];
     $$fullname{$userdom[0]}.'&nbsp;</td>';   if (!&canmodify($usec)) {
       my $numcols=scalar(@partid)*(scalar(@parts)-1)*2;
       $noupdate.=$line."<td colspan=\"$numcols\"><font color=\"red\">Not allowed to modify student</font></td></tr>";
       next;
    }
  foreach (@partid) {   foreach (@partid) {
     my $old_aw    = $ENV{'form.GD_'.$user.'_'.$_.'_awarded_s'};      my $old_aw    = $ENV{'form.GD_'.$user.'_'.$_.'_awarded_s'};
     my $old_part_pcr = $old_aw/($weight{$_} ne '0' ? $weight{$_}:1);      my $old_part_pcr = $old_aw/($weight{$_} ne '0' ? $weight{$_}:1);
Line 2002  sub editgrades { Line 2157  sub editgrades {
     }      }
     $score = 'excused' if (($ENV{'form.GD_'.$user.'_'.$_.'_solved'} eq 'excused') &&      $score = 'excused' if (($ENV{'form.GD_'.$user.'_'.$_.'_solved'} eq 'excused') &&
    ($score ne 'excused'));     ($score ne 'excused'));
     $result .= '<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>';
   
Line 2025  sub editgrades { Line 2180  sub editgrades {
     $newrecord{'resource.'.$part.'regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";      $newrecord{'resource.'.$part.'regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
     $updateflag=1;      $updateflag=1;
  }   }
  $result .= '<td align="center">'.$old_aw.'&nbsp;</td>'.   $line .= '<td align="center">'.$old_aw.'&nbsp;</td>'.
     '<td align="center">'.$awarded.'&nbsp;</td>';      '<td align="center">'.$awarded.'&nbsp;</td>';
     }      }
  }   }
  $result .= '</tr>'."\n";   $line.='</tr>'."\n";
  if ($updateflag) {   if ($updateflag) {
     $count++;      $count++;
     &Apache::lonnet::cstore(\%newrecord,$symb,$ENV{'request.course.id'},      &Apache::lonnet::cstore(\%newrecord,$symb,$ENV{'request.course.id'},
     $udom,$user);      $udom,$uname);
       $result.=$line;
    } else {
       $noupdate.=$line;
  }   }
     }      }
       if ($noupdate) {
    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;
       }
     $result .= '</table></td></tr></table>'."\n".      $result .= '</table></td></tr></table>'."\n".
  &show_grading_menu_form ($symb,$url);   &show_grading_menu_form ($symb,$url);
     my $msg = '<b>Number of records updated = '.$rec_update.      my $msg = '<b>Number of records updated = '.$rec_update.
Line 2214  sub csvuploadmap_footer { Line 2376  sub csvuploadmap_footer {
 ENDPICK  ENDPICK
 }  }
   
   sub upcsvScores_form {
       my ($request) = shift;
       my ($symb,$url)=&get_symb_and_url($request);
       if (!$symb) {return '';}
       my $result =<<CSVFORMJS;
   <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>
   CSVFORMJS
       $ENV{'form.probTitle'} = &Apache::lonnet::gettitle($symb);
       $result.='<br /><table width=100% border=0><tr><td bgcolor="#777777">'."\n";
       $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";
       $result.='&nbsp;<b>Specify a file containing the class scores for problem - '.$ENV{'form.probTitle'}.
    '.</b></td></tr>'."\n";
       $result.='<tr bgcolor=#ffffe6><td>'."\n";
       my $upfile_select=&Apache::loncommon::upfile_select_html();
       $result.=<<ENDUPFORM;
   <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
   <input type="hidden" name="symb" value="$symb" />
   <input type="hidden" name="url" value="$url" />
   <input type="hidden" name="command" value="csvuploadmap" />
   <input type="hidden" name="probTitle" value="$ENV{'form.probTitle'}" />
   <input type="hidden" name="saveState"  value="$ENV{'form.saveState'}" />
   $upfile_select
   <br /><input type="button" onClick="javascript:checkUpload(this.form);" value="Upload Scores" />
   
   </form>
   ENDUPFORM
       $result.='</td></tr></table>'."\n";
       $result.='</td></tr></table><br /><br />'."\n";
       $result.=&show_grading_menu_form($symb,$url);
   
       return $result;
   }
   
   
 sub csvuploadmap {  sub csvuploadmap {
     my ($request)= @_;      my ($request)= @_;
     my ($symb,$url)=&get_symb_and_url($request);      my ($symb,$url)=&get_symb_and_url($request);
Line 2273  sub csvuploadassign { Line 2477  sub csvuploadassign {
     }      }
     $request->print('<h3>Assigning Grades</h3>');      $request->print('<h3>Assigning Grades</h3>');
     my $courseid=$ENV{'request.course.id'};      my $courseid=$ENV{'request.course.id'};
     my ($classlist) = &getclasslist('all','1');      my ($classlist) = &getclasslist('all',0);
       my @notallowed;
     my @skipped;      my @skipped;
     my $countdone=0;      my $countdone=0;
     foreach my $grade (@gradedata) {      foreach my $grade (@gradedata) {
Line 2284  sub csvuploadassign { Line 2489  sub csvuploadassign {
     push(@skipped,"$username:$domain");      push(@skipped,"$username:$domain");
     next;      next;
  }   }
    my $usec=$classlist->{"$username:$domain"}[5];
    if (!&canmodify($usec)) {
       push(@notallowed,"$username:$domain");
       next;
    }
  my %grades;   my %grades;
  foreach my $dest (keys(%fields)) {   foreach my $dest (keys(%fields)) {
     if ($dest eq 'username' || $dest eq 'domain') { next; }      if ($dest eq 'username' || $dest eq 'domain') { next; }
Line 2302  sub csvuploadassign { Line 2512  sub csvuploadassign {
     }      }
     $request->print("<br />Stored $countdone students\n");      $request->print("<br />Stored $countdone students\n");
     if (@skipped) {      if (@skipped) {
  $request->print('<br /><font size="+1"><b>Skipped Students</b></font><br />');   $request->print('<p<font size="+1"><b>Skipped Students</b></font></p>');
  foreach my $student (@skipped) { $request->print("<br />$student"); }   foreach my $student (@skipped) { $request->print("$student<br />\n"); }
       }
       if (@notallowed) {
    $request->print('<p><font size="+1" color="red"><b>Students Not Allowed to Modify</b></font></p>');
    foreach my $student (@notallowed) { $request->print("$student<br />\n"); }
     }      }
     $request->print(&view_edit_entire_class_form($symb,$url));      $request->print("<br />\n");
     $request->print(&show_grading_menu_form($symb,$url));      $request->print(&show_grading_menu_form($symb,$url));
     return '';      return '';
 }  }
Line 2402  LISTJAVASCRIPT Line 2616  LISTJAVASCRIPT
  '<input type="radio" name="lastSub" value="all" /> all details'."\n";   '<input type="radio" name="lastSub" value="all" /> all details'."\n";
   
     $result.='<input type="hidden" name="section"     value="'.$getsec.'" />'."\n".      $result.='<input type="hidden" name="section"     value="'.$getsec.'" />'."\n".
    '<input type="hidden" name="Status"     value="'.$ENV{'form.Status'}.'" />'."\n".
  '<input type="hidden" name="command" value="displayPage" />'."\n".   '<input type="hidden" name="command" value="displayPage" />'."\n".
  '<input type="hidden" name="url"     value="'.$url.'" />'."\n".   '<input type="hidden" name="url"     value="'.$url.'" />'."\n".
  '<input type="hidden" name="symb"    value="'.$symb.'" />'."\n".   '<input type="hidden" name="symb"    value="'.$symb.'" />'."\n".
Line 2476  sub getSymbMap { Line 2691  sub getSymbMap {
     my $countProblems = 0;      my $countProblems = 0;
     $mapiterator->next(); # skip the first BEGIN_MAP      $mapiterator->next(); # skip the first BEGIN_MAP
     my $mapcurRes = $mapiterator->next(); # for "current resource"      my $mapcurRes = $mapiterator->next(); # for "current resource"
     my $ctr=0;      while ($mapdepth > 0) {
     while ($mapdepth > 0 && $ctr < 100) {  
  if($mapcurRes == $mapiterator->BEGIN_MAP) { $mapdepth++; }   if($mapcurRes == $mapiterator->BEGIN_MAP) { $mapdepth++; }
  if($mapcurRes == $mapiterator->END_MAP) { $mapdepth++; }   if($mapcurRes == $mapiterator->END_MAP) { $mapdepth--; }
   
  if (ref($mapcurRes) && $mapcurRes->is_problem() && !$mapcurRes->randomout) {   if (ref($mapcurRes) && $mapcurRes->is_problem() && !$mapcurRes->randomout) {
     $countProblems++;      $countProblems++;
  }   }
  $ctr++;   $mapcurRes = $mapiterator->next();
     }      }
     if ($countProblems > 0) {      if ($countProblems > 0) {
  my $title = $curRes->compTitle();   my $title = $curRes->compTitle();
Line 2510  sub displayPage { Line 2724  sub displayPage {
     my $cnum      = $ENV{"course.$ENV{'request.course.id'}.num"};      my $cnum      = $ENV{"course.$ENV{'request.course.id'}.num"};
     my $getsec    = $ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'};      my $getsec    = $ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'};
     my $pageTitle = $ENV{'form.page'};      my $pageTitle = $ENV{'form.page'};
     my (undef,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];
       if (!&canview($usec)) {
    $request->print('<font color="red">Unable to view requested student.('.$ENV{'form.student'}.')</font>');
    $request->print(&show_grading_menu_form($symb,$url));
    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: '.$$fullname{$ENV{'form.student'}}.
  '<font color="#999999"> ('.$uname.($udom eq $cdom ? '':':'.$udom).')</font></h3>'."\n";   '<font color="#999999"> ('.$uname.($udom eq $cdom ? '':':'.$udom).')</font></h3>'."\n";
Line 2547  sub displayPage { Line 2766  sub displayPage {
  '<td align="center"><b>&nbsp;No&nbsp;</b></td>'.   '<td align="center"><b>&nbsp;No&nbsp;</b></td>'.
  '<td><b>&nbsp;'.($ENV{'form.vProb'} eq 'no' ? 'Title' : 'Problem View').'/Grade</b></td></tr>';   '<td><b>&nbsp;'.($ENV{'form.vProb'} eq 'no' ? 'Title' : 'Problem View').'/Grade</b></td></tr>';
   
     my ($depth,$ctr,$question) = (1,0,1);      my ($depth,$question) = (1,1);
     $iterator->next(); # skip the first BEGIN_MAP      $iterator->next(); # skip the first BEGIN_MAP
     my $curRes = $iterator->next(); # for "current resource"      my $curRes = $iterator->next(); # for "current resource"
     while ($depth > 0 && $ctr < 100) { # ctr, just in case it never gets out of loop      while ($depth > 0) {
         if($curRes == $iterator->BEGIN_MAP) { $depth++; }          if($curRes == $iterator->BEGIN_MAP) { $depth++; }
         if($curRes == $iterator->END_MAP) { $depth++; }          if($curRes == $iterator->END_MAP) { $depth--; }
   
         if (ref($curRes) && $curRes->is_problem() && !$curRes->randomout) {          if (ref($curRes) && $curRes->is_problem() && !$curRes->randomout) {
     my $parts = $curRes->parts();      my $parts = $curRes->parts();
     $parts = &temp_parts_fix($parts); # remove line when lonnavmap is fixed  
             my $title = $curRes->compTitle();              my $title = $curRes->compTitle();
     my $symbx = $curRes->symb();      my $symbx = $curRes->symb();
     $studentTable.='<tr bgcolor="#ffffe6"><td align="center" valign="top" >'.$question.      $studentTable.='<tr bgcolor="#ffffe6"><td align="center" valign="top" >'.$question.
Line 2626  sub displayPage { Line 2844  sub displayPage {
  '','.submission');   '','.submission');
     
     }      }
       if (&canmodify($usec)) {
     foreach my $partid (@{$parts}) {   foreach my $partid (@{$parts}) {
  $studentTable.=&gradeBox($request,$symbx,$uname,$udom,$question,$partid,\%record);      $studentTable.=&gradeBox($request,$symbx,$uname,$udom,$question,$partid,\%record);
  $studentTable.='<input type="hidden" name="q_'.$question.'" value="'.$partid.'" />'."\n";      $studentTable.='<input type="hidden" name="q_'.$question.'" value="'.$partid.'" />'."\n";
  $question++;      $question++;
    }
     }      }
     $studentTable.='</td></tr>';      $studentTable.='</td></tr>';
   
        }   }
         $curRes = $iterator->next();          $curRes = $iterator->next();
  $ctr++;  
     }      }
   
       $navmap->untieHashes();
   
     $studentTable.='</td></tr></table></td></tr></table>'."\n".      $studentTable.='</td></tr></table></td></tr></table>'."\n".
  '&nbsp;&nbsp;<input type="button" value="Save" '.   '&nbsp;&nbsp;<input type="button" value="Save" '.
  'onClick="javascript:checkSubmitPage(this.form,'.$question.');" TARGET=_self />'.   'onClick="javascript:checkSubmitPage(this.form,'.$question.');" TARGET=_self />'.
Line 2649  sub displayPage { Line 2869  sub displayPage {
     return '';      return '';
 }  }
   
 sub temp_parts_fix { #remove sub once lonnavmap is fixed  
     my $parts = shift;  
     my %seen = ();  
     my @correctParts = ();  
     foreach (@{$parts}) {  
  next if ($seen{$_} > 0);  
  $seen{$_}++;  
  push @correctParts,$_;  
     }  
     return \@correctParts;  
 }  
   
 sub updateGradeByPage {  sub updateGradeByPage {
     my ($request) = shift;      my ($request) = shift;
   
Line 2668  sub updateGradeByPage { Line 2876  sub updateGradeByPage {
     my $cnum      = $ENV{"course.$ENV{'request.course.id'}.num"};      my $cnum      = $ENV{"course.$ENV{'request.course.id'}.num"};
     my $getsec    = $ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'};      my $getsec    = $ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'};
     my $pageTitle = $ENV{'form.page'};      my $pageTitle = $ENV{'form.page'};
     my (undef,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];
       if (!&canmodify($usec)) {
    $request->print('<font color="red">Unable to modify requested student.('.$ENV{'form.student'}.'</font>');
    $request->print(&show_grading_menu_form($ENV{'form.symb'},$ENV{'form.url'}));
    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: '.$$fullname{$ENV{'form.student'}}.
  '<font color="#999999"> ('.$uname.($udom eq $cdom ? '':':'.$udom).')</font></h3>'."\n";   '<font color="#999999"> ('.$uname.($udom eq $cdom ? '':':'.$udom).')</font></h3>'."\n";
Line 2694  sub updateGradeByPage { Line 2907  sub updateGradeByPage {
   
     $iterator->next(); # skip the first BEGIN_MAP      $iterator->next(); # skip the first BEGIN_MAP
     my $curRes = $iterator->next(); # for "current resource"      my $curRes = $iterator->next(); # for "current resource"
     my ($depth,$ctr,$question,$changeflag)= (1,0,1,0);      my ($depth,$question,$changeflag)= (1,1,0);
     while ($depth > 0 && $ctr < 100) { # ctr, just in case it never gets out of loop      while ($depth > 0) {
         if($curRes == $iterator->BEGIN_MAP) { $depth++; }          if($curRes == $iterator->BEGIN_MAP) { $depth++; }
         if($curRes == $iterator->END_MAP) { $depth++; }          if($curRes == $iterator->END_MAP) { $depth--; }
   
         if (ref($curRes) && $curRes->is_problem() && !$curRes->randomout) {          if (ref($curRes) && $curRes->is_problem() && !$curRes->randomout) {
     my $parts = $curRes->parts();      my $parts = $curRes->parts();
     $parts = &temp_parts_fix($parts); # remove line when lonnavmap is fixed  
             my $title = $curRes->compTitle();              my $title = $curRes->compTitle();
     my $symbx = $curRes->symb();      my $symbx = $curRes->symb();
     $studentTable.='<tr bgcolor="#ffffe6"><td align="center" valign="top" >'.$question.      $studentTable.='<tr bgcolor="#ffffe6"><td align="center" valign="top" >'.$question.
Line 2758  sub updateGradeByPage { Line 2970  sub updateGradeByPage {
   
  }   }
         $curRes = $iterator->next();          $curRes = $iterator->next();
  $ctr++;  
     }      }
   
       $navmap->untieHashes();
   
     $studentTable.='</td></tr></table></td></tr></table>';      $studentTable.='</td></tr></table></td></tr></table>';
     $studentTable.=&show_grading_menu_form($ENV{'form.symb'},$ENV{'form.url'});      $studentTable.=&show_grading_menu_form($ENV{'form.symb'},$ENV{'form.url'});
     my $grademsg=($changeflag == 0 ? 'No score was changed or updated.' :      my $grademsg=($changeflag == 0 ? 'No score was changed or updated.' :
Line 2924  sub scantron_parse_scanline { Line 3137  sub scantron_parse_scanline {
     my $data=substr($line,0,$$scantron_config{'Qstart'}-1);      my $data=substr($line,0,$$scantron_config{'Qstart'}-1);
     if ($$scantron_config{'CODElocation'} ne 0) {      if ($$scantron_config{'CODElocation'} ne 0) {
  if ($$scantron_config{'CODElocation'} < 0) {   if ($$scantron_config{'CODElocation'} < 0) {
     $record{'CODE'}=substr($data,$$scantron_config{'CODEstart'}-1,      $record{'scantron.CODE'}=substr($data,$$scantron_config{'CODEstart'}-1,
    $$scantron_config{'CODElength'});      $$scantron_config{'CODElength'});
  } else {   } else {
     #FIXME interpret first N questions      #FIXME interpret first N questions
  }   }
     }      }
     $record{'ID'}=substr($data,$$scantron_config{'IDstart'}-1,      $record{'scantron.ID'}=substr($data,$$scantron_config{'IDstart'}-1,
  $$scantron_config{'IDlength'});    $$scantron_config{'IDlength'});
     my @alphabet=('A'..'Z');      my @alphabet=('A'..'Z');
     my $questnum=0;      my $questnum=0;
     while ($questions) {      while ($questions) {
  $questnum++;   $questnum++;
  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; }
  my (@array)=split(/$$scantron_config{'Qon'}/,$currentquest);   my (@array)=split(/$$scantron_config{'Qon'}/,$currentquest);
  if (scalar(@array) gt 2) {   if (scalar(@array) gt 2) {
     #FIXME do something intelligent with double bubbles      #FIXME do something intelligent with double bubbles
     Apache->request->print("<br ><b>Wha!!!</b> ".scalar(@array).      Apache->request->print("<br ><b>Wha!!!</b> <pre>".scalar(@array).
    '-'.$questions.'-'.$currentquest.'-'.$questnum.     '-'.$currentquest.'-'.$questnum.'</pre><br />');
    '-'.length($questions).  
    '-'.$line.'-'.length($line).'-'.  
    '-'.$data.'-'.length($data).'-'.  
    '<br />');  
  }   }
  if (length($array[0]) eq $$scantron_config{'Qlength'}) {   if (length($array[0]) eq $$scantron_config{'Qlength'}) {
     $record{"$questnum.answer"}='';      $record{"scantron.$questnum.answer"}='';
  } else {   } else {
     $record{"$questnum.answer"}=$alphabet[length($array[0])];      $record{"scantron.$questnum.answer"}=$alphabet[length($array[0])];
  }   }
     }      }
     $record{'maxquest'}=$questnum;      $record{'scantron.maxquest'}=$questnum;
     $Apache::lonxml::debug=1;      return \%record;
     &Apache::lonhomework::showhash(%record);  
     $Apache::lonxml::debug=0;  
     return %record;  
 }  }
   
 sub scantron_add_delay {  sub scantron_add_delay {
 }  }
   
 sub scantron_find_student {  sub scantron_find_student {
       my ($scantron_record,$idmap)=@_;
       my $scanID=$$scantron_record{'scantron.ID'};
       foreach my $id (keys(%$idmap)) {
    Apache->request->print('<pre>checking studnet -'.$id.'- againt -'.$scanID.'- </pre>');
    if (lc($id) eq lc($scanID)) { Apache->request->print('success');return $$idmap{$id}; }
       }
       return undef;
   }
   
   sub scantron_filter {
       my ($curres)=@_;
       if (ref($curres) && $curres->is_problem() && !$curres->randomout) {
    return 1;
       }
       return 0;
 }  }
   
 sub scantron_process_students {  sub scantron_process_students {
Line 2976  sub scantron_process_students { Line 3198  sub scantron_process_students {
   
     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=Apache::File->new($Apache::lonnet::perlvar{'lonScansDir'}."/$ENV{'form.scantron_selectfile'}");
       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 $map=$navmap->getResourceByUrl($sequence);
       my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
       $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 2986  SCANTRONFORM Line 3213  SCANTRONFORM
     $r->print($result);      $r->print($result);
   
     my @delayqueue;      my @delayqueue;
       my $totalcorrect;
       my $totalincorrect;
   
       my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,
              'Scantron Status','Scantron Progress',scalar(@scanlines));
       foreach my $line (@scanlines) {
    my $studentcorrect;
    my $studentincorrect;
   
     foreach my $line (<$scanlines>) {   chomp($line);
  my $scan_record=&scantron_parse_scanline($line,\%scantron_config);   my $scan_record=&scantron_parse_scanline($line,\%scantron_config);
  my ($uname,$udom);   my ($uname,$udom);
  if ($uname=&scantron_find_student($scan_record,\%idmap)) {   if ($uname=&scantron_find_student($scan_record,\%idmap)) {
     &scantron_add_delay(\@delayqueue,$line,      &scantron_add_delay(\@delayqueue,$line,
  'Unable to find a student that matches');   'Unable to find a student that matches');
  }   }
    $r->print('<pre>doing studnet'.$uname.'</pre>');
  ($uname,$udom)=split(/:/,$uname);   ($uname,$udom)=split(/:/,$uname);
    &Apache::lonnet::delenv('form.counter');
    &Apache::lonnet::appenv(%$scan_record);
   #    &Apache::lonhomework::showhash(%ENV);
       $Apache::lonxml::debug=1;
    &Apache::lonxml::debug("line is $line");
   
       my $i=0;
    foreach my $resource (@resources) {
       $i++;
       my $result=&Apache::lonnet::ssi($resource->src(),
    ('submitted'     =>'scantron',
     'grade_target'  =>'grade',
     'grade_username'=>$uname,
     'grade_domain'  =>$udom,
     'grade_courseid'=>$ENV{'request.course.id'},
     '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;}
    }
    &Apache::lonnet::delenv('form.counter');
    &Apache::lonnet::delenv('scantron\.');
    &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
                'last student Who got a '.$studentcorrect.' correct and '.
        $studentincorrect.' incorrect. The class has gotten '.
                $totalcorrect.' correct and '.$totalincorrect.' incorrect');
    last;
  #FIXME   #FIXME
  #get iterator for $sequence   #get iterator for $sequence
  #foreach question 'submit' the students answer to the server   #foreach question 'submit' the students answer to the server
Line 3002  SCANTRONFORM Line 3279  SCANTRONFORM
  #   generate data to pass back that includes grade recevied   #   generate data to pass back that includes grade recevied
  #}   #}
     }      }
       $Apache::lonxml::debug=0;
     foreach my $delay (@delayqueue) {      foreach my $delay (@delayqueue) {
  #FIXME   #FIXME
  #print out each delayed student with interface to select how   #print out each delayed student with interface to select how
Line 3014  SCANTRONFORM Line 3292  SCANTRONFORM
     #FIXME      #FIXME
     # if delay queue exists 2 submits one to process delayed students one      # if delay queue exists 2 submits one to process delayed students one
     #     to ignore delayed students, possibly saving the delay queue for later      #     to ignore delayed students, possibly saving the delay queue for later
       
       $navmap->untieHashes();
 }  }
 #-------- end of section for handling grading scantron forms -------  #-------- end of section for handling grading scantron forms -------
 #  #
Line 3060  sub gradingmenu { Line 3339  sub gradingmenu {
     function checkChoice(formname) {      function checkChoice(formname) {
  var cmd = formname.command;   var cmd = formname.command;
  formname.saveState.value = "saveCmd="+radioSelection(cmd)+":saveSec="+pullDownSelection(formname.section)+   formname.saveState.value = "saveCmd="+radioSelection(cmd)+":saveSec="+pullDownSelection(formname.section)+
     ":saveSub="+radioSelection(formname.submitonly)+":saveStatus="+pullDownSelection(formname.status);      ":saveSub="+radioSelection(formname.submitonly)+":saveStatus="+pullDownSelection(formname.Status);
  if (cmd[0].checked || cmd[1].checked || cmd[2].checked || cmd[4].checked) formname.submit();   if (cmd[0].checked || cmd[1].checked || cmd[2].checked || cmd[3].checked || cmd[4].checked) formname.submit();
   
  if (cmd[3].checked) browseAndUpload();  
   
  if (cmd[5].checked) {   if (cmd[5].checked) {
     if (!checkReceiptNo(formname,'notOK')) { return false;}      if (!checkReceiptNo(formname,'notOK')) { return false;}
     formname.submit();      formname.submit();
Line 3113  sub gradingmenu { Line 3389  sub gradingmenu {
  }   }
     }      }
   
     function browseAndUpload() {  
  bNLoad = window.open('', 'BrowseAndUpload', 'toolbar=no,location=no,scrollbars=no,width=550,height=200,screenx=100,screeny=75');  
  bNLoad.focus();  
  var lDoc = bNLoad.document;  
  lDoc.write("<html><head>");  
  lDoc.write("<title>Browse And Upload</title>");  
   
  lDoc.write("<script language=javascript>");  
  lDoc.write("function checkUpload(formname) {");  
   
  lDoc.write("  if (formname.upfile.value == \\"\\") {");  
  lDoc.write("     alert(\\"Please use the browse button to select a file from your local directory.\\");");  
  lDoc.write("     return false;");  
  lDoc.write("   }");  
  lDoc.write("   var openformname = opener.document.gradingMenu;");  
  lDoc.write("   formname.saveState.value = \\"saveCmd=\\"+opener.radioSelection(openformname.command)+\\":saveSec=\\"+opener.pullDownSelection(openformname.section)+\\":saveSub=\\"+opener.radioSelection(openformname.submitonly)+\\":saveStatus=\\"+opener.pullDownSelection(openformname.status);");  
  lDoc.write("   document.gradesupload.submit();");  
  lDoc.write("   if (navigator.appName !=\\"Netscape\\") {self.close()};");  
  lDoc.write("   setTimeout('self.close()',750)");   
  lDoc.write("}");  
   
  lDoc.write("<");  
  lDoc.write("/script>");  
   
  lDoc.write("</head><body bgcolor=white>");  
  lDoc.write("<form method=\\"post\\" enctype=\\"multipart/form-data\\" action=\\"/adm/grades\\" name=\\"gradesupload\\" target=\\"LONcatInfo\\">");  
  lDoc.write("<input type=\\"hidden\\" name=\\"symb\\"       value=\\"$symb\\">");  
  lDoc.write("<input type=\\"hidden\\" name=\\"url\\"        value=\\"$url\\">");  
  lDoc.write("<input type=\\"hidden\\" name=\\"probTitle\\"  value=\\"$probTitle\\">");  
  lDoc.write("<input type=\\"hidden\\" name=\\"saveState\\"  value=\\"\\">");  
  lDoc.write("<input type=\\"hidden\\" name=\\"command\\"    value=\\"csvuploadmap\\">");  
   
  lDoc.write("<font color=\\"green\\" size=+1>&nbsp;<b>Specify a file containing the class scores for problem - $probTitle</b></font><br><br>");  
   
  lDoc.write("<table border=0 width=100%><tr><td bgcolor=\\"#777777\\">");  
  lDoc.write("<table border=0 width=100%><tr bgcolor=\\"#ddffff\\">");  
  lDoc.write("<td>");  
  lDoc.write("<input type=\\"file\\" name=\\"upfile\\" size=\\"50\\" />");  
  lDoc.write("<br />Type: <select name=\\"upfiletype\\">");  
         lDoc.write("<option value=\\"csv\\">CSV (comma separated values, spreadsheet)</option>");  
         lDoc.write("<option value=\\"space\\">Space separated</option>");  
         lDoc.write("<option value=\\"tab\\">Tabulator separated</option>");  
         lDoc.write("<option value=\\"xml\\">HTML/XML</option>");  
         lDoc.write("</select>");  
         lDoc.write("</td></tr></table>");  
         lDoc.write("</td></tr></table>&nbsp;");  
         lDoc.write("<input type=\\"button\\" value=\\"Upload Scores\\" onClick=\\"javascript:checkUpload(this.form)\\">&nbsp;&nbsp;");  
         lDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>");  
         lDoc.write("</form>");  
         lDoc.write("</body></html>");  
   }  
 </script>  </script>
 GRADINGMENUJS  GRADINGMENUJS
   
Line 3225  GRADINGMENUJS Line 3450  GRADINGMENUJS
  ($saveSub eq 'all' ? 'checked' : '').' /> everybody</td></tr>'."\n".   ($saveSub eq 'all' ? 'checked' : '').' /> everybody</td></tr>'."\n".
   
  '<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'.   '<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'.
  '<input type="radio" name="command" value="csvupload" '.   '<input type="radio" name="command" value="csvform" '.
  ($saveCmd eq 'csvupload' ? 'checked' : '').'> '.   ($saveCmd eq 'csvform' ? 'checked' : '').'> '.
  'Upload scores from file</td></tr>'."\n";   'Upload scores from file</td></tr>'."\n";
   
     $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'.      $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'.
Line 3252  GRADINGMENUJS Line 3477  GRADINGMENUJS
     }      }
     $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><select name="status">'.      $result.='Student Status:</b>'.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,undef);
  '<option value="Active" '.($saveStatus eq 'Active' ? 'selected' : '').'>Active</option>'.  
  '<option value="Expired" '.($saveStatus eq 'Expired' ? 'selected' : '').'>Expired</option>'.  
  '<option value="Any" '.($saveStatus eq 'Any' ? 'selected' : '').'>Any</option>'.  
  '</select>';  
   
     $result.=' &nbsp; <font color="red">(Applies to the first three options only.)</font>'."\n";      $result.=' &nbsp; <font color="red">(Applies to the first three options only.)</font>'."\n";
   
     if (ref($sections)) {      if (ref($sections)) {
Line 3276  GRADINGMENUJS Line 3496  GRADINGMENUJS
   
 sub handler {  sub handler {
     my $request=$_[0];      my $request=$_[0];
       
       undef(%perm);
     if ($ENV{'browser.mathml'}) {      if ($ENV{'browser.mathml'}) {
  $request->content_type('text/xml');   $request->content_type('text/xml');
     } else {      } else {
Line 3305  sub handler { Line 3526  sub handler {
  if ($tsymb) {   if ($tsymb) {
     my ($map,$id,$url)=split(/\_\_\_/,$tsymb);      my ($map,$id,$url)=split(/\_\_\_/,$tsymb);
     if (&Apache::lonnet::allowed('mgr',$tcrsid)) {      if (&Apache::lonnet::allowed('mgr',$tcrsid)) {
  $request->print(   $request->print(&Apache::lonnet::ssi_body('/res/'.$url,
  &Apache::lonnet::ssi('/res/'.$url,    ('grade_username' => $tuname,
      ('grade_username' => $tuname,     'grade_domain' => $tudom,
       'grade_domain' => $tudom,     'grade_courseid' => $tcrsid,
       'grade_courseid' => $tcrsid,     'grade_symb' => $tsymb)));
       'grade_symb' => $tsymb)));  
     } else {      } else {
  $request->print('<h3>Not authorized: '.$token.'</h3>');   $request->print('<h3>Not authorized: '.$token.'</h3>');
     }                 }
  } else {   } else {
     $request->print('<h3>Not a valid DocID: '.$token.'</h3>');      $request->print('<h3>Not a valid DocID: '.$token.'</h3>');
  }   }
Line 3322  sub handler { Line 3542  sub handler {
     }      }
  }   }
     } else {      } else {
  $Apache::grades::viewgrades=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'});   if (!($perm{'vgr'}=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'}))) {
  if ($command eq 'submission') {      if ($perm{'vgr'}=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'}.'/'.$ENV{'request.course.sec'})) {
    $perm{'vgr_section'}=$ENV{'request.course.sec'};
       } else {
    delete($perm{'vgr'});
       }
    }
    if (!($perm{'mgr'}=&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'}))) {
       if ($perm{'mgr'}=&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'}.'/'.$ENV{'request.course.sec'})) {
    $perm{'mgr_section'}=$ENV{'request.course.sec'};
       } else {
    delete($perm{'mgr'});
       }
    }
   
    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') {   } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {
     &pickStudentPage($request);      &pickStudentPage($request);
  } elsif ($command eq 'displayPage') {   } elsif ($command eq 'displayPage' && $perm{'vgr'}) {
     &displayPage($request);      &displayPage($request);
  } elsif ($command eq 'gradeByPage') {   } elsif ($command eq 'gradeByPage' && $perm{'mgr'}) {
     &updateGradeByPage($request);      &updateGradeByPage($request);
  } elsif ($command eq 'processGroup') {   } elsif ($command eq 'processGroup' && $perm{'vgr'}) {
     &processGroup($request);      &processGroup($request);
  } elsif ($command eq 'gradingmenu') {   } elsif ($command eq 'gradingmenu' && $perm{'vgr'}) {
     $request->print(&gradingmenu($request));      $request->print(&gradingmenu($request));
  } elsif ($command eq 'viewgrades') {   } elsif ($command eq 'viewgrades' && $perm{'vgr'}) {
     $request->print(&viewgrades($request));      $request->print(&viewgrades($request));
  } elsif ($command eq 'handgrade') {   } elsif ($command eq 'handgrade' && $perm{'mgr'}) {
     $request->print(&processHandGrade($request));      $request->print(&processHandGrade($request));
  } elsif ($command eq 'editgrades') {   } elsif ($command eq 'editgrades' && $perm{'mgr'}) {
     $request->print(&editgrades($request));      $request->print(&editgrades($request));
  } elsif ($command eq 'verify') {   } elsif ($command eq 'verify' && $perm{'vgr'}) {
     $request->print(&verifyreceipt($request));      $request->print(&verifyreceipt($request));
  } elsif ($command eq 'csvform') {   } elsif ($command eq 'csvform' && $perm{'mgr'}) {
     $request->print(&upcsvScores_form($request));      $request->print(&upcsvScores_form($request));
  } elsif ($command eq 'csvupload') {   } elsif ($command eq 'csvupload' && $perm{'mgr'}) {
     $request->print(&csvupload($request));      $request->print(&csvupload($request));
  } elsif ($command eq 'viewclasslist') {   } elsif ($command eq 'csvuploadmap' && $perm{'mgr'} ) {
     $request->print(&viewclasslist($request));  
  } elsif ($command eq 'csvuploadmap') {  
     $request->print(&csvuploadmap($request));      $request->print(&csvuploadmap($request));
  } elsif ($command eq 'csvuploadassign') {   } elsif ($command eq 'csvuploadassign' && $perm{'mgr'}) {
     if ($ENV{'form.associate'} ne 'Reverse Association') {      if ($ENV{'form.associate'} ne 'Reverse Association') {
  $request->print(&csvuploadassign($request));   $request->print(&csvuploadassign($request));
     } else {      } else {
Line 3362  sub handler { Line 3594  sub handler {
  }   }
  $request->print(&csvuploadmap($request));   $request->print(&csvuploadmap($request));
     }      }
  } elsif ($command eq 'scantron_selectphase') {   } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) {
     $request->print(&scantron_selectphase($request));      $request->print(&scantron_selectphase($request));
  } elsif ($command eq 'scantron_process') {   } elsif ($command eq 'scantron_process' && $perm{'mgr'}) {
     $request->print(&scantron_process_students($request));      $request->print(&scantron_process_students($request));
  } else {   } elsif ($command) {
     $request->print("Unknown action: $command:");      $request->print("Access Denied");
  }   }
     }      }
     &send_footer($request);      &send_footer($request);

Removed from v.1.82  
changed lines
  Added in v.1.112


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