Diff for /loncom/homework/grades.pm between versions 1.50 and 1.70

version 1.50, 2002/09/20 23:41:47 version 1.70, 2003/02/28 21:06:28
Line 31 Line 31
 # 8/20 Gerd Kortemeyer  # 8/20 Gerd Kortemeyer
 # Year 2002  # Year 2002
 # June-August H.K. Ng  # June-August H.K. Ng
   # Year 2003
   # February H.K. Ng
 #  #
   
 package Apache::grades;  package Apache::grades;
Line 39  use Apache::style; Line 41  use Apache::style;
 use Apache::lonxml;  use Apache::lonxml;
 use Apache::lonnet;  use Apache::lonnet;
 use Apache::loncommon;  use Apache::loncommon;
   use Apache::lonnavmaps;
 use Apache::lonhomework;  use Apache::lonhomework;
   use Apache::loncoursedata;
 use Apache::lonmsg qw(:user_normal_msg);  use Apache::lonmsg qw(:user_normal_msg);
 use Apache::Constants qw(:common);  use Apache::Constants qw(:common);
   
 # ----- These first few routines are general use routines.-----  # ----- These first few routines are general use routines.----
 #  #
 # --- Retrieve the parts that matches stores_\d+ from the metadata file.---  # --- Retrieve the parts that matches stores_\d+ from the metadata file.---
 sub getpartlist {  sub getpartlist {
Line 51  sub getpartlist { Line 55  sub getpartlist {
     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_(\w+)_.*/) {
     push(@parts,$key);      push(@parts,$key);
  }   }
     }      }
Line 72  sub get_symb_and_url { Line 76  sub get_symb_and_url {
 sub get_fullname {  sub get_fullname {
     my ($uname,$udom) = @_;      my ($uname,$udom) = @_;
     my %name=&Apache::lonnet::get('environment', ['lastname','generation',      my %name=&Apache::lonnet::get('environment', ['lastname','generation',
   'firstname','middlename'],$udom,$uname);    'firstname','middlename'],
                                     $udom,$uname);
     my $fullname;      my $fullname;
     my ($tmp) = keys(%name);      my ($tmp) = keys(%name);
     if ($tmp !~ /^(con_lost|error|no_such_host)/i) {      if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
  $fullname=$name{'lastname'}.$name{'generation'};          $fullname = &Apache::loncoursedata::ProcessFullName
  if ($fullname =~ /[^\s]+/) { $fullname.=', '; }              (@name{qw/lastname generation firstname middlename/});
  $fullname.=$name{'firstname'}.' '.$name{'middlename'};      } else {
           &Apache::lonnet::logthis('grades.pm: no name data for '.$uname.
                                    '@'.$udom.':'.$tmp);
     }      }
     return $fullname;      return $fullname;
 }  }
Line 91  sub response_type { Line 98  sub response_type {
     my %seen = ();      my %seen = ();
     my (@partlist,%handgrade);      my (@partlist,%handgrade);
     foreach (split(/,/,&Apache::lonnet::metadata($url,'packages'))) {      foreach (split(/,/,&Apache::lonnet::metadata($url,'packages'))) {
  if (/^\w+response_\d+.*/) {   if (/^\w+response_\w+.*/) {
     my ($responsetype,$part) = split(/_/,$_,2);      my ($responsetype,$part) = split(/_/,$_,2);
     my ($partid,$respid) = split(/_/,$part);      my ($partid,$respid) = split(/_/,$part);
     $handgrade{$part} = $responsetype.':'.($allkeys =~ /parameter_$part\_handgrade/ ? 'yes' : 'no');      $handgrade{$part} = $responsetype.':'.($allkeys =~ /parameter_$part\_handgrade/ ? 'yes' : 'no');
Line 107  sub response_type { Line 114  sub response_type {
 #--- section, ids and fullnames for each user.  #--- section, ids and fullnames for each user.
 sub getclasslist {  sub getclasslist {
     my ($getsec,$hideexpired) = @_;      my ($getsec,$hideexpired) = @_;
     my $now = time;      my $classlist=&Apache::loncoursedata::get_classlist();
     my %classlist=&Apache::lonnet::dump('classlist',  
  $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},  
  $ENV{'course.'.$ENV{'request.course.id'}.'.num'});  
     my ($tmp) = keys(%classlist);  
     # Bail out if we were unable to get the classlist      # Bail out if we were unable to get the classlist
     return if ($tmp =~ /^(con_lost|error|no_such_host)/i);      return if (! defined($classlist));
       #
     # codes to check for fields in the classlist      my %sections;
     # should contain end:start:id:section:fullname      my %fullnames;
     for (keys %classlist) {      foreach (keys(%$classlist)) {
  my (@fields) = split(/:/,$classlist{$_});          # the following undefs are for 'domain', and 'username' respectively.
  %classlist   = &reformat_classlist(\%classlist) if (scalar(@fields) <= 2);   my (undef,undef,$end,$start,$id,$section,$fullname,$status)=
  last;              @{$classlist->{$_}};
     }  
   
     my (@holdsec,@sections,%allids,%stusec,%fullname);  
     foreach (keys(%classlist)) {  
  my ($end,$start,$id,$section,$fullname)=split(/:/,$classlist{$_});  
  # still a student?   # still a student?
  if (($hideexpired) && ($end) && ($end < $now)) {   if (($hideexpired) && ($status ne 'Active')) {
     next;              delete ($classlist->{$_});
  }              next;
           }
  $section = ($section ne '' ? $section : 'no');   $section = ($section ne '' ? $section : 'no');
  push @holdsec,$section;  
  if ($getsec eq 'all' || $getsec eq $section) {   if ($getsec eq 'all' || $getsec eq $section) {
     push (@{ $classlist{$getsec} }, $_);              $sections{$section}++;
     $allids{$_}  =$id;              $fullnames{$_}=$fullname;
     $stusec{$_}  =$section;          } else {
     $fullname{$_}=$fullname;              delete($classlist->{$_});
  }          }
     }      }
     my %seen = ();      my %seen = ();
     foreach my $item (@holdsec) {      my @sections = sort(keys(%sections));
  push (@sections, $item) unless $seen{$item}++;      return ($classlist,\@sections,\%fullnames);
     }  
     return (\%classlist,\@sections,\%allids,\%stusec,\%fullname);  
 }  
   
 # add id, section and fullname to the classlist.db  
 # done to maintain backward compatibility with older versions  
 sub reformat_classlist {  
     my ($classlist) = shift;  
     foreach (sort keys(%$classlist)) {  
  my ($unam,$udom) = split(/:/);  
  my $section      = &Apache::lonnet::usection($udom,$unam,$ENV{'request.course.id'});  
  my $fullname     = &get_fullname ($unam,$udom);  
  my %userid       = &Apache::lonnet::idrget($udom,($unam));  
  $$classlist{$_}  = $$classlist{$_}.':'.$userid{$unam}.':'.$section.':'.$fullname;  
     }  
     my $putresult = &Apache::lonnet::put  
  ('classlist',\%$classlist,  
  $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},  
  $ENV{'course.'.$ENV{'request.course.id'}.'.num'});  
   
     return %$classlist;  
 }  }
   
 #find user domain  #find user domain
Line 263  sub verifyreceipt { Line 240  sub verifyreceipt {
  '<font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font><br><br>'."\n";   '<font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font><br><br>'."\n";
   
     my ($string,$contents,$matches) = ('','',0);      my ($string,$contents,$matches) = ('','',0);
     my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist('all','0');      my (undef,undef,$fullname) = &getclasslist('all','0');
       
     foreach (sort {$$fullname{$a} cmp $$fullname{$b} } keys %$fullname) {      foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {
  my ($uname,$udom)=split(/\:/);   my ($uname,$udom)=split(/\:/);
  if ($receipt eq    if ($receipt eq 
     &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb)) {      &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb)) {
Line 295  sub verifyreceipt { Line 272  sub verifyreceipt {
     return $string.&show_grading_menu_form($symb,$url);      return $string.&show_grading_menu_form($symb,$url);
 }  }
   
   #
   # Pick student and page/sequence for manual grading
   
   
 #--- This is called by a number of programs.  #--- This is called by a number of programs.
 #--- Called from the Grading Menu - View/Grade an individual student  #--- Called from the Grading Menu - View/Grade an individual student
 #--- Also called directly when one clicks on the subm button   #--- Also called directly when one clicks on the subm button 
Line 319  sub listStudents { Line 300  sub listStudents {
     }      }
     $result.='</table>';      $result.='</table>';
   
     my $viewgrade;      my $viewgrade = $ENV{'form.handgrade'} eq 'yes' ? 'View/Grade' : 'View';
     if ($ENV{'form.handgrade'} eq 'yes') {  
  $viewgrade = 'View/Grade';  
     } else {  
  $viewgrade = 'View';  
     }  
   
     $result='<h3><font color="#339933">&nbsp;'.      $result='<h3><font color="#339933">&nbsp;'.
  $viewgrade.   $viewgrade.
Line 365  LISTJAVASCRIPT Line 341  LISTJAVASCRIPT
     my $checklastsub = $ENV{'form.handgrade'} eq 'yes' ? '' : 'checked';      my $checklastsub = $ENV{'form.handgrade'} eq 'yes' ? '' : 'checked';
   
     my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'."\n".      my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'."\n".
  '&nbsp;<b>View Problem: </b><input type="radio" name="vProb" value="no" checked> no '."\n".   '&nbsp;<b>View Problem: </b><input type="radio" name="vProb" value="no" /> no '."\n".
  '<input type="radio" name="vProb" value="yes"> yes <br />'."\n".   '<input type="radio" name="vProb" value="yes" checked /> one student '."\n".
    '<input type="radio" name="vProb" value="all" /> all students <br />'."\n".
  '&nbsp;<b>Submissions: </b>'."\n";   '&nbsp;<b>Submissions: </b>'."\n";
     if ($ENV{'form.handgrade'} eq 'yes') {      if ($ENV{'form.handgrade'} eq 'yes') {
  $gradeTable.='<input type="radio" name="lastSub" value="hdgrade" '.$checkhdgrade.' /> handgrade only'."\n";   $gradeTable.='<input type="radio" name="lastSub" value="hdgrade" '.$checkhdgrade.' /> handgrade only'."\n";
Line 389  LISTJAVASCRIPT Line 366  LISTJAVASCRIPT
  'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n".   'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n".
  'value="'.$viewgrade.'" />'."\n";   'value="'.$viewgrade.'" />'."\n";
     
     my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($getsec,'0');      my (undef,undef,$fullname) = &getclasslist($getsec,'0');
           
     $gradeTable.='<table border="0"><tr><td bgcolor="#777777">'.      $gradeTable.='<table border="0"><tr><td bgcolor="#777777">'.
  '<table border="0"><tr bgcolor="#e6ffff">'.   '<table border="0"><tr bgcolor="#e6ffff">'.
Line 401  LISTJAVASCRIPT Line 378  LISTJAVASCRIPT
     $gradeTable.='</tr>'."\n";      $gradeTable.='</tr>'."\n";
   
     my $ctr = 0;      my $ctr = 0;
     foreach my $student (sort {$$fullname{$a} cmp $$fullname{$b} } keys %$fullname) {      foreach my $student (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {
  my ($uname,$udom) = split(/:/,$student);   my ($uname,$udom) = split(/:/,$student);
  my (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist);   my (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist);
  my $statusflg = '';   my $statusflg = '';
Line 697  sub sub_page_js { Line 674  sub sub_page_js {
     pWin.document.write("<tr bgcolor=\\"#ffffdd\\">");      pWin.document.write("<tr bgcolor=\\"#ffffdd\\">");
     pWin.document.write("<td>Subject</td>");      pWin.document.write("<td>Subject</td>");
     pWin.document.write("<td align=\\"center\\"><input name=\\"subchk\\" type=\\"checkbox\\"" +shwsel+"></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>");      pWin.document.write("<td><input name=\\"msgsub\\" type=\\"text\\" value=\\""+msg+"\\"size=\\"60\\" maxlength=\\"80\\"></td></tr>");
 }  }
   
 function displaySavedMsg(ctr,msg,shwsel) {  function displaySavedMsg(ctr,msg,shwsel) {
     pWin.document.write("<tr bgcolor=\\"#ffffdd\\">");      pWin.document.write("<tr bgcolor=\\"#ffffdd\\">");
     pWin.document.write("<td align=\\"center\\">"+ctr+"</td>");      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 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>");      pWin.document.write("<td><input name=\\"msg"+ctr+"\\" type=\\"text\\" value=\\""+msg+"\\" size=\\"60\\" maxlength=\\"80\\"></td></tr>");
 }  }
   
   function newMsg(newmsg,shwsel) {    function newMsg(newmsg,shwsel) {
     pWin.document.write("<tr bgcolor=\\"#ffffdd\\">");      pWin.document.write("<tr bgcolor=\\"#ffffdd\\">");
     pWin.document.write("<td align=\\"center\\">New</td>");      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 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>");      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() {    function msgTail() {
Line 821  SUBJAVASCRIPT Line 798  SUBJAVASCRIPT
 }  }
   
   
   sub show_problem {
       my ($request,$symb,$uname,$udom,$removeform) = @_;
       my $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom,
         $ENV{'request.course.id'});
       if ($removeform) {
    $rendered=~s|<form(.*?)>||g;
    $rendered=~s|</form>||g;
    $rendered=~s|name="submit"|name="would_have_been_submit"|g;
       }
       my $companswer=&Apache::loncommon::get_student_answers($symb,$uname,$udom,
      $ENV{'request.course.id'});
       if ($removeform) {
    $companswer=~s|<form(.*?)>||g;
    $companswer=~s|</form>||g;
    $rendered=~s|name="submit"|name="would_have_been_submit"|g;
       }
       my $result.='<table border="0" width="100%"><tr><td bgcolor="#777777">';
       $result.='<table border="0" width="100%"><tr><td bgcolor="#e6ffff">';
       $result.='<b> View of the problem - '.$ENV{'form.fullname'}.
    '</b></td></tr><tr><td bgcolor="#ffffff">'.$rendered.'<br />';
       $result.='<b>Correct answer:</b><br />'.$companswer;
       $result.='</td></tr></table>';
       $result.='</td></tr></table><br />';
       $request->print($result);
   }
   
 # --------------------------- show submissions of a student, option to grade   # --------------------------- show submissions of a student, option to grade 
 sub submission {  sub submission {
     my ($request,$counter,$total) = @_;      my ($request,$counter,$total) = @_;
Line 835  sub submission { Line 838  sub submission {
     my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));      my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));
     if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }      if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }
     my $last = ($ENV{'form.lastSub'} eq 'last' ? 'last' : '');      my $last = ($ENV{'form.lastSub'} eq 'last' ? 'last' : '');
     $ENV{'form.vProb'} = $ENV{'form.vProb'} ne '' ? $ENV{'form.vProb'} : 'yes';  #    $ENV{'form.vProb'} = $ENV{'form.vProb'} ne '' ? $ENV{'form.vProb'} : 'yes';
     my ($classlist,$seclist,$ids,$stusec,$fullname);  
   
     # header info      # header info
     if ($counter == 0) {      if ($counter == 0) {
Line 846  sub submission { Line 848  sub submission {
   
  # option to display problem, only once else it cause problems    # option to display problem, only once else it cause problems 
         # with the form later since the problem has a form.          # with the form later since the problem has a form.
  if ($ENV{'form.vProb'} eq 'yes') {   if ($ENV{'form.vProb'} eq 'yes' or !$ENV{'form.vProb'}) {
     my $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom,      &show_problem($request,$symb,$uname,$udom,0);
       $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> View of the problem - '.$ENV{'form.fullname'}.  
  '</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    # kwclr is the only variable that is guaranteed to be non blank 
Line 921  KEYWORDS Line 912  KEYWORDS
         }          }
     }      }
   
       if ($ENV{'form.vProb'} eq 'all') {
    $request->print('<br /><br /><br />');
    &show_problem($request,$symb,$uname,$udom,1);
       }
   
     my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);      my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);
     my ($partlist,$handgrade) = &response_type($url);      my ($partlist,$handgrade) = &response_type($url);
   
Line 937  KEYWORDS Line 933  KEYWORDS
   
     # If this is handgraded, then check for collaborators      # If this is handgraded, then check for collaborators
     my @col_fullnames;      my @col_fullnames;
       my ($classlist,$fullname);
     if ($ENV{'form.handgrade'} eq 'yes') {      if ($ENV{'form.handgrade'} eq 'yes') {
  my @col_list;   my @col_list;
  ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist('all','0');   ($classlist,undef,$fullname) = &getclasslist('all','0');
  for (keys (%$handgrade)) {   for (keys (%$handgrade)) {
     my $ncol = &Apache::lonnet::EXT('resource.'.$_.      my $ncol = &Apache::lonnet::EXT('resource.'.$_.
     '.maxcollaborators',$symb,$udom,$uname);      '.maxcollaborators',
     if ($ncol > 0) {                                              $symb,$udom,$uname);
  s/\_/\./g;      next if ($ncol <= 0);
  if ($record{'resource.'.$_.'.collaborators'} ne '') {              s/\_/\./g;
     my (@collaborators) = split(/,?\s+/,              next if ($record{'resource.'.$_.'.collaborators'} eq '');
  $record{'resource.'.$_.'.collaborators'});              my (@collaborators) = split(/,?\s+/,
     my (@badcollaborators);                                     $record{'resource.'.$_.'.collaborators'});
     if (scalar(@collaborators) != 0) {              my (@badcollaborators);
  $result.='<b>Collaborators: </b>';              if (scalar(@collaborators) != 0) {
  foreach my $collaborator (@collaborators) {                  $result.='<b>Collaborators: </b>';
     $collaborator = $collaborator =~ /\@|:/ ?                   foreach my $collaborator (@collaborators) {
  (split(/@|:/,$collaborator))[0] : $collaborator;                      my ($co_name,$co_dom) = split /\@|:/,$collaborator;
     next if ($collaborator eq $uname);                      $co_dom = $udom if (! defined($co_dom));
     if (!grep /^$collaborator:/i,keys %$classlist) {                      next if ($co_name eq $uname && $co_dom eq $udom);
  push @badcollaborators,$collaborator;                      # Doing this grep allows 'fuzzy' specification
  next;                      my @Matches = grep /^$co_name:$co_dom/i,
     }                      keys %$classlist;
     push @col_list, $collaborator;                      if (! scalar(@Matches)) {
     my ($lastname,$givenn) = split(/,/,$$fullname{$collaborator.':'.$udom});                          push @badcollaborators,$collaborator;
     push @col_fullnames, $givenn.' '.$lastname;                          next;
     $result.=$$fullname{$collaborator.':'.$udom}.'&nbsp; &nbsp; &nbsp;';                      }
  }                      push @col_list, @Matches;
  $result.='<br />'."\n";                      foreach (@Matches) {
  $result.='<table border="0"><tr bgcolor="#ffbbbb"><td>'.                          my ($lastname,$givenn) = split(/,/,$$fullname{$_});
     'This student has submitted '.                          push @col_fullnames, $givenn.' '.$lastname;
     (scalar (@badcollaborators) > 1 ? '' : 'an').                          $result.=$$fullname{$_}.'&nbsp; &nbsp; &nbsp;';
     ' invalid collaborator'.(scalar (@badcollaborators) > 1 ? 's. ' : '. ').                      }
     (join ', ',@badcollaborators).'</td></tr></table>'                   }
     if (scalar(@badcollaborators) > 0);                  $result.='<br />'."\n";
                   if (scalar(@badcollaborators) > 0) {
  $result.='<table border="0"><tr bgcolor="#ffbbbb"><td>'.                      $result.='<table border="0"><tr bgcolor="#ffbbbb"><td>';
     'This student has submitted too many collaborators. Maximum is '.                      $result.='This student has submitted ';
     $ncol.'.</td></tr></table>' if (scalar(@collaborators) > $ncol);                      if (scalar(@badcollaborators) == 1) {
  $result.='<input type="hidden" name="collaborator'.$counter.                          $result .= 'an invalid collaborator';
     '" value="'.(join ':',@col_list).'" />'."\n";                      } else {
     }                          $result .= 'invalid collaborators';
  }                      }
     }                      $result .= ': '.join(', ',@badcollaborators);
                       
                   }
                   if (scalar(@collaborators > $ncol)) {
                       $result .= '<table border="0"><tr bgcolor="#ffbbbb"><td>';
                       $result .= 'This student has sumbitted too many '.
                           'collaborators.  Maximum is '.$ncol;
                       $result .= '</td></tr></table>';
                   }
                   $result.='<input type="hidden" name="collaborator'.$counter.
                       '" value="'.(join ':',@col_list).'" />'."\n";
               }
  }   }
     }      }
     $request->print($result."\n");      $request->print($result."\n");
Line 1015  KEYWORDS Line 1023  KEYWORDS
     my ($ressub,$subval) = split(/:/,$_,2);      my ($ressub,$subval) = split(/:/,$_,2);
     $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '.      $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '.
  $partid.'</b> <font color="#999999">( ID '.$respid.   $partid.'</b> <font color="#999999">( ID '.$respid.
  ' )</font>&nbsp; &nbsp;<b>Answer: </b>'.   ' )</font>&nbsp; &nbsp;'.
                                   ($record{"resource.$partid.$respid.uploadedurl"}?
                                   '<a href="'.
                                   &Apache::lonnet::tokenwrapper($record{"resource.$partid.$respid.uploadedurl"}).
      '"><img src="/adm/lonIcons/unknown.gif" border=0"> File uploaded by student</a> <font color="red" size="1">Like all files provided by users, this file may contain virusses</font><br />':'').
                                   '<b>Answer: </b>'.
  &keywords_highlight($subval).'</td></tr>'."\n"   &keywords_highlight($subval).'</td></tr>'."\n"
  if ($ENV{'form.lastSub'} eq 'lastonly' ||    if ($ENV{'form.lastSub'} eq 'lastonly' || 
     ($ENV{'form.lastSub'} eq 'hdgrade' &&       ($ENV{'form.lastSub'} eq 'hdgrade' && 
Line 1067  KEYWORDS Line 1080  KEYWORDS
  $seen{$partid}++;   $seen{$partid}++;
  next if ($$handgrade{$_} =~ /:no$/);   next if ($$handgrade{$_} =~ /:no$/);
  push @partlist,$partid;   push @partlist,$partid;
  my $wgt    = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb,$udom,$uname);  
  my $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);  
  $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=&gradeBox($symb,$uname,$udom,$counter,$partid,\%record);
  $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.  
     ','.$wgt.')" /></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>'."\n";  
  $request->print($result);   $request->print($result);
     }      }
     $result='<input type="hidden" name="partlist'.$counter.      $result='<input type="hidden" name="partlist'.$counter.
Line 1161  sub get_last_submission { Line 1136  sub get_last_submission {
  for ($version=1;$version<=$returnhash{'version'};$version++) {   for ($version=1;$version<=$returnhash{'version'};$version++) {
     foreach (sort(split(/\:/,$returnhash{$version.':keys'}))) {      foreach (sort(split(/\:/,$returnhash{$version.':keys'}))) {
  $lasthash{$_}=$returnhash{$version.':'.$_};   $lasthash{$_}=$returnhash{$version.':'.$_};
  if ($returnhash{$version.':'.$_} =~ /(SUBMITTED|DRAFT)$/) {  # if ($returnhash{$version.':'.$_} =~ /(SUBMITTED|DRAFT)$/) {
    $timestamp = scalar(localtime($returnhash{$version.':timestamp'}));     $timestamp = scalar(localtime($returnhash{$version.':timestamp'}));
        }   #       } 
     }      }
  }   }
  foreach ((keys %lasthash)) {   foreach ((keys %lasthash)) {
Line 1187  sub keywords_highlight { Line 1162  sub keywords_highlight {
     (my $styleoff = $styleon) =~ s/\</\<\//;      (my $styleoff = $styleon) =~ s/\</\<\//;
     my @keylist   = split(/[,\s+]/,$ENV{'form.keywords'});      my @keylist   = split(/[,\s+]/,$ENV{'form.keywords'});
     foreach (@keylist) {      foreach (@keylist) {
  $string =~ s/\b$_(\b|\.)/\<font color\=$ENV{'form.kwclr'} $size\>$styleon$_$styleoff\<\/font\>/gi;   $string =~ s/\b\Q$_\E(\b|\.)/\<font color\=$ENV{'form.kwclr'} $size\>$styleon$_$styleoff\<\/font\>/gi;
     }      }
       # This is not really the right place to do this, but I cannot find a
       # better one at this time.  So here we go - the m in the s:::mg causes
       # ^ to match the beginning of a new line.  So we replace(???) the beginning
       # of the line with <br /> to make things formatted a little better.
       $string =~ s:^:<br />:mg;
     return $string;      return $string;
 }  }
   
Line 1209  sub processHandGrade { Line 1189  sub processHandGrade {
   
     my $includemsg = $ENV{'form.includemsg'.$ctr};      my $includemsg = $ENV{'form.includemsg'.$ctr};
     my ($subject,$message,$msgstatus) = ('','','');      my ($subject,$message,$msgstatus) = ('','','');
     if ($includemsg =~ /savemsg|new$ctr/) {      if ($includemsg =~ /savemsg|newmsg\Q$ctr\E/) {
  $subject = $ENV{'form.msgsub'} if ($includemsg =~ /^msgsub/);   $subject = $ENV{'form.msgsub'} if ($includemsg =~ /^msgsub/);
  my (@msgnum) = split(/,/,$includemsg);   my (@msgnum) = split(/,/,$includemsg);
  foreach (@msgnum) {   foreach (@msgnum) {
Line 1297  sub processHandGrade { Line 1277  sub processHandGrade {
  $laststu = $firststu if ($ctr > $ngrade);   $laststu = $firststu if ($ctr > $ngrade);
     }      }
   
     my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($ENV{'form.section'},'0');      my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'0');
     my (@parsedlist,@nextlist);      my (@parsedlist,@nextlist);
     my ($nextflg) = 0;      my ($nextflg) = 0;
     foreach (sort {$$fullname{$a} cmp $$fullname{$b} } keys %$fullname) {      foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {
  if ($nextflg == 1 && $button =~ /Next$/) {   if ($nextflg == 1 && $button =~ /Next$/) {
     push @parsedlist,$_;      push @parsedlist,$_;
  }   }
Line 1359  sub saveHandGrade { Line 1339  sub saveHandGrade {
     my %newrecord;      my %newrecord;
     foreach (split(/:/,$ENV{'form.partlist'.$newflg})) {      foreach (split(/:/,$ENV{'form.partlist'.$newflg})) {
  if ($ENV{'form.GD_SEL'.$newflg.'_'.$_} eq 'excused') {   if ($ENV{'form.GD_SEL'.$newflg.'_'.$_} eq 'excused') {
     $newrecord{'resource.'.$_.'.solved'} = 'excused'       if ($record{'resource.'.$_.'.solved'} ne 'excused') {
  if ($record{'resource.'.$_.'.solved'} ne 'excused');   $newrecord{'resource.'.$_.'.solved'} = 'excused';
    if (exists($record{'resource.'.$_.'.awarded'})) {
       $newrecord{'resource.'.$_.'.awarded'} = '';
    }
       }
  } else {   } else {
     my $pts = ($ENV{'form.GD_BOX'.$newflg.'_'.$_} ne '' ?       my $pts = ($ENV{'form.GD_BOX'.$newflg.'_'.$_} ne '' ? 
        $ENV{'form.GD_BOX'.$newflg.'_'.$_} :          $ENV{'form.GD_BOX'.$newflg.'_'.$_} : 
Line 1441  sub viewgrades_js { Line 1425  sub viewgrades_js {
  for (i=0;i<document.classgrade.total.value;i++) {   for (i=0;i<document.classgrade.total.value;i++) {
     var user = eval("document.classgrade.ctr"+i+".value");      var user = eval("document.classgrade.ctr"+i+".value");
     var scorename = eval("document.classgrade.GD_"+user+      var scorename = eval("document.classgrade.GD_"+user+
  "_"+partid+"_aw");   "_"+partid+"_awarded");
     var saveval   = eval("document.classgrade.GD_"+user+      var saveval   = eval("document.classgrade.GD_"+user+
  "_"+partid+"_sv_s.value");   "_"+partid+"_solved_s.value");
     var selname   = eval("document.classgrade.GD_"+user+"_"+partid+"_sv");      var selname   = eval("document.classgrade.GD_"+user+"_"+partid+"_solved");
     if (saveval != "correct") {      if (saveval != "correct") {
  scorename.value = point;   scorename.value = point;
  if (selname[0].selected != true) {   if (selname[0].selected != true) {
Line 1470  sub viewgrades_js { Line 1454  sub viewgrades_js {
     for (i=0;i<document.classgrade.total.value;i++) {      for (i=0;i<document.classgrade.total.value;i++) {
  var user = eval("document.classgrade.ctr"+i+".value");   var user = eval("document.classgrade.ctr"+i+".value");
  var scorename = eval("document.classgrade.GD_"+user+   var scorename = eval("document.classgrade.GD_"+user+
      "_"+partid+"_aw");       "_"+partid+"_awarded");
  var saveval   = eval("document.classgrade.GD_"+user+   var saveval   = eval("document.classgrade.GD_"+user+
      "_"+partid+"_sv_s.value");       "_"+partid+"_solved_s.value");
  var selname   = eval("document.classgrade.GD_"+user+   var selname   = eval("document.classgrade.GD_"+user+
      "_"+partid+"_sv");       "_"+partid+"_solved");
  if (saveval != "correct") {   if (saveval != "correct") {
     scorename.value = "";      scorename.value = "";
     selname[1].selected = true;      selname[1].selected = true;
Line 1484  sub viewgrades_js { Line 1468  sub viewgrades_js {
     for (i=0;i<document.classgrade.total.value;i++) {      for (i=0;i<document.classgrade.total.value;i++) {
  var user = eval("document.classgrade.ctr"+i+".value");   var user = eval("document.classgrade.ctr"+i+".value");
  var scorename = eval("document.classgrade.GD_"+user+   var scorename = eval("document.classgrade.GD_"+user+
      "_"+partid+"_aw");       "_"+partid+"_awarded");
  var saveval   = eval("document.classgrade.GD_"+user+   var saveval   = eval("document.classgrade.GD_"+user+
      "_"+partid+"_sv_s.value");       "_"+partid+"_solved_s.value");
  var selname   = eval("document.classgrade.GD_"+user+   var selname   = eval("document.classgrade.GD_"+user+
      "_"+partid+"_sv");       "_"+partid+"_solved");
  if (saveval != "correct") {   if (saveval != "correct") {
     scorename.value = eval("document.classgrade.GD_"+user+      scorename.value = eval("document.classgrade.GD_"+user+
      "_"+partid+"_aw_s.value");;       "_"+partid+"_awarded_s.value");;
     selname[0].selected = true;      selname[0].selected = true;
  }   }
     }      }
Line 1499  sub viewgrades_js { Line 1483  sub viewgrades_js {
     }      }
   
     function changeSelect(partid,user) {      function changeSelect(partid,user) {
  var selval = eval("document.classgrade.GD_"+user+'_'+partid+"_sv");   var selval = eval("document.classgrade.GD_"+user+'_'+partid+"_solved");
  var textbox = eval("document.classgrade.GD_"+user+'_'+partid+"_aw");   var textbox = eval("document.classgrade.GD_"+user+'_'+partid+"_awarded");
  var point  = textbox.value;   var point  = textbox.value;
  var weight = eval("document.classgrade.weight_"+partid+".value");   var weight = eval("document.classgrade.weight_"+partid+".value");
   
Line 1521  sub viewgrades_js { Line 1505  sub viewgrades_js {
     }      }
   
     function changeOneScore(partid,user) {      function changeOneScore(partid,user) {
  var selval = eval("document.classgrade.GD_"+user+'_'+partid+"_sv");   var selval = eval("document.classgrade.GD_"+user+'_'+partid+"_solved");
  if (selval[1].selected) {   if (selval[1].selected) {
     var boxval = eval("document.classgrade.GD_"+user+'_'+partid+"_aw");      var boxval = eval("document.classgrade.GD_"+user+'_'+partid+"_awarded");
     boxval.value = "";      boxval.value = "";
  }   }
     }      }
Line 1544  sub viewgrades_js { Line 1528  sub viewgrades_js {
     for (i=0;i<document.classgrade.total.value;i++) {      for (i=0;i<document.classgrade.total.value;i++) {
  var user = eval("document.classgrade.ctr"+i+".value");   var user = eval("document.classgrade.ctr"+i+".value");
  var resetscore = eval("document.classgrade.GD_"+user+   var resetscore = eval("document.classgrade.GD_"+user+
       "_"+partid+"_aw");        "_"+partid+"_awarded");
  resetscore.value = eval("document.classgrade.GD_"+user+   resetscore.value = eval("document.classgrade.GD_"+user+
  "_"+partid+"_aw_s.value");   "_"+partid+"_awarded_s.value");
   
  var saveselval   = eval("document.classgrade.GD_"+user+   var saveselval   = eval("document.classgrade.GD_"+user+
      "_"+partid+"_sv_s.value");       "_"+partid+"_solved_s.value");
   
  var selname   = eval("document.classgrade.GD_"+user+"_"+partid+"_sv");   var selname   = eval("document.classgrade.GD_"+user+"_"+partid+"_solved");
  if (saveselval == "excused") {   if (saveselval == "excused") {
     if (selname[1].selected == false) { selname[1].selected = true;}      if (selname[1].selected == false) { selname[1].selected = true;}
  } else {   } else {
Line 1584  sub viewgrades { Line 1568  sub viewgrades {
  '<input type="hidden" name="url"     value="'.$url.'" />'."\n".   '<input type="hidden" name="url"     value="'.$url.'" />'."\n".
  '<input type="hidden" name="command" value="editgrades" />'."\n".   '<input type="hidden" name="command" value="editgrades" />'."\n".
  '<input type="hidden" name="section" value="'.$ENV{'form.section'}.'" />'."\n";   '<input type="hidden" name="section" value="'.$ENV{'form.section'}.'" />'."\n";
     $result.='To assign the same score for all the students use the radio buttons or '.      $result.='<h3>Assign Common Grade To ';
  'text box below. To assign scores individually fill in the score boxes for '.      if ($ENV{'form.section'} eq 'all') {
  'each student in the table below. <font color="red">A part that has already '.   $result.='Class </h3>';
  'been graded does not get changed using the radio buttons or text box. '.      } elsif ($ENV{'form.section'} eq 'no') {
  'If needed, it has to be changed individually.</font>';   $result.='Students in no Section </h3>';
       } else {
    $result.='Students in Section '.$ENV{'form.section'}.'</h3>';
       }
       $result.= '<table border=0><tr><td bgcolor="#777777">'."\n".
    '<table border=0><tr bgcolor="#ffffdd"><td>';
   #    $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 part 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>';
   #    $result.='</td></tr><tr><td>';
     #radio buttons/text box for assigning points for a section or class.      #radio buttons/text box for assigning points for a section or class.
     #handles different parts of a problem      #handles different parts of a problem
     my ($partlist,$handgrade) = &response_type($ENV{'form.url'});      my ($partlist,$handgrade) = &response_type($ENV{'form.url'});
Line 1598  sub viewgrades { Line 1592  sub viewgrades {
     $result.='<table border="0">';      $result.='<table border="0">';
     my %seen = ();      my %seen = ();
     for (sort keys(%$handgrade)) {      for (sort keys(%$handgrade)) {
  my ($partid,$respid) = split (/_/);   my ($partid,$respid) = split (/_/,$_,2);
  next if $seen{$partid};   next if $seen{$partid};
  $seen{$partid}++;   $seen{$partid}++;
  my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});   my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});
Line 1614  sub viewgrades { Line 1608  sub viewgrades {
  my $ctr = 0;   my $ctr = 0;
  while ($ctr<=$weight{$partid}) { # display radio buttons in a nice table 10 across   while ($ctr<=$weight{$partid}) { # display radio buttons in a nice table 10 across
     $result.= '<td><input type="radio" name="RADVAL_'.$partid.'" '.      $result.= '<td><input type="radio" name="RADVAL_'.$partid.'" '.
  'onclick="javascript:writePoint('.$partid.','.$weight{$partid}.   'onclick="javascript:writePoint(\''.$partid.'\','.$weight{$partid}.
  ','.$ctr.')" />'.$ctr."</td>\n";   ','.$ctr.')" />'.$ctr."</td>\n";
     $result.=(($ctr+1)%10 == 0 ? '</tr><tr>' : '');      $result.=(($ctr+1)%10 == 0 ? '</tr><tr>' : '');
     $ctr++;      $ctr++;
  }   }
  $result.='</tr></table>';   $result.='</tr></table>';
  $result.= '</td><td><b> or </b><input type="text" name="TEXTVAL_'.   $result.= '</td><td><b> or </b><input type="text" name="TEXTVAL_'.
     $partid.'" size="4" '.      $partid.'" size="4" '.'onChange="javascript:writePoint(\''.
     'onChange="javascript:writePoint('.$partid.','.$weight{$partid}.   $partid.'\','.$weight{$partid}.',\'textval\')" /> /'.
     ',\'textval\')" /> /'.  
     $weight{$partid}.' (problem weight)</td>'."\n";      $weight{$partid}.' (problem weight)</td>'."\n";
  $result.= '</td><td><select name="SELVAL_'.$partid.'"'.   $result.= '</td><td><select name="SELVAL_'.$partid.'"'.
     'onChange="javascript:writeRadText('.$partid.','.$weight{$partid}.')" /> '.      'onChange="javascript:writeRadText(\''.$partid.'\','.
    $weight{$partid}.')"> '.
     '<option selected="on"> </option>'.      '<option selected="on"> </option>'.
     '<option>excused</option></select></td></tr>'."\n";      '<option>excused</option></select></td></tr>'."\n";
  $ctsparts++;   $ctsparts++;
     }      }
     $result.='</table><input type="hidden" name="totalparts" value="'.$ctsparts.'" />';      $result.='</table>'.'</td></tr></table>'.'</td></tr></table>'."\n".
    '<input type="hidden" name="totalparts" value="'.$ctsparts.'" />';
     $result.='<input type="button" value="Reset" '.      $result.='<input type="button" value="Reset" '.
  'onClick="javascript:resetEntry('.$ctsparts.');" TARGET=_self> &nbsp; &nbsp;';   'onClick="javascript:resetEntry('.$ctsparts.');" TARGET=_self> &nbsp; &nbsp;';
     $result.='<input type="button" value="Submit Changes" '.      $result.='<input type="button" value="Submit Changes" '.
Line 1639  sub viewgrades { Line 1634  sub viewgrades {
   
     #table listing all the students in a section/class      #table listing all the students in a section/class
     #header of table      #header of table
       $result.= '<h3>Assign Grade to Specific Students in ';
       if ($ENV{'form.section'} eq 'all') {
    $result.='the Class </h3>';
       } elsif ($ENV{'form.section'} eq 'no') {
    $result.='no Section </h3>';
       } else {
    $result.='Section '.$ENV{'form.section'}.'</h3>';
       }
     $result.= '<table border=0><tr><td bgcolor="#777777">'."\n".      $result.= '<table border=0><tr><td bgcolor="#777777">'."\n".
  '<table border=0><tr bgcolor="#deffff">'.   '<table border=0><tr bgcolor="#deffff">'.
  '<td><b>Fullname</b></td><td><b>Username</b></td><td><b>Domain</b></td>'."\n";   '<td><b>Fullname</b></td><td><b>Username</b></td><td><b>Domain</b></td>'."\n";
     my (@parts) = sort(&getpartlist($url));      my (@parts) = sort(&getpartlist($url));
     foreach my $part (@parts) {      foreach my $part (@parts) {
  my $display=&Apache::lonnet::metadata($url,$part.'.display');   my $display=&Apache::lonnet::metadata($url,$part.'.display');
  next if ($display =~ /^Number of Attempts/);  
  if  (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); }   if  (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); }
  if ($display =~ /^Partial Credit Factor/) {   if ($display =~ /^Partial Credit Factor/) {
     $_ = $display;      my ($partid) = &split_part_type($part);
     my ($partid) = /.*?(\d+).*/;      $result.='<td><b>Score Part '.$partid.'<br />(weight = '.
     $result.='<td><b>Score Part '.$partid.'<br>(weight = '.  
  $weight{$partid}.')</b></td>'."\n";   $weight{$partid}.')</b></td>'."\n";
     next;      next;
  }   }
  $display =~ s/Problem Status/Grade Status<br>/;   $display =~ s|Problem Status|Grade Status<br />|;
  $result.='<td><b>'.$display.'</b></td>'."\n";   $result.='<td><b>'.$display.'</b></td>'."\n";
     }      }
     $result.='</tr>';      $result.='</tr>';
   
     #get info for each student      #get info for each student
     #list all the students - with points and grade status      #list all the students - with points and grade status
     my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($ENV{'form.section'},'0');      my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'0');
     my $ctr = 0;      my $ctr = 0;
     foreach (sort {$$fullname{$a} cmp $$fullname{$b} } keys %$fullname) {      foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {
  my ($uname,$udom) = split(/:/);   my ($uname,$udom) = split(/:/);
  $result.='<input type="hidden" name="ctr'.$ctr.'" value="'.$uname.'" />'."\n";   $result.='<input type="hidden" name="ctr'.$ctr.'" value="'.$uname.'" />'."\n";
  $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},   $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},
Line 1687  sub viewstudentgrade { Line 1688  sub viewstudentgrade {
  '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.   '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.
  '\')"; TARGET=_self>'.$fullname.'</a>'.   '\')"; TARGET=_self>'.$fullname.'</a>'.
  '</td><td>'.$uname.'</td><td align="middle">'.$udom.'</td>'."\n";   '</td><td>'.$uname.'</td><td align="middle">'.$udom.'</td>'."\n";
     foreach my $part (@$parts) {      foreach my $apart (@$parts) {
  my ($temp,$part,$type)=split(/_/,$part);   my ($part,$type) = &split_part_type($apart);
  my $score=$record{"resource.$part.$type"};   my $score=$record{"resource.$part.$type"};
  next if $type eq 'tries';  
  if ($type eq 'awarded') {   if ($type eq 'awarded') {
     my $pts = $score eq '' ? '' : $score*$$weight{$part};      my $pts = $score eq '' ? '' : $score*$$weight{$part};
     $result.='<input type="hidden" name="'.      $result.='<input type="hidden" name="'.
  'GD_'.$uname.'_'.$part.'_aw_s" value="'.$pts.'" />'."\n";   'GD_'.$uname.'_'.$part.'_awarded_s" value="'.$pts.'" />'."\n";
     $result.='<td align="middle"><input type="text" name="'.      $result.='<td align="middle"><input type="text" name="'.
  'GD_'.$uname.'_'.$part.'_aw" '.   'GD_'.$uname.'_'.$part.'_awarded" '.
  'onChange="javascript:changeSelect('.$part.',\''.$uname.   'onChange="javascript:changeSelect(\''.$part.'\',\''.$uname.
  '\')" value="'.$pts.'" size="4" /></td>'."\n";   '\')" value="'.$pts.'" size="4" /></td>'."\n";
  } elsif ($type eq 'solved') {   } elsif ($type eq 'solved') {
     my ($status,$foo)=split(/_/,$score,2);      my ($status,$foo)=split(/_/,$score,2);
     $status = 'nothing' if ($status eq '');      $status = 'nothing' if ($status eq '');
     $result.='<input type="hidden" name="'.      $result.='<input type="hidden" name="'.'GD_'.$uname.'_'.
  'GD_'.$uname.'_'.$part.'_sv_s" value="'.$status.'" />'."\n";   $part.'_solved_s" value="'.$status.'" />'."\n";
     $result.='<td align="middle"><select name="'.      $result.='<td align="middle"><select name="'.
  'GD_'.$uname.'_'.$part.'_sv" '.   'GD_'.$uname.'_'.$part.'_solved" '.
  'onChange="javascript:changeOneScore('.$part.',\''.$uname.'\')" >'."\n";   'onChange="javascript:changeOneScore(\''.$part.'\',\''.$uname.'\')" >'."\n";
     my $optsel = '<option selected="on"> </option><option>excused</option>'."\n";      my $optsel = '<option selected="on"> </option><option>excused</option>'."\n";
     $optsel = '<option> </option><option selected="on">excused</option>'."\n"      $optsel = '<option> </option><option selected="on">excused</option>'."\n"
  if ($status eq 'excused');   if ($status eq 'excused');
     $result.=$optsel;      $result.=$optsel;
     $result.="</select></td>\n";      $result.="</select></td>\n";
    } else {
       $result.='<input type="hidden" name="'.
    'GD_'.$uname.'_'.$part.'_'.$type.'_s" value="'.$score.'" />'.
       "\n";
       $result.='<td align="middle"><input type="text" name="'.
    'GD_'.$uname.'_'.$part.'_'.$type.'" '.
    'value="'.$score.'" size="4" /></td>'."\n";
  }   }
     }      }
     $result.='</tr>';      $result.='</tr>';
Line 1740  sub editgrades { Line 1747  sub editgrades {
     'ungraded' =>'ungraded_attempted',      'ungraded' =>'ungraded_attempted',
     'nothing'  => '',      'nothing'  => '',
     );      );
     my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($ENV{'form.section'},'0');      my ($classlist,undef,$fullname) = &getclasslist($ENV{'form.section'},'0');
   
     my (@partid);      my (@partid);
     my %weight = ();      my %weight = ();
       my %columns = ();
     my ($i,$ctr,$count,$rec_update) = (0,0,0,0);      my ($i,$ctr,$count,$rec_update) = (0,0,0,0);
   
       my (@parts) = sort(&getpartlist($url));
       my $header;
     while ($ctr < $ENV{'form.totalparts'}) {      while ($ctr < $ENV{'form.totalparts'}) {
  my $partid = $ENV{'form.partid_'.$ctr};   my $partid = $ENV{'form.partid_'.$ctr};
  push @partid,$partid;   push @partid,$partid;
  $weight{$partid} = $ENV{'form.weight_'.$partid};   $weight{$partid} = $ENV{'form.weight_'.$partid};
  $ctr++;   $ctr++;
  $result .= '<td colspan = 2 align="center"><b>Part '.$partid.  
     '</b> (Weight = '.$weight{$partid}.')</td>';  
     }      }
     $result .= '</tr><tr bgcolor="#deffff">';      foreach my $partid (@partid) {
     foreach (@partid) {   $header .= '<td align="center">&nbsp;<b>Old Score</b>&nbsp;</td>'.
  $result .= '<td align="center">&nbsp;<b>Old Score</b>&nbsp;</td>'.  
     '<td align="center">&nbsp;<b>New Score</b>&nbsp;</td>';      '<td align="center">&nbsp;<b>New Score</b>&nbsp;</td>';
    $columns{$partid}=2;
    foreach my $stores (@parts) {
       my ($part,$type) = &split_part_type($stores);
       if ($part !~ m/^\Q$partid\E/) { next;}
       if ($type eq 'awarded' || $type eq 'solved') { next; }
       my $display=&Apache::lonnet::metadata($url,$stores.'.display');
       $display =~ s/\[Part: (\w)+\]//;
       $header .= '<td align="center">&nbsp;<b>Old</b> '.$display.'&nbsp;</td>'.
    '<td align="center">&nbsp;<b>New</b> '.$display.'&nbsp;</td>';
       $columns{$partid}+=2;
    }
     }      }
       foreach my $partid (@partid) {
    $result .= '<td colspan="'.$columns{$partid}.
       '" align="center"><b>Part '.$partid.
       '</b> (Weight = '.$weight{$partid}.')</td>';
   
       }
       $result .= '</tr><tr bgcolor="#deffff">';
       $result .= $header;
     $result .= '</tr>'."\n";      $result .= '</tr>'."\n";
   
     for ($i=0; $i<$ENV{'form.total'}; $i++) {      for ($i=0; $i<$ENV{'form.total'}; $i++) {
Line 1765  sub editgrades { Line 1792  sub editgrades {
  my %newrecord;   my %newrecord;
  my $updateflag = 0;   my $updateflag = 0;
  my @userdom = grep /^$user:/,keys %$classlist;   my @userdom = grep /^$user:/,keys %$classlist;
  my ($foo,$udom) = split(/:/,$userdom[0]);   my (undef,$udom) = split(/:/,$userdom[0]);
   
  $result .= '<tr bgcolor="#ffffde"><td>'.$user.'&nbsp;</td><td>'.   $result .= '<tr bgcolor="#ffffde"><td>'.$user.'&nbsp;</td><td>'.
     $$fullname{$userdom[0]}.'&nbsp;</td>';      $$fullname{$userdom[0]}.'&nbsp;</td>';
   
  foreach (@partid) {   foreach (@partid) {
     my $old_aw    = $ENV{'form.GD_'.$user.'_'.$_.'_aw_s'};      my $old_aw    = $ENV{'form.GD_'.$user.'_'.$_.'_awarded_s'};
     my $old_part  = $old_aw eq '' ? '' : $old_aw/$weight{$_};      my $old_part_pcr = $old_aw/($weight{$_} ne '0' ? $weight{$_}:1);
     my $old_score = $scoreptr{$ENV{'form.GD_'.$user.'_'.$_.'_sv_s'}};      my $old_part  = $old_aw eq '' ? '' : $old_part_pcr;
       my $old_score = $scoreptr{$ENV{'form.GD_'.$user.'_'.$_.'_solved_s'}};
     my $awarded   = $ENV{'form.GD_'.$user.'_'.$_.'_aw'};  
     my $partial   = $awarded eq '' ? '' : $awarded/$weight{$_};      my $awarded   = $ENV{'form.GD_'.$user.'_'.$_.'_awarded'};
       my $pcr       = $awarded/($weight{$_} ne '0' ? $weight{$_} : 1);
       my $partial   = $awarded eq '' ? '' : $pcr;
     my $score;      my $score;
     if ($partial eq '') {      if ($partial eq '') {
  $score = $scoreptr{$ENV{'form.GD_'.$user.'_'.$_.'_sv_s'}};   $score = $scoreptr{$ENV{'form.GD_'.$user.'_'.$_.'_solved_s'}};
     } elsif ($partial > 0) {      } elsif ($partial > 0) {
  $score = 'correct_by_override';   $score = 'correct_by_override';
     } elsif ($partial == 0) {      } elsif ($partial == 0) {
  $score = 'incorrect_by_override';   $score = 'incorrect_by_override';
     }      }
     $score = 'excused' if (($ENV{'form.GD_'.$user.'_'.$_.'_sv'} eq 'excused') &&      $score = 'excused' if (($ENV{'form.GD_'.$user.'_'.$_.'_solved'} eq 'excused') &&
    ($score ne 'excused'));     ($score ne 'excused'));
     $result .= '<td align="center">'.$old_aw.'&nbsp;</td>'.      $result .= '<td align="center">'.$old_aw.'&nbsp;</td>'.
  '<td align="center">'.$awarded.   '<td align="center">'.$awarded.
  ($score eq 'excused' ? $score : '').'&nbsp;</td>';   ($score eq 'excused' ? $score : '').'&nbsp;</td>';
   
     next if ($old_part eq $partial && $old_score eq $score);      if (!($old_part eq $partial && $old_score eq $score)) {
    $updateflag = 1;
     $updateflag = 1;   $newrecord{'resource.'.$_.'.awarded'}  = $partial if $partial ne '';
     $newrecord{'resource.'.$_.'.awarded'}  = $partial if $partial ne '';   $newrecord{'resource.'.$_.'.solved'}   = $score;
     $newrecord{'resource.'.$_.'.solved'}   = $score;   $rec_update++;
     $rec_update++;      }
   
       my $partid=$_;
       foreach my $stores (@parts) {
    my ($part,$type) = &split_part_type($stores);
    if ($part !~ m/^\Q$partid\E/) { next;}
    if ($type eq 'awarded' || $type eq 'solved') { next; }
    my $old_aw    = $ENV{'form.GD_'.$user.'_'.$part.'_'.$type.'_s'};
    my $awarded   = $ENV{'form.GD_'.$user.'_'.$part.'_'.$type};
    if ($awarded ne '' && $awarded ne $old_aw) {
       $newrecord{'resource.'.$part.'.'.$type}= $awarded;
       $updateflag=1;
    }
    $result .= '<td align="center">'.$old_aw.'&nbsp;</td>'.
       '<td align="center">'.$awarded.'&nbsp;</td>';
       }
  }   }
  $result .= '</tr>'."\n";   $result .= '</tr>'."\n";
  if ($updateflag) {   if ($updateflag) {
Line 1812  sub editgrades { Line 1855  sub editgrades {
  '<b>Total number of students = '.$ENV{'form.total'}.'</b><br />';   '<b>Total number of students = '.$ENV{'form.total'}.'</b><br />';
     return $title.$msg.$result;      return $title.$msg.$result;
 }  }
   
   sub split_part_type {
       my ($partstr) = @_;
       my ($temp,@allparts)=split(/_/,$partstr);
       my $type=pop(@allparts);
       my $part=join('.',@allparts);
       return ($part,$type);
   }
   
 #------------- end of section for handling grading by section/class ---------  #------------- end of section for handling grading by section/class ---------
 #  #
 #----------------------------------------------------------------------------  #----------------------------------------------------------------------------
Line 2104  sub gradingmenu { Line 2156  sub gradingmenu {
     $result.=&view_edit_entire_class_form($symb,$url).'<br />';      $result.=&view_edit_entire_class_form($symb,$url).'<br />';
     $result.=&upcsvScores_form($symb,$url).'<br />';      $result.=&upcsvScores_form($symb,$url).'<br />';
     $result.=&viewGradeaStu_form($symb,$url,$resptype,$hdgrade).'<br />';      $result.=&viewGradeaStu_form($symb,$url,$resptype,$hdgrade).'<br />';
       $result.=&gradeByPage_form($symb,$url,$resptype,$hdgrade).'<br />';
     $result.=&verifyReceipt_form($symb,$url)       $result.=&verifyReceipt_form($symb,$url) 
  if ((&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'})) && ($symb));   if ((&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'})) && ($symb));
     
Line 2113  sub gradingmenu { Line 2166  sub gradingmenu {
 #--- Menu for grading a section or the whole class ---  #--- Menu for grading a section or the whole class ---
 sub view_edit_entire_class_form {  sub view_edit_entire_class_form {
     my ($symb,$url)=@_;      my ($symb,$url)=@_;
     my ($classlist,$sections) = &getclasslist('all','0');      my ($classlist,$sections,undef) = &getclasslist('all','0');
     my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";      my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";
     $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";      $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";
     $result.='&nbsp;<b>View/Grade Entire Section/Class</b></td></tr>'."\n";      $result.='&nbsp;<b>Grade Entire Section or Class</b></td></tr>'."\n";
     $result.='<tr bgcolor=#ffffe6><td>'."\n";      $result.='<tr bgcolor=#ffffe6><td>'."\n";
     $result.='<form action="/adm/grades" method="post">'."\n".      $result.='<form action="/adm/grades" method="post">'."\n".
  '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".   '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
Line 2129  sub view_edit_entire_class_form { Line 2182  sub view_edit_entire_class_form {
  }   }
     }      }
     $result.='<option selected="on">all</select>'."<br />\n";      $result.='<option selected="on">all</select>'."<br />\n";
     $result.='&nbsp;<input type="button" onClick="submit();" value="View/Grade" /></form>'."\n";      $result.='&nbsp;<input type="button" onClick="submit();" value="Grade" /></form>'."\n";
     $result.='</td></tr></table>'."\n";      $result.='</td></tr></table>'."\n";
     $result.='</td></tr></table>'."\n";      $result.='</td></tr></table>'."\n";
     return $result;      return $result;
Line 2175  sub viewGradeaStu_form { Line 2228  sub viewGradeaStu_form {
     my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";      my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";
     $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";      $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n";
     $result.='&nbsp;<b>';      $result.='&nbsp;<b>';
     if ($handgrade eq 'yes') {      $result.=($handgrade eq 'yes' ? 'View/Grade' : 'View').' an Individual Student\'s Submission</b></td></tr>'."\n";
  $result.="View/Grade ";  
     } else {  
  $result.="View ";  
     }  
     $result.='an Individual Student\'s Submission</b></td></tr>'."\n";  
     $result.='<tr bgcolor=#ffffe6><td>'."\n";      $result.='<tr bgcolor=#ffffe6><td>'."\n";
     $result.='<form action="/adm/grades" method="post">'."\n".      $result.='<form action="/adm/grades" method="post">'."\n".
  '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".   '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
Line 2216  sub viewGradeaStu_form { Line 2264  sub viewGradeaStu_form {
     return $result;      return $result;
 }  }
   
   #--- Handgrading problems by page/sequence for each student ---
   sub gradeByPage_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>';
       $result.='Handgrade an Individual Student\'s by Page/Sequence</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="pickStudentPage" />'."\n";
   
       $result.='&nbsp;<b>Select section:</b> <select name="section">'."\n";
       if (ref($sections)) {
    foreach (sort (@$sections)) {$result.='<option>'.$_.'</option>'."\n";}
       }
       $result.= '<option selected="on">all</select>'."\n";
   
       $result.='<br />&nbsp;<input type="button" onClick="submit();" value="';
       $result.='View/Grade'.'" />'."\n".'</form>'."\n";
       $result.='</td></tr></table>'."\n";
       $result.='</td></tr></table>'."\n";
       return $result;
   }
   
   
   sub pickStudentPage {
       my ($request) = shift;
   
       $request->print(<<LISTJAVASCRIPT);
   <script type="text/javascript" language="javascript">
   
   function checkPickOne(formname) {
       var user = radioSelection(formname.student);
       if (user == null) {
    alert("Please select the student you wish to grade.");
    return;
       }
       var ptr = pullDownSelection(formname.selectpage);
       formname.page.value = formname.eval("page"+ptr).value;
       formname.title.value = formname.eval("title"+ptr).value;
       formname.submit();
   }
   
   function radioSelection(radioButton) {
       var selection=null;
       for (var i=0; i<radioButton.length; i++) {
           if (radioButton[i].checked) {
               selection=radioButton[i].value;
               return selection;
           }
       }
       return selection;
   }
   
   function pullDownSelection(selectOne) {
       var selection=null;
       for (var i=0; i<selectOne.length; i++) {
           if (selectOne[i].selected) {
               selection=selectOne[i].value;
               return selection;
           }
       }
   }
   </script>
   LISTJAVASCRIPT
   
       my ($symb,$url) = &get_symb_and_url();
       my $cdom      = $ENV{"course.$ENV{'request.course.id'}.domain"};
       my $cnum      = $ENV{"course.$ENV{'request.course.id'}.num"};
       my $getsec    = $ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'};
   
       my $result='<h3><font color="#339933">&nbsp;'.
    'Manual Grading by Page or Sequence</font></h3>';
   
       my ($pagepath,$pagename,$type,$mapId) = ($symb =~ /(.*\/)(.*?\.(page|sequence))___(\d+)___/); 
       my $curtitle = &Apache::lonnet::metadata($pagepath.$pagename,'title');
   
       $result.='<form action="/adm/grades" method="post" name="displayPage">'."<br>\n";
       $result.='&nbsp;<b>Problems from:</b> <select name="selectpage">'."\n";
       my ($titles,$symbx) = &getSymbMap();
   #    shift @$titles; # skip the top level sequence
       my $ctr=0;
       foreach (@$titles) {
    my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
    $result.='<option value="'.$ctr.'" '.
       ($showtitle eq $curtitle ? 'selected="on"' : '').'>'.$showtitle.'</option>'."\n";
    $ctr++;
       }
       $result.= '</select>'."<br>\n";
       $ctr=0;
       foreach (@$titles) {
    my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
    $result.='<input type="hidden" name="page'.$ctr.'" value="'.$$symbx{$_}.'" />'."\n";
    $result.='<input type="hidden" name="title'.$ctr.'" value="'.$showtitle.'" />'."\n";
    $ctr++;
       }
       $result.='<input type="hidden" name="page" />'."\n";
       $result.='<input type="hidden" name="title" />'."\n";
   
   #    $result.='&nbsp;<b>View Problems: </b><input type="radio" name="vProb" value="no" checked /> no '."\n".
   # '<input type="radio" name="vProb" value="yes" /> yes '."<br>\n";
   #    $result.='&nbsp;<b>Submission Details: </b>'.
   # '<input type="radio" name="lastSub" value="last" checked /> last sub only'."\n".
   # '<input type="radio" name="lastSub" value="all" /> all details'."\n";
       $result.='<input type="hidden" name="section"     value="'.$getsec.'" />'."\n".
    '<input type="hidden" name="command"  value="displayPage" />'."\n".
    '<input type="hidden" name="url"  value="'.$url.'" />'."\n".
    '<input type="hidden" name="symb" value="'.$symb.'" />'."<br><br>\n";
       $request->print($result);
   
       my $studentTable.='&nbsp;<b>Select a Student you wish to grade</b><br>'.
    '<table border="0"><tr><td bgcolor="#777777">'.
    '<table border="0"><tr bgcolor="#e6ffff">'.
    '<td><b>&nbsp;Fullname <font color="#999999">(username)</font></b></td>'.
    '<td><b>&nbsp;Fullname <font color="#999999">(username)</font></b></td>'.
    '<td><b>&nbsp;Fullname <font color="#999999">(username)</font></b></td>'.
    '<td><b>&nbsp;Fullname <font color="#999999">(username)</font></b></td></tr>';
    
       my (undef,undef,$fullname) = &getclasslist($getsec,'0');
       my $ptr = 1;
       foreach my $student (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {
    my ($uname,$udom) = split(/:/,$student);
    $studentTable.=($ptr%4 == 1 ? '<tr bgcolor="#ffffe6"><td>' : '</td><td>');
    $studentTable.='<input type="radio" name="student" value="'.$student.'" /> '.$$fullname{$student}.
       '<font color="#999999"> ('.$uname.($udom eq $cdom ? '':':'.$udom).')</font>'."\n";
    $studentTable.=($ptr%4 == 0 ? '</td></tr>' : '');
    $ptr++;
       }
       $studentTable.='</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;' if ($ptr%4 == 2);
       $studentTable.='</td><td>&nbsp;</td><td>&nbsp;' if ($ptr%4 == 3);
       $studentTable.='</td><td>&nbsp;' if ($ptr%4 == 0);
       $studentTable.='</td></tr></table></td></tr></table>'."\n";
       $studentTable.='<br />&nbsp;<input type="button" '.
    'onClick="javascript:checkPickOne(this.form);"value="Submit" /></form>'."\n";
   
       $studentTable.=&show_grading_menu_form($symb,$url);
       $request->print($studentTable);
   
       return '';
   }
   
   sub getSymbMap {
       my $navmap = Apache::lonnavmaps::navmap-> new(
     $ENV{'request.course.fn'}.'.db',
     $ENV{'request.course.fn'}.'_parms.db',1, 1);
   
       my $res = $navmap->firstResource(); # temp resource to access constants
       $navmap->init();
   
       # End navmap using boilerplate
   
       my $iterator = $navmap->getIterator(undef, undef, undef, 1);
       my $depth = 1;
       $iterator->next(); # ignore first BEGIN_MAP
       my $curRes = $iterator->next();
   
       my %symbx = ();
       my @titles = ();
       my $minder=0;
       while ($depth > 0) {
           if ($curRes == $iterator->BEGIN_MAP()) {$depth++;}
           if ($curRes == $iterator->END_MAP()) { $depth--; }
   
           if (ref($curRes) && $curRes->is_map()) {
               my $title = $curRes->compTitle();
       push @titles,$minder.'.'.$title; # minder, just in case two titles are identical
       $symbx{$minder.'.'.$title} = $curRes->symb();
       $minder++;
          }
           $curRes = $iterator->next();
       }
   
       $navmap->untieHashes();
       return \@titles,\%symbx;
   }
   
   sub displayPage {
       my ($request) = shift;
   
       my $cdom      = $ENV{"course.$ENV{'request.course.id'}.domain"};
       my $cnum      = $ENV{"course.$ENV{'request.course.id'}.num"};
       my $getsec    = $ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'};
       my $pageTitle = $ENV{'form.page'};
       my (undef,undef,$fullname) = &getclasslist($getsec,'0');
       my ($uname,$udom) = split(/:/,$ENV{'form.student'});
       my ($idx,$showtitle) = ($pageTitle =~ /(\d+)\.(.*)/);
   
       my $result='<h3><font color="#339933">&nbsp;'.$ENV{'form.title'}.'</font></h3>';
       $result.='<h3>&nbsp;Student: '.$$fullname{$ENV{'form.student'}}.
    '<font color="#999999"> ('.$uname.($udom eq $cdom ? '':':'.$udom).')</font></h3>'."\n";
   
       my $navmap = Apache::lonnavmaps::navmap-> new(
     $ENV{'request.course.fn'}.'.db',
     $ENV{'request.course.fn'}.'_parms.db',1, 1);
       my ($mapUrl, $id, $resUrl) = split(/___/, $ENV{'form.page'});
       my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps
   
       my $iterator = $navmap->getIterator($map->map_start(),
    $map->map_finish());
   
       my $depth = 1;
       $iterator->next(); # skip the first BEGIN_MAP
       my $curRes = $iterator->next(); # for "current resource"
       my %symbx = ();
       my @titles = ();
       my %parts = ();
       my $ctr=0;
       my $minder=0;
       while ($depth > 0 && $ctr < 100) { # ctr, just in case it never gets out of loop
           if($curRes == $iterator->BEGIN_MAP) { $depth++; }
           if($curRes == $iterator->END_MAP) { $depth++; }
   
           if (ref($curRes) && $curRes->is_problem() && !$curRes->randomout) {
       my $parts = $curRes->parts();
               my $title = $curRes->compTitle();
       push @titles,$minder.'.'.$title; # minder, just in case two titles are identical
       if (scalar(@{$parts}) > 1) { shift @{$parts}; }
       $parts{$minder.'.'.$title} = join '::',@{$parts};
               $symbx{$minder.'.'.$title} = $curRes->symb();
       $minder++;
   
          }
           $curRes = $iterator->next();
    $ctr++;
       }
   
   
       $navmap->init();
       $request->print($result);
       &sub_page_js($request);
   
       my $studentTable='<form action="/adm/grades" method="post" name="gradePage">'."\n".
    '<input type="hidden" name="command"  value="gradePage" />'."\n".
    '<input type="hidden" name="student"  value="'.$ENV{'form.student'}.'" />'."\n".
    '<input type="hidden" name="page"  value="'.$pageTitle.'" />'."\n".
    '<input type="hidden" name="title" value="'.$ENV{'form.title'}.'" />'."\n";
   
       $studentTable.=
    '<table border="0"><tr><td bgcolor="#777777">'.
    '<table border="0"><tr bgcolor="#e6ffff">'.
    '<td align="center"><b>&nbsp;No&nbsp;</b></td>'.
    '<td><b>&nbsp;Title</b></td>'.
    '<td><b>&nbsp;Answer</b></td>'.
    '<td><b>&nbsp;Grade</b></td></tr>';
       my $question=1;
       foreach (@titles) {
    my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
    my @parts = split(/::/,$parts{$_});
    $studentTable.='<tr bgcolor="#ffffe6"><td align="center" valign="top" >'.$question.
       (scalar(@parts) == 1 ? '' : '<br>('.scalar(@parts).'&nbsp;parts)').'</td>';
    $studentTable.='<td valign="top">&nbsp;'.$showtitle.'&nbsp;</td>';
    $studentTable.='<td>&nbsp;'.
       &Apache::loncommon::get_student_answers($symbx{$_},$uname,$udom,$ENV{'request.course.id'}).'</td>';
   
    my %record = &Apache::lonnet::restore($symbx{$_},$ENV{'request.course.id'},$udom,$uname);
    $studentTable.='<td>&nbsp;';
    foreach my $partid (@parts) {
       $studentTable.=&gradeBox($symbx{$_},$uname,$udom,$question,$partid,\%record);
       $question++;
    }
    $studentTable.='</td></tr>';
   
       }
   
       $studentTable.='</table></td></tr></table>';
       $studentTable.='</form>';
   
       $request->print($studentTable);
   
       return '';
   }
   
   sub gradeBox {
       my ($symb,$uname,$udom,$counter,$partid,$record) = @_;
       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);
       my $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.
    ','.$wgt.')" /></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";
       if ($$record{'resource.'.$partid.'.solved'} eq 'excused') {
    $result.='<option> </option>'.
       '<option selected="on">excused</option></select>';
       } else {
    $result.='<option selected="on"> </option>'.
       '<option>excused</option></select>';
       }
       $result.="&nbsp&nbsp\n";
       $result.='<input type="hidden" name="stores'.$counter.'_'.$partid.'" value="0" />';
       $result.='</td></tr></table>'."\n";
       return $result;
   }
   
 #--- Form to input a receipt number ---  #--- Form to input a receipt number ---
 sub verifyReceipt_form {  sub verifyReceipt_form {
     my ($symb,$url) = @_;      my ($symb,$url) = @_;
Line 2303  sub handler { Line 2680  sub handler {
     } else {      } else {
  $Apache::grades::viewgrades=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'});   $Apache::grades::viewgrades=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'});
  if ($command eq 'submission') {   if ($command eq 'submission') {
     &listStudents($request) if ($ENV{'form.student'} eq '');      ($ENV{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0));
     &submission($request,0,0) if ($ENV{'form.student'} ne '');  # if ($command eq 'submission') {
   #    &listStudents($request) if ($ENV{'form.student'} eq '');
   #    &submission($request,0,0) if ($ENV{'form.student'} ne '');
    } elsif ($command eq 'pickStudentPage') {
       &pickStudentPage($request);
    } elsif ($command eq 'displayPage') {
       &displayPage($request);
  } elsif ($command eq 'processGroup') {   } elsif ($command eq 'processGroup') {
     &processGroup($request);      &processGroup($request);
  } elsif ($command eq 'gradingmenu') {   } elsif ($command eq 'gradingmenu') {

Removed from v.1.50  
changed lines
  Added in v.1.70


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