Diff for /loncom/homework/grades.pm between versions 1.43 and 1.49

version 1.43, 2002/07/30 19:59:58 version 1.49, 2002/09/20 23:35:30
Line 30 Line 30
 # 7/26 H.K. Ng  # 7/26 H.K. Ng
 # 8/20 Gerd Kortemeyer  # 8/20 Gerd Kortemeyer
 # Year 2002  # Year 2002
 # June, July 2002 H.K. Ng  # June-August H.K. Ng
 #  #
   
 package Apache::grades;  package Apache::grades;
Line 42  use Apache::loncommon; Line 42  use Apache::loncommon;
 use Apache::lonhomework;  use Apache::lonhomework;
 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 Time::HiRes qw( gettimeofday tv_interval );  
   
 sub moreinfo {  # ----- These first few routines are general use routines.-----
     my ($request,$reason) = @_;  #
     $request->print("Unable to process request: $reason");  # --- Retrieve the parts that matches stores_\d+ from the metadata file.---
     if ( $Apache::grades::viewgrades eq 'F' ) {  sub getpartlist {
  $request->print('<form action="/adm/grades" method="post">'."\n");      my ($url) = @_;
  if ($ENV{'form.url'}) {      my @parts =();
     $request->print('<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />'."\n");      my (@metakeys) = split(/,/,&Apache::lonnet::metadata($url,'keys'));
  }      foreach my $key (@metakeys) {
  if ($ENV{'form.symb'}) {   if ( $key =~ m/stores_([0-9]+)_.*/) {
     $request->print('<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />'."\n");      push(@parts,$key);
  }   }
 #    $request->print('<input type="hidden" name="command" value="submission" />'."\n");  
  $request->print('<input type="hidden" name="command" value="'.$ENV{'form.command'}.'" />'."\n");  
  $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 '';  
 }  
   
 sub verifyreceipt {  
     my $request=shift;  
     my $courseid=$ENV{'request.course.id'};  
 #    my $cdom=$ENV{"course.$courseid.domain"};  
 #    my $cnum=$ENV{"course.$courseid.num"};  
     my $receipt=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}).'-'.  
  $ENV{'form.receipt'};  
     $receipt=~s/[^\-\d]//g;  
     my $symb=$ENV{'form.symb'};  
     unless ($symb) {  
  $symb=&Apache::lonnet::symbread($ENV{'form.url'});  
     }  
     if ((&Apache::lonnet::allowed('mgr',$courseid)) && ($symb)) {  
         $request->print('<h1>Verifying Submission Receipt '.$receipt.'</h1>');  
         my $matches=0;  
         my ($classlist) = &getclasslist('all','0');  
         foreach my $student ( sort(@{ $$classlist{'all'} }) ) {  
             my ($uname,$udom)=split(/\:/,$student);  
             if ($receipt eq   
  &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb)) {  
  $request->print('Matching '.$student.'<br>');  
  $matches++;  
    }  
         }  
         $request->printf('<p>'.$matches." match%s</p>",$matches <= 1 ? '' : 'es');  
 # needs to print who is matched  
     }      }
     return '';      return @parts;
 }  }
   
 sub student_gradeStatus {  # --- Get the symbolic name of a problem and the url
     my ($url,$udom,$uname,$partlist) = @_;  sub get_symb_and_url {
       my ($request) = @_;
       (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)));
     my %record= &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);      if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }
     my %partstatus = ();      return ($symb,$url);
     foreach (@$partlist) {  
  my ($status,$foo)=split(/_/,$record{"resource.$_.solved"},2);  
  $status = 'nothing' if ($status eq '');  
  $partstatus{$_} = $status;  
  $partstatus{"resource.$_.submitted_by"} = $record{"resource.$_.submitted_by"}   
  if ($record{"resource.$_.submitted_by"} ne '');  
     }  
     return %partstatus;  
 }  }
   
   # --- Retrieve the fullname for a user. Return lastname, first middle ---
   # --- Generation is attached next to the lastname if it exists. ---
 sub get_fullname {  sub get_fullname {
     my ($uname,$udom) = @_;      my ($uname,$udom) = @_;
     my %name=&Apache::lonnet::get('environment', ['lastname','generation',      my %name=&Apache::lonnet::get('environment', ['lastname','generation',
Line 124  sub get_fullname { Line 83  sub get_fullname {
     return $fullname;      return $fullname;
 }  }
   
   #--- Get the partlist and the response type for a given problem. ---
   #--- Indicate if a response type is coded handgraded or not. ---
 sub response_type {  sub response_type {
     my ($url) = shift;      my ($url) = shift;
     my $allkeys = &Apache::lonnet::metadata($url,'keys');      my $allkeys = &Apache::lonnet::metadata($url,'keys');
 #    print "allkeys=>$allkeys<br>";  
     my %seen = ();      my %seen = ();
     my (@partlist,%handgrade);      my (@partlist,%handgrade);
     foreach (split(/,/,&Apache::lonnet::metadata($url,'packages'))) {      foreach (split(/,/,&Apache::lonnet::metadata($url,'packages'))) {
Line 143  sub response_type { Line 103  sub response_type {
     return \@partlist,\%handgrade;      return \@partlist,\%handgrade;
 }  }
   
   #--- Dumps the class list with usernames,list of sections,
   #--- section, ids and fullnames for each user.
   sub getclasslist {
       my ($getsec,$hideexpired) = @_;
       my $now = time;
       my %classlist=&Apache::lonnet::dump('classlist',
    $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
    $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
       my ($tmp) = keys(%classlist);
       # Bail out if we were unable to get the classlist
       return if ($tmp =~ /^(con_lost|error|no_such_host)/i);
   
       # codes to check for fields in the classlist
       # should contain end:start:id:section:fullname
       for (keys %classlist) {
    my (@fields) = split(/:/,$classlist{$_});
    %classlist   = &reformat_classlist(\%classlist) if (scalar(@fields) <= 2);
    last;
       }
   
       my (@holdsec,@sections,%allids,%stusec,%fullname);
       foreach (keys(%classlist)) {
    my ($end,$start,$id,$section,$fullname)=split(/:/,$classlist{$_});
    # still a student?
    if (($hideexpired) && ($end) && ($end < $now)) {
       next;
    }
    $section = ($section ne '' ? $section : 'no');
    push @holdsec,$section;
    if ($getsec eq 'all' || $getsec eq $section) {
       push (@{ $classlist{$getsec} }, $_);
       $allids{$_}  =$id;
       $stusec{$_}  =$section;
       $fullname{$_}=$fullname;
    }
       }
       my %seen = ();
       foreach my $item (@holdsec) {
    push (@sections, $item) unless $seen{$item}++;
       }
       return (\%classlist,\@sections,\%allids,\%stusec,\%fullname);
   }
   
   # add id, section and fullname to the classlist.db
   # done to maintain backward compatibility with older versions
   sub reformat_classlist {
       my ($classlist) = shift;
       foreach (sort keys(%$classlist)) {
    my ($unam,$udom) = split(/:/);
    my $section      = &Apache::lonnet::usection($udom,$unam,$ENV{'request.course.id'});
    my $fullname     = &get_fullname ($unam,$udom);
    my %userid       = &Apache::lonnet::idrget($udom,($unam));
    $$classlist{$_}  = $$classlist{$_}.':'.$userid{$unam}.':'.$section.':'.$fullname;
       }
       my $putresult = &Apache::lonnet::put
    ('classlist',\%$classlist,
    $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
    $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
   
       return %$classlist;
   }
   
   #find user domain
   sub finduser {
       my ($name) = @_;
       my $domain = '';
       if ( $Apache::grades::viewgrades eq 'F' ) {
    my %classlist=&Apache::lonnet::dump('classlist',
       $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
       $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
    my (@fields) = grep /^$name:/, keys %classlist;
    ($name, $domain) = split(/:/,$fields[0]);
    return ($name,$domain);
       } else {
    return ($ENV{'user.name'},$ENV{'user.domain'});
       }
   }
   
   #--- Prompts a user to enter a username.
   sub moreinfo {
       my ($request,$reason) = @_;
       $request->print("Unable to process request: $reason");
       if ( $Apache::grades::viewgrades eq 'F' ) {
    $request->print('<form action="/adm/grades" method="post">'."\n");
    if ($ENV{'form.url'}) {
       $request->print('<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />'."\n");
    }
    if ($ENV{'form.symb'}) {
       $request->print('<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />'."\n");
    }
    $request->print('<input type="hidden" name="command" value="'.$ENV{'form.command'}.'" />'."\n");
    $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 '';
   }
   
   #--- Retrieve the grade status of a student for all the parts
   sub student_gradeStatus {
       my ($url,$symb,$udom,$uname,$partlist) = @_;
       my %record     = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);
       my %partstatus = ();
       foreach (@$partlist) {
    my ($status,$foo)    = split(/_/,$record{"resource.$_.solved"},2);
    $status              = 'nothing' if ($status eq '');
    $partstatus{$_}      = $status;
    my $subkey           = "resource.$_.submitted_by";
    $partstatus{$subkey} = $record{$subkey} if ($record{$subkey} ne '');
       }
       return %partstatus;
   }
   
   # hidden form and javascript that calls the form
   # Use by verifyscript and viewgrades
   # Shows a student's view of problem and submission
   sub jscriptNform {
       my ($url,$symb) = @_;
       my $jscript='<script type="text/javascript" language="javascript">'."\n".
    '    function viewOneStudent(user,domain) {'."\n".
    ' document.onestudent.student.value = user;'."\n".
    ' document.onestudent.userdom.value = domain;'."\n".
    ' document.onestudent.submit();'."\n".
    '    }'."\n".
    '</script>'."\n";
       $jscript.= '<form action="/adm/grades" method="post" name="onestudent">'."\n".
    '<input type="hidden" name="symb"    value="'.$symb.'" />'."\n".
    '<input type="hidden" name="url"     value="'.$url.'" />'."\n".
    '<input type="hidden" name="command" value="submission" />'."\n".
    '<input type="hidden" name="student" value="" />'."\n".
    '<input type="hidden" name="userdom" value="" />'."\n".
    '</form>'."\n";
       return $jscript;
   }
   
   #------------------ End of general use routines --------------------
   #-------------------------------------------------------------------
   
   #------------------------------------ Receipt Verification Routines
   #
   #--- Check whether a receipt number is valid.---
   sub verifyreceipt {
       my $request  = shift;
   
       my $courseid = $ENV{'request.course.id'};
       my $receipt  = unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}).'-'.
    $ENV{'form.receipt'};
       $receipt     =~ s/[^\-\d]//g;
       my $url      = $ENV{'form.url'};
       my $symb     = $ENV{'form.symb'};
       unless ($symb) {
    $symb    = &Apache::lonnet::symbread($url);
       }
   
       my $title.='<h3><font color="#339933">Verifying Submission Receipt '.
    $receipt.'</h3></font>'."\n".
    '<font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font><br><br>'."\n";
   
       my ($string,$contents,$matches) = ('','',0);
       my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist('all','0');
       
       foreach (sort {$$fullname{$a} cmp $$fullname{$b} } keys %$fullname) {
    my ($uname,$udom)=split(/\:/);
    if ($receipt eq 
       &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb)) {
       $contents.='<tr bgcolor="#ffffe6"><td>&nbsp;'."\n".
    '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.
    '\')"; TARGET=_self>'.$$fullname{$_}.'</a>&nbsp;</td>'."\n".
    '<td>&nbsp;'.$uname.'&nbsp;</td>'.
    '<td>&nbsp;'.$udom.'&nbsp;</td></tr>'."\n";
       
       $matches++;
    }
       }
       if ($matches == 0) {
    $string = $title.'No match found for the above receipt.';
       } else {
    $string = &jscriptNform($url,$symb).$title.
       'The above receipt matches the following student'.
       ($matches <= 1 ? '.' : 's.')."\n".
       '<table border="0"><tr><td bgcolor="#777777">'."\n".
       '<table border="0"><tr bgcolor="#e6ffff">'."\n".
       '<td><b>&nbsp;Fullname&nbsp;</b></td>'."\n".
       '<td><b>&nbsp;Username&nbsp;</b></td>'."\n".
       '<td><b>&nbsp;Domain&nbsp;</b></td></tr>'."\n".
       $contents.
       '</table></td></tr></table>'."\n";
       }
       return $string.&show_grading_menu_form ($symb,$url);
   }
   
   #--- This is called by a number of programs.
   #--- Called from the Grading Menu - View/Grade an individual student
   #--- Also called directly when one clicks on the subm button 
   #    on the problem page.
 sub listStudents {  sub listStudents {
     my ($request) = shift;      my ($request) = shift;
     my $cdom      =$ENV{"course.$ENV{'request.course.id'}.domain"};  
     my $cnum      =$ENV{"course.$ENV{'request.course.id'}.num"};  
     my $getsec    =$ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'};  
     my $submitonly=$ENV{'form.submitonly'} eq '' ? 'all' : $ENV{'form.submitonly'};  
   
     my $result='<h2><font color="#339933">&nbsp;View Submissions for a Student or a Group of Students</font></h2>';      my ($symb,$url) = &get_symb_and_url();
     $result.='<table border="0">';      my $cdom      = $ENV{"course.$ENV{'request.course.id'}.domain"};
     $result.='<tr><td colspan=3><font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font></td></tr>';      my $cnum      = $ENV{"course.$ENV{'request.course.id'}.num"};
     my ($partlist,$handgrade) = &response_type($ENV{'form.url'});      my $getsec    = $ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'};
       my $submitonly= $ENV{'form.submitonly'} eq '' ? 'all' : $ENV{'form.submitonly'};
   
       my $result;
       my ($partlist,$handgrade) = &response_type($url);
     for (sort keys(%$handgrade)) {      for (sort keys(%$handgrade)) {
  my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});   my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});
  $ENV{'form.handgrade'} = 'yes' if ($handgrade eq 'yes');   $ENV{'form.handgrade'} = 'yes' if ($handgrade eq 'yes');
  $result.='<tr><td><b>Part id: </b>'.(split(/_/))[0].'</td>'.   $result.='<tr><td><b>Part </b>'.(split(/_/))[0].'</td>'.
     '<td><b>Type: </b>'.$responsetype.'</td>'.      '<td><b>Type: </b>'.$responsetype.'</td>'.
     '<td><b>Handgrade: </b>'.$handgrade.'</font></td></tr>';      '<td><b>Handgrade: </b>'.$handgrade.'</font></td></tr>';
     }      }
     $result.='</table>';      $result.='</table>';
     $request->print($result);  
   
     $request->print(<<ENDTABLEST);      my $viewgrade;
 <form action="/adm/grades" method="post">      if ($ENV{'form.handgrade'} eq 'yes') {
 &nbsp;<b>View Problem: </b><input type="radio" name="vProb" value="no" checked> no    $viewgrade = 'View/Grade';
 <input type="radio" name="vProb" value="yes"> yes <br />      } else {
 &nbsp;<b>Submissions: </b>   $viewgrade = 'View';
 <input type="radio" name="lastSub" value="hdgrade" checked /> handgrade only  
 <input type="radio" name="lastSub" value="lastonly" /> last sub only  
 <input type="radio" name="lastSub" value="last" /> last sub & parts info  
 <input type="radio" name="lastSub" value="all" /> all details  
 <input type="hidden" name="section" value="$getsec" />  
 <input type="hidden" name="submitonly" value="$submitonly" />  
 <input type="hidden" name="response" value="$ENV{'form.response'}" />  
 <input type="hidden" name="handgrade" value="$ENV{'form.handgrade'}" /><br />  
 <input type="hidden" name="showgrading" value="$ENV{'form.showgrading'}" /><br />  
 <input type="submit" name="submit" value="View/Grade" />  
 ENDTABLEST  
     if ($ENV{'form.url'}) {  
  $request->print('<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />'."\n");  
     }      }
     if ($ENV{'form.symb'}) {  
  $request->print('<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />'."\n");      $result='<h3><font color="#339933">&nbsp;'.
    $viewgrade.
       ' Submissions for a Student or a Group of Students</font></h3>'.
    '<table border="0"><tr><td colspan=3><font size=+1>'.
       '<b>Resource: </b>'.$url.'</font></td></tr>'.$result;
   
       $request->print(<<LISTJAVASCRIPT);
   <script type="text/javascript" language="javascript">
     function checkSelect(checkBox) {
       var ctr=0;
       var sense="";
       if (checkBox.length > 1) {
          for (var i=0; i<checkBox.length; i++) {
     if (checkBox[i].checked) {
        ctr++;
     }
          }
          sense = "a student or group of students";
       } else {
          if (checkBox.checked) {
      ctr = 1;
          }
          sense = "the student";
       }
       if (ctr == 0) {
          alert("Please select "+sense+" before clicking on the $viewgrade button.");
          return false;
     }      }
     $request->print('<input type="hidden" name="command" value="processGroup" />'."\n");      document.gradesub.submit();
         }
   </script>
   LISTJAVASCRIPT
   
       $request->print($result);
   
       my $checkhdgrade = $ENV{'form.handgrade'} eq 'yes' ? 'checked' : '';
       my $checklastsub = $ENV{'form.handgrade'} eq 'yes' ? '' : 'checked';
   
       my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'."\n".
    '&nbsp;<b>View Problem: </b><input type="radio" name="vProb" value="no" checked> no '."\n".
    '<input type="radio" name="vProb" value="yes"> yes <br />'."\n".
    '&nbsp;<b>Submissions: </b>'."\n";
       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="lastonly" '.$checklastsub.' /> last sub only'."\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="hidden" name="section"     value="'.$getsec.'" />'."\n".
    '<input type="hidden" name="submitonly"  value="'.$submitonly.'" />'."\n".
    '<input type="hidden" name="response"    value="'.$ENV{'form.response'}.'" />'."\n".
    '<input type="hidden" name="handgrade"   value="'.$ENV{'form.handgrade'}.'" /><br />'."\n".
    '<input type="hidden" name="showgrading" value="'.$ENV{'form.showgrading'}.'" /><br />'."\n".
    '<input type="hidden" name="url"  value="'.$url.'" />'."\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".
    '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".
    '<input type="hidden" name="command" value="processGroup" />'."\n".
    '<input type="button" '."\n".
    'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n".
    'value="'.$viewgrade.'" />'."\n";
    
     my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($getsec,'0');      my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($getsec,'0');
           
     $result='<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;Username&nbsp;</b></td>'.   '<td><b>&nbsp;Select&nbsp;</b></td><td><b>&nbsp;Fullname&nbsp;</b></td>'.
  '<td><b>&nbsp;Fullname&nbsp;</b></td><td><b>&nbsp;Domain&nbsp;</b></td>';   '<td><b>&nbsp;Username&nbsp;</b></td><td><b>&nbsp;Domain&nbsp;</b></td>';
     foreach (sort(@$partlist)) {      foreach (sort(@$partlist)) {
  $result.='<td><b>&nbsp;Part ID '.(split(/_/))[0].' Status&nbsp;</b></td>';   $gradeTable.='<td><b>&nbsp;Part '.(split(/_/))[0].' Status&nbsp;</b></td>';
     }      }
     $request->print($result.'</tr>'."\n");      $gradeTable.='</tr>'."\n";
   
     foreach my $student (sort(@{ $$classlist{$getsec} }) ) {      my $ctr = 0;
       foreach my $student (sort {$$fullname{$a} cmp $$fullname{$b} } keys %$fullname) {
  my ($uname,$udom) = split(/:/,$student);   my ($uname,$udom) = split(/:/,$student);
  my (%status) = &student_gradeStatus($ENV{'form.url'},$udom,$uname,$partlist);   my (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist);
  my $statusflg = '';   my $statusflg = '';
  foreach (keys(%status)) {   foreach (keys(%status)) {
     $statusflg = 1 if ($status{$_} ne 'nothing');      $statusflg = 1 if ($status{$_} ne 'nothing');
     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 = '';   $statusflg = '';
  $request->print('<input type="hidden" name="'.   $gradeTable.='<input type="hidden" name="'.
  $student.':submitted_by" value="'.      $student.':submitted_by" value="'.
  $status{'resource.'.$partid.'.submitted_by'}.'" />');      $status{'resource.'.$partid.'.submitted_by'}.'" />';
     }      }
  }   }
  next if ($statusflg eq '' && $submitonly eq 'yes');   next if ($statusflg eq '' && $submitonly eq 'yes');
   
    $ctr++;
  if ( $Apache::grades::viewgrades eq 'F' ) {   if ( $Apache::grades::viewgrades eq 'F' ) {
     $result='<tr bgcolor="#ffffe6">'.      $gradeTable.='<tr bgcolor="#ffffe6">'.
  '<td align="center"><input type=checkbox name="stuinfo" value="'.   '<td align="center"><input type=checkbox name="stuinfo" value="'.
  $student.':'.$$fullname{$student}.'"></td>'."\n".   $student.':'.$$fullname{$student}.'"></td>'."\n".
  '<td>&nbsp;'.$uname.'&nbsp;</td>'."\n".  
  '<td>&nbsp;'.$$fullname{$student}.'&nbsp;</td>'."\n".   '<td>&nbsp;'.$$fullname{$student}.'&nbsp;</td>'."\n".
    '<td>&nbsp;'.$uname.'&nbsp;</td>'."\n".
  '<td align="middle">&nbsp;'.$udom.'&nbsp;</td>'."\n";   '<td align="middle">&nbsp;'.$udom.'&nbsp;</td>'."\n";
           
     foreach (sort keys(%status)) {      foreach (sort keys(%status)) {
  next if (/^resource.*?submitted_by$/);   next if (/^resource.*?submitted_by$/);
  $result.='<td align="middle">&nbsp;'.$status{$_}.'&nbsp;</td>'."\n";   $gradeTable.='<td align="middle">&nbsp;'.$status{$_}.'&nbsp;</td>'."\n";
     }      }
     $request->print($result.'</tr>'."\n");      $gradeTable.='</tr>'."\n";
  }   }
     }      }
     $request->print('</table></td></tr></table>');      $gradeTable.='</table></td></tr></table>'.
     $request->print('<input type="submit" name="submit" value="View/Grade" /><form />');   '<input type="button" '.
    'onClick="javascript:checkSelect(this.form.stuinfo);" '.
    'value="'.$viewgrade.'" /><form />'."\n";
       if ($ctr == 0) {
    $gradeTable='<br />&nbsp;<font color="red">'.
       'No submission found for this resource.</font><br />';
    $gradeTable.=&show_grading_menu_form($symb,$url);
       } elsif ($ctr == 1) {
    $gradeTable =~ s/type=checkbox/type=checkbox checked/;
       }
       $request->print($gradeTable);
       return '';
 }  }
   
   #---- Called from the listStudents routine
   #     Displays the submissions for one student or a group of students
 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 = (ref($ENV{'form.stuinfo'}) ? @{$ENV{'form.stuinfo'}}
       : ($ENV{'form.stuinfo'}));        : ($ENV{'form.stuinfo'}));
     my $total      = scalar(@stuchecked)-1;      my $total      = scalar(@stuchecked)-1;
     if ($stuchecked[0] eq '') {  
  &userError($request,'No student was selected for viewing/grading.');  
  return;  
     }  
     foreach (@stuchecked) {      foreach (@stuchecked) {
  my ($uname,$udom,$fullname) = split(/:/);   my ($uname,$udom,$fullname) = split(/:/);
  $ENV{'form.student'} = $uname;   $ENV{'form.student'}        = $uname;
  $ENV{'form.fullname'} = $fullname;   $ENV{'form.userdom'}        = $udom;
    $ENV{'form.fullname'}       = $fullname;
  &submission($request,$ctr,$total);   &submission($request,$ctr,$total);
  $ctr++;   $ctr++;
     }      }
     return '';      return '';
 }  }
   
 sub userError {  #------------------------------------------------------------------------------------
     my ($request, $reason, $step) = @_;  #
     $request->print('<h3><font color="red">LON-CAPA User Error</font></h3><br />'."\n");  #-------------------------- Next few routines handles grading by student, essentially
     $request->print('<b>Reason: </b>'.$reason.'<br /><br />'."\n");  #                           handles essay response type problem/part
     $request->print('<b>Step: </b>'.($step ne '' ? $step : 'Use your browser back button to correct')  #
     .'<br /><br />'."\n");  #--- Javascript to handle the submission page functionality ---
     return '';  sub sub_page_js {
 }      my $request = shift;
       $request->print(<<SUBJAVASCRIPT);
 #FIXME - needs to handle multiple matches  <script type="text/javascript" language="javascript">
 sub finduser {    function updateRadio(radioButton,formtextbox,formsel,scores,weight) {
     my ($name) = @_;       var pts = formtextbox.value;
     my $domain = '';       var resetbox =false;
     if ( $Apache::grades::viewgrades eq 'F' ) {       if (isNaN(pts) || pts < 0) {
  my ($classlist) = &getclasslist('all','0');          alert("A number equal or greater than 0 is expected. Entered value = "+pts);
  foreach ( sort(@{ $$classlist{'all'} }) ) {          for (var i=0; i<radioButton.length; i++) {
     my ($posname,$posdomain) = split(/:/);             if (radioButton[i].checked) {
     if ($posname =~ $name) { $name=$posname; $domain=$posdomain; last; }        formtextbox.value = i;
         resetbox = true;
      }
  }   }
  return ($name,$domain);   if (!resetbox) {
     } else {     formtextbox.value = "";
  return ($ENV{'user.name'},$ENV{'user.domain'});   }
    return;
        }
   
        if (pts > weight) {
           var resp = confirm("You entered a value ("+pts+
             ") greater than the weight for the part. Accept?");
           if (resp == false) {
              formtextbox.value = "";
              return;
          }
     }      }
 }  
   
 sub getclasslist {      for (var i=0; i<radioButton.length; i++) {
     my ($getsec,$hideexpired) = @_;   radioButton[i].checked=false;
     my $now = time;   if (pts == i) {
     my %classlist=&Apache::lonnet::dump('classlist',     radioButton[i].checked=true;
  $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},  
  $ENV{'course.'.$ENV{'request.course.id'}.'.num'});  
     my (@holdsec,@sections,%allids,%stusec,%fullname);  
     foreach (keys(%classlist)) {  
  my ($end,$start,$id,$section,$fullname)=split(/:/,$classlist{$_});  
        # still a student?  
  if (($hideexpired) && ($end) && ($end < $now)) {  
     next;  
  }   }
  $section = ($section ne '' ? $section : 'no');      }
  push @holdsec,$section;      updateSelect(formsel);
  if ($getsec eq 'all' || $getsec eq $section) {      scores.value = "0";
     push (@{ $classlist{$getsec} }, $_);    }
     $allids{$_}=$id;  
     $stusec{$_}=$section;    function writeBox(formrad,formsel,pts,scores) {
     $fullname{$_}=$fullname;      formrad.value = pts;
       scores.value = "0";
       updateSelect(formsel,pts);
       return;
     }
   
     function clearRadBox(radioButton,formbox,formsel,scores) {
       for (var i=0; i<formsel.length; i++) {
    if (formsel[i].selected) {
       var selectx=i;
  }   }
     }      }
     my %seen = ();      if (selectx == scores.value) { return };
     foreach my $item (@holdsec) {      formbox.value = "";
  push (@sections, $item) unless $seen{$item}++;      for (var i=0; i<radioButton.length; i++) {
    radioButton[i].checked=false;
     }      }
     return (\%classlist,\@sections,\%allids,\%stusec,\%fullname);      scores.value = selectx;
 }    }
   
 sub getpartlist {    function updateSelect(formsel) {
     my ($url) = @_;      formsel[0].selected = true;
     my @parts =();      return;
     my (@metakeys) = split(/,/,&Apache::lonnet::metadata($url,'keys'));    }
     foreach my $key (@metakeys) {  
  if ( $key =~ m/stores_([0-9]+)_.*/) {  //=================== Check that a point is assigned for all the parts  ==============
     push(@parts,$key);    function checksubmit(val,total,parttot) {
  }       document.SCORE.gradeOpt.value = val;
        if (val == "Save & Next") {
    for (i=0;i<=total;i++) {
      for (j=0;j<parttot;j++) {
         var partid = eval("document.SCORE.partid"+i+"_"+j+".value");
         var selopt = eval("document.SCORE.GD_SEL"+i+"_"+partid);
         if (selopt[0].selected) {
    var points = eval("document.SCORE.GD_BOX"+i+"_"+partid+".value");
    if (points == "") {
        var name = eval("document.SCORE.name"+i+".value");
        alert("Please assign a score for "+name+", part "+partid+".");
        return false;
    }
         }
   
     }
          }
   
        }
        document.SCORE.submit();
    }
   
   //===================== Show list of keywords ====================
     function keywords(keyform) {
       var keywds = keyform.value;
       var nret = prompt("Keywords list, separated by a space. Add/delete to list if desired.",keywds);
       if (nret==null) return;
       keyform.value = nret;
   
       document.SCORE.refresh.value = "on";
       if (document.SCORE.keywords.value != "") {
    document.SCORE.submit();
     }      }
     return @parts;      return;
 }    }
   
   //===================== Script to view submitted by ==================
     function viewSubmitter(submitter) {
       document.SCORE.refresh.value = "on";
       document.SCORE.NCT.value = "1";
       document.SCORE.unamedom0.value = submitter;
       document.SCORE.submit();
       return;
     }
   
 sub print_hash {  //===================== Script to add keyword(s) ==================
     my ($request, $hash) = @_;    function getSel() {
     $request->print('<table border=1><tr><td>Key</td><td>Value</td></tr>');      if (document.getSelection) txt = document.getSelection();
     for (sort keys (%$hash)) {      else if (document.selection) txt = document.selection.createRange().text;
  $request->print('<tr><td>'.$_.'</td><td>'.$$hash{$_}.'&nbsp;</td></tr>');      else return;
       var cleantxt = txt.replace(new RegExp('([\\f\\n\\r\\t\\v ])+', 'g')," ");
       if (cleantxt=="") {
    alert("Please select a word or group of words from document and then click this link.");
    return;
     }      }
     $request->print('</table>');      var nret = prompt("Add selection to keyword list? Edit if desired.",cleantxt);
     return '';      if (nret==null) return;
       var curlist = document.SCORE.keywords.value;
       document.SCORE.keywords.value = curlist+" "+nret;
       document.SCORE.refresh.value = "on";
       if (document.SCORE.keywords.value != "") {
    document.SCORE.submit();
       }
       return;
     }
   
   //====================== Script for composing message ==============
     function msgCenter(msgform,usrctr,fullname) {
       var Nmsg  = msgform.savemsgN.value;
       savedMsgHeader(Nmsg,usrctr,fullname);
       var subject = msgform.msgsub.value;
       var rtrchk  = eval("document.SCORE.includemsg"+usrctr);
       var msgchk = rtrchk.value;
       re = /msgsub/;
       var shwsel = "";
       if (re.test(msgchk)) { shwsel = "checked" }
       displaySubject(subject,shwsel);
       for (var i=1; i<=Nmsg; i++) {
    var testpt = "savemsg"+i+",";
    re = /testpt/;
    shwsel = "";
    if (re.test(msgchk)) { shwsel = "checked" }
    var message = eval("document.SCORE.savemsg"+i+".value");
    displaySavedMsg(i,message,shwsel);
       }
       newmsg = eval("document.SCORE.newmsg"+usrctr+".value");
       shwsel = "";
       re = /newmsg/;
       if (re.test(msgchk)) { shwsel = "checked" }
       newMsg(newmsg,shwsel);
       msgTail(); 
       return;
     }
   
     function savedMsgHeader(Nmsg,usrctr,fullname) {
       var height = 30*Nmsg+250;
       var scrollbar = "no";
       if (height > 600) {
    height = 600;
    scrollbar = "yes";
       }
   /*    if (window.pWin)
    window.pWin.close(); */
       pWin = window.open('', 'MessageCenter', 'toolbar=no,location=no,scrollbars='+scrollbar+',screenx=70,screeny=75,width=600,height='+height);
       pWin.document.write("<html><head>");
       pWin.document.write("<title>Message Central</title>");
   
       pWin.document.write("<script language=javascript>");
       pWin.document.write("function checkInput() {");
       pWin.document.write("  opener.document.SCORE.msgsub.value = document.msgcenter.msgsub.value;");
       pWin.document.write("  var nmsg   = opener.document.SCORE.savemsgN.value;");
       pWin.document.write("  var usrctr = document.msgcenter.usrctr.value;");
       pWin.document.write("  var newval = eval(\\"opener.document.SCORE.newmsg\\"+usrctr);");
       pWin.document.write("  newval.value = document.msgcenter.newmsg.value;");
   
       pWin.document.write("  var msgchk = \\"\\";");
       pWin.document.write("  if (document.msgcenter.subchk.checked) {");
       pWin.document.write("     msgchk = \\"msgsub,\\";");
       pWin.document.write("  }");
       pWin.document.write(   "for (var i=1; i<=nmsg; i++) {");
       pWin.document.write("      var opnmsg = eval(\\"opener.document.SCORE.savemsg\\"+i);");
       pWin.document.write("      var frmmsg = eval(\\"document.msgcenter.msg\\"+i);");
       pWin.document.write("      opnmsg.value = frmmsg.value;");
       pWin.document.write("      var chkbox = eval(\\"document.msgcenter.msgn\\"+i);");
       pWin.document.write("      if (chkbox.checked) {");
       pWin.document.write("         msgchk += \\"savemsg\\"+i+\\",\\";");
       pWin.document.write("      }");
       pWin.document.write("  }");
       pWin.document.write("  if (document.msgcenter.newmsgchk.checked) {");
       pWin.document.write("     msgchk += \\"newmsg\\"+usrctr;");
       pWin.document.write("  }");
       pWin.document.write("  var includemsg = eval(\\"opener.document.SCORE.includemsg\\"+usrctr);");
       pWin.document.write("  includemsg.value = msgchk;");
   
       pWin.document.write("  self.close()");
   
       pWin.document.write("}");
   
       pWin.document.write("<");
       pWin.document.write("/script>");
   
       pWin.document.write("</head><body bgcolor=white>");
   
       pWin.document.write("<form action=\\"inactive\\" name=\\"msgcenter\\">");
       pWin.document.write("<input value=\\""+usrctr+"\\" name=\\"usrctr\\" type=\\"hidden\\">");
       pWin.document.write("<font color=\\"green\\" size=+1>&nbsp;Compose Message for \"+fullname+\"</font><br><br>");
   
       pWin.document.write("<table border=0 width=100%><tr><td bgcolor=\\"#777777\\">");
       pWin.document.write("<table border=0 width=100%><tr bgcolor=\\"#ddffff\\">");
       pWin.document.write("<td><b>Type</b></td><td><b>Include</b></td><td><b>Message</td></tr>");
 }  }
 #      function displaySubject(msg,shwsel) {
 # --------------------------- show submissions of a student, option to grade --------      pWin.document.write("<tr bgcolor=\\"#ffffdd\\">");
       pWin.document.write("<td>Subject</td>");
       pWin.document.write("<td align=\\"center\\"><input name=\\"subchk\\" type=\\"checkbox\\"" +shwsel+"></td>");
       pWin.document.write("<td><input name=\\"msgsub\\" type=\\"text\\" value=\\""+msg+" \\"size=\\"60\\" maxlength=\\"80\\"></td></tr>");
   }
   
   function displaySavedMsg(ctr,msg,shwsel) {
       pWin.document.write("<tr bgcolor=\\"#ffffdd\\">");
       pWin.document.write("<td align=\\"center\\">"+ctr+"</td>");
       pWin.document.write("<td align=\\"center\\"><input name=\\"msgn"+ctr+"\\" type=\\"checkbox\\"" +shwsel+"></td>");
       pWin.document.write("<td><input name=\\"msg"+ctr+"\\" type=\\"text\\" value=\\""+msg+" \\" size=\\"60\\" maxlength=\\"80\\"></td></tr>");
   }
   
     function newMsg(newmsg,shwsel) {
       pWin.document.write("<tr bgcolor=\\"#ffffdd\\">");
       pWin.document.write("<td align=\\"center\\">New</td>");
       pWin.document.write("<td align=\\"center\\"><input name=\\"newmsgchk\\" type=\\"checkbox\\"" +shwsel+"></td>");
       pWin.document.write("<td><input name=\\"newmsg\\" type=\\"text\\" onchange=\\"javascript:this.form.newmsgchk.checked=true\\" value=\\""+newmsg+" \\" size=\\"60\\" maxlength=\\"80\\"></td></tr>");
   }
   
     function msgTail() {
       pWin.document.write("</table>");
       pWin.document.write("</td></tr></table>&nbsp;");
       pWin.document.write("<input type=\\"button\\" value=\\"Save\\" onClick=\\"javascript:checkInput()\\">&nbsp;&nbsp;");
       pWin.document.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>");
       pWin.document.write("</form>");
       pWin.document.write("</body></html>");
   }
   
   //====================== Script for keyword highlight options ==============
     function kwhighlight() {
       var kwclr    = document.SCORE.kwclr.value;
       var kwsize   = document.SCORE.kwsize.value;
       var kwstyle  = document.SCORE.kwstyle.value;
       var redsel = "";
       var grnsel = "";
       var blusel = "";
       if (kwclr=="red")   {var redsel="checked"};
       if (kwclr=="green") {var grnsel="checked"};
       if (kwclr=="blue")  {var blusel="checked"};
       var sznsel = "";
       var sz1sel = "";
       var sz2sel = "";
       if (kwsize=="0")  {var sznsel="checked"};
       if (kwsize=="+1") {var sz1sel="checked"};
       if (kwsize=="+2") {var sz2sel="checked"};
       var synsel = "";
       var syisel = "";
       var sybsel = "";
       if (kwstyle=="")    {var synsel="checked"};
       if (kwstyle=="<i>") {var syisel="checked"};
       if (kwstyle=="<b>") {var sybsel="checked"};
       highlightCentral();
       highlightbody('red','red',redsel,'0','normal',sznsel,'','normal',synsel);
       highlightbody('green','green',grnsel,'+1','+1',sz1sel,'<i>','italic',syisel);
       highlightbody('blue','blue',blusel,'+2','+2',sz2sel,'<b>','bold',sybsel);
       highlightend();
       return;
     }
   
   
     function highlightCentral() {
       hwdWin = window.open('', 'KeywordHighlightCentral', 'toolbar=no,location=no,scrollbars=no,width=400,height=300,screenx=100,screeny=75');
       hwdWin.document.write("<html><head>");
       hwdWin.document.write("<title>Highlight Central</title>");
   
       hwdWin.document.write("<script language=javascript>");
       hwdWin.document.write("function updateChoice(flag) {");
       hwdWin.document.write("  opener.document.SCORE.kwclr.value = radioSelection(document.hlCenter.kwdclr);");
       hwdWin.document.write("  opener.document.SCORE.kwsize.value = radioSelection(document.hlCenter.kwdsize);");
       hwdWin.document.write("  opener.document.SCORE.kwstyle.value = radioSelection(document.hlCenter.kwdstyle);");
       hwdWin.document.write("  opener.document.SCORE.refresh.value = \\"on\\";");
       hwdWin.document.write("  if (opener.document.SCORE.keywords.value!=\\"\\"){");
       hwdWin.document.write("     opener.document.SCORE.submit();");
       hwdWin.document.write("  }");
       hwdWin.document.write("  self.close()");
       hwdWin.document.write("}");
   
       hwdWin.document.write("function radioSelection(radioButton) {");
       hwdWin.document.write("    var selection=null;");
       hwdWin.document.write("    for (var i=0; i<radioButton.length; i++) {");
       hwdWin.document.write("        if (radioButton[i].checked) {");
       hwdWin.document.write("            selection=radioButton[i].value;");
       hwdWin.document.write("            return selection;");
       hwdWin.document.write("        }");
       hwdWin.document.write("    }");
       hwdWin.document.write("}");
   
       hwdWin.document.write("<");
       hwdWin.document.write("/script>");
   
       hwdWin.document.write("</head><body bgcolor=white>");
   
       hwdWin.document.write("<form action=\\"inactive\\" name=\\"hlCenter\\">");
       hwdWin.document.write("<font color=\\"green\\" size=+1>&nbsp;Keyword Highlight Options</font><br><br>");
   
       hwdWin.document.write("<table border=0 width=100%><tr><td bgcolor=\\"#777777\\">");
       hwdWin.document.write("<table border=0 width=100%><tr bgcolor=\\"#ddffff\\">");
       hwdWin.document.write("<td><b>Text Color</b></td><td><b>Font Size</b></td><td><b>Font Style</td></tr>");
     }
   
     function highlightbody(clrval,clrtxt,clrsel,szval,sztxt,szsel,syval,sytxt,sysel) { 
       hwdWin.document.write("<tr bgcolor=\\"#ffffdd\\">");
       hwdWin.document.write("<td align=\\"left\\">");
       hwdWin.document.write("<input name=\\"kwdclr\\" type=\\"radio\\" value=\\""+clrval+"\\" "+clrsel+">&nbsp;"+clrtxt+"</td>");
       hwdWin.document.write("<td align=\\"left\\">");
       hwdWin.document.write("<input name=\\"kwdsize\\" type=\\"radio\\" value=\\""+szval+"\\" "+szsel+">&nbsp;"+sztxt+"</td>");
       hwdWin.document.write("<td align=\\"left\\">");
       hwdWin.document.write("<input name=\\"kwdstyle\\" type=\\"radio\\" value=\\""+syval+"\\" "+sysel+">&nbsp;"+sytxt+"</td>");
       hwdWin.document.write("</tr>");
     }
   
     function highlightend() { 
       hwdWin.document.write("</table>");
       hwdWin.document.write("</td></tr></table>&nbsp;");
   //    hwdWin.document.write("<input type=\\"button\\" value=\\"Save\\" onClick=\\"javascript:updateChoice(0)\\">&nbsp;&nbsp;");
       hwdWin.document.write("<input type=\\"button\\" value=\\"Save\\" onClick=\\"javascript:updateChoice(1)\\">&nbsp;&nbsp;");
       hwdWin.document.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>");
       hwdWin.document.write("</form>");
       hwdWin.document.write("</body></html>");
     }
   
   </script>
   SUBJAVASCRIPT
   }
   
   
   # --------------------------- show submissions of a student, option to grade 
 sub submission {  sub submission {
     my ($request,$counter,$total) = @_;      my ($request,$counter,$total) = @_;
   
     (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'})--;
     if ($ENV{'form.student'} eq '') { &moreinfo($request,'Need student login id'); return ''; }  #    if ($ENV{'form.student'} eq '') { &moreinfo($request,'Need student login id'); return ''; }
     my ($uname,$udom) = &finduser($ENV{'form.student'});      my ($uname,$udom)     = ($ENV{'form.student'},$ENV{'form.userdom'});
     if ($uname eq '') { &moreinfo($request,'Unable to find student'); return ''; }      ($uname,$udom)        = &finduser($uname) if $udom eq '';
       $ENV{'form.fullname'} = &get_fullname ($uname,$udom) if $ENV{'form.fullname'} eq '';
   #    if ($uname eq '') { &moreinfo($request,'Unable to find student'); return ''; }
   
     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 ''; }
Line 349  sub submission { Line 841  sub submission {
     # header info      # header info
     if ($counter == 0) {      if ($counter == 0) {
  &sub_page_js($request);   &sub_page_js($request);
  $request->print('<h2>&nbsp;<font color="#339933">Submission Record</font></h2>'.   $request->print('<h3>&nbsp;<font color="#339933">Submission Record</font></h3>'."\n".
  '<font size=+1>&nbsp;<b>Resource: </b>'.$url.'</font>');   '<font size=+1>&nbsp;<b>Resource: </b>'.$url.'</font>'."\n");
   
  # option to display problem, only once else it cause problems with the form later    # option to display problem, only once else it cause problems 
  # since the problem has a form.          # with the form later since the problem has a form.
  if ($ENV{'form.vProb'} eq 'yes') {   if ($ENV{'form.vProb'} eq 'yes') {
     my $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom,      my $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom,
       $ENV{'request.course.id'});        $ENV{'request.course.id'});
Line 361  sub submission { Line 853  sub submission {
    $ENV{'request.course.id'});     $ENV{'request.course.id'});
     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%"><tr><td bgcolor="#e6ffff">';      $result.='<table border="0" width="100%"><tr><td bgcolor="#e6ffff">';
     $result.='<b>Student\'s view of the problem</b></td></tr><tr><td bgcolor="#ffffff">'.$rendered.'<br />';      $result.='<b> View of the problem - '.$ENV{'form.fullname'}.
    '</b></td></tr><tr><td bgcolor="#ffffff">'.$rendered.'<br />';
     $result.='<b>Correct answer:</b><br />'.$companswer;      $result.='<b>Correct answer:</b><br />'.$companswer;
     $result.='</td></tr></table>';      $result.='</td></tr></table>';
     $result.='</td></tr></table><br />';      $result.='</td></tr></table><br />';
     $request->print($result);      $request->print($result);
  }   }
   
  # kwclr is the only variable that is guaranteed to be non blank if this subroutine has been called once.   # kwclr is the only variable that is guaranteed to be non blank 
           # if this subroutine has been called once.
  my %keyhash = ();   my %keyhash = ();
  if ($ENV{'form.kwclr'} eq '') {   if ($ENV{'form.kwclr'} eq '') {
     %keyhash = &Apache::lonnet::dump('nohist_handgrade',      %keyhash = &Apache::lonnet::dump('nohist_handgrade',
Line 385  sub submission { Line 879  sub submission {
     $ENV{'form.savemsgN'} = $keyhash{$symb.'_savemsgN'} ne '' ? $keyhash{$symb.'_savemsgN'} : '0';      $ENV{'form.savemsgN'} = $keyhash{$symb.'_savemsgN'} ne '' ? $keyhash{$symb.'_savemsgN'} : '0';
   
  }   }
   
  $request->print('<form action="/adm/grades" method="post" name="SCORE">'."\n".   $request->print('<form action="/adm/grades" method="post" name="SCORE">'."\n".
  '<input type="hidden" name="command"    value="handgrade" />'."\n".   '<input type="hidden" name="command"    value="handgrade" />'."\n".
  '<input type="hidden" name="refresh"    value="off" />'."\n".   '<input type="hidden" name="refresh"    value="off" />'."\n".
Line 425  sub submission { Line 920  sub submission {
 KEYWORDS  KEYWORDS
         }          }
     }      }
   
     my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);      my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);
     my ($partlist,$handgrade) = &response_type($url);      my ($partlist,$handgrade) = &response_type($url);
 #    &print_hash($request,\%record);  
   
     # Student info      # Display student info
     $request->print(($counter == 0 ? '' : '<br />'));      $request->print(($counter == 0 ? '' : '<br />'));
 #    my $fullname = ($ENV{'form.fullname'} ne '' ? $ENV{'form.fullname'} : &get_fullname($uname,$udom));      my $result='<table border="0" width=100%><tr><td bgcolor="#777777">'."\n".
     my $result='<table border="0" width=100%><tr><td bgcolor="#777777">'.   '<table border="0" width=100%><tr bgcolor="#edffff"><td>'."\n";
  '<table border="0" width=100%><tr bgcolor="#ffffff"><td>';  
       $result.='<b>Fullname: </b>'.$ENV{'form.fullname'}.
     $result.='<table border="0"><tr bgcolor="#ffffff"><td><b>Fullname: </b>'.$ENV{'form.fullname'}.   '<font color="#999999">&nbsp; &nbsp;Username: '.$uname.'</font>'.
 #    $result.='<table border="0"><tr bgcolor="#ffffff"><td><b>Fullname: </b>'.$fullname.   '<font color="#999999">&nbsp; &nbsp;Domain: '.$udom.'</font><br />'."\n";
  '</td><td>&nbsp; &nbsp;<b>Username: </b>'.$uname.      $result.='<input type="hidden" name="name'.$counter.
  '</td><td>&nbsp; &nbsp;<b>Domain: </b>'.$udom.'</td></tr>';   '" value="'.$ENV{'form.fullname'}.'" />'."\n";
   
       # If this is handgraded, then check for collaborators
       my @col_fullnames;
     if ($ENV{'form.handgrade'} eq 'yes') {      if ($ENV{'form.handgrade'} eq 'yes') {
  my @col_list;   my @col_list;
  ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist('all','0');   ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist('all','0');
  for (keys (%$handgrade)) {   for (keys (%$handgrade)) {
     my $ncol = &Apache::lonnet::EXT('resource.'.$_.'.maxcollaborators',$symb,$udom,$uname);      my $ncol = &Apache::lonnet::EXT('resource.'.$_.
       '.maxcollaborators',$symb,$udom,$uname);
     if ($ncol > 0) {      if ($ncol > 0) {
  s/\_/\./g;   s/\_/\./g;
  if ($record{'resource.'.$_.'.collaborators'} ne '') {   if ($record{'resource.'.$_.'.collaborators'} ne '') {
     my (@collaborators) = split(/,?\s+/,$record{'resource.'.$_.'.collaborators'});      my (@collaborators) = split(/,?\s+/,
    $record{'resource.'.$_.'.collaborators'});
     my (@badcollaborators);      my (@badcollaborators);
     if (scalar(@collaborators) != 0) {      if (scalar(@collaborators) != 0) {
  $result.='<tr bgcolor="#ffffff"><td colspan=3><b>Collaborators: </b>';   $result.='<b>Collaborators: </b>';
  foreach my $collaborator (@collaborators) {   foreach my $collaborator (@collaborators) {
     $collaborator = $collaborator =~ /\@|:/ ?       $collaborator = $collaborator =~ /\@|:/ ? 
  (split(/@|:/,$collaborator))[0] : $collaborator;   (split(/@|:/,$collaborator))[0] : $collaborator;
Line 460  KEYWORDS Line 960  KEYWORDS
  next;   next;
     }      }
     push @col_list, $collaborator;      push @col_list, $collaborator;
     $result.=$$fullname{$collaborator.':'.$udom}.' ('.$collaborator.') &nbsp; &nbsp;';      my ($lastname,$givenn) = split(/,/,$$fullname{$collaborator.':'.$udom});
       push @col_fullnames, $givenn.' '.$lastname;
       $result.=$$fullname{$collaborator.':'.$udom}.'&nbsp; &nbsp; &nbsp;';
  }   }
  $result.='</td></tr>'."\n";   $result.='<br />'."\n";
  $result.='<tr bgcolor="#ffbbbb"><td colspan=2>'.   $result.='<table border="0"><tr bgcolor="#ffbbbb"><td>'.
     'This student has submitted '.(scalar (@badcollaborators) > 1 ? '' : 'an').      'This student has submitted '.
       (scalar (@badcollaborators) > 1 ? '' : 'an').
     ' invalid collaborator'.(scalar (@badcollaborators) > 1 ? 's. ' : '. ').      ' invalid collaborator'.(scalar (@badcollaborators) > 1 ? 's. ' : '. ').
     (join ', ',@badcollaborators).'</td></tr>'       (join ', ',@badcollaborators).'</td></tr></table>' 
     if (scalar(@badcollaborators) > 0);      if (scalar(@badcollaborators) > 0);
   
  $result.='<tr bgcolor="#ffbbbb"><td colspan=2>'.   $result.='<table border="0"><tr bgcolor="#ffbbbb"><td>'.
     'This student has submitted too many collaborators. Maximum is '.      'This student has submitted too many collaborators. Maximum is '.
     $ncol.'.</td></tr>' if (scalar(@collaborators) > $ncol);      $ncol.'.</td></tr></table>' if (scalar(@collaborators) > $ncol);
  $result.='<input type="hidden" name="collaborator'.$counter.   $result.='<input type="hidden" name="collaborator'.$counter.
     '" value="'.(join ':',@col_list).'" />'."\n";      '" value="'.(join ':',@col_list).'" />'."\n";
     }      }
Line 479  KEYWORDS Line 982  KEYWORDS
     }      }
  }   }
     }      }
     $request->print($result.'</table>'."\n");      $request->print($result."\n");
   
     # print student answer      # print student answer/submission
       # Options are (1) Handgaded submission only
       #             (2) Last submission, includes submission that is not handgraded 
       #                  (for multi-response type part)
       #             (3) Last submission plus the parts info
       #             (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'}) {   if ($ENV{'form.'.$uname.':'.$udom.':submitted_by'}) {
     my $submitby='</td></tr><tr><td bgcolor="#e6ffff">'.      my $submitby=''.
  '<b>Collaborative submission by: </b>'.   '<b>Collaborative submission by: </b>'.
  '<a href="javascript:viewSubmitter(\''.$ENV{'form.'.$uname.':'.$udom.':submitted_by'}.   '<a href="javascript:viewSubmitter(\''.
    $ENV{'form.'.$uname.':'.$udom.':submitted_by'}.
  '\')"; TARGET=_self>'.   '\')"; TARGET=_self>'.
  $$fullname{$ENV{'form.'.$uname.':'.$udom.':submitted_by'}}.'</a>';   $$fullname{$ENV{'form.'.$uname.':'.$udom.':submitted_by'}}.'</a>';
     $submitby.='</td></tr><tr><td bgcolor="#ffffff">'."\n";  
     $request->print($submitby);      $request->print($submitby);
  } else {   } else {
     my ($string,$timestamp)=&get_last_submission ($symb,$uname,$udom,$ENV{'request.course.id'});      my ($string,$timestamp)=
     my $lastsubonly.='</td></tr><tr><td bgcolor="#e6ffff"><b>Last Submission Only</b>'.   &get_last_submission (%record);
  ($$timestamp eq '' ? '' : '&nbsp; &nbsp; <b>Date Submitted:</b> '.$$timestamp).'</td></tr>';      my $lastsubonly.=''.
    ($$timestamp eq '' ? '' : '<b>Date Submitted:</b> '.
    $$timestamp).'';
     if ($$timestamp eq '') {      if ($$timestamp eq '') {
  $lastsubonly.='<tr><td bgcolor="#ffffe6">'.$$string[0].'</td></tr>';   $lastsubonly.='<tr><td bgcolor="#ffffe6">'.$$string[0].'</td></tr>'."\n";
     } 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\.(\d+)\.(\d+)\.submission/;
  if ($part eq ($partid.'_'.$respid)) {   if ($part eq ($partid.'_'.$respid)) {
     my ($ressub,$subval) = split(/:/,$_,2);      my ($ressub,$subval) = split(/:/,$_,2);
     $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part ID</b> '.      $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '.
  $partid.' <b>Response ID</b> '.$respid.   $partid.'</b> <font color="#999999">( ID '.$respid.
  ' <b>Submission</b> '.&keywords_highlight($subval).'</td></tr>'   ' )</font>&nbsp; &nbsp;<b>Answer: </b>'.
    &keywords_highlight($subval).'</td></tr>'."\n"
  if ($ENV{'form.lastSub'} eq 'lastonly' ||    if ($ENV{'form.lastSub'} eq 'lastonly' || 
     ($ENV{'form.lastSub'} eq 'hdgrade' && $$handgrade{$part} =~ /:yes$/));      ($ENV{'form.lastSub'} eq 'hdgrade' && 
        $$handgrade{$part} =~ /:yes$/));
  }   }
     }      }
  }   }
     }      }
     $lastsubonly.='</td></tr><tr><td bgcolor="#ffffff">'."\n";      $lastsubonly.='</td></tr>'."\n";
     $request->print($lastsubonly);      $request->print($lastsubonly);
  }   }
     } else {      } else {
  $request->print(&Apache::loncommon::get_previous_attempt($symb,$uname,$udom,   $request->print(&Apache::loncommon::get_previous_attempt($symb,$uname,$udom,
  $ENV{'request.course.id'},$last,   $ENV{'request.course.id'},
  '.submission','Apache::grades::keywords_highlight'));   $last,'.submission',
    'Apache::grades::keywords_highlight'));
     }      }
           
     # view submission with no grading option      # return if view submission with no grading option
     if ($ENV{'form.showgrading'} eq '') {      if ($ENV{'form.showgrading'} eq '') {
  $request->print('</td></tr></table></td></tr></table></form>');   $request->print('</td></tr></table></td></tr></table></form>'."\n");
  return;   return;
     }      }
   
       # Grading options
     $result='<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n".      $result='<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n".
  '<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n".   '<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n".
  '<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':'.$udom.'" />'."\n";   '<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':'
     $result.='&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.   .$udom.'" />'."\n";
  ',\''.$fullname.'\')"; TARGET=_self>Compose Message</a><br />'."\n" if ($ENV{'form.handgrade'} eq 'yes');      my ($lastname,$givenn) = split(/,/,$ENV{'form.fullname'});
       my $msgfor = $givenn.' '.$lastname;
       if (scalar(@col_fullnames) > 0) {
    my $lastone = pop @col_fullnames;
    $msgfor .= ', '.(join ', ',@col_fullnames).' and '.$lastone.'.';
       }
       $result.='<tr><td bgcolor="#ffffff">'."\n".
    '&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.
    ',\''.$msgfor.'\')"; TARGET=_self>'.
    'Compose Message to student'.(scalar(@col_fullnames) >= 1 ? 's' : '').'</a>'.
    '<br />&nbsp;(Message will be sent when you click on Save & Next below.)'."\n" 
    if ($ENV{'form.handgrade'} eq 'yes');
     $request->print($result);      $request->print($result);
   
     my %seen = ();      my %seen = ();
Line 543  KEYWORDS Line 1068  KEYWORDS
  next if ($$handgrade{$_} =~ /:no$/);   next if ($$handgrade{$_} =~ /:no$/);
  push @partlist,$partid;   push @partlist,$partid;
  my $wgt    = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb,$udom,$uname);   my $wgt    = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb,$udom,$uname);
  my $wgtmsg = ($wgt > 0 ? '(problem weight)' : '<font color="red">problem weight assigned by computer</font>');   my $wgtmsg = ($wgt > 0 ? '(problem weight)' : 
         '<font color="red">problem weight assigned by computer</font>');
  $wgt       = ($wgt > 0 ? $wgt : '1');   $wgt       = ($wgt > 0 ? $wgt : '1');
  my $score  = ($record{'resource.'.$partid.'.awarded'} eq '' ?   my $score  = ($record{'resource.'.$partid.'.awarded'} eq '' ?
       '' : $record{'resource.'.$partid.'.awarded'}*$wgt);        '' : $record{'resource.'.$partid.'.awarded'}*$wgt);
   
  # display grading options  
  $result='<input type="hidden" name="WGT'.$counter.'_'.$partid.'" value="'.$wgt.'" />';   $result='<input type="hidden" name="WGT'.$counter.'_'.$partid.'" value="'.$wgt.'" />';
  $result.='<table border="0"><tr><td><b>Part </b>'.$partid.' <b>Points</b></td><td>';   $result.='<table border="0"><tr><td><b>Part </b>'.$partid.' <b>Points: </b></td><td>';
   
  my $ctr = 0;   my $ctr = 0;
  $result.='<table border="0"><tr>';  # display radio buttons in a nice table 10 across   $result.='<table border="0"><tr>';  # display radio buttons in a nice table 10 across
Line 571  KEYWORDS Line 1095  KEYWORDS
     'onChange="javascript:updateRadio(this.form.RADVAL'.$counter.'_'.$partid.      'onChange="javascript:updateRadio(this.form.RADVAL'.$counter.'_'.$partid.
     ',this.form.GD_BOX'.$counter.'_'.$partid.      ',this.form.GD_BOX'.$counter.'_'.$partid.
     ',this.form.GD_SEL'.$counter.'_'.$partid.      ',this.form.GD_SEL'.$counter.'_'.$partid.
     ',this.form.stores'.$counter.'_'.$partid.')" /></td>'."\n";      ',this.form.stores'.$counter.'_'.$partid.
       ','.$wgt.')" /></td>'."\n";
  $result.='<td>/'.$wgt.' '.$wgtmsg.' </td><td>';   $result.='<td>/'.$wgt.' '.$wgtmsg.' </td><td>';
   
  $result.='<select name="GD_SEL'.$counter.'_'.$partid.'" '.   $result.='<select name="GD_SEL'.$counter.'_'.$partid.'" '.
Line 582  KEYWORDS Line 1107  KEYWORDS
     '<option selected="on"> </option>'.      '<option selected="on"> </option>'.
     '<option>excused</option></select>'."&nbsp&nbsp\n";      '<option>excused</option></select>'."&nbsp&nbsp\n";
  $result.='<input type="hidden" name="stores'.$counter.'_'.$partid.'" value="0" />';   $result.='<input type="hidden" name="stores'.$counter.'_'.$partid.'" value="0" />';
  $result.='</td></tr></table>';   $result.='</td></tr></table>'."\n";
  $request->print($result);   $request->print($result);
     }      }
     $request->print('<input type="hidden" name="partlist'.$counter.'" value="'.(join ":",@partlist).'" />'."\n");      $result='<input type="hidden" name="partlist'.$counter.
     $request->print('</td></tr></table></td></tr></table>'."\n");   '" value="'.(join ":",@partlist).'" />'."\n";
       my $ctr = 0;
       while ($ctr < scalar(@partlist)) {
    $result.='<input type="hidden" name="partid'.$counter.'_'.$ctr.'" value="'.
       $partlist[$ctr].'" />'."\n";
    $ctr++;
       }
       $request->print($result.'</td></tr></table></td></tr></table>'."\n");
   
     # print end of form      # print end of form
     if ($counter == $total) {      if ($counter == $total) {
  my $endform.='<table border="0"><tr><td><input type="submit" name="gradeOpt" value="Save & Next" />';   my $endform='<table border="0"><tr><td>'.
  my $ntstu ='<select name="NTSTU">'.      '<input type="hidden" name="gradeOpt" value="" />'."\n";
     '<option>1</option><option>2</option>'.   if ($ENV{'form.handgrade'} eq 'yes') {
     '<option>3</option><option>5</option>'.      $endform.='<input type="button" value="Save & Next" '.
     '<option>7</option><option>10</option></select>'."\n";   'onClick="javascript:checksubmit(\'Save & Next\','.
  my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1');   $total.','.scalar(@partlist).');" TARGET=_self> &nbsp;'."\n";
  $ntstu =~ s/<option>$nsel</<option selected="on">$nsel</;      my $ntstu ='<select name="NTSTU">'.
  $endform.=$ntstu.'student(s) &nbsp;&nbsp;'.   '<option>1</option><option>2</option>'.
     '<input type="submit" name="gradeOpt" value="Next" />&nbsp'.   '<option>3</option><option>5</option>'.
     '<input type="submit" name="gradeOpt" value="Previous" />&nbsp'.   '<option>7</option><option>10</option></select>'."\n";
     '(Next and Previous do not save the scores.)'.      my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1');
     '</td><tr></table></form>';      $ntstu =~ s/<option>$nsel</<option selected="on">$nsel</;
       $endform.=$ntstu.'student(s) &nbsp;&nbsp;';
    } else {
       $endform.='<input type="hidden" name="NTSTU" value="1" />'."\n";
    }
    $endform.='<input type="button" value="Next" '.
       'onClick="javascript:checksubmit(\'Next\');" TARGET=_self> &nbsp;'."\n".
       '<input type="button" value="Previous" '.
       'onClick="javascript:checksubmit(\'Previous\');" TARGET=_self> &nbsp;';
    $endform.='(Next and Previous do not save the scores.)'."\n" 
       if ($ENV{'form.handgrade'} eq 'yes');
    $endform.='</td><tr></table></form>';
  $request->print($endform);   $request->print($endform);
     }      }
     return '';      return '';
 }  }
   
   #--- Retrieve the last submission for all the parts
 sub get_last_submission {  sub get_last_submission {
     my ($symb,$username,$domain,$course)=@_;      my (%returnhash)=@_;
     if ($symb) {      my (@string,$timestamp);
  my (@string,$timestamp);      if ($returnhash{'version'}) {
  my (%returnhash)=&Apache::lonnet::restore($symb,$course,$domain,$username);   my %lasthash=();
  if ($returnhash{'version'}) {   my ($version);
     my %lasthash=();   for ($version=1;$version<=$returnhash{'version'};$version++) {
     my ($version);      foreach (sort(split(/\:/,$returnhash{$version.':keys'}))) {
     for ($version=1;$version<=$returnhash{'version'};$version++) {   $lasthash{$_}=$returnhash{$version.':'.$_};
  foreach (sort(split(/\:/,$returnhash{$version.':keys'}))) {   if ($returnhash{$version.':'.$_} =~ /(SUBMITTED|DRAFT)$/) {
     $lasthash{$_}=$returnhash{$version.':'.$_};     $timestamp = scalar(localtime($returnhash{$version.':timestamp'}));
  }         } 
     }      }
     foreach ((keys %lasthash)) {   }
  if ($_ =~ /\.submission$/) {push @string, (join(':',$_,$lasthash{$_}))}   foreach ((keys %lasthash)) {
  if ($_ =~ /timestamp/) {$timestamp = scalar(localtime($lasthash{$_}))};      if ($_ =~ /\.submission$/) {
    my ($partid,$foo) = split(/submission$/,$_);
    my $draft  = $lasthash{$partid.'awarddetail'} eq 'DRAFT' ?
       '<font color="red">Draft Copy</font> ' : '';
    push @string, (join(':',$_,$draft.$lasthash{$_}));
     }      }
  }   }
  @string = $string[0] eq '' ? 'Nothing submitted - no attempts.' : @string;  
  return \@string,\$timestamp;  
     }      }
       @string = $string[0] eq '' ? 'Nothing submitted - no attempts.' : @string;
       return \@string,\$timestamp;
 }  }
   
   #--- High light keywords, with style choosen by user.
 sub keywords_highlight {  sub keywords_highlight {
     my $string  = shift;      my $string    = shift;
     my $size    = $ENV{'form.kwsize'} eq '0' ? '' : 'size='.$ENV{'form.kwsize'};      my $size      = $ENV{'form.kwsize'} eq '0' ? '' : 'size='.$ENV{'form.kwsize'};
     my $styleon = $ENV{'form.kwstyle'} eq ''  ? '' : $ENV{'form.kwstyle'};      my $styleon   = $ENV{'form.kwstyle'} eq ''  ? '' : $ENV{'form.kwstyle'};
     (my $styleoff = $styleon) =~ s/\</\<\//;      (my $styleoff = $styleon) =~ s/\</\<\//;
     my @keylist = split(/[,\s+]/,$ENV{'form.keywords'});      my @keylist   = split(/[,\s+]/,$ENV{'form.keywords'});
     foreach (@keylist) {      foreach (@keylist) {
  $string =~ s/\b$_(\b|\.)/\<font color\=$ENV{'form.kwclr'} $size\>$styleon$_$styleoff\<\/font\>/gi;   $string =~ s/\b$_(\b|\.)/\<font color\=$ENV{'form.kwclr'} $size\>$styleon$_$styleoff\<\/font\>/gi;
     }      }
     return $string;      return $string;
 }  }
   
   #--- Called from submission routine
 sub processHandGrade {  sub processHandGrade {
     my ($request) = shift;      my ($request) = shift;
     my $url    = $ENV{'form.url'};      my $url    = $ENV{'form.url'};
Line 650  sub processHandGrade { Line 1200  sub processHandGrade {
     my $ngrade = $ENV{'form.NCT'};      my $ngrade = $ENV{'form.NCT'};
     my $ntstu  = $ENV{'form.NTSTU'};      my $ntstu  = $ENV{'form.NTSTU'};
   
       if ($button eq 'Save & Next') {
    my $ctr = 0;
    while ($ctr < $ngrade) {
       my ($uname,$udom) = split(/:/,$ENV{'form.unamedom'.$ctr});
       my ($errorflag) = &saveHandGrade($request,$url,$symb,$uname,$udom,$ctr);
   
       my $includemsg = $ENV{'form.includemsg'.$ctr};
       my ($subject,$message,$msgstatus) = ('','','');
       if ($includemsg =~ /savemsg|new$ctr/) {
    $subject = $ENV{'form.msgsub'} if ($includemsg =~ /^msgsub/);
    my (@msgnum) = split(/,/,$includemsg);
    foreach (@msgnum) {
       $message.=$ENV{'form.'.$_} if ($_ =~ /savemsg|newmsg/ && $_ ne '');
    }
    $message =~ s/\s+/ /g;
    $msgstatus = &Apache::lonmsg::user_normal_msg ($uname,$udom,
          $ENV{'form.msgsub'},$message);
       }
       if ($ENV{'form.collaborator'.$ctr}) {
    my (@collaborators) = split(/:/,$ENV{'form.collaborator'.$ctr});
    foreach (@collaborators) {
       &saveHandGrade($request,$url,$symb,$_,$udom,$ctr,
      $ENV{'form.unamedom'.$ctr});
       if ($message ne '') {
    $msgstatus = &Apache::lonmsg::user_normal_msg ($_,$udom,
          $ENV{'form.msgsub'},
          $message);
       }
    }
       }
       $ctr++;
    }
       }
   
       # Keywords sorted in alphabatical order
     my $loginuser = $ENV{'user.name'}.':'.$ENV{'user.domain'};      my $loginuser = $ENV{'user.name'}.':'.$ENV{'user.domain'};
     my %keyhash = ();      my %keyhash = ();
     $ENV{'form.keywords'}           =~ s/,\s{0,}|\s+/ /g;      $ENV{'form.keywords'}           =~ s/,\s{0,}|\s+/ /g;
     $ENV{'form.keywords'}           =~ s/^\s+|\s+$//;      $ENV{'form.keywords'}           =~ s/^\s+|\s+$//;
       my (@keywords) = sort(split(/\s+/,$ENV{'form.keywords'}));
       $ENV{'form.keywords'} = join(' ',@keywords);
     $keyhash{$symb.'_keywords'}     = $ENV{'form.keywords'};      $keyhash{$symb.'_keywords'}     = $ENV{'form.keywords'};
     $keyhash{$symb.'_subject'}      = $ENV{'form.msgsub'};      $keyhash{$symb.'_subject'}      = $ENV{'form.msgsub'};
     $keyhash{$loginuser.'_kwclr'}   = $ENV{'form.kwclr'};      $keyhash{$loginuser.'_kwclr'}   = $ENV{'form.kwclr'};
     $keyhash{$loginuser.'_kwsize'}  = $ENV{'form.kwsize'};      $keyhash{$loginuser.'_kwsize'}  = $ENV{'form.kwsize'};
     $keyhash{$loginuser.'_kwstyle'} = $ENV{'form.kwstyle'};      $keyhash{$loginuser.'_kwstyle'} = $ENV{'form.kwstyle'};
   
       # message center - Order of message gets changed. Blank line is eliminated.
       # New messages are saved in ENV for the next student.
       # All messages are saved in nohist_handgrade.db
     my ($ctr,$idx) = (1,1);      my ($ctr,$idx) = (1,1);
     while ($ctr <= $ENV{'form.savemsgN'}) {      while ($ctr <= $ENV{'form.savemsgN'}) {
  if ($ENV{'form.savemsg'.$ctr} ne '') {   if ($ENV{'form.savemsg'.$ctr} ne '') {
Line 684  sub processHandGrade { Line 1274  sub processHandGrade {
  $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},   $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
  $ENV{'course.'.$ENV{'request.course.id'}.'.num'});   $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
   
       # Called by Save & Refresh from Highlight Attribute Window
     if ($ENV{'form.refresh'} eq 'on') {      if ($ENV{'form.refresh'} eq 'on') {
  my $ctr = 0;   my $ctr = 0;
  $ENV{'form.NTSTU'}=$ngrade;   $ENV{'form.NTSTU'}=$ngrade;
  while ($ctr < $ngrade) {   while ($ctr < $ngrade) {
     ($ENV{'form.student'},my $udom) = split(/:/,$ENV{'form.unamedom'.$ctr});      ($ENV{'form.student'},$ENV{'form.userdom'}) = split(/:/,$ENV{'form.unamedom'.$ctr});
     &submission($request,$ctr,$ngrade-1);      &submission($request,$ctr,$ngrade-1);
     $ctr++;      $ctr++;
  }   }
  return '';   return '';
     }      }
   
     if ($button eq 'Save & Next') {      # Get the next/previous one or group of students
  my $ctr = 0;  
  while ($ctr < $ngrade) {  
     my ($uname,$udom) = split(/:/,$ENV{'form.unamedom'.$ctr});  
     my ($errorflg) = &saveHandGrade($request,$url,$symb,$uname,$udom,$ctr);  
     return '' if ($errorflg eq 'error');  
   
     my $includemsg = $ENV{'form.includemsg'.$ctr};  
     my ($subject,$message,$msgstatus) = ('','','');  
     if ($includemsg =~ /savemsg|new$ctr/) {  
  $subject = $ENV{'form.msgsub'} if ($includemsg =~ /^msgsub/);  
  my (@msgnum) = split(/,/,$includemsg);  
  foreach (@msgnum) {  
     $message.=$ENV{'form.'.$_} if ($_ =~ /savemsg|newmsg/ && $_ ne '');  
  }  
  $message =~ s/\s+/ /g;  
  $msgstatus = &Apache::lonmsg::user_normal_msg ($uname,$udom,  
        $ENV{'form.msgsub'},$message);  
     }  
     if ($ENV{'form.collaborator'.$ctr}) {  
  my (@collaborators) = split(/:/,$ENV{'form.collaborator'.$ctr});  
  foreach (@collaborators) {  
     &saveHandGrade($request,$url,$symb,$_,$udom,$ctr,  
    $ENV{'form.unamedom'.$ctr});  
     if ($message ne '') {  
  $msgstatus = &Apache::lonmsg::user_normal_msg ($_,$udom,  
        $ENV{'form.msgsub'},  
        $message);  
     }  
  }  
     }  
     $ctr++;  
  }  
     }  
     my $firststu = $ENV{'form.unamedom0'};      my $firststu = $ENV{'form.unamedom0'};
     my $laststu = $ENV{'form.unamedom'.($ngrade-1)};      my $laststu = $ENV{'form.unamedom'.($ngrade-1)};
     $ctr = 2;      $ctr = 2;
Line 737  sub processHandGrade { Line 1295  sub processHandGrade {
  $ctr++;   $ctr++;
  $laststu = $firststu if ($ctr > $ngrade);   $laststu = $firststu if ($ctr > $ngrade);
     }      }
     my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($ENV{'form.section'},'0');  
   
       my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($ENV{'form.section'},'0');
     my (@parsedlist,@nextlist);      my (@parsedlist,@nextlist);
     my ($nextflg) = 0;      my ($nextflg) = 0;
     foreach ( sort(@{ $$classlist{$ENV{'form.section'}} }) ) {      foreach (sort {$$fullname{$a} cmp $$fullname{$b} } keys %$fullname) {
  if ($nextflg == 1 && $button =~ /Next$/) {   if ($nextflg == 1 && $button =~ /Next$/) {
     push @parsedlist,$_;      push @parsedlist,$_;
  }   }
Line 757  sub processHandGrade { Line 1315  sub processHandGrade {
     foreach my $student (@parsedlist) {      foreach my $student (@parsedlist) {
  my ($uname,$udom) = split(/:/,$student);   my ($uname,$udom) = split(/:/,$student);
  if ($ENV{'form.submitonly'} eq 'yes') {   if ($ENV{'form.submitonly'} eq 'yes') {
     my (%status) = &student_gradeStatus($ENV{'form.url'},$udom,$uname,$partlist) ;      my (%status) = &student_gradeStatus($ENV{'form.url'},$symb,$udom,$uname,$partlist) ;
     my $statusflg = '';      my $statusflg = '';
     foreach (keys(%status)) {      foreach (keys(%status)) {
  $statusflg = 1 if ($status{$_} ne 'nothing');   $statusflg = 1 if ($status{$_} ne 'nothing');
  my ($foo,$partid,$foo1) = split(/\./,$_);   my ($foo,$partid,$foo1) = split(/\./);
  $statusflg = '' if ($status{'resource.'.$partid.'.submitted_by'} ne '');   $statusflg = '' if ($status{'resource.'.$partid.'.submitted_by'} ne '');
     }      }
     next if ($statusflg eq '');      next if ($statusflg eq '');
Line 775  sub processHandGrade { Line 1333  sub processHandGrade {
   
     foreach (sort @nextlist) {      foreach (sort @nextlist) {
  my ($uname,$udom,$submitter) = split(/:/);   my ($uname,$udom,$submitter) = split(/:/);
  $ENV{'form.student'} = $uname;   $ENV{'form.student'}  = $uname;
    $ENV{'form.userdom'}  = $udom;
  $ENV{'form.fullname'} = $$fullname{$_};   $ENV{'form.fullname'} = $$fullname{$_};
 # $ENV{'form.'.$_.':submitted_by'} = $submitter;  # $ENV{'form.'.$_.':submitted_by'} = $submitter;
 # print "submitter=$ENV{'form.'.$_.':submitted_by'}= $submitter:<br>";  # print "submitter=$ENV{'form.'.$_.':submitted_by'}= $submitter:<br>";
Line 792  sub processHandGrade { Line 1351  sub processHandGrade {
     return '';      return '';
 }  }
   
   #---- 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 %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;
     foreach (split(/:/,$ENV{'form.partlist'.$newflg})) {      foreach (split(/:/,$ENV{'form.partlist'.$newflg})) {
  if ($ENV{'form.GD_SEL'.$newflg.'_'.$_} eq 'excused') {   if ($ENV{'form.GD_SEL'.$newflg.'_'.$_} eq 'excused') {
     $newrecord{'resource.'.$_.'.solved'} = 'excused';      $newrecord{'resource.'.$_.'.solved'} = 'excused' 
    if ($record{'resource.'.$_.'.solved'} ne 'excused');
  } else {   } else {
     my $pts    = ($ENV{'form.GD_BOX'.$newflg.'_'.$_} ne '' ?       my $pts = ($ENV{'form.GD_BOX'.$newflg.'_'.$_} ne '' ? 
   $ENV{'form.GD_BOX'.$newflg.'_'.$_} : $ENV{'form.RADVAL'.$newflg.'_'.$_});         $ENV{'form.GD_BOX'.$newflg.'_'.$_} : 
     if ($pts eq '') {         $ENV{'form.RADVAL'.$newflg.'_'.$_});
  &userError($request,'No point was assigned for part id '.$_.' and for username '.$stuname.'.');      my $wgt = $ENV{'form.WGT'.$newflg.'_'.$_} eq '' ? 1 : 
  return 'error';   $ENV{'form.WGT'.$newflg.'_'.$_};
     }  
     my $wgt    = $ENV{'form.WGT'.$newflg.'_'.$_} eq '' ? 1 : $ENV{'form.WGT'.$newflg.'_'.$_};  
     my $partial= $pts/$wgt;      my $partial= $pts/$wgt;
     $newrecord{'resource.'.$_.'.awarded'}  = $partial;      $newrecord{'resource.'.$_.'.awarded'}  = $partial 
    if ($record{'resource.'.$_.'.awarded'} ne $partial);
       my $reckey = 'resource.'.$_.'.solved';
     if ($partial == 0) {      if ($partial == 0) {
  $newrecord{'resource.'.$_.'.solved'} = 'incorrect_by_override';   $newrecord{$reckey} = 'incorrect_by_override' 
       if ($record{$reckey} ne 'incorrect_by_override');
     } else {      } else {
  $newrecord{'resource.'.$_.'.solved'} = 'correct_by_override';   $newrecord{$reckey} = 'correct_by_override' 
       if ($record{$reckey} ne 'correct_by_override');
     }      }
     $newrecord{'resource.'.$_.'.submitted_by'} = $submitter if ($submitter);      $newrecord{'resource.'.$_.'.submitted_by'} = $submitter 
    if ($submitter && ($record{'resource.'.$_.'.submitted_by'} ne $submitter));
  }   }
     }      }
       
     if ( scalar(keys(%newrecord)) > 0 ) {  
  $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";  
 # &print_hash($request,\%newrecord);  
  &Apache::lonnet::cstore(\%newrecord,$symb,$ENV{'request.course.id'},$domain,$stuname);  
     }  
     return '';  
 }  
   
 sub get_symb_and_url {  
     my ($request) = @_;  
     (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)));  
     if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }  
     return ($symb,$url);  
 }  
   
 sub show_grading_menu_form {      if (scalar(keys(%newrecord)) > 0) {
     my ($symb,$url)=@_;   $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
     my $result.='<form action="/adm/grades" method="post">'."\n".   &Apache::lonnet::cstore(\%newrecord,$symb,
  '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".   $ENV{'request.course.id'},$domain,$stuname);
  '<input type="hidden" name="url" value="'.$url.'" />'."\n".  
  '<input type="hidden" name="command" value="gradingmenu" />'."\n".  
  '<input type="submit" name="submit" value="Grading Menu" />'."\n".  
  '</form>'."\n";  
     return $result;  
 }  
   
 sub gradingmenu {  
     my ($request) = @_;  
     my ($symb,$url)=&get_symb_and_url($request);  
     if (!$symb) {return '';}  
     my $result='<h2>&nbsp;<font color="#339933">Select a Grading Method</font></h2>';  
     $result.='<table border="0">';  
     $result.='<tr><td colspan=3><font size=+1><b>Resource: </b>'.$url.'</font></td></tr>';  
     my ($partlist,$handgrade) = &response_type($url);  
     my ($resptype,$hdgrade)=('','no');  
     for (sort keys(%$handgrade)) {  
  my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});  
  $resptype = $responsetype;  
  $hdgrade = $handgrade if ($handgrade eq 'yes');  
  $result.='<tr><td><b>Part ID: </b>'.(split(/_/))[0].'</td>'.  
     '<td><b>Type: </b>'.$responsetype.'</td>'.  
     '<td><b>Handgrade: </b>'.$handgrade.'</font></td></tr>';  
     }      }
     $result.='</table>';  
     $result.=&view_edit_entire_class_form($symb,$url).'<br />';  
     $result.=&upcsvScores_form($symb,$url).'<br />';  
     $result.=&viewGradeaStu_form($symb,$url,$resptype,$hdgrade).'<br />';  
     $result.=&verifyReceipt_form($symb,$url).'<br />';  
     $result.=&view_classlist_form($symb,$url);  
   
     return $result;  
 }  
   
 sub view_classlist_form {  
     my ($symb,$url)=@_;  
     my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";  
     $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";  
     $result.='&nbsp;<b>View Class List</b></td></tr>'."\n";  
     $result.='<tr bgcolor=#ffffe6><td>'."\n";  
     $result.='<form action="/adm/grades" method="post">'."\n".  
  '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".  
  '<input type="hidden" name="url" value="'.$url.'" />'."\n".  
  '<input type="hidden" name="command" value="viewclasslist" />'."\n";  
     $result.='&nbsp;<input type="submit" name="submit" value="View Class" /></form>'."\n";  
     $result.='</td></tr></table>'."\n";  
     $result.='</td></tr></table>'."\n";  
     return $result;  
 }  
   
 sub viewclasslist {  
     my ($request) = shift;  
     my ($coursedomain,$coursenum) = split(/_/,$ENV{'request.course.id'});  
     my %classlist=&Apache::lonnet::dump('classlist',$coursedomain,$coursenum);  
     $request->print('<table border=1>');  
     foreach (sort keys(%classlist)) {  
 #    my ($unam,$udom) = split(/:/,$_,2);  
 #    my $section = &Apache::lonnet::usection($udom,$unam,$ENV{'request.course.id'});  
 #    my $fullname = &get_fullname ($unam,$udom);  
 #    my @uname;  
 #    $uname[0]=$unam;  
 #    my %userid=&Apache::lonnet::idrget($udom,@uname);  
 #    my $value=$classlist{$_}.':'.$userid{$unam}.':'.$section.':'.$fullname;  
 #    $classlist{$_}=$value;  
  $request->print('<tr><td>'.$_.' </td><td><pre> '.$classlist{$_}.'</pre></td></tr>');  
     }  
     $request->print('</table>');  
 #  my $putresult = &Apache::lonnet::put  
 #      ('classlist',\%classlist,  
 #       $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},  
 #       $ENV{'course.'.$ENV{'request.course.id'}.'.num'});  
   
     return '';      return '';
 }  }
   
 sub view_edit_entire_class_form {  #--------------------------------------------------------------------------------------
     my ($symb,$url)=@_;  #
     my ($classlist,$sections) = &getclasslist('all','0');  #-------------------------- Next few routines handles grading by section or whole class
     my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";  #
     $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";  #--- Javascript to handle grading by section or whole class
     $result.='&nbsp;<b>View/Grade Entire Section/Class</b></td></tr>'."\n";  
     $result.='<tr bgcolor=#ffffe6><td>'."\n";  
     $result.='<form action="/adm/grades" method="post">'."\n".  
  '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".  
  '<input type="hidden" name="url" value="'.$url.'" />'."\n".  
  '<input type="hidden" name="command" value="viewgrades" />'."\n";  
     $result.='&nbsp;<b>Select section:</b> <select name="section">'."\n";  
     foreach (sort (@$sections)) {  
  $result.= '<option>'.$_.'</option>'."\n";  
     }  
     $result.='<option selected="on">all</select>'."<br />\n";  
     $result.='&nbsp;<input type="submit" name="submit" value="View/Grade" /></form>'."\n";  
     $result.='</td></tr></table>'."\n";  
     $result.='</td></tr></table>'."\n";  
     return $result;  
 }  
   
 sub upcsvScores_form {  
     my ($symb,$url) = @_;  
     if (!$symb) {return '';}  
     my $result.='<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 above resource</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" />  
 $upfile_select  
 <br />&nbsp;<input type="submit" name="submit" value="Upload Grades" />  
 </form>  
 ENDUPFORM  
     $result.='</td></tr></table>'."\n";  
     $result.='</td></tr></table>'."\n";  
     return $result;  
 }  
   
 sub viewGradeaStu_form {  
     my ($symb,$url,$response,$handgrade) = @_;  
     my ($classlist,$sections) = &getclasslist('all','0');  
     my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";  
     $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";  
     $result.='&nbsp;<b>View/Grade an Individual Student\'s Submission</b></td></tr>'."\n";  
     $result.='<tr bgcolor=#ffffe6><td>'."\n";  
     $result.='<form action="/adm/grades" method="post">'."\n".  
  '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".  
  '<input type="hidden" name="url" value="'.$url.'" />'."\n".  
  '<input type="hidden" name="response" value="'.$response.'" />'."\n".  
  '<input type="hidden" name="handgrade" value="'.$handgrade.'" />'."\n".  
  '<input type="hidden" name="showgrading" value="yes" />'."\n".  
  '<input type="hidden" name="command" value="submission" />'."\n";  
   
     $result.='&nbsp;<b>Select section:</b> <select name="section">'."\n";  
     foreach (sort (@$sections)) {  
  $result.= '<option>'.$_.'</option>'."\n";  
     }  
     $result.= '<option selected="on">all</select>'."\n";  
     $result.='&nbsp;&nbsp;<b>Display students who has: </b>'.  
  '<input type="radio" name="submitonly" value="yes" checked> submitted'.  
  '<input type="radio" name="submitonly" value="all"> everybody <br />';  
     $result.='&nbsp;(Section "no" implies the students were not assigned a section.)<br />'   
  if (grep /no/,@$sections);  
       
     $result.='<br />&nbsp;<input type="submit" name="submit" value="View/Grade" />'."\n".  
  '</form>'."\n";  
     $result.='</td></tr></table>'."\n";  
     $result.='</td></tr></table>'."\n";  
     return $result;  
 }  
   
 sub verifyReceipt_form {  
     my ($symb,$url) = @_;  
     my $cdom=$ENV{"course.$ENV{'request.course.id'}.domain"};  
     my $cnum=$ENV{"course.$ENV{'request.course.id'}.num"};  
     my $hostver=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'});  
   
     my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";  
     $result.='<table width=100% border=0><tr><td bgcolor=#e6ffff>'."\n";  
     $result.='&nbsp;<b>Verify a Submission Receipt Issued by this Server</td></tr>'."\n";  
     $result.='<tr bgcolor=#ffffe6><td>'."\n";  
     $result.='<form action="/adm/grades" method="post">'."\n";  
     $result.='&nbsp;<tt>'.$hostver.'-<input type="text" name="receipt" size="4"></tt><br />'."\n";  
     $result.='&nbsp;<input type="submit" name="submit" value="Verify Receipt">'."\n";  
     $result.='<input type="hidden" name="command" value="verify">'."\n";  
     if ($ENV{'form.url'}) {  
  $result.='<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />';  
     }  
     if ($ENV{'form.symb'}) {  
  $result.='<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />';  
     }  
     $result.='</form>';  
     $result.='</td></tr></table>'."\n";  
     $result.='</td></tr></table>'."\n";  
     return $result;  
 }  
   
 sub viewgrades_js {  sub viewgrades_js {
     my ($request) = shift;      my ($request) = shift;
   
     $request->print(<<VIEWJAVASCRIPT);      $request->print(<<VIEWJAVASCRIPT);
 <script type="text/javascript" language="javascript">  <script type="text/javascript" language="javascript">
     function viewOneStudent(user) {     function writePoint(partid,weight,point) {
  document.onestudent.student.value = user;  
  document.onestudent.submit();  
     }  
   
     function writePoint(partid,weight,point) {  
  var radioButton = eval("document.classgrade.RADVAL_"+partid);   var radioButton = eval("document.classgrade.RADVAL_"+partid);
  var textbox = eval("document.classgrade.TEXTVAL_"+partid);   var textbox = eval("document.classgrade.TEXTVAL_"+partid);
  if (point == "textval") {   if (point == "textval") {
Line 1045  sub viewgrades_js { Line 1419  sub viewgrades_js {
  }   }
  return;   return;
     }      }
       if (point > weight) {
    var resp = confirm("You entered a value ("+point+
      ") greater than the weight for the part. Accept?");
    if (resp == false) {
       textbox.value = "";
       return;
    }
       }
     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 (point == i) {
Line 1117  sub viewgrades_js { Line 1499  sub viewgrades_js {
   
     function changeSelect(partid,user) {      function changeSelect(partid,user) {
  var selval = eval("document.classgrade.GD_"+user+'_'+partid+"_sv");   var selval = eval("document.classgrade.GD_"+user+'_'+partid+"_sv");
    var textbox = eval("document.classgrade.GD_"+user+'_'+partid+"_aw");
    var point  = textbox.value;
    var weight = eval("document.classgrade.weight_"+partid+".value");
   
    if (isNaN(point) || point < 0) {
       alert("A number equal or greater than 0 is expected. Entered value = "+point);
       textbox.value = "";
       return;
    }
    if (point > weight) {
       var resp = confirm("You entered a value ("+point+
          ") greater than the weight of the part. Accept?");
       if (resp == false) {
    textbox.value = "";
    return;
       }
    }
  selval[0].selected = true;   selval[0].selected = true;
     }      }
   
Line 1161  sub viewgrades_js { Line 1560  sub viewgrades_js {
  }   }
     }      }
   
     function submitForm() {  
  document.classgrade.submit();  
     }  
   
 </script>  </script>
 VIEWJAVASCRIPT  VIEWJAVASCRIPT
 }  }
   
   #--- show scores for a section or whole class w/ option to change/update a score
 sub viewgrades {  sub viewgrades {
     my ($request) = shift;      my ($request) = shift;
     &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='<h2><font color="#339933">Manual Grading</font></h2>';      my $result='<h3><font color="#339933">Manual Grading</font></h3>';
   
     $result.='<font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font>'."\n";      $result.='<font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font>'."\n";
   
     #view individual student submission form - called using Javascript viewOneStudent      #view individual student submission form - called using Javascript viewOneStudent
     $result.= '<form action="/adm/grades" method="post" name="onestudent">'."\n".      $result.=&jscriptNform($url,$symb);
  '<input type="hidden" name="symb"    value="'.$symb.'" />'."\n".  
  '<input type="hidden" name="url"     value="'.$url.'" />'."\n".  
  '<input type="hidden" name="command" value="submission" />'."\n".  
  '<input type="hidden" name="student" value="" />'."\n".  
  '</form>'."\n";  
   
     #start the form      #beginning of class grading form
     $result.= '<form action="/adm/grades" method="post" name="classgrade">'."\n".      $result.= '<form action="/adm/grades" method="post" name="classgrade">'."\n".
  '<input type="hidden" name="symb"    value="'.$symb.'" />'."\n".   '<input type="hidden" name="symb"    value="'.$symb.'" />'."\n".
  '<input type="hidden" name="url"     value="'.$url.'" />'."\n".   '<input type="hidden" name="url"     value="'.$url.'" />'."\n".
  '<input type="hidden" name="command" value="editgrades" />'."\n".   '<input type="hidden" name="command" value="editgrades" />'."\n".
  '<input type="hidden" name="section" value="'.$ENV{'form.section'}.'" />'."\n";   '<input type="hidden" name="section" value="'.$ENV{'form.section'}.'" />'."\n";
   
     $result.='To assign the same score for all the students use the radio buttons or '.      $result.='To assign the same score for all the students use the radio buttons or '.
  'text box below. To assign scores individually fill in the score boxes for '.   'text box below. To assign scores individually fill in the score boxes for '.
  'each student in the table below. <font color="red">A score that has already '.   'each student in the table below. <font color="red">A part that has already '.
  'been graded does not get changed using the radio buttons or text box. '.   'been graded does not get changed using the radio buttons or text box. '.
  'If needed, it has to be changed individually.</font>';   'If needed, it has to be changed individually.</font>';
   
       #radio buttons/text box for assigning points for a section or class.
       #handles different parts of a problem
     my ($partlist,$handgrade) = &response_type($ENV{'form.url'});      my ($partlist,$handgrade) = &response_type($ENV{'form.url'});
     my %weight = ();      my %weight = ();
     my $ctsparts = 0;      my $ctsparts = 0;
     $result.='<table border="0">';      $result.='<table border="0">';
       my %seen = ();
     for (sort keys(%$handgrade)) {      for (sort keys(%$handgrade)) {
  my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});  
  my ($partid,$respid) = split (/_/);   my ($partid,$respid) = split (/_/);
    next if $seen{$partid};
    $seen{$partid}++;
    my ($responsetype,$handgrade)=split(/:/,$$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;
   
  $result.='<input type="hidden" name="partid_'.$ctsparts.'" value="'.$partid.'" />'."\n";   $result.='<input type="hidden" name="partid_'.
  $result.='<tr><td><b>Part ID:</b> '.$partid.'&nbsp; &nbsp;</td><td>';      $ctsparts.'" value="'.$partid.'" />'."\n";
    $result.='<input type="hidden" name="weight_'.
       $partid.'" value="'.$weight{$partid}.'" />'."\n";
    $result.='<tr><td><b>Part  '.$partid.'&nbsp; &nbsp;Point:</b> </td><td>';
  $result.='<table border="0"><tr>';     $result.='<table border="0"><tr>';  
  my $ctr = 0;   my $ctr = 0;
  while ($ctr<=$weight{$partid}) { # display radio buttons in a nice table 10 across   while ($ctr<=$weight{$partid}) { # display radio buttons in a nice table 10 across
Line 1221  sub viewgrades { Line 1619  sub viewgrades {
     $ctr++;      $ctr++;
  }   }
  $result.='</tr></table>';   $result.='</tr></table>';
  $result.= '</td><td><b> or </b><input type="text" name="TEXTVAL_'.$partid.'" size="4" '.   $result.= '</td><td><b> or </b><input type="text" name="TEXTVAL_'.
     'onChange="javascript:writePoint('.$partid.','.$weight{$partid}.',\'textval\')" /> /'.      $partid.'" size="4" '.
       'onChange="javascript:writePoint('.$partid.','.$weight{$partid}.
       ',\'textval\')" /> /'.
     $weight{$partid}.' (problem weight)</td>'."\n";      $weight{$partid}.' (problem weight)</td>'."\n";
  $result.= '</td><td><select name="SELVAL_'.$partid.'"'.   $result.= '</td><td><select name="SELVAL_'.$partid.'"'.
     'onChange="javascript:writeRadText('.$partid.','.$weight{$partid}.')" /> '.      'onChange="javascript:writeRadText('.$partid.','.$weight{$partid}.')" /> '.
Line 1233  sub viewgrades { Line 1633  sub viewgrades {
     $result.='</table><input type="hidden" name="totalparts" value="'.$ctsparts.'" />';      $result.='</table><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> &nbsp; &nbsp;';
 #    $result.='<input type="button" value="Submit Changes" '.      $result.='<input type="button" value="Submit Changes" '.
 # 'onClick="document.classgrade.submit();" TARGET=_self />'."\n";   'onClick="javascript:submit();" TARGET=_self />'."\n";
     $result.= '<input type="submit" name="submit"  value="Submit Changes" />'."\n";  
   
       #table listing all the students in a section/class
       #header of table
     $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>Username</b></td><td><b>Fullname</b></td><td><b>Domain</b></td>'."\n";   '<td><b>Fullname</b></td><td><b>Username</b></td><td><b>Domain</b></td>'."\n";
     #get list of parts for this problem  
     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 1257  sub viewgrades { Line 1657  sub viewgrades {
  $result.='<td><b>'.$display.'</b></td>'."\n";   $result.='<td><b>'.$display.'</b></td>'."\n";
     }      }
     $result.='</tr>';      $result.='</tr>';
   
     #get info for each student      #get info for each student
       #list all the students - with points and grade status
     my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($ENV{'form.section'},'0');      my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($ENV{'form.section'},'0');
     my $ctr = 0;      my $ctr = 0;
     foreach ( sort(@{ $$classlist{$ENV{'form.section'}} }) ) {      foreach (sort {$$fullname{$a} cmp $$fullname{$b} } keys %$fullname) {
  (my $username = $_) = split(/:/);   my ($uname,$udom) = split(/:/);
  $result.='<input type="hidden" name="ctr'.$ctr.'" value="'.$username.'" />'."\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);
  $ctr++;   $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="submit" name="submit" value="Submit Changes" /></form>';      $result.='<input type="button" value="Submit Changes" '.
    'onClick="javascript:submit();" TARGET=_self /></form>'."\n";
     $result.=&show_grading_menu_form($symb,$url);      $result.=&show_grading_menu_form($symb,$url);
     return $result;      return $result;
 }  }
   
   #--- 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) = @_;
     my ($username,$domain) = split(/:/,$student);      my ($uname,$udom) = split(/:/,$student);
     my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$username);      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(\''.$username.'\')"; TARGET=_self>'.$username.'</a>'.   '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.
  '</td><td>'.$fullname.'</td><td align="middle">'.$domain.'</td>'."\n";   '\')"; TARGET=_self>'.$fullname.'</a>'.
    '</td><td>'.$uname.'</td><td align="middle">'.$udom.'</td>'."\n";
     foreach my $part (@$parts) {      foreach my $part (@$parts) {
  my ($temp,$part,$type)=split(/_/,$part);   my ($temp,$part,$type)=split(/_/,$part);
  my $score=$record{"resource.$part.$type"};   my $score=$record{"resource.$part.$type"};
Line 1288  sub viewstudentgrade { Line 1693  sub viewstudentgrade {
  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_'.$username.'_'.$part.'_aw_s" value="'.$pts.'" />'."\n";   'GD_'.$uname.'_'.$part.'_aw_s" value="'.$pts.'" />'."\n";
     $result.='<td align="middle"><input type="text" name="'.      $result.='<td align="middle"><input type="text" name="'.
  'GD_'.$username.'_'.$part.'_aw"'.   'GD_'.$uname.'_'.$part.'_aw" '.
  'onChange="javascript:changeSelect('.$part.',\''.$username.'\')" value="'.   'onChange="javascript:changeSelect('.$part.',\''.$uname.
  $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="'.      $result.='<input type="hidden" name="'.
  'GD_'.$username.'_'.$part.'_sv_s" value="'.$status.'" />'."\n";   'GD_'.$uname.'_'.$part.'_sv_s" value="'.$status.'" />'."\n";
     $result.='<td align="middle"><select name="'.      $result.='<td align="middle"><select name="'.
  'GD_'.$username.'_'.$part.'_sv" '.   'GD_'.$uname.'_'.$part.'_sv" '.
  'onChange="javascript:changeOneScore('.$part.',\''.$username.'\')" >'."\n";   'onChange="javascript:changeOneScore('.$part.',\''.$uname.'\')" >'."\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 1312  sub viewstudentgrade { Line 1717  sub viewstudentgrade {
     return $result;      return $result;
 }  }
   
   #--- change scores for all the students in a section/class
   #    record does not get update if unchanged
 sub editgrades {  sub editgrades {
     my ($request) = @_;      my ($request) = @_;
   
     my $symb=$ENV{'form.symb'};      my $symb=$ENV{'form.symb'};
     my $url =$ENV{'form.url'};      my $url =$ENV{'form.url'};
     my $result='<h2><font color="#339933">Current Grade Status</font></h2>';      my $title='<h3><font color="#339933">Current Grade Status</font></h3>';
     $result.='<font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font><br />'."\n";      $title.='<font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font><br />'."\n";
     $result.='<font size=+1><b>Section: </b>'.$ENV{'form.section'}.'</font>'."\n";      $title.='<font size=+1><b>Section: </b>'.$ENV{'form.section'}.'</font>'."\n";
     $result.= &show_grading_menu_form ($symb,$url);      $title.= &show_grading_menu_form ($symb,$url);
     $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>Fullname</b></td>'."\n";
   
Line 1337  sub editgrades { Line 1743  sub editgrades {
   
     my (@partid);      my (@partid);
     my %weight = ();      my %weight = ();
     my ($i,$ctr) = (0,0);      my ($i,$ctr,$count,$rec_update) = (0,0,0,0);
     while ($ctr < $ENV{'form.totalparts'}) {      while ($ctr < $ENV{'form.totalparts'}) {
  my $partid = $ENV{'form.partid_'.$ctr};   my $partid = $ENV{'form.partid_'.$ctr};
  push @partid,$partid;   push @partid,$partid;
  my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb);   $weight{$partid} = $ENV{'form.weight_'.$partid};
  $weight{$partid} = $wgt eq '' ? '1' : $wgt;  
  $ctr++;   $ctr++;
  $result .= '<td colspan = 2 align="center"><b>Part ID '.$partid.   $result .= '<td colspan = 2 align="center"><b>Part '.$partid.
     '</b> (Weight = '.$weight{$partid}.')</td>';      '</b> (Weight = '.$weight{$partid}.')</td>';
     }      }
     $result .= '</tr><tr bgcolor="#deffff">';      $result .= '</tr><tr bgcolor="#deffff">';
Line 1389  sub editgrades { Line 1794  sub editgrades {
   
     $updateflag = 1;      $updateflag = 1;
     $newrecord{'resource.'.$_.'.awarded'}  = $partial if $partial ne '';      $newrecord{'resource.'.$_.'.awarded'}  = $partial if $partial ne '';
     $newrecord{'resource.'.$_.'.solved'} = $score;      $newrecord{'resource.'.$_.'.solved'}   = $score;
       $rec_update++;
  }   }
  $result .= '</tr>'."\n";   $result .= '</tr>'."\n";
  if ($updateflag) {   if ($updateflag) {
       $count++;
     $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";      $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
     &Apache::lonnet::cstore(\%newrecord,$symb,$ENV{'request.course.id'},      &Apache::lonnet::cstore(\%newrecord,$symb,$ENV{'request.course.id'},
     $udom,$user);      $udom,$user);
  }   }
     }      }
     $result .= '</table></td></tr></table>'."\n";      $result .= '</table></td></tr></table>'."\n";
     return $result;      my $msg = '<b>Number of records updated = '.$rec_update.
 }   ' for '.$count.' student'.($count <= 1 ? '' : 's').'.</b><br />'.
    '<b>Total number of students = '.$ENV{'form.total'}.'</b><br />';
       return $title.$msg.$result;
 #FIXME need to look at the metadata <stores> spec on what type of data to accept and provide an  
 #interface based on that, also do that to above function.  
 sub setstudentgrade {  
     my ($url,$symb,$courseid,$student,@parts) = @_;  
     my $result ='';  
     my ($stuname,$domain) = split(/:/,$student);  
     my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$stuname);  
     my %newrecord;  
   
     foreach my $part (@parts) {  
  my ($temp,$part,$type)=split(/_/,$part);  
  my $oldscore=$record{"resource.$part.$type"};  
  my $newscore=$ENV{"form.GD.$student.$part.$type"};  
  if ($type eq 'solved') {  
     my $update=0;  
     if ($newscore eq 'nothing' ) {  
  if ($oldscore ne '') {  
     $update=1;  
     $newscore = '';  
  }  
     } elsif ($oldscore !~ m/^$newscore/) {  
  $update=1;  
  $result.="Updating $stuname to $newscore<br />\n";  
  if ($newscore eq 'correct')   { $newscore = 'correct_by_override'; }  
  if ($newscore eq 'incorrect') { $newscore = 'incorrect_by_override'; }  
  if ($newscore eq 'excused')   { $newscore = 'excused'; }  
  if ($newscore eq 'ungraded')  { $newscore = 'ungraded_attempted'; }  
     } else {  
  #$result.="$stuname:$part:$type:unchanged  $oldscore to $newscore:<br />\n";  
     }  
     if ($update) { $newrecord{"resource.$part.$type"}=$newscore; }  
  } else {  
     if ($oldscore ne $newscore) {  
  $newrecord{"resource.$part.$type"}=$newscore;  
  $result.="Updating $student"."'s status for $part.$type to $newscore<br />\n";  
     } else {  
  #$result.="$stuname:$part:$type:unchanged  $oldscore to $newscore:<br />\n";  
     }  
  }  
     }  
     if ( scalar(keys(%newrecord)) > 0 ) {  
  $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";  
 #       &Apache::lonnet::cstore(\%newrecord,$symb,$courseid,$domain,$stuname);  
   
  $result.="Stored away ".scalar(keys(%newrecord))." elements.<br />\n";  
     }  
     return $result;  
 }  
   
   
 sub sub_page_js {  
     my $request = shift;  
     $request->print(<<SUBJAVASCRIPT);  
 <script type="text/javascript" language="javascript">  
   function updateRadio(radioButton,formtextbox,formsel,scores) {  
      var pts = formtextbox.value;  
      var resetbox =false;  
      if (isNaN(pts) || pts < 0) {  
  alert("A number equal or greater than 0 is expected. Entered value = "+pts);  
  for (var i=0; i<radioButton.length; i++) {  
    if (radioButton[i].checked) {  
       formtextbox.value = i;  
       resetbox = true;  
    }  
  }  
  if (!resetbox) {  
    formtextbox.value = "";  
  }  
  return;  
     }  
   
     for (var i=0; i<radioButton.length; i++) {  
  radioButton[i].checked=false;  
  if (pts == i) {  
    radioButton[i].checked=true;  
  }  
     }  
     updateSelect(formsel);  
     scores.value = "0";  
   }  
   
   function writeBox(formrad,formsel,pts,scores) {  
     formrad.value = pts;  
     scores.value = "0";  
     updateSelect(formsel,pts);  
     return;  
   }  
   
   function clearRadBox(radioButton,formbox,formsel,scores) {  
     for (var i=0; i<formsel.length; i++) {  
  if (formsel[i].selected) {  
     var selectx=i;  
  }  
     }  
     if (selectx == scores.value) { return };  
     formbox.value = "";  
     for (var i=0; i<radioButton.length; i++) {  
  radioButton[i].checked=false;  
     }  
     scores.value = selectx;  
   }  
   
   function updateSelect(formsel) {  
     formsel[0].selected = true;  
     return;  
   }  
   
 //===================== Show list of keywords ====================  
   function keywords(keyform) {  
     var keywds = keyform.value;  
     var nret = prompt("Keywords list, separated by a space. Add/delete to list if desired.",keywds);  
     if (nret==null) return;  
     keyform.value = nret;  
     return;  
   }  
   
 //===================== Script to view submitted by ==================  
   function viewSubmitter(submitter) {  
     document.SCORE.refresh.value = "on";  
     document.SCORE.NCT.value = "1";  
     document.SCORE.unamedom0.value = submitter;  
     document.SCORE.submit();  
     return;  
   }  
   
 //===================== Script to add keyword(s) ==================  
   function getSel() {  
     if (document.getSelection) txt = document.getSelection();  
     else if (document.selection) txt = document.selection.createRange().text;  
     else return;  
     var cleantxt = txt.replace(new RegExp('([\\f\\n\\r\\t\\v ])+', 'g')," ");  
     if (cleantxt=="") {  
  alert("Select a word or group of words from document and then click this link.");  
  return;  
     }  
     var nret = prompt("Add selection to keyword list? Edit if desired.",cleantxt);  
     if (nret==null) return;  
     var curlist = document.SCORE.keywords.value;  
     document.SCORE.keywords.value = curlist+" "+nret;  
     return;  
   }  
   
 //====================== Script for composing message ==============  
   function msgCenter(msgform,usrctr,fullname) {  
     var Nmsg  = msgform.savemsgN.value;  
     savedMsgHeader(Nmsg,usrctr,fullname);  
     var subject = msgform.msgsub.value;  
     var rtrchk  = eval("document.SCORE.includemsg"+usrctr);  
     var msgchk = rtrchk.value;  
 //    alert("checked=>"+msgchk);  
     re = /msgsub/;  
     var shwsel = "";  
     if (re.test(msgchk)) { shwsel = "checked" }  
     displaySubject(subject,shwsel);  
     for (var i=1; i<=Nmsg; i++) {  
  var testpt = "savemsg"+i+",";  
  re = /testpt/;  
  shwsel = "";  
  if (re.test(msgchk)) { shwsel = "checked" }  
  var message = eval("document.SCORE.savemsg"+i+".value");  
  displaySavedMsg(i,message,shwsel);  
     }  
     newmsg = eval("document.SCORE.newmsg"+usrctr+".value");  
     shwsel = "";  
     re = /newmsg/;  
     if (re.test(msgchk)) { shwsel = "checked" }  
     newMsg(newmsg,shwsel);  
     msgTail();   
     return;  
   }  
   
   function savedMsgHeader(Nmsg,usrctr,fullname) {  
     var height = 30*Nmsg+250;  
     var scrollbar = "no";  
     if (height > 600) {  
  height = 600;  
  scrollbar = "yes";  
     }  
 /*    if (window.pWin)  
  window.pWin.close(); */  
     pWin = window.open('', 'MessageCenter', 'toolbar=no,location=no,scrollbars='+scrollbar+',screenx=70,screeny=75,width=600,height='+height);  
     pWin.document.write("<html><head>");  
     pWin.document.write("<title>Message Central</title>");  
   
     pWin.document.write("<script language=javascript>");  
     pWin.document.write("function checkInput() {");  
     pWin.document.write("  opener.document.SCORE.msgsub.value = document.msgcenter.msgsub.value;");  
     pWin.document.write("  var nmsg   = opener.document.SCORE.savemsgN.value;");  
     pWin.document.write("  var usrctr = document.msgcenter.usrctr.value;");  
     pWin.document.write("  var newval = eval(\\"opener.document.SCORE.newmsg\\"+usrctr);");  
     pWin.document.write("  newval.value = document.msgcenter.newmsg.value;");  
   
     pWin.document.write("  var msgchk = \\"\\";");  
     pWin.document.write("  if (document.msgcenter.subchk.checked) {");  
     pWin.document.write("     msgchk = \\"msgsub,\\";");  
     pWin.document.write("  }");  
     pWin.document.write(   "for (var i=1; i<=nmsg; i++) {");  
     pWin.document.write("      var opnmsg = eval(\\"opener.document.SCORE.savemsg\\"+i);");  
     pWin.document.write("      var frmmsg = eval(\\"document.msgcenter.msg\\"+i);");  
     pWin.document.write("      opnmsg.value = frmmsg.value;");  
     pWin.document.write("      var chkbox = eval(\\"document.msgcenter.msgn\\"+i);");  
     pWin.document.write("      if (chkbox.checked) {");  
     pWin.document.write("         msgchk += \\"savemsg\\"+i+\\",\\";");  
     pWin.document.write("      }");  
     pWin.document.write("  }");  
     pWin.document.write("  if (document.msgcenter.newmsgchk.checked) {");  
     pWin.document.write("     msgchk += \\"newmsg\\"+usrctr;");  
     pWin.document.write("  }");  
     pWin.document.write("  var includemsg = eval(\\"opener.document.SCORE.includemsg\\"+usrctr);");  
     pWin.document.write("  includemsg.value = msgchk;");  
   
 //    pWin.document.write("  alert(\\"slected=\\"+msgchk)");  
     pWin.document.write("  self.close()");  
   
     pWin.document.write("}");  
   
     pWin.document.write("<");  
     pWin.document.write("/script>");  
   
     pWin.document.write("</head><body bgcolor=white>");  
   
     pWin.document.write("<form action=\\"inactive\\" name=\\"msgcenter\\">");  
     pWin.document.write("<input value=\\""+usrctr+"\\" name=\\"usrctr\\" type=\\"hidden\\">");  
     pWin.document.write("<font color=\\"green\\" size=+1>&nbsp;Compose Message for \"+fullname+\"</font><br><br>");  
   
     pWin.document.write("<table border=0 width=100%><tr><td bgcolor=\\"#777777\\">");  
     pWin.document.write("<table border=0 width=100%><tr bgcolor=\\"#ddffff\\">");  
     pWin.document.write("<td><b>Type</b></td><td><b>Include</b></td><td><b>Message</td></tr>");  
 }  
     function displaySubject(msg,shwsel) {  
     pWin.document.write("<tr bgcolor=\\"#ffffdd\\">");  
     pWin.document.write("<td>Subject</td>");  
     pWin.document.write("<td align=\\"center\\"><input name=\\"subchk\\" type=\\"checkbox\\"" +shwsel+"></td>");  
     pWin.document.write("<td><input name=\\"msgsub\\" type=\\"text\\" value=\\""+msg+" \\"size=\\"60\\" maxlength=\\"80\\"></td></tr>");  
 }  
   
 function displaySavedMsg(ctr,msg,shwsel) {  
     pWin.document.write("<tr bgcolor=\\"#ffffdd\\">");  
     pWin.document.write("<td align=\\"center\\">"+ctr+"</td>");  
     pWin.document.write("<td align=\\"center\\"><input name=\\"msgn"+ctr+"\\" type=\\"checkbox\\"" +shwsel+"></td>");  
     pWin.document.write("<td><input name=\\"msg"+ctr+"\\" type=\\"text\\" value=\\""+msg+" \\" size=\\"60\\" maxlength=\\"80\\"></td></tr>");  
 }  }
   #------------- end of section for handling grading by section/class ---------
   #
   #----------------------------------------------------------------------------
   
   function newMsg(newmsg,shwsel) {  
     pWin.document.write("<tr bgcolor=\\"#ffffdd\\">");  
     pWin.document.write("<td align=\\"center\\">New</td>");  
     pWin.document.write("<td align=\\"center\\"><input name=\\"newmsgchk\\" type=\\"checkbox\\"" +shwsel+"></td>");  
     pWin.document.write("<td><input name=\\"newmsg\\" type=\\"text\\" onchange=\\"javascript:this.form.newmsgchk.checked=true\\" value=\\""+newmsg+" \\" size=\\"60\\" maxlength=\\"80\\"></td></tr>");  
 }  
   
   function msgTail() {  
     pWin.document.write("</table>");  
     pWin.document.write("</td></tr></table>&nbsp;");  
     pWin.document.write("<input type=\\"button\\" value=\\"Save\\" onClick=\\"javascript:checkInput()\\">&nbsp;&nbsp;");  
     pWin.document.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>");  
     pWin.document.write("</form>");  
     pWin.document.write("</body></html>");  
 }  
   
 //====================== Script for keyword highlight options ==============  
   function kwhighlight() {  
     var kwclr    = document.SCORE.kwclr.value;  
     var kwsize   = document.SCORE.kwsize.value;  
     var kwstyle  = document.SCORE.kwstyle.value;  
     var redsel = "";  
     var grnsel = "";  
     var blusel = "";  
     if (kwclr=="red")   {var redsel="checked"};  
     if (kwclr=="green") {var grnsel="checked"};  
     if (kwclr=="blue")  {var blusel="checked"};  
     var sznsel = "";  
     var sz1sel = "";  
     var sz2sel = "";  
     if (kwsize=="0")  {var sznsel="checked"};  
     if (kwsize=="+1") {var sz1sel="checked"};  
     if (kwsize=="+2") {var sz2sel="checked"};  
     var synsel = "";  
     var syisel = "";  
     var sybsel = "";  
     if (kwstyle=="")    {var synsel="checked"};  
     if (kwstyle=="<i>") {var syisel="checked"};  
     if (kwstyle=="<b>") {var sybsel="checked"};  
     highlightCentral();  
     highlightbody('red','red',redsel,'0','normal',sznsel,'','normal',synsel);  
     highlightbody('green','green',grnsel,'+1','+1',sz1sel,'<i>','italic',syisel);  
     highlightbody('blue','blue',blusel,'+2','+2',sz2sel,'<b>','bold',sybsel);  
     highlightend();  
     return;  
   }  
   
   
   function highlightCentral() {  
     hwdWin = window.open('', 'KeywordHighlightCentral', 'toolbar=no,location=no,scrollbars=no,width=400,height=300,screenx=100,screeny=75');  
     hwdWin.document.write("<html><head>");  
     hwdWin.document.write("<title>Highlight Central</title>");  
   
     hwdWin.document.write("<script language=javascript>");  
     hwdWin.document.write("function updateChoice(flag) {");  
     hwdWin.document.write("  opener.document.SCORE.kwclr.value = radioSelection(document.hlCenter.kwdclr);");  
     hwdWin.document.write("  opener.document.SCORE.kwsize.value = radioSelection(document.hlCenter.kwdsize);");  
     hwdWin.document.write("  opener.document.SCORE.kwstyle.value = radioSelection(document.hlCenter.kwdstyle);");  
 //    hwdWin.document.write("     var kwords=opener.document.SCORE.keywords.value;");  
 //    hwdWin.document.write("     alert(\\"keywords=\\"+opener.document.SCORE.keywords.value);");  
 //    hwdWin.document.write("     return;");  
   
     hwdWin.document.write("  if (flag==1){");  
     hwdWin.document.write("     opener.document.SCORE.refresh.value = \\"on\\";");  
     hwdWin.document.write("     if (opener.document.SCORE.keywords.value!=\\"\\"){");  
     hwdWin.document.write("        opener.document.SCORE.submit();");  
     hwdWin.document.write("     }");  
     hwdWin.document.write("   }");  
     hwdWin.document.write("  self.close()");  
     hwdWin.document.write("}");  
   
     hwdWin.document.write("function radioSelection(radioButton) {");  
     hwdWin.document.write("    var selection=null;");  
     hwdWin.document.write("    for (var i=0; i<radioButton.length; i++) {");  
     hwdWin.document.write("        if (radioButton[i].checked) {");  
     hwdWin.document.write("            selection=radioButton[i].value;");  
     hwdWin.document.write("            return selection;");  
     hwdWin.document.write("        }");  
     hwdWin.document.write("    }");  
     hwdWin.document.write("}");  
   
     hwdWin.document.write("<");  
     hwdWin.document.write("/script>");  
   
     hwdWin.document.write("</head><body bgcolor=white>");  
   
     hwdWin.document.write("<form action=\\"inactive\\" name=\\"hlCenter\\">");  
     hwdWin.document.write("<font color=\\"green\\" size=+1>&nbsp;Keyword Highlight Options</font><br><br>");  
   
     hwdWin.document.write("<table border=0 width=100%><tr><td bgcolor=\\"#777777\\">");  
     hwdWin.document.write("<table border=0 width=100%><tr bgcolor=\\"#ddffff\\">");  
     hwdWin.document.write("<td><b>Text Color</b></td><td><b>Font Size</b></td><td><b>Font Style</td></tr>");  
   }  
   
   function highlightbody(clrval,clrtxt,clrsel,szval,sztxt,szsel,syval,sytxt,sysel) {   
     hwdWin.document.write("<tr bgcolor=\\"#ffffdd\\">");  
     hwdWin.document.write("<td align=\\"left\\">");  
     hwdWin.document.write("<input name=\\"kwdclr\\" type=\\"radio\\" value=\\""+clrval+"\\" "+clrsel+">&nbsp;"+clrtxt+"</td>");  
     hwdWin.document.write("<td align=\\"left\\">");  
     hwdWin.document.write("<input name=\\"kwdsize\\" type=\\"radio\\" value=\\""+szval+"\\" "+szsel+">&nbsp;"+sztxt+"</td>");  
     hwdWin.document.write("<td align=\\"left\\">");  
     hwdWin.document.write("<input name=\\"kwdstyle\\" type=\\"radio\\" value=\\""+syval+"\\" "+sysel+">&nbsp;"+sytxt+"</td>");  
     hwdWin.document.write("</tr>");  
   }  
   
   function highlightend() {   
     hwdWin.document.write("</table>");  
     hwdWin.document.write("</td></tr></table>&nbsp;");  
     hwdWin.document.write("<input type=\\"button\\" value=\\"Save\\" onClick=\\"javascript:updateChoice(0)\\">&nbsp;&nbsp;");  
     hwdWin.document.write("<input type=\\"button\\" value=\\"Save & Refresh\\" onClick=\\"javascript:updateChoice(1)\\">&nbsp;&nbsp;");  
     hwdWin.document.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>");  
     hwdWin.document.write("</form>");  
     hwdWin.document.write("</body></html>");  
   }  
   
 </script>  
 SUBJAVASCRIPT  
 }  
   
   #----------------------------------------------------------------------------
   #
   #-------------------------- Next few routines handles grading by csv upload
   #
   #--- Javascript to handle csv upload
 sub csvupload_javascript_reverse_associate {  sub csvupload_javascript_reverse_associate {
   return(<<ENDPICK);    return(<<ENDPICK);
   function verify(vf) {    function verify(vf) {
Line 1841  ENDPICK Line 1896  ENDPICK
   
 sub csvuploadmap_header {  sub csvuploadmap_header {
     my ($request,$symb,$url,$datatoken,$distotal)= @_;      my ($request,$symb,$url,$datatoken,$distotal)= @_;
     my $result;  
     my $javascript;      my $javascript;
     if ($ENV{'form.upfile_associate'} eq 'reverse') {      if ($ENV{'form.upfile_associate'} eq 'reverse') {
  $javascript=&csvupload_javascript_reverse_associate();   $javascript=&csvupload_javascript_reverse_associate();
     } else {      } else {
  $javascript=&csvupload_javascript_forward_associate();   $javascript=&csvupload_javascript_forward_associate();
     }      }
   
       my $result='<table border="0">';
       $result.='<tr><td colspan=3><font size=+1><b>Resource: </b>'.$url.'</font></td></tr>';
       my ($partlist,$handgrade) = &response_type($url);
       my ($resptype,$hdgrade)=('','no');
       for (sort keys(%$handgrade)) {
    my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});
    $resptype = $responsetype;
    $hdgrade = $handgrade if ($handgrade eq 'yes');
    $result.='<tr><td><b>Part </b>'.(split(/_/))[0].'</td>'.
       '<td><b>Type: </b>'.$responsetype.'</td>'.
       '<td><b>Handgrade: </b>'.$handgrade.'</font></td></tr>';
       }
       $result.='</table>';
     $request->print(<<ENDPICK);      $request->print(<<ENDPICK);
 <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">  <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
 <h3>Uploading Class Grades for resource $url</h3>  <h3><font color="#339933">Uploading Class Grades</font></h3>
   $result
 <hr>  <hr>
 <h3>Identify fields</h3>  <h3>Identify fields</h3>
 Total number of records found in file: $distotal <hr />  Total number of records found in file: $distotal <hr />
Line 1918  sub csvuploadmap { Line 1987  sub csvuploadmap {
     my ($i,$keyfields);      my ($i,$keyfields);
     if (@records) {      if (@records) {
  my @fields=&csvupload_fields($url);   my @fields=&csvupload_fields($url);
   
  if ($ENV{'form.upfile_associate'} eq 'reverse') {   if ($ENV{'form.upfile_associate'} eq 'reverse') {
     &Apache::loncommon::csv_print_samples($request,\@records);      &Apache::loncommon::csv_print_samples($request,\@records);
     $i=&Apache::loncommon::csv_print_select_table($request,\@records,      $i=&Apache::loncommon::csv_print_select_table($request,\@records,
Line 1941  sub csvuploadassign { Line 2011  sub csvuploadassign {
     my ($symb,$url)=&get_symb_and_url($request);      my ($symb,$url)=&get_symb_and_url($request);
     if (!$symb) {return '';}      if (!$symb) {return '';}
     &Apache::loncommon::load_tmp_file($request);      &Apache::loncommon::load_tmp_file($request);
     my @gradedata=&Apache::loncommon::upfile_record_sep();      my @gradedata = &Apache::loncommon::upfile_record_sep();
     my @keyfields = split(/\,/,$ENV{'form.keyfields'});      my @keyfields = split(/\,/,$ENV{'form.keyfields'});
     my %fields=();      my %fields=();
     for (my $i=0; $i<=$ENV{'form.nfields'}; $i++) {      for (my $i=0; $i<=$ENV{'form.nfields'}; $i++) {
Line 1957  sub csvuploadassign { Line 2027  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 $cdom=$ENV{"course.$courseid.domain"};  
 #  my $cnum=$ENV{"course.$courseid.num"};  
     my ($classlist) = &getclasslist('all','1');      my ($classlist) = &getclasslist('all','1');
     my @skipped;      my @skipped;
     my $countdone=0;      my $countdone=0;
Line 1995  sub csvuploadassign { Line 2063  sub csvuploadassign {
     $request->print(&show_grading_menu_form($symb,$url));      $request->print(&show_grading_menu_form($symb,$url));
     return '';      return '';
 }  }
   #------------- end of section for handling csv file upload ---------
   #
   #-------------------------------------------------------------------
   
 sub send_header {  #-------------------------- Menu interface -------------------------
     my ($request)= @_;  #
     $request->print(&Apache::lontexconvert::header());  #--- Show a Grading Menu button - Calls the next routine ---
 #  $request->print("  sub show_grading_menu_form {
 #<script>      my ($symb,$url)=@_;
 #remotewindow=open('','homeworkremote');      my $result.='<form action="/adm/grades" method="post">'."\n".
 #remotewindow.close();   '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
 #</script>");    '<input type="hidden" name="url" value="'.$url.'" />'."\n".
     $request->print('<body bgcolor="#FFFFFF">');   '<input type="hidden" name="command" value="gradingmenu" />'."\n".
    '<input type="submit" name="submit" value="Grading Menu" />'."\n".
    '</form>'."\n";
       return $result;
 }  }
   
 sub send_footer {  #--- Displays the main menu page -------
     my ($request)= @_;  sub gradingmenu {
     $request->print('</body>');      my ($request) = @_;
     $request->print(&Apache::lontexconvert::footer());      my ($symb,$url)=&get_symb_and_url($request);
       if (!$symb) {return '';}
       my $result='<h3>&nbsp;<font color="#339933">Select a Grading Method</font></h3>';
       $result.='<table border="0">';
       $result.='<tr><td colspan=3><font size=+1><b>Resource: </b>'.$url.'</font></td></tr>';
       my ($partlist,$handgrade) = &response_type($url);
       my ($resptype,$hdgrade)=('','no');
       for (sort keys(%$handgrade)) {
    my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});
    $resptype = $responsetype;
    $hdgrade = $handgrade if ($handgrade eq 'yes');
    $result.='<tr><td><b>Part </b>'.(split(/_/))[0].'</td>'.
       '<td><b>Type: </b>'.$responsetype.'</td>'.
       '<td><b>Handgrade: </b>'.$handgrade.'</font></td></tr>';
       }
       $result.='</table>';
       $result.=&view_edit_entire_class_form($symb,$url).'<br />';
       $result.=&upcsvScores_form($symb,$url).'<br />';
       $result.=&viewGradeaStu_form($symb,$url,$resptype,$hdgrade).'<br />';
       $result.=&verifyReceipt_form($symb,$url) 
    if ((&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'})) && ($symb));
    
       return $result;
   }
   
   #--- Menu for grading a section or the whole class ---
   sub view_edit_entire_class_form {
       my ($symb,$url)=@_;
       my ($classlist,$sections) = &getclasslist('all','0');
       my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";
       $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";
       $result.='&nbsp;<b>View/Grade Entire Section/Class</b></td></tr>'."\n";
       $result.='<tr bgcolor=#ffffe6><td>'."\n";
       $result.='<form action="/adm/grades" method="post">'."\n".
    '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
    '<input type="hidden" name="url" value="'.$url.'" />'."\n".
    '<input type="hidden" name="command" value="viewgrades" />'."\n";
       $result.='&nbsp;<b>Select section:</b> <select name="section">'."\n";
       if (ref($sections)) {
    foreach (sort (@$sections)) {
       $result.= '<option>'.$_.'</option>'."\n";
    }
       }
       $result.='<option selected="on">all</select>'."<br />\n";
       $result.='&nbsp;<input type="button" onClick="submit();" value="View/Grade" /></form>'."\n";
       $result.='</td></tr></table>'."\n";
       $result.='</td></tr></table>'."\n";
       return $result;
   }
   
   #--- Menu to upload a csv scores ---
   sub upcsvScores_form {
       my ($symb,$url) = @_;
       if (!$symb) {return '';}
       my $result = '<script type="text/javascript" language="javascript">'."\n".
    '  function checkUpload(formname) {'."\n".
    '    if (formname.upfile.value == "") {'."\n".
    '       alert("Please use the browse button to select a file from your local directory.");'."\n".
    '       return false;'."\n".
    '    }'."\n".
    '    formname.submit();'."\n".
    '  }'."\n".
    '</script>'."\n";
   
       $result.='<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 above resource</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" />
   $upfile_select
   <br />&nbsp;<input type="button" onClick="javascript:checkUpload(this.form);" value="Upload Grades" />
   </form>
   ENDUPFORM
       $result.='</td></tr></table>'."\n";
       $result.='</td></tr></table>'."\n";
       return $result;
   }
   
   #--- Handgrading problems ---
   sub viewGradeaStu_form {
       my ($symb,$url,$response,$handgrade) = @_;
       my ($classlist,$sections) = &getclasslist('all','0');
       my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";
       $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";
       $result.='&nbsp;<b>';
       if ($handgrade eq 'yes') {
    $result.="View/Grade ";
       } else {
    $result.="View ";
       }
       $result.='an Individual Student\'s Submission</b></td></tr>'."\n";
       $result.='<tr bgcolor=#ffffe6><td>'."\n";
       $result.='<form action="/adm/grades" method="post">'."\n".
    '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
    '<input type="hidden" name="url" value="'.$url.'" />'."\n".
    '<input type="hidden" name="response" value="'.$response.'" />'."\n".
    '<input type="hidden" name="handgrade" value="'.$handgrade.'" />'."\n".
    '<input type="hidden" name="showgrading" value="yes" />'."\n".
    '<input type="hidden" name="command" value="submission" />'."\n";
   
       $result.='&nbsp;<b>Select section:</b> <select name="section">'."\n";
       if (ref($sections)) {
    foreach (sort (@$sections)) {$result.='<option>'.$_.'</option>'."\n";}
       }
       $result.= '<option selected="on">all</select>'."\n";
       $result.='&nbsp;&nbsp;<b>Display students who has: </b>'.
    '<input type="radio" name="submitonly" value="yes" checked> submitted'.
    '<input type="radio" name="submitonly" value="all"> everybody <br />';
       if (ref($sections)) {
    $result.='&nbsp;(Section "no" implies the students were not assigned a section.)<br />' 
       if (grep /no/,@$sections);
       }
   
   
       $result.='<br />&nbsp;<input type="button" onClick="submit();" value="';
       if ($handgrade eq 'yes') {
    $result.="View/Grade";
       } else {
    $result.="View";
       }
       $result.='" />'."\n".'</form>'."\n";
       $result.='</td></tr></table>'."\n";
       $result.='</td></tr></table>'."\n";
       return $result;
   }
   
   #--- Form to input a receipt number ---
   sub verifyReceipt_form {
       my ($symb,$url) = @_;
       my $result = '<script type="text/javascript" language="javascript">'."\n".
    '  function checkEntry(formname) {'."\n".
    '    var receipt = formname.receipt.value;'."\n".
    '    if (isNaN(receipt) || receipt == "") {'."\n".
    '       alert("Please enter a receipt number given by a student in the box.");'."\n".
    '       return false;'."\n".
    '    }'."\n".
    '    formname.submit();'."\n".
    '  }'."\n".
    '</script>'."\n";
   
       my $hostver=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'});
   
       $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";
       $result.='<table width=100% border=0><tr><td bgcolor=#e6ffff>'."\n";
       $result.='&nbsp;<b>Verify a Submission Receipt Issued by this Server</td></tr>'."\n";
       $result.='<tr bgcolor=#ffffe6><td>'."\n";
       $result.='<form action="/adm/grades" method="post" name="verifyform">'."\n";
       $result.='&nbsp;<tt>'.$hostver.'-<input type="text" name="receipt" size="4"></tt><br />'."\n";
       $result.='&nbsp;<input type="button" onClick="javascript:checkEntry(this.form);"'.
    ' value="Verify Receipt">'."\n";
       $result.='<input type="hidden" name="command" value="verify">'."\n";
       if ($ENV{'form.url'}) {
    $result.='<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />';
       }
       if ($ENV{'form.symb'}) {
    $result.='<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />';
       }
       $result.='</form>';
       $result.='</td></tr></table>'."\n";
       $result.='</td></tr></table>'."\n";
       return $result;
 }  }
   
 sub handler {  sub handler {
Line 2022  sub handler { Line 2261  sub handler {
  $request->content_type('text/html');   $request->content_type('text/html');
     }      }
     $request->send_http_header;      $request->send_http_header;
     return OK 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'};
Line 2051  sub handler { Line 2290  sub handler {
       'grade_courseid' => $tcrsid,        'grade_courseid' => $tcrsid,
       'grade_symb' => $tsymb)));        'grade_symb' => $tsymb)));
     } else {      } else {
  $request->print('<h1>Not authorized: '.$token.'</h1>');   $request->print('<h3>Not authorized: '.$token.'</h3>');
     }                 }           
  } else {   } else {
     $request->print('<h1>Not a valid DocID: '.$token.'</h1>');      $request->print('<h3>Not a valid DocID: '.$token.'</h3>');
  }   }
     } else {      } else {
  $request->print(&Apache::lonxml::tokeninputfield());   $request->print(&Apache::lonxml::tokeninputfield());
     }      }
  }   }
     } else {      } else {
  #&Apache::lonhomework::showhashsubset(\%ENV,'^form');  
  $Apache::grades::viewgrades=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'});   $Apache::grades::viewgrades=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'});
  if ($command eq 'submission') {   if ($command eq 'submission') {
     &listStudents($request) if ($ENV{'form.student'} eq '');      &listStudents($request) if ($ENV{'form.student'} eq '');
Line 2084  sub handler { Line 2322  sub handler {
     $request->print(&viewclasslist($request));      $request->print(&viewclasslist($request));
  } elsif ($command eq 'csvuploadmap') {   } elsif ($command eq 'csvuploadmap') {
     $request->print(&csvuploadmap($request));      $request->print(&csvuploadmap($request));
 #    } elsif ($command eq 'receiptInput') {  
 #      &receiptInput($request);  
  } elsif ($command eq 'csvuploadassign') {   } elsif ($command eq 'csvuploadassign') {
     if ($ENV{'form.associate'} ne 'Reverse Association') {      if ($ENV{'form.associate'} ne 'Reverse Association') {
  $request->print(&csvuploadassign($request));   $request->print(&csvuploadassign($request));
Line 2102  sub handler { Line 2338  sub handler {
  }   }
     }      }
     &send_footer($request);      &send_footer($request);
     return OK;      return '';
   }
   
   sub send_header {
       my ($request)= @_;
       $request->print(&Apache::lontexconvert::header());
   #  $request->print("
   #<script>
   #remotewindow=open('','homeworkremote');
   #remotewindow.close();
   #</script>"); 
       $request->print(&Apache::loncommon::bodytag('Grading'));
   }
   
   sub send_footer {
       my ($request)= @_;
       $request->print('</body>');
       $request->print(&Apache::lontexconvert::footer());
 }  }
   
 1;  1;

Removed from v.1.43  
changed lines
  Added in v.1.49


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