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

version 1.32, 2002/06/26 21:25:31 version 1.43, 2002/07/30 19:59:58
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 2002 H.K. Ng  # June, July 2002 H.K. Ng
 #  #
   
 package Apache::grades;  package Apache::grades;
Line 40  use Apache::lonxml; Line 40  use Apache::lonxml;
 use Apache::lonnet;  use Apache::lonnet;
 use Apache::loncommon;  use Apache::loncommon;
 use Apache::lonhomework;  use Apache::lonhomework;
   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 {  sub moreinfo {
   my ($request,$reason) = @_;      my ($request,$reason) = @_;
   $request->print("Unable to process request: $reason");      $request->print("Unable to process request: $reason");
   if ( $Apache::grades::viewgrades eq 'F' ) {      if ( $Apache::grades::viewgrades eq 'F' ) {
     $request->print('<form action="/adm/grades" method="post">'."\n");   $request->print('<form action="/adm/grades" method="post">'."\n");
     if ($ENV{'form.url'}) {   if ($ENV{'form.url'}) {
       $request->print('<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />'."\n");      $request->print('<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />'."\n");
     }   }
     if ($ENV{'form.symb'}) {   if ($ENV{'form.symb'}) {
       $request->print('<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />'."\n");      $request->print('<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />'."\n");
    }
   #    $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>');
     }      }
     $request->print('<input type="hidden" name="command" value="'.$ENV{'form.command'}.'" />'."\n");      return '';
     $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 {  sub verifyreceipt {
     my $request=shift;      my $request=shift;
     my $courseid=$ENV{'request.course.id'};      my $courseid=$ENV{'request.course.id'};
     my $cdom=$ENV{"course.$courseid.domain"};  #    my $cdom=$ENV{"course.$courseid.domain"};
     my $cnum=$ENV{"course.$courseid.num"};  #    my $cnum=$ENV{"course.$courseid.num"};
     my $receipt=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}).'-'.      my $receipt=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}).'-'.
                 $ENV{'form.receipt'};   $ENV{'form.receipt'};
     $receipt=~s/[^\-\d]//g;      $receipt=~s/[^\-\d]//g;
     my $symb=$ENV{'form.symb'};      my $symb=$ENV{'form.symb'};
     unless ($symb) {      unless ($symb) {
Line 77  sub verifyreceipt { Line 80  sub verifyreceipt {
     if ((&Apache::lonnet::allowed('mgr',$courseid)) && ($symb)) {      if ((&Apache::lonnet::allowed('mgr',$courseid)) && ($symb)) {
         $request->print('<h1>Verifying Submission Receipt '.$receipt.'</h1>');          $request->print('<h1>Verifying Submission Receipt '.$receipt.'</h1>');
         my $matches=0;          my $matches=0;
         my (%classlist) = &getclasslist($cdom,$cnum,'0');          my ($classlist) = &getclasslist('all','0');
         foreach my $student ( sort(@{ $classlist{'allids'} }) ) {          foreach my $student ( sort(@{ $$classlist{'all'} }) ) {
             my ($uname,$udom)=split(/\:/,$student);              my ($uname,$udom)=split(/\:/,$student);
             if ($receipt eq               if ($receipt eq 
              &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb)) {   &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb)) {
                $request->print('Matching '.$student.'<br>');   $request->print('Matching '.$student.'<br>');
                $matches++;   $matches++;
    }     }
         }          }
         $request->printf('<p>'.$matches." match%s</p>",$matches <= 1 ? '' : 'es');          $request->printf('<p>'.$matches." match%s</p>",$matches <= 1 ? '' : 'es');
   # needs to print who is matched
     }      }
     return '';      return '';
 }  }
   
 sub receiptInput {  sub student_gradeStatus {
   my ($request) = shift;      my ($url,$udom,$uname,$partlist) = @_;
   my $cdom=$ENV{"course.$ENV{'request.course.id'}.domain"};      my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));
   my $cnum=$ENV{"course.$ENV{'request.course.id'}.num"};      my %record= &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);
   my $hostver=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'});      my %partstatus = ();
   $request->print(<<ENDHEADER);      foreach (@$partlist) {
 <h2><font color="#339933">Verify a Submission Receipt Issued by this Server</font></h2>   my ($status,$foo)=split(/_/,$record{"resource.$_.solved"},2);
 <form action="/adm/grades" method="post">   $status = 'nothing' if ($status eq '');
 <tt>$hostver-<input type="text" name="receipt" size="4"></tt>   $partstatus{$_} = $status;
 <input type="submit" name="submit" value="Verify">   $partstatus{"resource.$_.submitted_by"} = $record{"resource.$_.submitted_by"} 
 <input type="hidden" name="command" value="verify">   if ($record{"resource.$_.submitted_by"} ne '');
 ENDHEADER      }
   if ($ENV{'form.url'}) {      return %partstatus;
     $request->print(  }
     '<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />');  
   }  sub get_fullname {
   if ($ENV{'form.symb'}) {      my ($uname,$udom) = @_;
     $request->print(      my %name=&Apache::lonnet::get('environment', ['lastname','generation',
     '<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />');    'firstname','middlename'],$udom,$uname);
   }      my $fullname;
 #  $request->print(<<ENDTABLEST);      my ($tmp) = keys(%name);
   $request->print('</form>');      if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
     return '';   $fullname=$name{'lastname'}.$name{'generation'};
    if ($fullname =~ /[^\s]+/) { $fullname.=', '; }
    $fullname.=$name{'firstname'}.' '.$name{'middlename'};
       }
       return $fullname;
 }  }
   
 sub student_gradeStatus {  sub response_type {
   my ($url,$udom,$uname) = @_;      my ($url) = shift;
   my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));      my $allkeys = &Apache::lonnet::metadata($url,'keys');
   my %record= &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);  #    print "allkeys=>$allkeys<br>";
   foreach my $part (&getpartlist($url)) {      my %seen = ();
     my ($temp,$part,$type)=split(/_/,$part);      my (@partlist,%handgrade);
     if ($type eq 'solved') {      foreach (split(/,/,&Apache::lonnet::metadata($url,'packages'))) {
       my ($status,$foo)=split(/_/,$record{"resource.$part.$type"},2);   if (/^\w+response_\d+.*/) {
       $status = 'nothing' if ($status eq '');      my ($responsetype,$part) = split(/_/,$_,2);
       return $type,$status;      my ($partid,$respid) = split(/_/,$part);
       $handgrade{$part} = $responsetype.':'.($allkeys =~ /parameter_$part\_handgrade/ ? 'yes' : 'no');
       next if ($seen{$partid} > 0);
       $seen{$partid}++;
       push @partlist,$partid;
    }
     }      }
   }      return \@partlist,\%handgrade;
   return '';  
 }  }
   
   
 sub listStudents {  sub listStudents {
   my ($request) = shift;      my ($request) = shift;
   my $cdom=$ENV{"course.$ENV{'request.course.id'}.domain"};      my $cdom      =$ENV{"course.$ENV{'request.course.id'}.domain"};
   my $cnum=$ENV{"course.$ENV{'request.course.id'}.num"};      my $cnum      =$ENV{"course.$ENV{'request.course.id'}.num"};
       my $getsec    =$ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'};
   $request->print(<<ENDTABLEST);      my $submitonly=$ENV{'form.submitonly'} eq '' ? 'all' : $ENV{'form.submitonly'};
 <h2><font color="#339933">Show Student Submissions on Assessment</font></h2>  
       my $result='<h2><font color="#339933">&nbsp;View Submissions for a Student or a Group of Students</font></h2>';
 <table border="0"><tr><td bgcolor="#777777">      $result.='<table border="0">';
 <table border="0">      $result.='<tr><td colspan=3><font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font></td></tr>';
 <tr bgcolor="#e6ffff"><td colspan="7"><b>Resource: </b> $ENV{'form.url'}</td></tr>      my ($partlist,$handgrade) = &response_type($ENV{'form.url'});
 <tr bgcolor="#e6ffff"><td><b>Username</b></td><td><b>Name</b></td><td><b>Domain</b></td>      for (sort keys(%$handgrade)) {
 <td><b>View Problem</b></td><td><b>Submissions</b></td>   my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});
 <td><b>Grade Status</b></td><td><b>Action</b></td></tr>   $ENV{'form.handgrade'} = 'yes' 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>';
       $request->print($result);
   
       $request->print(<<ENDTABLEST);
   <form action="/adm/grades" method="post">
   &nbsp;<b>View Problem: </b><input type="radio" name="vProb" value="no" checked> no 
   <input type="radio" name="vProb" value="yes"> yes <br />
   &nbsp;<b>Submissions: </b>
   <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  ENDTABLEST
   my (%classlist) = &getclasslist($cdom,$cnum,'0');      if ($ENV{'form.url'}) {
   foreach my $student ( sort(@{ $classlist{'allids'} }) ) {   $request->print('<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />'."\n");
       my ($sname,$sdom) = split(/:/,$student);      }
       if ($ENV{'form.symb'}) {
       my %name=&Apache::lonnet::get('environment', ['lastname','generation',   $request->print('<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />'."\n");
     'firstname','middlename'],      }
     $sdom,$sname);      $request->print('<input type="hidden" name="command" value="processGroup" />'."\n");
       my $fullname;      
       my ($tmp) = keys(%name);      my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($getsec,'0');
       if ($tmp !~ /^(con_lost|error|no_such_host)/i) {      
  $fullname=$name{'lastname'}.$name{'generation'};      $result='<table border="0"><tr><td bgcolor="#777777">'.
  if ($fullname =~ /[^\s]+/) { $fullname.=', '; }   '<table border="0"><tr bgcolor="#e6ffff">'.
  $fullname.=$name{'firstname'}.' '.$name{'middlename'};   '<td><b>&nbsp;Select&nbsp;</b></td><td><b>&nbsp;Username&nbsp;</b></td>'.
       }   '<td><b>&nbsp;Fullname&nbsp;</b></td><td><b>&nbsp;Domain&nbsp;</b></td>';
       if ( $Apache::grades::viewgrades eq 'F' ) {      foreach (sort(@$partlist)) {
   $request->print("\n".'<tr bgcolor=#ffffe6>'."<td>$sname</td><td>$fullname</td><td align=\"middle\">$sdom</td>".   $result.='<td><b>&nbsp;Part ID '.(split(/_/))[0].' Status&nbsp;</b></td>';
   '<form action="/adm/grades" method="post">');      }
   if ($ENV{'form.url'}) {      $request->print($result.'</tr>'."\n");
     $request->print(  
     '<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />');      foreach my $student (sort(@{ $$classlist{$getsec} }) ) {
   }   my ($uname,$udom) = split(/:/,$student);
   if ($ENV{'form.symb'}) {   my (%status) = &student_gradeStatus($ENV{'form.url'},$udom,$uname,$partlist);
     $request->print(   my $statusflg = '';
     '<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />');   foreach (keys(%status)) {
   }      $statusflg = 1 if ($status{$_} ne 'nothing');
   $request->print(      my ($foo,$partid,$foo1) = split(/\./,$_);
   '<input type="hidden" name="command" value="'.$ENV{'form.command'}.'" />');      if ($status{'resource.'.$partid.'.submitted_by'} ne '') {
   $request->print(   $statusflg = '';
   '<input type="hidden" name="student" value="'.$sname.'" />');   $request->print('<input type="hidden" name="'.
   $request->print(   $student.':submitted_by" value="'.
   '<input type="hidden" name="fullname" value="'.$fullname.'" />');   $status{'resource.'.$partid.'.submitted_by'}.'" />');
   $request->print(      }
   '<input type="hidden" name="domain" value="'.$sdom.'" />');   }
   $request->print('<td>'.   next if ($statusflg eq '' && $submitonly eq 'yes');
   '<input type="radio" name="vProb" value="no" checked> no '.  
   '<input type="radio" name="vProb" value="yes"> yes </td>');   if ( $Apache::grades::viewgrades eq 'F' ) {
   $request->print('<td>'.      $result='<tr bgcolor="#ffffe6">'.
   '<input type="radio" name="submission" value="last" checked> last '.   '<td align="center"><input type=checkbox name="stuinfo" value="'.
   '<input type="radio" name="submission" value="all"> all </td>');   $student.':'.$$fullname{$student}.'"></td>'."\n".
   my ($type,$status) = &student_gradeStatus($ENV{'form.url'},$cdom,$sname);   '<td>&nbsp;'.$uname.'&nbsp;</td>'."\n".
   $request->print(   '<td>&nbsp;'.$$fullname{$student}.'&nbsp;</td>'."\n".
   '<td align="middle">'.$status.'&nbsp;</td>');   '<td align="middle">&nbsp;'.$udom.'&nbsp;</td>'."\n";
   $request->print(      
                          '<td><input type="submit" name="submit" value="View/Grade" />');      foreach (sort keys(%status)) {
   $request->print('</td></tr></form>');   next if (/^resource.*?submitted_by$/);
 #  $request->print('</form></td></tr>');   $result.='<td align="middle">&nbsp;'.$status{$_}.'&nbsp;</td>'."\n";
       }      }
   }      $request->print($result.'</tr>'."\n");
   $request->print('</table></td></tr></table>');   }
       }
       $request->print('</table></td></tr></table>');
       $request->print('<input type="submit" name="submit" value="View/Grade" /><form />');
   }
   
   sub processGroup {
       my ($request)  = shift;
       my $ctr        = 0;
       my @stuchecked = (ref($ENV{'form.stuinfo'}) ? @{$ENV{'form.stuinfo'}}
         : ($ENV{'form.stuinfo'}));
       my $total      = scalar(@stuchecked)-1;
       if ($stuchecked[0] eq '') {
    &userError($request,'No student was selected for viewing/grading.');
    return;
       }
       foreach (@stuchecked) {
    my ($uname,$udom,$fullname) = split(/:/);
    $ENV{'form.student'} = $uname;
    $ENV{'form.fullname'} = $fullname;
    &submission($request,$ctr,$total);
    $ctr++;
       }
       return '';
 }  }
   
   sub userError {
       my ($request, $reason, $step) = @_;
       $request->print('<h3><font color="red">LON-CAPA User Error</font></h3><br />'."\n");
       $request->print('<b>Reason: </b>'.$reason.'<br /><br />'."\n");
       $request->print('<b>Step: </b>'.($step ne '' ? $step : 'Use your browser back button to correct')
       .'<br /><br />'."\n");
       return '';
   }
   
 #FIXME - needs to handle multiple matches  #FIXME - needs to handle multiple matches
 sub finduser {  sub finduser {
   my ($name) = @_;      my ($name) = @_;
   my $domain = '';      my $domain = '';
       if ( $Apache::grades::viewgrades eq 'F' ) {
   if ( $Apache::grades::viewgrades eq 'F' ) {   my ($classlist) = &getclasslist('all','0');
     #get classlist   foreach ( sort(@{ $$classlist{'all'} }) ) {
     my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});      my ($posname,$posdomain) = split(/:/);
     #print "Found $cdom:$cnum<br />";      if ($posname =~ $name) { $name=$posname; $domain=$posdomain; last; }
     my (%classlist) = &getclasslist($cdom,$cnum,'0');   }
     foreach my $student ( sort(@{ $classlist{'allids'} }) ) {   return ($name,$domain);
       my ($posname,$posdomain) = split(/:/,$student);      } else {
       if ($posname =~ $name) { $name=$posname; $domain=$posdomain; last; }   return ($ENV{'user.name'},$ENV{'user.domain'});
     }      }
     return ($name,$domain);  
   } else {  
     return ($ENV{'user.name'},$ENV{'user.domain'});  
   }  
 }  }
   
 sub getclasslist {  sub getclasslist {
   my ($coursedomain,$coursenum,$hideexpired) = @_;      my ($getsec,$hideexpired) = @_;
   my %classlist=&Apache::lonnet::dump('classlist',$coursedomain,$coursenum);      my $now = time;
   my $now = time;      my %classlist=&Apache::lonnet::dump('classlist',
   foreach my $student (keys(%classlist)) {   $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
     my ($end,$start)=split(/:/,$classlist{$student});   $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
     # still a student?      my (@holdsec,@sections,%allids,%stusec,%fullname);
     if (($hideexpired) && ($end) && ($end < $now)) {      foreach (keys(%classlist)) {
       #print "Skipping:$name:$end:$now<br />\n";   my ($end,$start,$id,$section,$fullname)=split(/:/,$classlist{$_});
       next;         # 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;
    }
     }      }
     #print "record=$record<br>";      my %seen = ();
     push( @{ $classlist{'allids'} }, $student);      foreach my $item (@holdsec) {
   }   push (@sections, $item) unless $seen{$item}++;
   return (%classlist);      }
       return (\%classlist,\@sections,\%allids,\%stusec,\%fullname);
 }  }
   
 sub getpartlist {  sub getpartlist {
   my ($url) = @_;      my ($url) = @_;
   my @parts =();      my @parts =();
   my (@metakeys) = split(/,/,&Apache::lonnet::metadata($url,'keys'));      my (@metakeys) = split(/,/,&Apache::lonnet::metadata($url,'keys'));
   foreach my $key (@metakeys) {      foreach my $key (@metakeys) {
     if ( $key =~ m/stores_([0-9]+)_.*/) {   if ( $key =~ m/stores_([0-9]+)_.*/) {
       push(@parts,$key);      push(@parts,$key);
    }
     }      }
   }      return @parts;
   return @parts;  
 }  }
   
 sub viewstudentgrade {  sub print_hash {
   my ($url,$symb,$courseid,$student,@parts) = @_;      my ($request, $hash) = @_;
   my $result ='';      $request->print('<table border=1><tr><td>Key</td><td>Value</td></tr>');
   my $cellclr = '"#ffffdd"';      for (sort keys (%$hash)) {
   my ($username,$domain) = split(/:/,$student);   $request->print('<tr><td>'.$_.'</td><td>'.$$hash{$_}.'&nbsp;</td></tr>');
   
   my (@requests) = ('lastname','firstname','middlename','generation');  
   my (%name) = &Apache::lonnet::get('environment',\@requests,$domain,$username);  
   my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$username);  
   
   my $fullname=$name{'lastname'}.$name{'generation'};  
   if ($fullname =~ /[^\s]+/) { $fullname.=', '; }  
   $fullname.=$name{'firstname'}.' '.$name{'middlename'};  
   
   $result.="<tr bgcolor=$cellclr><td>$username</td><td>$fullname</td><td align=\"middle\">$domain</td>\n";  
   foreach my $part (@parts) {  
     my ($temp,$part,$type)=split(/_/,$part);  
     my $score=$record{"resource.$part.$type"};  
     if ($type eq 'awarded' || $type eq 'tries') {  
       $result.='<td align="middle"><input type="text" name="GRADE.'.$student.'.'.$part.'.'.$type.  
   '" value="'.$score.'" size="4" /></td>'."\n";  
     } elsif ($type eq 'solved') {  
       my ($status,$foo)=split(/_/,$score,2);  
       $result.="<td align=\"middle\"><select name=\"GRADE.$student.$part.$type\">\n";  
       my $optsel = '<option>correct</option><option>incorrect</option><option>excused</option>'.  
   '<option>ungraded</option><option>handgraded</option><option>nothing</option>'."\n";  
       $status = 'nothing' if ($status eq '');  
       $optsel =~ s/<option>$status/<option selected="on">$status/;  
       $result.=$optsel;  
       $result.="</select></td>\n";  
     }      }
   }      $request->print('</table>');
   $result.='<td></td></tr>';      return '';
   return $result;  
 }  }
   #
   # --------------------------- show submissions of a student, option to grade --------
   sub submission {
       my ($request,$counter,$total) = @_;
   
 #FIXME need to look at the metadata <stores> spec on what type of data to accept and provide an      (my $url=$ENV{'form.url'})=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
 #interface based on that, also do that to above function.      if ($ENV{'form.student'} eq '') { &moreinfo($request,'Need student login id'); return ''; }
 sub setstudentgrade {      my ($uname,$udom) = &finduser($ENV{'form.student'});
   my ($url,$symb,$courseid,$student,@parts) = @_;      if ($uname eq '') { &moreinfo($request,'Unable to find student'); return ''; }
   
       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 ''; }
       my $last = ($ENV{'form.lastSub'} eq 'last' ? 'last' : '');
       $ENV{'form.vProb'} = $ENV{'form.vProb'} ne '' ? $ENV{'form.vProb'} : 'yes';
       my ($classlist,$seclist,$ids,$stusec,$fullname);
   
       # header info
       if ($counter == 0) {
    &sub_page_js($request);
    $request->print('<h2>&nbsp;<font color="#339933">Submission Record</font></h2>'.
    '<font size=+1>&nbsp;<b>Resource: </b>'.$url.'</font>');
   
    # option to display problem, only once else it cause problems with the form later 
    # since the problem has a form.
    if ($ENV{'form.vProb'} eq 'yes') {
       my $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom,
         $ENV{'request.course.id'});
       my $companswer=&Apache::loncommon::get_student_answers($symb,$uname,$udom,
      $ENV{'request.course.id'});
       my $result.='<table border="0" width="100%"><tr><td bgcolor="#777777">';
       $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>Correct answer:</b><br />'.$companswer;
       $result.='</td></tr></table>';
       $result.='</td></tr></table><br />';
       $request->print($result);
    }
   
    # kwclr is the only variable that is guaranteed to be non blank if this subroutine has been called once.
    my %keyhash = ();
    if ($ENV{'form.kwclr'} eq '') {
       %keyhash = &Apache::lonnet::dump('nohist_handgrade',
        $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
        $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
   
       my $loginuser = $ENV{'user.name'}.':'.$ENV{'user.domain'};
       $ENV{'form.keywords'} = $keyhash{$symb.'_keywords'} ne '' ? $keyhash{$symb.'_keywords'} : '';
       $ENV{'form.kwclr'}    = $keyhash{$loginuser.'_kwclr'} ne '' ? $keyhash{$loginuser.'_kwclr'} : 'red';
       $ENV{'form.kwsize'}   = $keyhash{$loginuser.'_kwsize'} ne '' ? $keyhash{$loginuser.'_kwsize'} : '0';
       $ENV{'form.kwstyle'}  = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : '';
       $ENV{'form.msgsub'}   = $keyhash{$symb.'_subject'} ne '' ? 
    $keyhash{$symb.'_subject'} : &Apache::lonnet::metadata($url,'title');
       $ENV{'form.savemsgN'} = $keyhash{$symb.'_savemsgN'} ne '' ? $keyhash{$symb.'_savemsgN'} : '0';
   
   my $result ='';   }
   my ($stuname,$domain) = split(/:/,$student);   $request->print('<form action="/adm/grades" method="post" name="SCORE">'."\n".
   my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$stuname);   '<input type="hidden" name="command"    value="handgrade" />'."\n".
   my %newrecord;   '<input type="hidden" name="refresh"    value="off" />'."\n".
    '<input type="hidden" name="symb"       value="'.$symb.'" />'."\n".
   foreach my $part (@parts) {   '<input type="hidden" name="url"        value="'.$url.'" />'."\n".
     my ($temp,$part,$type)=split(/_/,$part);   '<input type="hidden" name="showgrading" value="'.$ENV{'form.showgrading'}.'" />'."\n".
     my $oldscore=$record{"resource.$part.$type"};   '<input type="hidden" name="vProb"      value="'.$ENV{'form.vProb'}.'" />'."\n".
     my $newscore=$ENV{"form.GRADE.$student.$part.$type"};   '<input type="hidden" name="lastSub"    value="'.$ENV{'form.lastSub'}.'" />'."\n".
     print "old=$oldscore:new=$newscore:<br>";   '<input type="hidden" name="section"    value="'.$ENV{'form.section'}.'">'."\n".
     if ($type eq 'solved') {   '<input type="hidden" name="submitonly" value="'.$ENV{'form.submitonly'}.'">'."\n".
       my $update=0;   '<input type="hidden" name="response"   value="'.$ENV{'form.response'}.'">'."\n".
       if ($newscore eq 'nothing' ) {   '<input type="hidden" name="handgrade"  value="'.$ENV{'form.handgrade'}.'">'."\n".
  if ($oldscore ne '') {   '<input type="hidden" name="keywords"   value="'.$ENV{'form.keywords'}.'" />'."\n".
   $update=1;   '<input type="hidden" name="kwclr"      value="'.$ENV{'form.kwclr'}.'" />'."\n".
   $newscore = '';   '<input type="hidden" name="kwsize"     value="'.$ENV{'form.kwsize'}.'" />'."\n".
  }   '<input type="hidden" name="kwstyle"    value="'.$ENV{'form.kwstyle'}.'" />'."\n".
       } elsif ($oldscore !~ m/^$newscore/) {   '<input type="hidden" name="msgsub"     value="'.$ENV{'form.msgsub'}.'" />'."\n".
  $update=1;   '<input type="hidden" name="savemsgN"   value="'.$ENV{'form.savemsgN'}.'" />'."\n".
  $result.="Updating $stuname to $newscore<br />\n";   '<input type="hidden" name="NCT"'.
  if ($newscore eq 'correct') { $newscore = 'correct_by_override'; }   ' value="'.($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : $total+1).'" />'."\n");
  if ($newscore eq 'incorrect') { $newscore = 'incorrect_by_override'; }  
  if ($newscore eq 'excused') { $newscore = 'excused'; }   my ($cts,$prnmsg) = (1,'');
  if ($newscore eq 'ungraded') { $newscore = 'ungraded_attempted'; }   while ($cts <= $ENV{'form.savemsgN'}) {
       } else {      $prnmsg.='<input type="hidden" name="savemsg'.$cts.'" value="'.
  #$result.="$stuname:$part:$type:unchanged  $oldscore to $newscore:<br />\n";   ($keyhash{$symb.'_savemsg'.$cts} eq '' ? $ENV{'form.savemsg'.$cts} : $keyhash{$symb.'_savemsg'.$cts}).
       }   '" />'."\n";
       if ($update) { $newrecord{"resource.$part.$type"}=$newscore; }      $cts++;
     } else {   }
       if ($oldscore ne $newscore) {   $request->print($prnmsg);
  $newrecord{"resource.$part.$type"}=$newscore;  
  $result.="Updating $student"."'s status for $part.$type to $newscore<br />\n";   if ($ENV{'form.handgrade'} eq 'yes' && $ENV{'form.showgrading'} eq 'yes') {
       } else {      $request->print(<<KEYWORDS);
  #$result.="$stuname:$part:$type:unchanged  $oldscore to $newscore:<br />\n";  &nbsp;<b>Keyword Options:</b>&nbsp;
       }  <a href="javascript:keywords(document.SCORE.keywords)"; TARGET=_self>List</a>&nbsp; &nbsp;
   <a href="#" onMouseDown="javascript:getSel(); return false"
    CLASS="page">Paste Selection to List</a>&nbsp; &nbsp;
   <a href="javascript:kwhighlight()"; TARGET=_self>Highlight Attribute</a><br /><br />
   KEYWORDS
           }
     }      }
   }      my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);
   if ( scalar(keys(%newrecord)) > 0 ) {      my ($partlist,$handgrade) = &response_type($url);
     $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";  #    &print_hash($request,\%record);
     print "grader=$newrecord{'resource.regrader'}:<br>records<br>";  
     while (my ($k,$v) = each %newrecord) {      # Student info
  print "k=$k:v=$v:<br>\n";      $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">'.
    '<table border="0" width=100%><tr bgcolor="#ffffff"><td>';
   
       $result.='<table border="0"><tr bgcolor="#ffffff"><td><b>Fullname: </b>'.$ENV{'form.fullname'}.
   #    $result.='<table border="0"><tr bgcolor="#ffffff"><td><b>Fullname: </b>'.$fullname.
    '</td><td>&nbsp; &nbsp;<b>Username: </b>'.$uname.
    '</td><td>&nbsp; &nbsp;<b>Domain: </b>'.$udom.'</td></tr>';
       if ($ENV{'form.handgrade'} eq 'yes') {
    my @col_list;
    ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist('all','0');
    for (keys (%$handgrade)) {
       my $ncol = &Apache::lonnet::EXT('resource.'.$_.'.maxcollaborators',$symb,$udom,$uname);
       if ($ncol > 0) {
    s/\_/\./g;
    if ($record{'resource.'.$_.'.collaborators'} ne '') {
       my (@collaborators) = split(/,?\s+/,$record{'resource.'.$_.'.collaborators'});
       my (@badcollaborators);
       if (scalar(@collaborators) != 0) {
    $result.='<tr bgcolor="#ffffff"><td colspan=3><b>Collaborators: </b>';
    foreach my $collaborator (@collaborators) {
       $collaborator = $collaborator =~ /\@|:/ ? 
    (split(/@|:/,$collaborator))[0] : $collaborator;
       next if ($collaborator eq $uname);
       if (!grep /^$collaborator:/i,keys %$classlist) {
    push @badcollaborators,$collaborator;
    next;
       }
       push @col_list, $collaborator;
       $result.=$$fullname{$collaborator.':'.$udom}.' ('.$collaborator.') &nbsp; &nbsp;';
    }
    $result.='</td></tr>'."\n";
    $result.='<tr bgcolor="#ffbbbb"><td colspan=2>'.
       'This student has submitted '.(scalar (@badcollaborators) > 1 ? '' : 'an').
       ' invalid collaborator'.(scalar (@badcollaborators) > 1 ? 's. ' : '. ').
       (join ', ',@badcollaborators).'</td></tr>' 
       if (scalar(@badcollaborators) > 0);
   
    $result.='<tr bgcolor="#ffbbbb"><td colspan=2>'.
       'This student has submitted too many collaborators. Maximum is '.
       $ncol.'.</td></tr>' if (scalar(@collaborators) > $ncol);
    $result.='<input type="hidden" name="collaborator'.$counter.
       '" value="'.(join ':',@col_list).'" />'."\n";
       }
    }
       }
    }
     }      }
     &Apache::lonnet::cstore(\%newrecord,$symb,$courseid,$domain,$stuname);      $request->print($result.'</table>'."\n");
   
     $result.="Stored away ".scalar(keys(%newrecord))." elements.<br />\n";      # print student answer
   }      if ($ENV{'form.lastSub'} =~ /^(lastonly|hdgrade)$/) {
   return $result;   if ($ENV{'form.'.$uname.':'.$udom.':submitted_by'}) {
       my $submitby='</td></tr><tr><td bgcolor="#e6ffff">'.
    '<b>Collaborative submission by: </b>'.
    '<a href="javascript:viewSubmitter(\''.$ENV{'form.'.$uname.':'.$udom.':submitted_by'}.
    '\')"; TARGET=_self>'.
    $$fullname{$ENV{'form.'.$uname.':'.$udom.':submitted_by'}}.'</a>';
       $submitby.='</td></tr><tr><td bgcolor="#ffffff">'."\n";
       $request->print($submitby);
    } else {
       my ($string,$timestamp)=&get_last_submission ($symb,$uname,$udom,$ENV{'request.course.id'});
       my $lastsubonly.='</td></tr><tr><td bgcolor="#e6ffff"><b>Last Submission Only</b>'.
    ($$timestamp eq '' ? '' : '&nbsp; &nbsp; <b>Date Submitted:</b> '.$$timestamp).'</td></tr>';
       if ($$timestamp eq '') {
    $lastsubonly.='<tr><td bgcolor="#ffffe6">'.$$string[0].'</td></tr>';
       } else {
    for my $part (sort keys(%$handgrade)) {
       foreach (@$string) {
    my ($partid,$respid) = /^resource\.(\d+)\.(\d+)\.submission/;
    if ($part eq ($partid.'_'.$respid)) {
       my ($ressub,$subval) = split(/:/,$_,2);
       $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part ID</b> '.
    $partid.' <b>Response ID</b> '.$respid.
    ' <b>Submission</b> '.&keywords_highlight($subval).'</td></tr>'
    if ($ENV{'form.lastSub'} eq 'lastonly' || 
       ($ENV{'form.lastSub'} eq 'hdgrade' && $$handgrade{$part} =~ /:yes$/));
    }
       }
    }
       }
       $lastsubonly.='</td></tr><tr><td bgcolor="#ffffff">'."\n";
       $request->print($lastsubonly);
    }
       } else {
    $request->print(&Apache::loncommon::get_previous_attempt($symb,$uname,$udom,
    $ENV{'request.course.id'},$last,
    '.submission','Apache::grades::keywords_highlight'));
       }
       
       # view submission with no grading option
       if ($ENV{'form.showgrading'} eq '') {
    $request->print('</td></tr></table></td></tr></table></form>');
    return;
       }
   
       $result='<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n".
    '<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n".
    '<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':'.$udom.'" />'."\n";
       $result.='&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.
    ',\''.$fullname.'\')"; TARGET=_self>Compose Message</a><br />'."\n" if ($ENV{'form.handgrade'} eq 'yes');
       $request->print($result);
   
       my %seen = ();
       my @partlist;
       for (sort keys(%$handgrade)) {
    my ($partid,$respid) = split(/_/);
    next if ($seen{$partid} > 0);
    $seen{$partid}++;
    next if ($$handgrade{$_} =~ /:no$/);
    push @partlist,$partid;
    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>');
    $wgt       = ($wgt > 0 ? $wgt : '1');
    my $score  = ($record{'resource.'.$partid.'.awarded'} eq '' ?
         '' : $record{'resource.'.$partid.'.awarded'}*$wgt);
   
    # display grading options
    $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>';
   
    my $ctr = 0;
    $result.='<table border="0"><tr>';  # display radio buttons in a nice table 10 across
    while ($ctr<=$wgt) {
       $result.= '<td><input type="radio" name="RADVAL'.$counter.'_'.$partid.'" '.
    'onclick="javascript:writeBox(this.form.GD_BOX'.$counter.'_'.$partid.
    ',this.form.GD_SEL'.$counter.'_'.$partid.','.$ctr.
    ',this.form.stores'.$counter.'_'.$partid.')" '.
    ($score eq $ctr ? 'checked':'').' /> '.$ctr."</td>\n";
       $result.=(($ctr+1)%10 == 0 ? '</tr><tr>' : '');
       $ctr++;
    }
    $result.='</tr></table>';
   
    $result.='</td><td>&nbsp;<b>or</b>&nbsp;</td>';
    $result.='<td><input type="text" name="GD_BOX'.$counter.'_'.$partid.'"'.
       ($score ne ''? ' value = "'.$score.'"':'').' size="4" '.
       'onChange="javascript:updateRadio(this.form.RADVAL'.$counter.'_'.$partid.
       ',this.form.GD_BOX'.$counter.'_'.$partid.
       ',this.form.GD_SEL'.$counter.'_'.$partid.
       ',this.form.stores'.$counter.'_'.$partid.')" /></td>'."\n";
    $result.='<td>/'.$wgt.' '.$wgtmsg.' </td><td>';
   
    $result.='<select name="GD_SEL'.$counter.'_'.$partid.'" '.
       'onChange="javascript:clearRadBox(this.form.RADVAL'.$counter.'_'.$partid.
       ',this.form.GD_BOX'.$counter.'_'.$partid.
       ',this.form.GD_SEL'.$counter.'_'.$partid.
       ',this.form.stores'.$counter.'_'.$partid.')" />'."\n".
       '<option selected="on"> </option>'.
       '<option>excused</option></select>'."&nbsp&nbsp\n";
    $result.='<input type="hidden" name="stores'.$counter.'_'.$partid.'" value="0" />';
    $result.='</td></tr></table>';
    $request->print($result);
       }
       $request->print('<input type="hidden" name="partlist'.$counter.'" value="'.(join ":",@partlist).'" />'."\n");
       $request->print('</td></tr></table></td></tr></table>'."\n");
   
       # print end of form
       if ($counter == $total) {
    my $endform.='<table border="0"><tr><td><input type="submit" name="gradeOpt" value="Save & Next" />';
    my $ntstu ='<select name="NTSTU">'.
       '<option>1</option><option>2</option>'.
       '<option>3</option><option>5</option>'.
       '<option>7</option><option>10</option></select>'."\n";
    my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1');
    $ntstu =~ s/<option>$nsel</<option selected="on">$nsel</;
    $endform.=$ntstu.'student(s) &nbsp;&nbsp;'.
       '<input type="submit" name="gradeOpt" value="Next" />&nbsp'.
       '<input type="submit" name="gradeOpt" value="Previous" />&nbsp'.
       '(Next and Previous do not save the scores.)'.
       '</td><tr></table></form>';
    $request->print($endform);
       }
       return '';
 }  }
   
 # --------------------------- show submissions of a student, option to grade --------  sub get_last_submission {
 #      my ($symb,$username,$domain,$course)=@_;
 sub submission {      if ($symb) {
   my ($request) = @_;   my (@string,$timestamp);
   $request->print(<<JAVASCRIPT);   my (%returnhash)=&Apache::lonnet::restore($symb,$course,$domain,$username);
 <script type="text/javascript" language="javascript">   if ($returnhash{'version'}) {
     function updateRadio() {      my %lasthash=();
  var pts = document.SCORE.GRADE_BOX.value;      my ($version);
  var radioButton = document.SCORE.radval;      for ($version=1;$version<=$returnhash{'version'};$version++) {
  var checked  =true;   foreach (sort(split(/\:/,$returnhash{$version.':keys'}))) {
  var unchecked=false;      $lasthash{$_}=$returnhash{$version.':'.$_};
  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) {  
     document.SCORE.GRADE_BOX.value = i;  
     resetbox = true;  
  }   }
     }      }
     if (!resetbox) {      foreach ((keys %lasthash)) {
  document.SCORE.GRADE_BOX.value = "";   if ($_ =~ /\.submission$/) {push @string, (join(':',$_,$lasthash{$_}))}
    if ($_ =~ /timestamp/) {$timestamp = scalar(localtime($lasthash{$_}))};
     }      }
     return;  
  }   }
    @string = $string[0] eq '' ? 'Nothing submitted - no attempts.' : @string;
    return \@string,\$timestamp;
       }
   }
   
  for (var i=0; i<radioButton.length; i++) {  sub keywords_highlight {
     radioButton[i].checked=unchecked;      my $string  = shift;
     if (pts == i) {      my $size    = $ENV{'form.kwsize'} eq '0' ? '' : 'size='.$ENV{'form.kwsize'};
  radioButton[i].checked=checked;      my $styleon = $ENV{'form.kwstyle'} eq ''  ? '' : $ENV{'form.kwstyle'};
       (my $styleoff = $styleon) =~ s/\</\<\//;
       my @keylist = split(/[,\s+]/,$ENV{'form.keywords'});
       foreach (@keylist) {
    $string =~ s/\b$_(\b|\.)/\<font color\=$ENV{'form.kwclr'} $size\>$styleon$_$styleoff\<\/font\>/gi;
       }
       return $string;
   }
   
   sub processHandGrade {
       my ($request) = shift;
       my $url    = $ENV{'form.url'};
       my $symb   = $ENV{'form.symb'};
       my $button = $ENV{'form.gradeOpt'};
       my $ngrade = $ENV{'form.NCT'};
       my $ntstu  = $ENV{'form.NTSTU'};
   
       my $loginuser = $ENV{'user.name'}.':'.$ENV{'user.domain'};
       my %keyhash = ();
       $ENV{'form.keywords'}           =~ s/,\s{0,}|\s+/ /g;
       $ENV{'form.keywords'}           =~ s/^\s+|\s+$//;
       $keyhash{$symb.'_keywords'}     = $ENV{'form.keywords'};
       $keyhash{$symb.'_subject'}      = $ENV{'form.msgsub'};
       $keyhash{$loginuser.'_kwclr'}   = $ENV{'form.kwclr'};
       $keyhash{$loginuser.'_kwsize'}  = $ENV{'form.kwsize'};
       $keyhash{$loginuser.'_kwstyle'} = $ENV{'form.kwstyle'};
   
       my ($ctr,$idx) = (1,1);
       while ($ctr <= $ENV{'form.savemsgN'}) {
    if ($ENV{'form.savemsg'.$ctr} ne '') {
       $keyhash{$symb.'_savemsg'.$idx} = $ENV{'form.savemsg'.$ctr};
       $idx++;
    }
    $ctr++;
       }
       $ctr = 0;
       while ($ctr < $ngrade) {
    if ($ENV{'form.newmsg'.$ctr} ne '') {
       $keyhash{$symb.'_savemsg'.$idx} = $ENV{'form.newmsg'.$ctr};
       $ENV{'form.savemsg'.$idx} = $ENV{'form.newmsg'.$ctr};
       $idx++;
    }
    $ctr++;
       }
       $ENV{'form.savemsgN'} = --$idx;
       $keyhash{$symb.'_savemsgN'} = $ENV{'form.savemsgN'};
       my $putresult = &Apache::lonnet::put
    ('nohist_handgrade',\%keyhash,
    $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
    $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
   
       if ($ENV{'form.refresh'} eq 'on') {
    my $ctr = 0;
    $ENV{'form.NTSTU'}=$ngrade;
    while ($ctr < $ngrade) {
       ($ENV{'form.student'},my $udom) = split(/:/,$ENV{'form.unamedom'.$ctr});
       &submission($request,$ctr,$ngrade-1);
       $ctr++;
    }
    return '';
       }
   
       if ($button eq 'Save & Next') {
    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 $laststu = $ENV{'form.unamedom'.($ngrade-1)};
       $ctr = 2;
       while ($laststu eq '') {
    $laststu  = $ENV{'form.unamedom'.($ngrade-$ctr)};
    $ctr++;
    $laststu = $firststu if ($ctr > $ngrade);
       }
       my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($ENV{'form.section'},'0');
   
       my (@parsedlist,@nextlist);
       my ($nextflg) = 0;
       foreach ( sort(@{ $$classlist{$ENV{'form.section'}} }) ) {
    if ($nextflg == 1 && $button =~ /Next$/) {
       push @parsedlist,$_;
    }
    $nextflg = 1 if ($_ eq $laststu);
    if ($button eq 'Previous') {
       last if ($_ eq $firststu);
       push @parsedlist,$_;
    }
       }
       $ctr = 0;
       my ($partlist,$handgrade) = &response_type($ENV{'form.url'});
       @parsedlist = reverse @parsedlist if ($button eq 'Previous');
       foreach my $student (@parsedlist) {
    my ($uname,$udom) = split(/:/,$student);
    if ($ENV{'form.submitonly'} eq 'yes') {
       my (%status) = &student_gradeStatus($ENV{'form.url'},$udom,$uname,$partlist) ;
       my $statusflg = '';
       foreach (keys(%status)) {
    $statusflg = 1 if ($status{$_} ne 'nothing');
    my ($foo,$partid,$foo1) = split(/\./,$_);
    $statusflg = '' if ($status{'resource.'.$partid.'.submitted_by'} ne '');
     }      }
       next if ($statusflg eq '');
  }   }
    push @nextlist,$student if ($ctr < $ntstu);
    $ctr++;
     }      }
   
 </script>      $ctr = 0;
 JAVASCRIPT      my $total = scalar(@nextlist)-1;
   my $url=$ENV{'form.url'};  
   $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;  
   if ($ENV{'form.student'} eq '') { &moreinfo($request,"Need student login id"); return ''; }  
   my ($uname,$udom) = &finduser($ENV{'form.student'});  
   if ($uname eq '') { &moreinfo($request,"Unable to find student"); return ''; }  
   
   my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));      foreach (sort @nextlist) {
   if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }   my ($uname,$udom,$submitter) = split(/:/);
 #   $ENV{'form.student'} = $uname;
 # header info   $ENV{'form.fullname'} = $$fullname{$_};
   my $result='<h2><font color="#339933">Submission Record</font></h2>';  # $ENV{'form.'.$_.':submitted_by'} = $submitter;
   $result.='<table border="0"><tr><td><b>Username: </b>'.$uname.'</td><td><b>Fullname: </b>'.$ENV{'form.fullname'}.'</td><td><b>Domain: </b>'.$udom.'</td></tr>';  # print "submitter=$ENV{'form.'.$_.':submitted_by'}= $submitter:<br>";
   $result.='<tr><td colspan=3><b>Resource: </b>'.$url.'</td></tr></table>';   &submission($request,$ctr,$total);
 #   $ctr++;
 # option to display problem      }
   if ($ENV{'form.vProb'} eq 'yes') {      if ($total < 0) {
       my $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom,   my $the_end = '<h3><font color="red">LON-CAPA User Message</font></h3><br />'."\n";
    $ENV{'request.course.id'});   $the_end.='<b>Message: </b> No more students for this section or class.<br /><br />'."\n";
       my $companswer=&Apache::loncommon::get_student_answers($symb,$uname,$udom,   $the_end.='Click on the button below to return to the grading menu.<br /><br />'."\n";
  $ENV{'request.course.id'});   $the_end.=&show_grading_menu_form ($symb,$url);
       $result.='<table border="0"><tr><td bgcolor="#777777">';   $request->print($the_end);
       $result.='<table border="0"><tr><td bgcolor="#e6ffff">';      }
       $result.='<b>Student\'s view of the problem</b></td></tr><tr><td bgcolor="#ffffff">'.$rendered.'<br />';      return '';
       $result.='<b>Correct answer:</b><br />'.$companswer;  
       $result.='</td></tr></table>';  
       $result.='</td></tr></table><br />';  
   }  
   my $last = '';  
   $last = 'last' if ($ENV{'form.submission'} eq 'last');  
   my $answer=&Apache::loncommon::get_previous_attempt($symb,$uname,$udom,  
       $ENV{'request.course.id'},$last);  
   $result.=$answer;  
   
   my $wgt   = &Apache::lonnet::EXT('resource.partid.weight',$symb,$udom,$uname);  
   my %record= &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);  
   my $score = $record{'resource.0.awarded'}*$wgt;  
   
   $result.= '<form action="/adm/grades" method="post" name="SCORE">'."\n".  
     '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".  
       '<input type="hidden" name="url" value="'.$url.'" />'."\n".  
  '<input type="hidden" name="command" value="handgrade" />'."\n";  
   
   $result.='<table border="0"><tr><td><b>Points</b></td><td>';  
   my $ctr = 0;  
   while ($ctr<=$wgt) {  
       $result.= '<input type="radio" name="radval" '.  
 #  'onclick="javascript:writeBox(\'GRADE_'.$ENV{'form.student'}.'\',\''.$ctr.'\')" '.  
   'onclick="javascript:SCORE.GRADE_BOX.value='.$ctr.'" '.  
   ($score == $ctr? 'checked':'').' /> '.$ctr."\n";  
       $ctr++;  
   }  
   $result.='</td><td>&nbsp;<b>or</b>&nbsp;</td>';  
   $result.='<td><input type="text" name="GRADE_BOX"'.  
       ($score ne ''? ' value = "'.$score.'"':'').' size="4" '.  
       'onChange="javascript:updateRadio()" /></td>'."\n";    
   $result.='<td>/'.$wgt.' (problem weight)</td></tr>';  
   
   $result.='<input type="hidden" name="GRADE_'.$uname.':'.$udom.'" value="handgraded" />'."\n";  
   $result.='<tr><td colspan="5"><input type="submit" name="gradeOpt" value="Save & Next" />&nbsp;';  
   $result.='<input type="submit" name="gradeOpt" value="Next" />&nbsp';  
   $result.='<input type="submit" name="gradeOpt" value="Previous" />&nbsp';  
   $result.='</td><tr></table></form>';  
   return $result;  
 }  }
   
 sub processHandGrade {  sub saveHandGrade {
   my ($url,$symb,$courseid,$student,@parts) = @_;      my ($request,$url,$symb,$stuname,$domain,$newflg,$submitter) = @_;
   #   my %record=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},$domain,$stuname);
   my ($stuname,$domain) = split(/:/,$student);      my %newrecord;
   my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$stuname);      foreach (split(/:/,$ENV{'form.partlist'.$newflg})) {
   my %newrecord;   if ($ENV{'form.GD_SEL'.$newflg.'_'.$_} eq 'excused') {
       $newrecord{'resource.'.$_.'.solved'} = 'excused';
   foreach my $part (@parts) {   } else {
     my ($temp,$part,$type)=split(/_/,$part);      my $pts    = ($ENV{'form.GD_BOX'.$newflg.'_'.$_} ne '' ? 
     my $oldscore=$record{"resource.$part.$type"};    $ENV{'form.GD_BOX'.$newflg.'_'.$_} : $ENV{'form.RADVAL'.$newflg.'_'.$_});
     my $newscore=($ENV{'form.GRADE_BOX'} ne '' ? $ENV{"form.GRADE_BOX"} : $ENV{'form.radval'});      if ($pts eq '') {
     if ($type eq 'solved') {   &userError($request,'No point was assigned for part id '.$_.' and for username '.$stuname.'.');
       my $update=0;   return 'error';
       if ($newscore eq 'nothing' ) {      }
  if ($oldscore ne '') {      my $wgt    = $ENV{'form.WGT'.$newflg.'_'.$_} eq '' ? 1 : $ENV{'form.WGT'.$newflg.'_'.$_};
   $update=1;      my $partial= $pts/$wgt;
   $newscore = '';      $newrecord{'resource.'.$_.'.awarded'}  = $partial;
  }      if ($partial == 0) {
       } elsif ($oldscore !~ m/^$newscore/) {   $newrecord{'resource.'.$_.'.solved'} = 'incorrect_by_override';
  $update=1;      } else {
  if ($newscore eq 'correct')   { $newscore = 'correct_by_override'; }   $newrecord{'resource.'.$_.'.solved'} = 'correct_by_override';
  if ($newscore eq 'incorrect') { $newscore = 'incorrect_by_override'; }      }
  if ($newscore eq 'excused')   { $newscore = 'excused'; }      $newrecord{'resource.'.$_.'.submitted_by'} = $submitter if ($submitter);
  if ($newscore eq 'ungraded')  { $newscore = 'ungraded_attempted'; }   }
  if ($newscore eq 'handgraded') { $newscore = 'handgraded_by_grader'; }  
       }  
       if ($update) { $newrecord{"resource.$part.$type"}=$newscore; }  
     } else {  
       if ($oldscore ne $newscore) {  
  $newrecord{"resource.$part.$type"}=$newscore;  
     }      }
   }      
   if ( scalar(keys(%newrecord)) > 0 ) {      if ( scalar(keys(%newrecord)) > 0 ) {
     $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";   $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
     print "grader=$newrecord{'resource.regrader'}:<br>records<br>";  # &print_hash($request,\%newrecord);
     while (my ($k,$v) = each %newrecord) {   &Apache::lonnet::cstore(\%newrecord,$symb,$ENV{'request.course.id'},$domain,$stuname);
  print "k=$k:v=$v:<br>\n";  
     }      }
     &Apache::lonnet::cstore(\%newrecord,$symb,$courseid,$domain,$stuname);      return '';
   }  
   return '';  
 }  }
   
 sub get_symb_and_url {  sub get_symb_and_url {
  my ($request) = @_;      my ($request) = @_;
   my $url=$ENV{'form.url'};      (my $url=$ENV{'form.url'}) =~ s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
   $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'};      if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }
 #  if (!$symb) { $symb=&Apache::lonnet::symbread($url); }      return ($symb,$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 ''; }  
  return ($symb,$url);  
 }  
   
 sub view_edit_entire_class_form {  
   my ($symb,$url)=@_;  
   my $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".  
   '<input type="submit" name="submit" value="View/Grade Entire Class" />'."\n".  
     '</form>'."\n";  
   return $result;  
 }  }
   
 sub show_grading_menu_form {  sub show_grading_menu_form {
   my ($symb,$url)=@_;      my ($symb,$url)=@_;
   my $result.='<form action="/adm/grades" method="post">'."\n".      my $result.='<form action="/adm/grades" method="post">'."\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="gradingmenu" />'."\n".   '<input type="hidden" name="command" value="gradingmenu" />'."\n".
   '<input type="submit" name="submit" value="Grading Menu" />'."\n".   '<input type="submit" name="submit" value="Grading Menu" />'."\n".
     '</form>'."\n";   '</form>'."\n";
   return $result;      return $result;
 }  }
   
 sub gradingmenu {  sub gradingmenu {
   my ($request) = @_;      my ($request) = @_;
   my ($symb,$url)=&get_symb_and_url($request);      my ($symb,$url)=&get_symb_and_url($request);
   if (!$symb) {return '';}      if (!$symb) {return '';}
       my $result='<h2>&nbsp;<font color="#339933">Select a Grading Method</font></h2>';
   my $result='<h2>&nbsp;<font color="#339933">Select a Grading Method</font></h2><br />';      $result.='<table border="0">';
   $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";      $result.='<tr><td colspan=3><font size=+1><b>Resource: </b>'.$url.'</font></td></tr>';
   $result.='<table width=100% border=0><tr><td bgcolor=#e6ffff>'."\n";      my ($partlist,$handgrade) = &response_type($url);
   $result.='&nbsp;<b>Resource :</b> '.$url.'</td></tr>'."\n";      my ($resptype,$hdgrade)=('','no');
   $result.='<tr bgcolor=#ffffe6><td>'."\n";      for (sort keys(%$handgrade)) {
   $result.=&view_edit_entire_class_form($symb,$url);   my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});
   $result.='<form action="/adm/grades" method="post">'."\n".   $resptype = $responsetype;
      '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".   $hdgrade = $handgrade if ($handgrade eq 'yes');
       '<input type="hidden" name="url" value="'.$url.'" />'."\n".   $result.='<tr><td><b>Part ID: </b>'.(split(/_/))[0].'</td>'.
  '<input type="hidden" name="command" value="csvupload" />'."\n".      '<td><b>Type: </b>'.$responsetype.'</td>'.
   '<input type="submit" name="submit" value="Upload Scores" />'."\n".      '<td><b>Handgrade: </b>'.$handgrade.'</font></td></tr>';
     '</form>'."\n";      }
   $result.='<form action="/adm/grades" method="post">'."\n".      $result.='</table>';
      '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".      $result.=&view_edit_entire_class_form($symb,$url).'<br />';
       '<input type="hidden" name="url" value="'.$url.'" />'."\n".      $result.=&upcsvScores_form($symb,$url).'<br />';
  '<input type="hidden" name="command" value="submission" />'."\n".      $result.=&viewGradeaStu_form($symb,$url,$resptype,$hdgrade).'<br />';
   '<input type="submit" name="submit" value="View/Grade A Student" />'."\n".      $result.=&verifyReceipt_form($symb,$url).'<br />';
     '</form>'."\n";      $result.=&view_classlist_form($symb,$url);
   $result.='<form action="/adm/grades" method="post">'."\n".  
      '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".      return $result;
       '<input type="hidden" name="url" value="'.$url.'" />'."\n".  }
  '<input type="hidden" name="command" value="receiptInput" />'."\n".  
   '<input type="submit" name="submit" value="Verify Receipt" />'."\n".  sub view_classlist_form {
     '</form>'."\n";      my ($symb,$url)=@_;
   $result.='</td></tr></table>'."\n";      my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";
   $result.='</td></tr></table>'."\n";      $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";
   return $result;      $result.='&nbsp;<b>View Class List</b></td></tr>'."\n";
 }      $result.='<tr bgcolor=#ffffe6><td>'."\n";
       $result.='<form action="/adm/grades" method="post">'."\n".
 sub viewgrades {   '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
   my ($request) = @_;   '<input type="hidden" name="url" value="'.$url.'" />'."\n".
   my $result='';   '<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'});
   
   #get resource reference      return '';
   my ($symb,$url)=&get_symb_and_url($request);  
   if (!$symb) {return '';}  
   #get classlist  
   my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});  
   #print "Found $cdom:$cnum<br />";  
   my (%classlist) = &getclasslist($cdom,$cnum,'0');  
   my $headerclr = '"#ccffff"';  
   my $cellclr = '"#ffffcc"';  
   
   #get list of parts for this problem  
   my (@parts) = sort(&getpartlist($url));  
   
   $request->print ("<h2><font color=\"#339933\">Manual Grading</font></h2>");  
   
   #start the form  
   $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="editgrades" />'."\n".  
   '<input type="submit" name="submit" value="Submit Changes" />'."\n".  
     '<table border=0><tr><td bgcolor="#777777">'."\n".  
      '<table border=0>'."\n".  
       '<tr bgcolor='.$headerclr.'><td><b>Username</b></td><td><b>Name</b></td><td><b>Domain</b></td>'."\n";  
   foreach my $part (@parts) {  
      my $display=&Apache::lonnet::metadata($url,$part.'.display');  
      if  (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); }  
       print "Manual grading:$url:$part:$display:<br>";  
      $result.='<td><b>'.$display.'</b></td>'."\n";  
   }  
   $result.='</tr>';  
   #get info for each student  
   foreach my $student ( sort(@{ $classlist{'allids'} }) ) {  
     my $display=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},$student,@parts);  
 #      print "ID=$ENV{'request.course.id'}:STU=$student:DIS=$display:<br>\n";  
     $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},$student,@parts);  
   }  
   $result.='</table></td></tr></table>';  
   $result.='<input type="submit" name="submit" value="Submit Changes" /></form>';  
   $result.=&show_grading_menu_form($symb,$url);  
   return $result;  
 }  }
   
 sub editgrades {  sub view_edit_entire_class_form {
   my ($request) = @_;      my ($symb,$url)=@_;
   my $result='';      my ($classlist,$sections) = &getclasslist('all','0');
       my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";
   my $symb=$ENV{'form.symb'};      $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";
   if ($symb eq '') { $request->print("Unable to handle ambiguous references:$symb:$ENV{'form.url'}"); return ''; }      $result.='&nbsp;<b>View/Grade Entire Section/Class</b></td></tr>'."\n";
   my $url=$ENV{'form.url'};      $result.='<tr bgcolor=#ffffe6><td>'."\n";
   #get classlist      $result.='<form action="/adm/grades" method="post">'."\n".
   my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});   '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
   #print "Found $cdom:$cnum<br />";   '<input type="hidden" name="url" value="'.$url.'" />'."\n".
   my (%classlist) = &getclasslist($cdom,$cnum,'0');   '<input type="hidden" name="command" value="viewgrades" />'."\n";
       $result.='&nbsp;<b>Select section:</b> <select name="section">'."\n";
   #get list of parts for this problem      foreach (sort (@$sections)) {
   my (@parts) = &getpartlist($url);   $result.= '<option>'.$_.'</option>'."\n";
       }
   $result.='<form action="/adm/grades" method="post">'."\n".      $result.='<option selected="on">all</select>'."<br />\n";
     '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".      $result.='&nbsp;<input type="submit" name="submit" value="View/Grade" /></form>'."\n";
       '<input type="hidden" name="url" value="'.$url.'" />'."\n".      $result.='</td></tr></table>'."\n";
  '<input type="hidden" name="command" value="viewgrades" />'."\n".      $result.='</td></tr></table>'."\n";
   '<input type="submit" name="submit" value="See Grades" /> <br />'."\n";      return $result;
   }
   foreach my $student ( sort(@{ $classlist{'allids'} }) ) {  
     $result.=&setstudentgrade($url,$symb,$ENV{'request.course.id'},$student,@parts);  sub upcsvScores_form {
   }      my ($symb,$url) = @_;
       if (!$symb) {return '';}
   $result.='<input type="submit" name="submit" value="See Grades" /></table></form>';      my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";
   return $result;      $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";
 sub csvupload {      my $upfile_select=&Apache::loncommon::upfile_select_html();
   my ($request)= @_;  
   my $result;  
   my ($symb,$url)=&get_symb_and_url($request);  
   if (!$symb) {return '';}  
   my $upfile_select=&Apache::loncommon::upfile_select_html();  
   $result.=<<ENDUPFORM;    $result.=<<ENDUPFORM;
 <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">  <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
 <input type="hidden" name="symb" value="$symb" />  <input type="hidden" name="symb" value="$symb" />
 <input type="hidden" name="url" value="$url" />  <input type="hidden" name="url" value="$url" />
 <input type="hidden" name="command" value="csvuploadmap" />  <input type="hidden" name="command" value="csvuploadmap" />
 <hr />  
 <h3>Specify a file containing the class grades for resource $url</h3>  
 $upfile_select  $upfile_select
 <p><input type="submit" name="submit" value="Upload Grades" />  <br />&nbsp;<input type="submit" name="submit" value="Upload Grades" />
   </form>
 ENDUPFORM  ENDUPFORM
   return $result;      $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 {
       my ($request) = shift;
   
       $request->print(<<VIEWJAVASCRIPT);
   <script type="text/javascript" language="javascript">
       function viewOneStudent(user) {
    document.onestudent.student.value = user;
    document.onestudent.submit();
       }
   
       function writePoint(partid,weight,point) {
    var radioButton = eval("document.classgrade.RADVAL_"+partid);
    var textbox = eval("document.classgrade.TEXTVAL_"+partid);
    if (point == "textval") {
       var point = eval("document.classgrade.TEXTVAL_"+partid+".value");
       if (isNaN(point) || point < 0) {
    alert("A number equal or greater than 0 is expected. Entered value = "+point);
    var resetbox = false;
    for (var i=0; i<radioButton.length; i++) {
       if (radioButton[i].checked) {
    textbox.value = i;
    resetbox = true;
       }
    }
    if (!resetbox) {
       textbox.value = "";
    }
    return;
       }
       for (var i=0; i<radioButton.length; i++) {
    radioButton[i].checked=false;
    if (point == i) {
       radioButton[i].checked=true;
    }
       }
   
    } else {
       textbox.value = point;
    }
    for (i=0;i<document.classgrade.total.value;i++) {
       var user = eval("document.classgrade.ctr"+i+".value");
       var scorename = eval("document.classgrade.GD_"+user+
    "_"+partid+"_aw");
       var saveval   = eval("document.classgrade.GD_"+user+
    "_"+partid+"_sv_s.value");
       var selname   = eval("document.classgrade.GD_"+user+"_"+partid+"_sv");
       if (saveval != "correct") {
    scorename.value = point;
    if (selname[0].selected != true) {
       selname[0].selected = true;
    }
       }
    }
    var selval   = eval("document.classgrade.SELVAL_"+partid);
    selval[0].selected = true;
       }
   
       function writeRadText(partid,weight) {
    var selval   = eval("document.classgrade.SELVAL_"+partid);
    var radioButton = eval("document.classgrade.RADVAL_"+partid);
    var textbox = eval("document.classgrade.TEXTVAL_"+partid);
    if (selval[1].selected) {
       for (var i=0; i<radioButton.length; i++) {
    radioButton[i].checked=false;
   
       }
       textbox.value = "";
   
       for (i=0;i<document.classgrade.total.value;i++) {
    var user = eval("document.classgrade.ctr"+i+".value");
    var scorename = eval("document.classgrade.GD_"+user+
        "_"+partid+"_aw");
    var saveval   = eval("document.classgrade.GD_"+user+
        "_"+partid+"_sv_s.value");
    var selname   = eval("document.classgrade.GD_"+user+
        "_"+partid+"_sv");
    if (saveval != "correct") {
       scorename.value = "";
       selname[1].selected = true;
    }
       }
    } else {
       for (i=0;i<document.classgrade.total.value;i++) {
    var user = eval("document.classgrade.ctr"+i+".value");
    var scorename = eval("document.classgrade.GD_"+user+
        "_"+partid+"_aw");
    var saveval   = eval("document.classgrade.GD_"+user+
        "_"+partid+"_sv_s.value");
    var selname   = eval("document.classgrade.GD_"+user+
        "_"+partid+"_sv");
    if (saveval != "correct") {
       scorename.value = eval("document.classgrade.GD_"+user+
        "_"+partid+"_aw_s.value");;
       selname[0].selected = true;
    }
       }
    }    
       }
   
       function changeSelect(partid,user) {
    var selval = eval("document.classgrade.GD_"+user+'_'+partid+"_sv");
    selval[0].selected = true;
       }
   
       function changeOneScore(partid,user) {
    var selval = eval("document.classgrade.GD_"+user+'_'+partid+"_sv");
    if (selval[1].selected) {
       var boxval = eval("document.classgrade.GD_"+user+'_'+partid+"_aw");
       boxval.value = "";
    }
       }
   
       function resetEntry(numpart) {
    for (ctpart=0;ctpart<numpart;ctpart++) {
       var partid = eval("document.classgrade.partid_"+ctpart+".value");
       var radioButton = eval("document.classgrade.RADVAL_"+partid);
       var textbox = eval("document.classgrade.TEXTVAL_"+partid);
       var selval  = eval("document.classgrade.SELVAL_"+partid);
       for (var i=0; i<radioButton.length; i++) {
    radioButton[i].checked=false;
   
       }
       textbox.value = "";
       selval[0].selected = true;
   
       for (i=0;i<document.classgrade.total.value;i++) {
    var user = eval("document.classgrade.ctr"+i+".value");
    var resetscore = eval("document.classgrade.GD_"+user+
         "_"+partid+"_aw");
    resetscore.value = eval("document.classgrade.GD_"+user+
    "_"+partid+"_aw_s.value");
   
    var saveselval   = eval("document.classgrade.GD_"+user+
        "_"+partid+"_sv_s.value");
   
    var selname   = eval("document.classgrade.GD_"+user+"_"+partid+"_sv");
    if (saveselval == "excused") {
       if (selname[1].selected == false) { selname[1].selected = true;}
    } else {
       if (selname[0].selected == false) {selname[0].selected = true};
    }
       }
    }
       }
   
       function submitForm() {
    document.classgrade.submit();
       }
   
   </script>
   VIEWJAVASCRIPT
   }
   
   sub viewgrades {
       my ($request) = shift;
       &viewgrades_js($request);
   
       my ($symb,$url) = ($ENV{'form.symb'},$ENV{'form.url'}); 
       my $result='<h2><font color="#339933">Manual Grading</font></h2>';
   
       $result.='<font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font>'."\n";
   
       #view individual student submission form - called using Javascript viewOneStudent
       $result.= '<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".
    '</form>'."\n";
   
       #start the form
       $result.= '<form action="/adm/grades" method="post" name="classgrade">'."\n".
    '<input type="hidden" name="symb"    value="'.$symb.'" />'."\n".
    '<input type="hidden" name="url"     value="'.$url.'" />'."\n".
    '<input type="hidden" name="command" value="editgrades" />'."\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 '.
    '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 '.
    'been graded does not get changed using the radio buttons or text box. '.
    'If needed, it has to be changed individually.</font>';
   
       my ($partlist,$handgrade) = &response_type($ENV{'form.url'});
       my %weight = ();
       my $ctsparts = 0;
       $result.='<table border="0">';
       for (sort keys(%$handgrade)) {
    my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});
    my ($partid,$respid) = split (/_/);
    my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb);
    $weight{$partid} = $wgt eq '' ? '1' : $wgt;
   
    $result.='<input type="hidden" name="partid_'.$ctsparts.'" value="'.$partid.'" />'."\n";
    $result.='<tr><td><b>Part ID:</b> '.$partid.'&nbsp; &nbsp;</td><td>';
    $result.='<table border="0"><tr>';  
    my $ctr = 0;
    while ($ctr<=$weight{$partid}) { # display radio buttons in a nice table 10 across
       $result.= '<td><input type="radio" name="RADVAL_'.$partid.'" '.
    'onclick="javascript:writePoint('.$partid.','.$weight{$partid}.
    ','.$ctr.')" />'.$ctr."</td>\n";
       $result.=(($ctr+1)%10 == 0 ? '</tr><tr>' : '');
       $ctr++;
    }
    $result.='</tr></table>';
    $result.= '</td><td><b> or </b><input type="text" name="TEXTVAL_'.$partid.'" size="4" '.
       'onChange="javascript:writePoint('.$partid.','.$weight{$partid}.',\'textval\')" /> /'.
       $weight{$partid}.' (problem weight)</td>'."\n";
    $result.= '</td><td><select name="SELVAL_'.$partid.'"'.
       'onChange="javascript:writeRadText('.$partid.','.$weight{$partid}.')" /> '.
       '<option selected="on"> </option>'.
       '<option>excused</option></select></td></tr>'."\n";
    $ctsparts++;
       }
       $result.='</table><input type="hidden" name="totalparts" value="'.$ctsparts.'" />';
       $result.='<input type="button" value="Reset" '.
    'onClick="javascript:resetEntry('.$ctsparts.');" TARGET=_self> &nbsp; &nbsp;';
   #    $result.='<input type="button" value="Submit Changes" '.
   # 'onClick="document.classgrade.submit();" TARGET=_self />'."\n";
       $result.= '<input type="submit" name="submit"  value="Submit Changes" />'."\n";
   
       $result.= '<table border=0><tr><td bgcolor="#777777">'."\n".
    '<table border=0><tr bgcolor="#deffff">'.
    '<td><b>Username</b></td><td><b>Fullname</b></td><td><b>Domain</b></td>'."\n";
       #get list of parts for this problem
       my (@parts) = sort(&getpartlist($url));
       foreach my $part (@parts) {
    my $display=&Apache::lonnet::metadata($url,$part.'.display');
    next if ($display =~ /^Number of Attempts/);
    if  (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); }
    if ($display =~ /^Partial Credit Factor/) {
       $_ = $display;
       my ($partid) = /.*?(\d+).*/;
       $result.='<td><b>Score Part '.$partid.'<br>(weight = '.
    $weight{$partid}.')</b></td>'."\n";
       next;
    }
    $display =~ s/Problem Status/Grade Status<br>/;
    $result.='<td><b>'.$display.'</b></td>'."\n";
       }
       $result.='</tr>';
       #get info for each student
       my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($ENV{'form.section'},'0');
       my $ctr = 0;
       foreach ( sort(@{ $$classlist{$ENV{'form.section'}} }) ) {
    (my $username = $_) = split(/:/);
    $result.='<input type="hidden" name="ctr'.$ctr.'" value="'.$username.'" />'."\n";
    $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},
      $_,$$fullname{$_},\@parts,\%weight);
    $ctr++;
       }
       $result.='</table></td></tr></table>';
       $result.='<input type="hidden" name="total" value="'.$ctr.'" />'."\n";
       $result.='<input type="submit" name="submit" value="Submit Changes" /></form>';
       $result.=&show_grading_menu_form($symb,$url);
       return $result;
   }
   
   sub viewstudentgrade {
       my ($url,$symb,$courseid,$student,$fullname,$parts,$weight) = @_;
       my ($username,$domain) = split(/:/,$student);
       my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$username);
       my $result='<tr bgcolor="#ffffdd"><td>'.
    '<a href="javascript:viewOneStudent(\''.$username.'\')"; TARGET=_self>'.$username.'</a>'.
    '</td><td>'.$fullname.'</td><td align="middle">'.$domain.'</td>'."\n";
       foreach my $part (@$parts) {
    my ($temp,$part,$type)=split(/_/,$part);
    my $score=$record{"resource.$part.$type"};
    next if $type eq 'tries';
    if ($type eq 'awarded') {
       my $pts = $score eq '' ? '' : $score*$$weight{$part};
       $result.='<input type="hidden" name="'.
    'GD_'.$username.'_'.$part.'_aw_s" value="'.$pts.'" />'."\n";
       $result.='<td align="middle"><input type="text" name="'.
    'GD_'.$username.'_'.$part.'_aw"'.
    'onChange="javascript:changeSelect('.$part.',\''.$username.'\')" value="'.
    $pts.'" size="4" /></td>'."\n";
    } elsif ($type eq 'solved') {
       my ($status,$foo)=split(/_/,$score,2);
       $status = 'nothing' if ($status eq '');
       $result.='<input type="hidden" name="'.
    'GD_'.$username.'_'.$part.'_sv_s" value="'.$status.'" />'."\n";
       $result.='<td align="middle"><select name="'.
    'GD_'.$username.'_'.$part.'_sv" '.
    'onChange="javascript:changeOneScore('.$part.',\''.$username.'\')" >'."\n";
       my $optsel = '<option selected="on"> </option><option>excused</option>'."\n";
       $optsel = '<option> </option><option selected="on">excused</option>'."\n"
    if ($status eq 'excused');
       $result.=$optsel;
       $result.="</select></td>\n";
    }
       }
       $result.='</tr>';
       return $result;
   }
   
   
   sub editgrades {
       my ($request) = @_;
   
       my $symb=$ENV{'form.symb'};
       my $url =$ENV{'form.url'};
       my $result='<h2><font color="#339933">Current Grade Status</font></h2>';
       $result.='<font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font><br />'."\n";
       $result.='<font size=+1><b>Section: </b>'.$ENV{'form.section'}.'</font>'."\n";
       $result.= &show_grading_menu_form ($symb,$url);
       $result.= '<table border="0"><tr><td bgcolor="#777777">'."\n";
       $result.= '<table border="0"><tr bgcolor="#deffff">'.
    '<td rowspan=2><b>Username</b></td><td rowspan=2><b>Fullname</b></td>'."\n";
   
       my %scoreptr = (
       'correct'  =>'correct_by_override',
       'incorrect'=>'incorrect_by_override',
       'excused'  =>'excused',
       'ungraded' =>'ungraded_attempted',
       'nothing'  => '',
       );
       my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($ENV{'form.section'},'0');
   
       my (@partid);
       my %weight = ();
       my ($i,$ctr) = (0,0);
       while ($ctr < $ENV{'form.totalparts'}) {
    my $partid = $ENV{'form.partid_'.$ctr};
    push @partid,$partid;
    my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb);
    $weight{$partid} = $wgt eq '' ? '1' : $wgt;
    $ctr++;
    $result .= '<td colspan = 2 align="center"><b>Part ID '.$partid.
       '</b> (Weight = '.$weight{$partid}.')</td>';
       }
       $result .= '</tr><tr bgcolor="#deffff">';
       foreach (@partid) {
    $result .= '<td align="center">&nbsp;<b>Old Score</b>&nbsp;</td>'.
       '<td align="center">&nbsp;<b>New Score</b>&nbsp;</td>';
       }
       $result .= '</tr>'."\n";
   
       for ($i=0; $i<$ENV{'form.total'}; $i++) {
    my $user = $ENV{'form.ctr'.$i};
    my %newrecord;
    my $updateflag = 0;
    my @userdom = grep /^$user:/,keys %$classlist;
    my ($foo,$udom) = split(/:/,$userdom[0]);
   
    $result .= '<tr bgcolor="#ffffde"><td>'.$user.'&nbsp;</td><td>'.
       $$fullname{$userdom[0]}.'&nbsp;</td>';
   
    foreach (@partid) {
       my $old_aw    = $ENV{'form.GD_'.$user.'_'.$_.'_aw_s'};
       my $old_part  = $old_aw eq '' ? '' : $old_aw/$weight{$_};
       my $old_score = $scoreptr{$ENV{'form.GD_'.$user.'_'.$_.'_sv_s'}};
   
       my $awarded   = $ENV{'form.GD_'.$user.'_'.$_.'_aw'};
       my $partial   = $awarded eq '' ? '' : $awarded/$weight{$_};
       my $score;
       if ($partial eq '') {
    $score = $scoreptr{$ENV{'form.GD_'.$user.'_'.$_.'_sv_s'}};
       } elsif ($partial > 0) {
    $score = 'correct_by_override';
       } elsif ($partial == 0) {
    $score = 'incorrect_by_override';
       }
       $score = 'excused' if (($ENV{'form.GD_'.$user.'_'.$_.'_sv'} eq 'excused') &&
      ($score ne 'excused'));
       $result .= '<td align="center">'.$old_aw.'&nbsp;</td>'.
    '<td align="center">'.$awarded.
    ($score eq 'excused' ? $score : '').'&nbsp;</td>';
   
       next if ($old_part eq $partial && $old_score eq $score);
   
       $updateflag = 1;
       $newrecord{'resource.'.$_.'.awarded'}  = $partial if $partial ne '';
       $newrecord{'resource.'.$_.'.solved'} = $score;
   
    }
    $result .= '</tr>'."\n";
    if ($updateflag) {
       $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
       &Apache::lonnet::cstore(\%newrecord,$symb,$ENV{'request.course.id'},
       $udom,$user);
    }
       }
       $result .= '</table></td></tr></table>'."\n";
       return $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>");
   }
   
     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
 }  }
   
 sub csvupload_javascript_reverse_associate {  sub csvupload_javascript_reverse_associate {
Line 718  ENDPICK Line 1840  ENDPICK
 }  }
   
 sub csvuploadmap_header {  sub csvuploadmap_header {
   my ($request,$symb,$url,$datatoken,$distotal)= @_;      my ($request,$symb,$url,$datatoken,$distotal)= @_;
   my $result;      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();
   }      }
   $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>Uploading Class Grades for resource $url</h3>
 <hr>  <hr>
Line 750  to this page if the data selected is ins Line 1872  to this page if the data selected is ins
 $javascript  $javascript
 </script>  </script>
 ENDPICK  ENDPICK
   return '';  return '';
   
 }  }
   
 sub csvupload_fields {  sub csvupload_fields {
   my ($url) = @_;      my ($url) = @_;
   my (@parts) = &getpartlist($url);      my (@parts) = &getpartlist($url);
   my @fields=(['username','Student Username'],['domain','Student Domain']);      my @fields=(['username','Student Username'],['domain','Student Domain']);
   foreach my $part (sort(@parts)) {      foreach my $part (sort(@parts)) {
     my @datum;   my @datum;
     my $display=&Apache::lonnet::metadata($url,$part.'.display');   my $display=&Apache::lonnet::metadata($url,$part.'.display');
     my $name=$part;   my $name=$part;
     if  (!$display) { $display = $name; }   if  (!$display) { $display = $name; }
     @datum=($name,$display);   @datum=($name,$display);
     push(@fields,\@datum);   push(@fields,\@datum);
   }      }
   return (@fields);      return (@fields);
 }  }
   
 sub csvuploadmap_footer {  sub csvuploadmap_footer {
   my ($request,$i,$keyfields) =@_;      my ($request,$i,$keyfields) =@_;
   $request->print(<<ENDPICK);      $request->print(<<ENDPICK);
 </table>  </table>
 <input type="hidden" name="nfields" value="$i" />  <input type="hidden" name="nfields" value="$i" />
 <input type="hidden" name="keyfields" value="$keyfields" />  <input type="hidden" name="keyfields" value="$keyfields" />
Line 781  ENDPICK Line 1903  ENDPICK
 }  }
   
 sub csvuploadmap {  sub csvuploadmap {
   my ($request)= @_;      my ($request)= @_;
   my ($symb,$url)=&get_symb_and_url($request);      my ($symb,$url)=&get_symb_and_url($request);
   if (!$symb) {return '';}      if (!$symb) {return '';}
   my $datatoken;      my $datatoken;
   if (!$ENV{'form.datatoken'}) {      if (!$ENV{'form.datatoken'}) {
     $datatoken=&Apache::loncommon::upfile_store($request);   $datatoken=&Apache::loncommon::upfile_store($request);
   } else {  
     $datatoken=$ENV{'form.datatoken'};  
     &Apache::loncommon::load_tmp_file($request);  
   }  
   my @records=&Apache::loncommon::upfile_record_sep();  
   &csvuploadmap_header($request,$symb,$url,$datatoken,$#records+1);  
   my $i;  
   my $keyfields;  
   if (@records) {  
     my @fields=&csvupload_fields($url);  
     if ($ENV{'form.upfile_associate'} eq 'reverse') {  
       &Apache::loncommon::csv_print_samples($request,\@records);  
       $i=&Apache::loncommon::csv_print_select_table($request,\@records,  
     \@fields);  
       foreach (@fields) { $keyfields.=$_->[0].','; }  
       chop($keyfields);  
     } else {      } else {
       unshift(@fields,['none','']);   $datatoken=$ENV{'form.datatoken'};
       $i=&Apache::loncommon::csv_samples_select_table($request,\@records,   &Apache::loncommon::load_tmp_file($request);
       \@fields);  
       my %sone=&Apache::loncommon::record_sep($records[0]);  
       $keyfields=join(',',sort(keys(%sone)));  
     }      }
   }      my @records=&Apache::loncommon::upfile_record_sep();
   &csvuploadmap_footer($request,$i,$keyfields);      &csvuploadmap_header($request,$symb,$url,$datatoken,$#records+1);
   return '';      my ($i,$keyfields);
       if (@records) {
    my @fields=&csvupload_fields($url);
    if ($ENV{'form.upfile_associate'} eq 'reverse') {
       &Apache::loncommon::csv_print_samples($request,\@records);
       $i=&Apache::loncommon::csv_print_select_table($request,\@records,
     \@fields);
       foreach (@fields) { $keyfields.=$_->[0].','; }
       chop($keyfields);
    } else {
       unshift(@fields,['none','']);
       $i=&Apache::loncommon::csv_samples_select_table($request,\@records,
       \@fields);
       my %sone=&Apache::loncommon::record_sep($records[0]);
       $keyfields=join(',',sort(keys(%sone)));
    }
       }
       &csvuploadmap_footer($request,$i,$keyfields);
       return '';
 }  }
   
 sub csvuploadassign {  sub csvuploadassign {
   my ($request)= @_;      my ($request)= @_;
   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++) {
     if ($ENV{'form.upfile_associate'} eq 'reverse') {   if ($ENV{'form.upfile_associate'} eq 'reverse') {
       if ($ENV{'form.f'.$i} ne 'none') {      if ($ENV{'form.f'.$i} ne 'none') {
  $fields{$keyfields[$i]}=$ENV{'form.f'.$i};   $fields{$keyfields[$i]}=$ENV{'form.f'.$i};
       }      }
     } else {   } else {
       if ($ENV{'form.f'.$i} ne 'none') {      if ($ENV{'form.f'.$i} ne 'none') {
  $fields{$ENV{'form.f'.$i}}=$keyfields[$i];   $fields{$ENV{'form.f'.$i}}=$keyfields[$i];
       }      }
    }
     }      }
   }      $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 $cdom=$ENV{"course.$courseid.domain"};  #  my $cnum=$ENV{"course.$courseid.num"};
   my $cnum=$ENV{"course.$courseid.num"};      my ($classlist) = &getclasslist('all','1');
   my (%classlist) = &getclasslist($cdom,$cnum,'1');      my @skipped;
   my @skipped;      my $countdone=0;
   my $countdone=0;      foreach my $grade (@gradedata) {
   foreach my $grade (@gradedata) {   my %entries=&Apache::loncommon::record_sep($grade);
     my %entries=&Apache::loncommon::record_sep($grade);   my $username=$entries{$fields{'username'}};
     my $username=$entries{$fields{'username'}};   my $domain=$entries{$fields{'domain'}};
     my $domain=$entries{$fields{'domain'}};   if (!exists($$classlist{"$username:$domain"})) {
     if (!exists($classlist{"$username:$domain"})) {      push(@skipped,"$username:$domain");
       push(@skipped,"$username:$domain");      next;
       next;   }
     }   my %grades;
     my %grades;   foreach my $dest (keys(%fields)) {
     foreach my $dest (keys(%fields)) {      if ($dest eq 'username' || $dest eq 'domain') { next; }
       if ($dest eq 'username' || $dest eq 'domain') { next; }      if ($entries{$fields{$dest}} eq '') { next; }
       if ($entries{$fields{$dest}} eq '') { next; }      my $store_key=$dest;
       my $store_key=$dest;      $store_key=~s/^stores/resource/;
       $store_key=~s/^stores/resource/;      $store_key=~s/_/\./g;
       $store_key=~s/_/\./g;      $grades{$store_key}=$entries{$fields{$dest}};
       $grades{$store_key}=$entries{$fields{$dest}};   }
     }   $grades{"resource.regrader"}="$ENV{'user.name'}:$ENV{'user.domain'}";
     $grades{"resource.regrader"}="$ENV{'user.name'}:$ENV{'user.domain'}";   &Apache::lonnet::cstore(\%grades,$symb,$ENV{'request.course.id'},
     &Apache::lonnet::cstore(\%grades,$symb,$ENV{'request.course.id'},   $domain,$username);
     $domain,$username);   $request->print('.');
     $request->print('.');   $request->rflush();
     $request->rflush();   $countdone++;
     $countdone++;      }
   }      $request->print("<br />Stored $countdone students\n");
   $request->print("<br />Stored $countdone students\n");      if (@skipped) {
   if (@skipped) {   $request->print('<br /><font size="+1"><b>Skipped Students</b></font><br />');
     $request->print('<br /><font size="+1"><b>Skipped Students</b></font><br />');   foreach my $student (@skipped) { $request->print("<br />$student"); }
     foreach my $student (@skipped) { $request->print("<br />$student"); }      }
   }      $request->print(&view_edit_entire_class_form($symb,$url));
   $request->print(&view_edit_entire_class_form($symb,$url));      $request->print(&show_grading_menu_form($symb,$url));
   $request->print(&show_grading_menu_form($symb,$url));      return '';
   return '';  
 }  }
   
 sub send_header {  sub send_header {
   my ($request)= @_;      my ($request)= @_;
   $request->print(&Apache::lontexconvert::header());      $request->print(&Apache::lontexconvert::header());
 #  $request->print("  #  $request->print("
 #<script>  #<script>
 #remotewindow=open('','homeworkremote');  #remotewindow=open('','homeworkremote');
 #remotewindow.close();  #remotewindow.close();
 #</script>");   #</script>"); 
   $request->print('<body bgcolor="#FFFFFF">');      $request->print('<body bgcolor="#FFFFFF">');
 }  }
   
 sub send_footer {  sub send_footer {
   my ($request)= @_;      my ($request)= @_;
   $request->print('</body>');      $request->print('</body>');
   $request->print(&Apache::lontexconvert::footer());      $request->print(&Apache::lontexconvert::footer());
 }  }
   
 sub handler {  sub handler {
   my $request=$_[0];      my $request=$_[0];
       
   if ($ENV{'browser.mathml'}) {      if ($ENV{'browser.mathml'}) {
     $request->content_type('text/xml');   $request->content_type('text/xml');
   } else {      } else {
     $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 OK if $request->header_only;
   &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
   my $url=$ENV{'form.url'};      my $url=$ENV{'form.url'};
   my $symb=$ENV{'form.symb'};      my $symb=$ENV{'form.symb'};
   my $command=$ENV{'form.command'};      my $command=$ENV{'form.command'};
   if (!$url) {      if (!$url) {
     my ($temp1,$temp2);   my ($temp1,$temp2);
     ($temp1,$temp2,$ENV{'form.url'})=split(/___/,$symb);   ($temp1,$temp2,$ENV{'form.url'})=split(/___/,$symb);
     $url = $ENV{'form.url'};   $url = $ENV{'form.url'};
   }      }
   &send_header($request);      &send_header($request);
   if ($url eq '' && $symb eq '') {      if ($url eq '' && $symb eq '') {
      if ($ENV{'user.adv'}) {   if ($ENV{'user.adv'}) {
          if (($ENV{'form.codeone'}) && ($ENV{'form.codetwo'}) &&      if (($ENV{'form.codeone'}) && ($ENV{'form.codetwo'}) &&
              ($ENV{'form.codethree'})) {   ($ENV{'form.codethree'})) {
              my $token=$ENV{'form.codeone'}.'*'.$ENV{'form.codetwo'}.'*'.   my $token=$ENV{'form.codeone'}.'*'.$ENV{'form.codetwo'}.'*'.
         $ENV{'form.codethree'};      $ENV{'form.codethree'};
              my ($tsymb,$tuname,$tudom,$tcrsid)=   my ($tsymb,$tuname,$tudom,$tcrsid)=
  &Apache::lonnet::checkin($token);      &Apache::lonnet::checkin($token);
              if ($tsymb) {   if ($tsymb) {
                 my ($map,$id,$url)=split(/\_\_\_/,$tsymb);      my ($map,$id,$url)=split(/\_\_\_/,$tsymb);
                 if (&Apache::lonnet::allowed('mgr',$tcrsid)) {      if (&Apache::lonnet::allowed('mgr',$tcrsid)) {
                    $request->print(   $request->print(
                      &Apache::lonnet::ssi('/res/'.$url,   &Apache::lonnet::ssi('/res/'.$url,
                         ('grade_username' => $tuname,       ('grade_username' => $tuname,
                          'grade_domain' => $tudom,        'grade_domain' => $tudom,
                          'grade_courseid' => $tcrsid,        'grade_courseid' => $tcrsid,
                          'grade_symb' => $tsymb)));        'grade_symb' => $tsymb)));
                 } else {      } else {
                    $request->print('<h1>Not authorized: '.$token.'</h1>');   $request->print('<h1>Not authorized: '.$token.'</h1>');
                 }                 }           
    } else {
       $request->print('<h1>Not a valid DocID: '.$token.'</h1>');
    }
     } else {      } else {
                 $request->print('<h1>Not a valid DocID: '.$token.'</h1>');   $request->print(&Apache::lonxml::tokeninputfield());
             }      }
  } else {  
              $request->print(&Apache::lonxml::tokeninputfield());  
          }  
      }  
   } else {  
     #&Apache::lonhomework::showhashsubset(\%ENV,'^form');  
     $Apache::grades::viewgrades=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'});  
     if ($command eq 'submission') {  
       &listStudents($request) if ($ENV{'form.student'} eq '');  
       $request->print(&submission($request)) if ($ENV{'form.student'} ne '');  
     } elsif ($command eq 'gradingmenu') {  
       $request->print(&gradingmenu($request));  
     } elsif ($command eq 'viewgrades') {  
       $request->print(&viewgrades($request));  
     } elsif ($command eq 'editgrades') {  
       $request->print(&editgrades($request));  
     } elsif ($command eq 'verify') {  
       $request->print(&verifyreceipt($request));  
     } elsif ($command eq 'csvupload') {  
       $request->print(&csvupload($request));  
     } elsif ($command eq 'csvuploadmap') {  
       $request->print(&csvuploadmap($request));  
     } elsif ($command eq 'receiptInput') {  
       &receiptInput($request);  
     } elsif ($command eq 'csvuploadassign') {  
       if ($ENV{'form.associate'} ne 'Reverse Association') {  
  $request->print(&csvuploadassign($request));  
       } else {  
  if ( $ENV{'form.upfile_associate'} ne 'reverse' ) {  
   $ENV{'form.upfile_associate'} = 'reverse';  
  } else {  
   $ENV{'form.upfile_associate'} = 'forward';  
  }   }
  $request->print(&csvuploadmap($request));  
       }  
     } else {      } else {
       $request->print("Unknown action: $command:");   #&Apache::lonhomework::showhashsubset(\%ENV,'^form');
    $Apache::grades::viewgrades=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'});
    if ($command eq 'submission') {
       &listStudents($request) if ($ENV{'form.student'} eq '');
       &submission($request,0,0) if ($ENV{'form.student'} ne '');
    } elsif ($command eq 'processGroup') {
       &processGroup($request);
    } elsif ($command eq 'gradingmenu') {
       $request->print(&gradingmenu($request));
    } elsif ($command eq 'viewgrades') {
       $request->print(&viewgrades($request));
    } elsif ($command eq 'handgrade') {
       $request->print(&processHandGrade($request));
    } elsif ($command eq 'editgrades') {
       $request->print(&editgrades($request));
    } elsif ($command eq 'verify') {
       $request->print(&verifyreceipt($request));
    } elsif ($command eq 'csvupload') {
       $request->print(&csvupload($request));
    } elsif ($command eq 'viewclasslist') {
       $request->print(&viewclasslist($request));
    } elsif ($command eq 'csvuploadmap') {
       $request->print(&csvuploadmap($request));
   #    } elsif ($command eq 'receiptInput') {
   #      &receiptInput($request);
    } elsif ($command eq 'csvuploadassign') {
       if ($ENV{'form.associate'} ne 'Reverse Association') {
    $request->print(&csvuploadassign($request));
       } else {
    if ( $ENV{'form.upfile_associate'} ne 'reverse' ) {
       $ENV{'form.upfile_associate'} = 'reverse';
    } else {
       $ENV{'form.upfile_associate'} = 'forward';
    }
    $request->print(&csvuploadmap($request));
       }
    } else {
       $request->print("Unknown action: $command:");
    }
     }      }
   }      &send_footer($request);
   &send_footer($request);      return OK;
   return OK;  
 }  }
   
 1;  1;

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


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