Diff for /loncom/homework/grades.pm between versions 1.446 and 1.477

version 1.446, 2007/10/08 22:29:59 version 1.477, 2007/11/03 00:08:09
Line 35  use Apache::loncommon; Line 35  use Apache::loncommon;
 use Apache::lonhtmlcommon;  use Apache::lonhtmlcommon;
 use Apache::lonnavmaps;  use Apache::lonnavmaps;
 use Apache::lonhomework;  use Apache::lonhomework;
   use Apache::lonpickcode;
 use Apache::loncoursedata;  use Apache::loncoursedata;
 use Apache::lonmsg();  use Apache::lonmsg();
 use Apache::Constants qw(:common);  use Apache::Constants qw(:common);
Line 47  use POSIX qw(floor); Line 48  use POSIX qw(floor);
   
   
 my %perm=();  my %perm=();
 my %bubble_lines_per_response;     # no. bubble lines for each response.  my %bubble_lines_per_response = ();     # no. bubble lines for each response.
                                    # index is "symb.part_id"                                     # index is "symb.part_id"
   
   my %first_bubble_line = (); # First bubble line no. for each bubble.
   
   # Save and restore the bubble lines array to the form env.
   
   
   sub save_bubble_lines {
       foreach my $line (keys(%bubble_lines_per_response)) {
    $env{"form.scantron.bubblelines.$line"}  = $bubble_lines_per_response{$line};
    $env{"form.scantron.first_bubble_line.$line"} =
       $first_bubble_line{$line};
       }
   }
   
   
   sub restore_bubble_lines {
       my $line = 0;
       %bubble_lines_per_response = ();
       while ($env{"form.scantron.bubblelines.$line"}) {
    my $value = $env{"form.scantron.bubblelines.$line"};
    $bubble_lines_per_response{$line} = $value;
    $first_bubble_line{$line}  =
       $env{"form.scantron.first_bubble_line.$line"};
    $line++;
       }
   
   }
   
   #  Given the parsed scanline, get the response for 
   #  'answer' number n:
   
   sub get_response_bubbles {
       my ($parsed_line, $response)  = @_;
   
   
       my $bubble_line = $first_bubble_line{$response-1} +1;
       my $bubble_lines= $bubble_lines_per_response{$response-1};
       
       my $selected = "";
   
       for (my $bline = 0; $bline < $bubble_lines; $bline++) {
    $selected .= $$parsed_line{"scantron.$bubble_line.answer"}.":";
    $bubble_line++;
       }
       return $selected;
   }
   
   
 # ----- These first few routines are general use routines.----  # ----- These first few routines are general use routines.----
   
   # Return the number of occurences of a pattern in a string.
   
   sub occurence_count {
       my ($string, $pattern) = @_;
   
       my @matches = ($string =~ /$pattern/g);
   
       return scalar(@matches);
   }
   
   
   # Take a string known to have digits and convert all the
   # digits into letters in the range J,A..I.
   
   sub digits_to_letters {
       my ($input) = @_;
   
       my @alphabet = ('J', 'A'..'I');
   
       my @input    = split(//, $input);
       my $output ='';
       for (my $i = 0; $i < scalar(@input); $i++) {
    if ($input[$i] =~ /\d/) {
       $output .= $alphabet[$input[$i]];
    } else {
       $output .= $input[$i];
    }
       }
       return $output;
   }
   
 #  #
 # --- Retrieve the parts from the metadata file.---  # --- Retrieve the parts from the metadata file.---
 sub getpartlist {  sub getpartlist {
Line 253  sub cleanRecord { Line 332  sub cleanRecord {
     $bottomrow.='<td>'.$grayFont.$foil.'</span>&nbsp;</td>';      $bottomrow.='<td>'.$grayFont.$foil.'</span>&nbsp;</td>';
  }   }
  return '<blockquote><table border="1">'.   return '<blockquote><table border="1">'.
     '<tr valign="top"><td>Answer</td>'.$toprow.'</tr>'.      '<tr valign="top"><td>'.&mt('Answer').'</td>'.$toprow.'</tr>'.
     '<tr valign="top"><td>'.$grayFont.'Option ID</span></td>'.      '<tr valign="top"><td>'.$grayFont.&mt('Option ID').'</span></td>'.
     $grayFont.$bottomrow.'</tr>'.'</table></blockquote>';      $grayFont.$bottomrow.'</tr>'.'</table></blockquote>';
     } elsif ($response eq 'match') {      } elsif ($response eq 'match') {
  my %answer=&Apache::lonnet::str2hash($answer);   my %answer=&Apache::lonnet::str2hash($answer);
Line 273  sub cleanRecord { Line 352  sub cleanRecord {
     $bottomrow.='<td>'.$grayFont.$foil.'</span>&nbsp;</td>';      $bottomrow.='<td>'.$grayFont.$foil.'</span>&nbsp;</td>';
  }   }
  return '<blockquote><table border="1">'.   return '<blockquote><table border="1">'.
     '<tr valign="top"><td>Answer</td>'.$toprow.'</tr>'.      '<tr valign="top"><td>'.&mt('Answer').'</td>'.$toprow.'</tr>'.
     '<tr valign="top"><td>'.$grayFont.'Item ID</span></td>'.      '<tr valign="top"><td>'.$grayFont.&mt('Item ID').'</span></td>'.
     $middlerow.'</tr>'.      $middlerow.'</tr>'.
     '<tr valign="top"><td>'.$grayFont.'Option ID</span></td>'.      '<tr valign="top"><td>'.$grayFont.&mt('Option ID').'</span></td>'.
     $bottomrow.'</tr>'.'</table></blockquote>';      $bottomrow.'</tr>'.'</table></blockquote>';
     } elsif ($response eq 'radiobutton') {      } elsif ($response eq 'radiobutton') {
  my %answer=&Apache::lonnet::str2hash($answer);   my %answer=&Apache::lonnet::str2hash($answer);
Line 286  sub cleanRecord { Line 365  sub cleanRecord {
  foreach my $foil (@$order) {   foreach my $foil (@$order) {
     if (exists($answer{$foil})) {      if (exists($answer{$foil})) {
  if ($foil eq $correct) {   if ($foil eq $correct) {
     $toprow.='<td><b>true</b></td>';      $toprow.='<td><b>'.&mt('true').'</b></td>';
  } else {   } else {
     $toprow.='<td><i>true</i></td>';      $toprow.='<td><i>'.&mt('true').'</i></td>';
  }   }
     } else {      } else {
  $toprow.='<td>false</td>';   $toprow.='<td>'.&mt('false').'</td>';
     }      }
     $bottomrow.='<td>'.$grayFont.$foil.'</span>&nbsp;</td>';      $bottomrow.='<td>'.$grayFont.$foil.'</span>&nbsp;</td>';
  }   }
  return '<blockquote><table border="1">'.   return '<blockquote><table border="1">'.
     '<tr valign="top"><td>Answer</td>'.$toprow.'</tr>'.      '<tr valign="top"><td>'.&mt('Answer').'</td>'.$toprow.'</tr>'.
     '<tr valign="top"><td>'.$grayFont.'Option ID</span></td>'.      '<tr valign="top"><td>'.$grayFont.&mt('Option ID').'</span></td>'.
     $grayFont.$bottomrow.'</tr>'.'</table></blockquote>';      $grayFont.$bottomrow.'</tr>'.'</table></blockquote>';
     } elsif ($response eq 'essay') {      } elsif ($response eq 'essay') {
  if (! exists ($env{'form.'.$symb})) {   if (! exists ($env{'form.'.$symb})) {
Line 396  COMMONJSFUNCTIONS Line 475  COMMONJSFUNCTIONS
 #--- Dumps the class list with usernames,list of sections,  #--- Dumps the class list with usernames,list of sections,
 #--- section, ids and fullnames for each user.  #--- section, ids and fullnames for each user.
 sub getclasslist {  sub getclasslist {
     my ($getsec,$filterlist) = @_;      my ($getsec,$filterlist,$getgroup) = @_;
     my @getsec;      my @getsec;
       my @getgroup;
     my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));      my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));
     if (!ref($getsec)) {      if (!ref($getsec)) {
  if ($getsec ne '' && $getsec ne 'all') {   if ($getsec ne '' && $getsec ne 'all') {
Line 407  sub getclasslist { Line 487  sub getclasslist {
  @getsec=@{$getsec};   @getsec=@{$getsec};
     }      }
     if (grep(/^all$/,@getsec)) { undef(@getsec); }      if (grep(/^all$/,@getsec)) { undef(@getsec); }
       if (!ref($getgroup)) {
    if ($getgroup ne '' && $getgroup ne 'all') {
       @getgroup=($getgroup);
    }
       } else {
    @getgroup=@{$getgroup};
       }
       if (grep(/^all$/,@getgroup)) { undef(@getgroup); }
   
     my $classlist=&Apache::loncoursedata::get_classlist();      my ($classlist,$keylist)=&Apache::loncoursedata::get_classlist();
     # Bail out if we were unable to get the classlist      # Bail out if we were unable to get the classlist
     return if (! defined($classlist));      return if (! defined($classlist));
       &Apache::loncoursedata::get_group_memberships($classlist,$keylist);
     #      #
     my %sections;      my %sections;
     my %fullnames;      my %fullnames;
Line 427  sub getclasslist { Line 516  sub getclasslist {
             $classlist->{$student}->[&Apache::loncoursedata::CL_FULLNAME()];              $classlist->{$student}->[&Apache::loncoursedata::CL_FULLNAME()];
         my $status   =           my $status   = 
             $classlist->{$student}->[&Apache::loncoursedata::CL_STATUS()];              $classlist->{$student}->[&Apache::loncoursedata::CL_STATUS()];
           my $group   = 
               $classlist->{$student}->[&Apache::loncoursedata::CL_GROUP()];
  # filter students according to status selected   # filter students according to status selected
  if ($filterlist && (!($stu_status =~ /Any/))) {   if ($filterlist && (!($stu_status =~ /Any/))) {
     if (!($stu_status =~ $status)) {      if (!($stu_status =~ $status)) {
  delete ($classlist->{$student});   delete($classlist->{$student});
  next;   next;
     }      }
  }   }
    # filter students according to groups selected
    my @stu_groups = split(/,/,$group);
    if (@getgroup) {
       my $exclude = 1;
       foreach my $grp (@getgroup) {
           foreach my $stu_group (@stu_groups) {
               if ($stu_group eq $grp) {
                   $exclude = 0;
                  } 
           }
              if (($grp eq 'none') && !$group) {
                  $exclude = 0;
           }
       }
       if ($exclude) {
           delete($classlist->{$student});
       }
    }
  $section = ($section ne '' ? $section : 'none');   $section = ($section ne '' ? $section : 'none');
  if (&canview($section)) {   if (&canview($section)) {
     if (!@getsec || grep(/^\Q$section\E$/,@getsec)) {      if (!@getsec || grep(/^\Q$section\E$/,@getsec)) {
  $sections{$section}++;   $sections{$section}++;
  $fullnames{$student}=$fullname;   if ($classlist->{$student}) {
       $fullnames{$student}=$fullname;
    }
     } else {      } else {
  delete($classlist->{$student});   delete($classlist->{$student});
     }      }
Line 531  sub jscriptNform { Line 642  sub jscriptNform {
     return $jscript;      return $jscript;
 }  }
   
   
   
 # Given the score (as a number [0-1] and the weight) what is the final  # Given the score (as a number [0-1] and the weight) what is the final
 # point value? This function will round to the nearest tenth, third,  # point value? This function will round to the nearest tenth, third,
 # or quarter if one of those is within the tolerance of .00001.  # or quarter if one of those is within the tolerance of .00001.
Line 687  sub listStudents { Line 800  sub listStudents {
     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'};      my $getsec    = $env{'form.section'} eq '' ? 'all' : $env{'form.section'};
       my $getgroup  = $env{'form.group'} eq '' ? 'all' : $env{'form.group'};
     my $submitonly= $env{'form.submitonly'} eq '' ? 'all' : $env{'form.submitonly'};      my $submitonly= $env{'form.submitonly'} eq '' ? 'all' : $env{'form.submitonly'};
   
     my $viewgrade = $env{'form.showgrading'} eq 'yes' ? 'View/Grade/Regrade' : 'View';      my $viewgrade = $env{'form.showgrading'} eq 'yes' ? 'View/Grade/Regrade' : 'View';
     $env{'form.probTitle'} = $env{'form.probTitle'} eq '' ?       $env{'form.probTitle'} = $env{'form.probTitle'} eq '' ? 
  &Apache::lonnet::gettitle($symb) : $env{'form.probTitle'};   &Apache::lonnet::gettitle($symb) : $env{'form.probTitle'};
Line 752  LISTJAVASCRIPT Line 865  LISTJAVASCRIPT
     my $saveStatus = $stu_status eq '' ? 'Active' : $stu_status;      my $saveStatus = $stu_status eq '' ? 'Active' : $stu_status;
     $env{'form.Status'} = $saveStatus;      $env{'form.Status'} = $saveStatus;
     $gradeTable.='<label><input type="radio" name="lastSub" value="lastonly" '.$checklastsub.' /> last submission only </label>'."\n".      $gradeTable.='<label><input type="radio" name="lastSub" value="lastonly" '.$checklastsub.' /> last submission only </label>'."\n".
  '<label><input type="radio" name="lastSub" value="last" /> last submission & parts info </label>'."\n".   '<label><input type="radio" name="lastSub" value="last" /> last submission &amp; parts info </label>'."\n".
  '<label><input type="radio" name="lastSub" value="datesub" /> by dates and submissions </label>'."\n".   '<label><input type="radio" name="lastSub" value="datesub" /> by dates and submissions </label>'."\n".
  '<label><input type="radio" name="lastSub" value="all" /> all details</label><br />'."\n".   '<label><input type="radio" name="lastSub" value="all" /> all details</label><br />'."\n".
         '&nbsp;<b>Grading Increments:</b> <select name="increment">'.          '&nbsp;<b>Grading Increments:</b> <select name="increment">'.
Line 788  LISTJAVASCRIPT Line 901  LISTJAVASCRIPT
  'value="Next->" /> <br />'."\n";   'value="Next->" /> <br />'."\n";
     $gradeTable.=&check_buttons();      $gradeTable.=&check_buttons();
     $gradeTable.='<label><input type="checkbox" name="checkPlag" checked="checked" />Check For Plagiarism</label>';      $gradeTable.='<label><input type="checkbox" name="checkPlag" checked="checked" />Check For Plagiarism</label>';
     my ($classlist, undef, $fullname) = &getclasslist($getsec,'1');      my ($classlist, undef, $fullname) = &getclasslist($getsec,'1',$getgroup);
     $gradeTable.='<table border="0"><tr><td bgcolor="#777777">'.      $gradeTable.= &Apache::loncommon::start_data_table().
  '<table border="0"><tr bgcolor="#e6ffff">';   &Apache::loncommon::start_data_table_header_row();
     my $loop = 0;      my $loop = 0;
     while ($loop < 2) {      while ($loop < 2) {
  $gradeTable.='<td><b>&nbsp;No.</b>&nbsp;</td><td><b>&nbsp;Select&nbsp;</b></td>'.   $gradeTable.='<th>No.</th><th>Select</th>'.
     '<td>'.&nameUserString('header').'&nbsp;Section/Group</td>';      '<th>'.&nameUserString('header').'&nbsp;'.'Section/Group</th>';
  if ($env{'form.showgrading'} eq 'yes'    if ($env{'form.showgrading'} eq 'yes' 
     && $submitonly ne 'queued'      && $submitonly ne 'queued'
     && $submitonly ne 'all') {      && $submitonly ne 'all') {
     foreach (sort(@$partlist)) {      foreach (sort(@$partlist)) {
  my $display_part=&get_display_part((split(/_/))[0],$symb);   my $display_part=&get_display_part((split(/_/))[0],$symb);
  $gradeTable.='<td><b>&nbsp;Part: '.$display_part.   $gradeTable.='<th>Part: '.$display_part.
     ' Status&nbsp;</b></td>';      ' Status</h>';
     }      }
  } elsif ($submitonly eq 'queued') {   } elsif ($submitonly eq 'queued') {
     $gradeTable.='<td><b>&nbsp;'.&mt('Queue Status').'&nbsp;</b></td>';      $gradeTable.='<th>'.&mt('Queue Status').'&nbsp;</th>';
  }   }
  $loop++;   $loop++;
 # $gradeTable.='<td></td>' if ($loop%2 ==1);  # $gradeTable.='<td></td>' if ($loop%2 ==1);
     }      }
     $gradeTable.='</tr>'."\n";      $gradeTable.=&Apache::loncommon::end_data_table_header_row()."\n";
   
     my $ctr = 0;      my $ctr = 0;
     foreach my $student (sort       foreach my $student (sort 
Line 863  LISTJAVASCRIPT Line 976  LISTJAVASCRIPT
   
  $ctr++;   $ctr++;
  my $section = $classlist->{$student}->[&Apache::loncoursedata::CL_SECTION()];   my $section = $classlist->{$student}->[&Apache::loncoursedata::CL_SECTION()];
           my $group = $classlist->{$student}->[&Apache::loncoursedata::CL_GROUP()];
  if ( $perm{'vgr'} eq 'F' ) {   if ( $perm{'vgr'} eq 'F' ) {
     $gradeTable.='<tr bgcolor="#ffffe6">' if ($ctr%2 ==1);      if ($ctr%2 ==1) {
    $gradeTable.= &Apache::loncommon::start_data_table_row();
       }
     $gradeTable.='<td align="right">'.$ctr.'&nbsp;</td>'.      $gradeTable.='<td align="right">'.$ctr.'&nbsp;</td>'.
                '<td align="center"><label><input type=checkbox name="stuinfo" value="'.                 '<td align="center"><label><input type=checkbox name="stuinfo" value="'.
                $student.':'.$$fullname{$student}.':::SECTION'.$section.                 $student.':'.$$fullname{$student}.':::SECTION'.$section.
        ')&nbsp;" />&nbsp;&nbsp;</label></td>'."\n".'<td>'.         ')&nbsp;" />&nbsp;&nbsp;</label></td>'."\n".'<td>'.
        &nameUserString(undef,$$fullname{$student},$uname,$udom).         &nameUserString(undef,$$fullname{$student},$uname,$udom).
        '&nbsp;'.$section.'</td>'."\n";         '&nbsp;'.$section.($group ne '' ?'/'.$group:'').'</td>'."\n";
   
     if ($env{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {      if ($env{'form.showgrading'} eq 'yes' && $submitonly ne 'all') {
  foreach (sort keys(%status)) {   foreach (sort keys(%status)) {
Line 880  LISTJAVASCRIPT Line 995  LISTJAVASCRIPT
  }   }
     }      }
 #    $gradeTable.='<td></td>' if ($ctr%2 ==1);  #    $gradeTable.='<td></td>' if ($ctr%2 ==1);
     $gradeTable.='</tr>'."\n" if ($ctr%2 ==0);      if ($ctr%2 ==0) {
    $gradeTable.=&Apache::loncommon::end_data_table_row()."\n";
       }
  }   }
     }      }
     if ($ctr%2 ==1) {      if ($ctr%2 ==1) {
Line 894  LISTJAVASCRIPT Line 1011  LISTJAVASCRIPT
     } elsif ($submitonly eq 'queued') {      } elsif ($submitonly eq 'queued') {
  $gradeTable.='<td>&nbsp;</td>';   $gradeTable.='<td>&nbsp;</td>';
     }      }
  $gradeTable.='</tr>';   $gradeTable.=&Apache::loncommon::end_data_table_row();
     }      }
   
     $gradeTable.='</table></td></tr></table>'."\n".      $gradeTable.=&Apache::loncommon::end_data_table()."\n".
  '<input type="button" '.   '<input type="button" '.
  'onClick="javascript:checkSelect(this.form.stuinfo);" '.   'onClick="javascript:checkSelect(this.form.stuinfo);" '.
  'value="Next->" /></form>'."\n";   'value="Next->" /></form>'."\n";
Line 915  LISTJAVASCRIPT Line 1032  LISTJAVASCRIPT
  ' students checked for '.$submissions.')</span><br />';   ' students checked for '.$submissions.')</span><br />';
  }   }
     } elsif ($ctr == 1) {      } elsif ($ctr == 1) {
  $gradeTable =~ s/type=checkbox/type=checkbox checked/;   $gradeTable =~ s/type="checkbox"/type="checkbox" checked="checked"/;
     }      }
     $gradeTable.=&show_grading_menu_form($symb);      $gradeTable.=&show_grading_menu_form($symb);
     $request->print($gradeTable);      $request->print($gradeTable);
Line 1367  INNERJS Line 1484  INNERJS
   
     pDoc.write("<form action=\\"inactive\\" name=\\"msgcenter\\">");      pDoc.write("<form action=\\"inactive\\" name=\\"msgcenter\\">");
     pDoc.write("<input value=\\""+usrctr+"\\" name=\\"usrctr\\" type=\\"hidden\\">");      pDoc.write("<input value=\\""+usrctr+"\\" name=\\"usrctr\\" type=\\"hidden\\">");
     pDoc.write("<h3><span class=\\"LC_info\\">&nbsp;Compose Message for \"+fullname+\"</span></h3><br /><br />");      pDoc.write("<h3><span class=\\"LC_info\\">&nbsp;Compose Message for \"+fullname+\"<\\/span><\\/h3><br /><br />");
   
     pDoc.write("<table border=0 width=100%><tr><td bgcolor=\\"#777777\\">");      pDoc.write("<table border=0 width=100%><tr><td bgcolor=\\"#777777\\">");
     pDoc.write("<table border=0 width=100%><tr bgcolor=\\"#ddffff\\">");      pDoc.write("<table border=0 width=100%><tr bgcolor=\\"#ddffff\\">");
     pDoc.write("<td><b>Type</b></td><td><b>Include</b></td><td><b>Message</td></tr>");      pDoc.write("<td><b>Type<\\/b><\\/td><td><b>Include<\\/b><\\/td><td><b>Message<\\/td><\\/tr>");
 }  }
     function displaySubject(msg,shwsel) {      function displaySubject(msg,shwsel) {
     pDoc = pWin.document;      pDoc = pWin.document;
     pDoc.write("<tr bgcolor=\\"#ffffdd\\">");      pDoc.write("<tr bgcolor=\\"#ffffdd\\">");
     pDoc.write("<td>Subject</td>");      pDoc.write("<td>Subject<\\/td>");
     pDoc.write("<td align=\\"center\\"><input name=\\"subchk\\" type=\\"checkbox\\"" +shwsel+"></td>");      pDoc.write("<td align=\\"center\\"><input name=\\"subchk\\" type=\\"checkbox\\"" +shwsel+"><\\/td>");
     pDoc.write("<td><input name=\\"msgsub\\" type=\\"text\\" value=\\""+msg+"\\"size=\\"60\\" maxlength=\\"80\\"></td></tr>");      pDoc.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) {
     pDoc = pWin.document;      pDoc = pWin.document;
     pDoc.write("<tr bgcolor=\\"#ffffdd\\">");      pDoc.write("<tr bgcolor=\\"#ffffdd\\">");
     pDoc.write("<td align=\\"center\\">"+ctr+"</td>");      pDoc.write("<td align=\\"center\\">"+ctr+"<\\/td>");
     pDoc.write("<td align=\\"center\\"><input name=\\"msgn"+ctr+"\\" type=\\"checkbox\\"" +shwsel+"></td>");      pDoc.write("<td align=\\"center\\"><input name=\\"msgn"+ctr+"\\" type=\\"checkbox\\"" +shwsel+"><\\/td>");
     pDoc.write("<td><textarea name=\\"msg"+ctr+"\\" cols=\\"60\\" rows=\\"3\\">"+msg+"</textarea></td></tr>");      pDoc.write("<td><textarea name=\\"msg"+ctr+"\\" cols=\\"60\\" rows=\\"3\\">"+msg+"<\\/textarea><\\/td><\\/tr>");
 }  }
   
   function newMsg(newmsg,shwsel) {    function newMsg(newmsg,shwsel) {
     pDoc = pWin.document;      pDoc = pWin.document;
     pDoc.write("<tr bgcolor=\\"#ffffdd\\">");      pDoc.write("<tr bgcolor=\\"#ffffdd\\">");
     pDoc.write("<td align=\\"center\\">New</td>");      pDoc.write("<td align=\\"center\\">New<\\/td>");
     pDoc.write("<td align=\\"center\\"><input name=\\"newmsgchk\\" type=\\"checkbox\\"" +shwsel+"></td>");      pDoc.write("<td align=\\"center\\"><input name=\\"newmsgchk\\" type=\\"checkbox\\"" +shwsel+"><\\/td>");
     pDoc.write("<td><textarea name=\\"newmsg\\" cols=\\"60\\" rows=\\"3\\" onchange=\\"javascript:this.form.newmsgchk.checked=true\\" >"+newmsg+"</textarea></td></tr>");      pDoc.write("<td><textarea name=\\"newmsg\\" cols=\\"60\\" rows=\\"3\\" onchange=\\"javascript:this.form.newmsgchk.checked=true\\" >"+newmsg+"<\\/textarea><\\/td><\\/tr>");
 }  }
   
   function msgTail() {    function msgTail() {
     pDoc = pWin.document;      pDoc = pWin.document;
     pDoc.write("</table>");      pDoc.write("<\\/table>");
     pDoc.write("</td></tr></table>&nbsp;");      pDoc.write("<\\/td><\\/tr><\\/table>&nbsp;");
     pDoc.write("<input type=\\"button\\" value=\\"Save\\" onClick=\\"javascript:checkInput()\\">&nbsp;&nbsp;");      pDoc.write("<input type=\\"button\\" value=\\"Save\\" onClick=\\"javascript:checkInput()\\">&nbsp;&nbsp;");
     pDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br /><br />");      pDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br /><br />");
     pDoc.write("</form>");      pDoc.write("<\\/form>");
     pDoc.write('$end_page_msg_central');      pDoc.write('$end_page_msg_central');
     pDoc.close();      pDoc.close();
 }  }
Line 1452  INNERJS Line 1569  INNERJS
     hDoc.$docopen;      hDoc.$docopen;
     hDoc.write('$start_page_highlight_central');      hDoc.write('$start_page_highlight_central');
     hDoc.write("<form action=\\"inactive\\" name=\\"hlCenter\\">");      hDoc.write("<form action=\\"inactive\\" name=\\"hlCenter\\">");
     hDoc.write("<h3><span class=\\"LC_info\\">&nbsp;Keyword Highlight Options</span></h3><br /><br />");      hDoc.write("<h3><span class=\\"LC_info\\">&nbsp;Keyword Highlight Options<\\/span><\\/h3><br /><br />");
   
     hDoc.write("<table border=0 width=100%><tr><td bgcolor=\\"#777777\\">");      hDoc.write("<table border=0 width=100%><tr><td bgcolor=\\"#777777\\">");
     hDoc.write("<table border=0 width=100%><tr bgcolor=\\"#ddffff\\">");      hDoc.write("<table border=0 width=100%><tr bgcolor=\\"#ddffff\\">");
     hDoc.write("<td><b>Text Color</b></td><td><b>Font Size</b></td><td><b>Font Style</td></tr>");      hDoc.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) {     function highlightbody(clrval,clrtxt,clrsel,szval,sztxt,szsel,syval,sytxt,sysel) { 
     var hDoc = hwdWin.document;      var hDoc = hwdWin.document;
     hDoc.write("<tr bgcolor=\\"#ffffdd\\">");      hDoc.write("<tr bgcolor=\\"#ffffdd\\">");
     hDoc.write("<td align=\\"left\\">");      hDoc.write("<td align=\\"left\\">");
     hDoc.write("<input name=\\"kwdclr\\" type=\\"radio\\" value=\\""+clrval+"\\" "+clrsel+">&nbsp;"+clrtxt+"</td>");      hDoc.write("<input name=\\"kwdclr\\" type=\\"radio\\" value=\\""+clrval+"\\" "+clrsel+">&nbsp;"+clrtxt+"<\\/td>");
     hDoc.write("<td align=\\"left\\">");      hDoc.write("<td align=\\"left\\">");
     hDoc.write("<input name=\\"kwdsize\\" type=\\"radio\\" value=\\""+szval+"\\" "+szsel+">&nbsp;"+sztxt+"</td>");      hDoc.write("<input name=\\"kwdsize\\" type=\\"radio\\" value=\\""+szval+"\\" "+szsel+">&nbsp;"+sztxt+"<\\/td>");
     hDoc.write("<td align=\\"left\\">");      hDoc.write("<td align=\\"left\\">");
     hDoc.write("<input name=\\"kwdstyle\\" type=\\"radio\\" value=\\""+syval+"\\" "+sysel+">&nbsp;"+sytxt+"</td>");      hDoc.write("<input name=\\"kwdstyle\\" type=\\"radio\\" value=\\""+syval+"\\" "+sysel+">&nbsp;"+sytxt+"<\\/td>");
     hDoc.write("</tr>");      hDoc.write("<\\/tr>");
   }    }
   
   function highlightend() {     function highlightend() { 
     var hDoc = hwdWin.document;      var hDoc = hwdWin.document;
     hDoc.write("</table>");      hDoc.write("<\\/table>");
     hDoc.write("</td></tr></table>&nbsp;");      hDoc.write("<\\/td><\\/tr><\\/table>&nbsp;");
     hDoc.write("<input type=\\"button\\" value=\\"Save\\" onClick=\\"javascript:updateChoice(1)\\">&nbsp;&nbsp;");      hDoc.write("<input type=\\"button\\" value=\\"Save\\" onClick=\\"javascript:updateChoice(1)\\">&nbsp;&nbsp;");
     hDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br /><br />");      hDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br /><br />");
     hDoc.write("</form>");      hDoc.write("<\\/form>");
     hDoc.write('$end_page_highlight_central');      hDoc.write('$end_page_highlight_central');
     hDoc.close();      hDoc.close();
   }    }
Line 1502  sub gradeBox { Line 1619  sub gradeBox {
  '" src="'.$request->dir_config('lonIconsURL').   '" src="'.$request->dir_config('lonIconsURL').
  '/check.gif" height="16" border="0" />';   '/check.gif" height="16" border="0" />';
     my $wgt    = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb,$udom,$uname);      my $wgt    = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb,$udom,$uname);
     my $wgtmsg = ($wgt > 0 ? '(problem weight)' :       my $wgtmsg = ($wgt > 0) ? &mt('(problem weight)') 
   '<span class="LC_info">problem weight assigned by computer</span>');                             : '<span class="LC_info">'.&mt('problem weight assigned by computer').'</span>';
     $wgt       = ($wgt > 0 ? $wgt : '1');      $wgt       = ($wgt > 0 ? $wgt : '1');
     my $score  = ($$record{'resource.'.$partid.'.awarded'} eq '' ?      my $score  = ($$record{'resource.'.$partid.'.awarded'} eq '' ?
   '' : &compute_points($$record{'resource.'.$partid.'.awarded'},$wgt));    '' : &compute_points($$record{'resource.'.$partid.'.awarded'},$wgt));
     my $result='<input type="hidden" name="WGT'.$counter.'_'.$partid.'" value="'.$wgt.'" />'."\n";      my $result='<input type="hidden" name="WGT'.$counter.'_'.$partid.'" value="'.$wgt.'" />'."\n";
     my $display_part=&get_display_part($partid,$symb);      my $display_part= &get_display_part($partid,$symb);
     my %last_resets = &get_last_resets($symb,$env{'request.course.id'},      my %last_resets = &get_last_resets($symb,$env{'request.course.id'},
        [$partid]);         [$partid]);
     my $aggtries = $$record{'resource.'.$partid.'.tries'};      my $aggtries = $$record{'resource.'.$partid.'.tries'};
Line 1590  sub handback_box { Line 1707  sub handback_box {
     '<span class="LC_filename">'.$file_disp.'</span>');      '<span class="LC_filename">'.$file_disp.'</span>');
            $result.='<input type="file"   name="'.$prefix.'returndoc'.$file_counter.'" />'."\n";             $result.='<input type="file"   name="'.$prefix.'returndoc'.$file_counter.'" />'."\n";
            $result.='<input type="hidden" name="'.$prefix.'origdoc'.$file_counter.'" value="'.$file.'" /><br />';             $result.='<input type="hidden" name="'.$prefix.'origdoc'.$file_counter.'" value="'.$file.'" /><br />';
            $result.='(File will be uploaded when you click on Save & Next below.)<br />';             $result.='(File will be uploaded when you click on Save &amp; Next below.)<br />';
            $file_counter++;             $file_counter++;
     }      }
  }   }
Line 1626  sub show_problem { Line 1743  sub show_problem {
  $companswer=~s|</form>||g;   $companswer=~s|</form>||g;
  $companswer=~s|name="submit"|name="would_have_been_submit"|g;   $companswer=~s|name="submit"|name="would_have_been_submit"|g;
     }      }
     my $result.='<table border="0" width="100%"><tr><td bgcolor="#777777">';      $rendered=
     $result.='<table border="0" width="100%">';   '<div class="LC_grade_show_problem_header">'.
     if ($viewon) {   &mt('View of the problem').
  $result.='<tr><td bgcolor="#e6ffff"><b> ';   '</div><div class="LC_grade_show_problem_problem">'.
  if ($mode eq 'both' or $mode eq 'text') {   $rendered.
     $result.='View of the problem - ';   '</div>';
  } else {      $companswer=
     $result.='Correct answer: ';   '<div class="LC_grade_show_problem_header">'.
  }   &mt('Correct answer').
  $result.=$env{'form.fullname'}.'</b></td></tr>';   '</div><div class="LC_grade_show_problem_problem">'.
     }   $companswer.
    '</div>';
       my $result;
     if ($mode eq 'both') {      if ($mode eq 'both') {
  $result.='<tr><td bgcolor="#ffffff">'.$rendered.'<br />';   $result=$rendered.$companswer;
  $result.='<b>Correct answer:</b><br />'.$companswer;  
     } elsif ($mode eq 'text') {      } elsif ($mode eq 'text') {
  $result.='<tr><td bgcolor="#ffffff">'.$rendered;   $result=$rendered;
     } elsif ($mode eq 'answer') {      } elsif ($mode eq 'answer') {
  $result.='<tr><td bgcolor="#ffffff">'.$companswer;   $result=$companswer;
     }      }
     $result.='</td></tr></table>';      $result='<div class="LC_grade_show_problem">'.$result.'</div>';
     $result.='</td></tr></table><br />';  
     return $result;      return $result;
 }  }
   
Line 1703  sub build_section_inputs { Line 1820  sub build_section_inputs {
 # --------------------------- 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) = @_;
   
     my ($uname,$udom)     = ($env{'form.student'},$env{'form.userdom'});      my ($uname,$udom)     = ($env{'form.student'},$env{'form.userdom'});
     $udom = ($udom eq '' ? $env{'user.domain'} : $udom); #has form.userdom changed for a student?      $udom = ($udom eq '' ? $env{'user.domain'} : $udom); #has form.userdom changed for a student?
     my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'});      my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'});
Line 1740  sub submission { Line 1856  sub submission {
  $request->print('<h3>&nbsp;<span class="LC_info">Submission Record</span></h3>'."\n".   $request->print('<h3>&nbsp;<span class="LC_info">Submission Record</span></h3>'."\n".
  '<h4>&nbsp;<b>Resource: </b>'.$env{'form.probTitle'}.'</h4>'."\n");   '<h4>&nbsp;<b>Resource: </b>'.$env{'form.probTitle'}.'</h4>'."\n");
   
  if ($env{'form.handgrade'} eq 'no') {  
     my $checkMark='<br /><br />&nbsp;<b>Note:</b> Part(s) graded correct by the computer is marked with a '.  
  $checkIcon.' symbol.'."\n";  
     $request->print($checkMark);  
  }  
   
  # option to display problem, only once else it cause problems    # option to display problem, only once else it cause problems 
         # with the form later since the problem has a form.          # with the form later since the problem has a form.
  if ($env{'form.vProb'} eq 'yes' or $env{'form.vAns'} eq 'yes') {   if ($env{'form.vProb'} eq 'yes' or $env{'form.vAns'} eq 'yes') {
Line 1847  KEYWORDS Line 1957  KEYWORDS
     }      }
   
 # This is where output for one specific student would start  # This is where output for one specific student would start
     my $bgcolor='#DDEEDD';      my $add_class = ($counter%2) ? 'LC_grade_show_user_odd_row' : '';
     if (int($counter/2) eq $counter) { $bgcolor='#DDDDEE'; }  
     $request->print("\n\n".      $request->print("\n\n".
                     '<p><table border="2"><tr><th bgcolor="'.$bgcolor.'">'.$env{'form.fullname'}.'</th></tr><tr><td bgcolor="'.$bgcolor.'">');                      '<div class="LC_grade_show_user '.$add_class.'">'.
       '<div class="LC_grade_user_name">'.&nameUserString(undef,$env{'form.fullname'},$uname,$udom).'</div>'.
       '<div class="LC_grade_show_user_body">'."\n");
   
     if ($env{'form.vProb'} eq 'all' or $env{'form.vAns'} eq 'all') {      if ($env{'form.vProb'} eq 'all' or $env{'form.vAns'} eq 'all') {
  my $mode;   my $mode;
Line 1862  KEYWORDS Line 1973  KEYWORDS
     $mode='answer';      $mode='answer';
  }   }
  &Apache::lonxml::clear_problem_counter();   &Apache::lonxml::clear_problem_counter();
  $request->print(&show_problem($request,$symb,$uname,$udom,1,1,$mode));   $request->print(&show_problem($request,$symb,$uname,$udom,1,1,$mode,{'request.prefix' => 'ctr'.$counter}));
     }      }
   
     my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname);      my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname);
Line 1870  KEYWORDS Line 1981  KEYWORDS
   
     # Display student info      # Display student info
     $request->print(($counter == 0 ? '' : '<br />'));      $request->print(($counter == 0 ? '' : '<br />'));
     my $result='<table border="0" width="100%"><tr><td bgcolor="#777777">'."\n".      my $result='<div class="LC_grade_submissions">';
  '<table border="0" width="100%"><tr bgcolor="#edffff"><td>'."\n";      
       $result.='<div class="LC_grade_submissions_header">';
     $result.='<b>Fullname: </b>'.&nameUserString(undef,$env{'form.fullname'},$uname,$udom).'<br />'."\n";      $result.= &mt('Submissions');
     $result.='<input type="hidden" name="name'.$counter.      $result.='<input type="hidden" name="name'.$counter.
  '" value="'.$env{'form.fullname'}.'" />'."\n";   '" value="'.$env{'form.fullname'}.'" />'."\n";
       if ($env{'form.handgrade'} eq 'no') {
    $result.='<span class="LC_grade_check_note">'.
       &mt('Part(s) graded correct by the computer is marked with a [_1] symbol.',$checkIcon)."</span>\n";
   
       }
   
   
   
     # If any part of the problem is an essay-response (handgraded), then check for collaborators      # If any part of the problem is an essay-response (handgraded), then check for collaborators
     my @col_fullnames;      my $fullname;
     my ($classlist,$fullname);      my $col_fullnames = [];
     if ($env{'form.handgrade'} eq 'yes') {      if ($env{'form.handgrade'} eq 'yes') {
  ($classlist,undef,$fullname) = &getclasslist('all','0');   (my $sub_result,$fullname,$col_fullnames)=
  for (keys (%$handgrade)) {      &check_collaborators($symb,$uname,$udom,\%record,$handgrade,
     my $ncol = &Apache::lonnet::EXT('resource.'.$_.   $counter);
     '.maxcollaborators',   $result.=$sub_result;
                                             $symb,$udom,$uname);  
     next if ($ncol <= 0);  
             s/\_/\./g;  
             next if ($record{'resource.'.$_.'.collaborators'} eq '');  
             my @goodcollaborators = ();  
             my @badcollaborators  = ();  
     foreach (split(/,?\s+/,$record{'resource.'.$_.'.collaborators'})) {   
  $_ =~ s/[\$\^\(\)]//g;  
  next if ($_ eq '');  
  my ($co_name,$co_dom) = split /\@|:/,$_;  
  $co_dom = $udom if (! defined($co_dom) || $co_dom =~ /^domain$/i);  
  next if ($co_name eq $uname && $co_dom eq $udom);  
  # Doing this grep allows 'fuzzy' specification  
  my @Matches = grep /^$co_name:$co_dom$/i,keys %$classlist;  
  if (! scalar(@Matches)) {  
     push @badcollaborators,$_;  
  } else {  
     push @goodcollaborators, @Matches;  
  }  
     }  
             if (scalar(@goodcollaborators) != 0) {  
                 $result.='<b>Collaborators: </b>';  
                 foreach (@goodcollaborators) {  
     my ($lastname,$givenn) = split(/,/,$$fullname{$_});  
     push @col_fullnames, $givenn.' '.$lastname;  
     $result.=$$fullname{$_}.'&nbsp; &nbsp; &nbsp;';  
  }  
                 $result.='<br />'."\n";  
  my ($part)=split(/\./,$_);  
  $result.='<input type="hidden" name="collaborator'.$counter.  
     '" value="'.$part.':'.(join ':',@goodcollaborators).'" />'.  
     "\n";  
     }  
     if (scalar(@badcollaborators) > 0) {  
  $result.='<table border="0"><tr bgcolor="#ffbbbb"><td>';  
  $result.='This student has submitted ';  
  $result.=(scalar(@badcollaborators) == 1) ? 'an invalid collaborator' : 'invalid collaborators';  
  $result .= ': '.join(', ',@badcollaborators);  
  $result .= '</td></tr></table>';  
     }           
     if (scalar(@badcollaborators > $ncol)) {  
  $result .= '<table border="0"><tr bgcolor="#ffbbbb"><td>';  
  $result .= 'This student has submitted too many '.  
     'collaborators.  Maximum is '.$ncol.'.';  
  $result .= '</td></tr></table>';  
     }  
  }  
     }      }
     $request->print($result."\n");      $request->print($result."\n");
       $request->print('</div>'."\n");
     # print student answer/submission      # print student answer/submission
     # Options are (1) Handgaded submission only      # Options are (1) Handgaded submission only
     #             (2) Last submission, includes submission that is not handgraded       #             (2) Last submission, includes submission that is not handgraded 
Line 1943  KEYWORDS Line 2014  KEYWORDS
     #             (4) The whole record for this student      #             (4) The whole record for this student
     if ($env{'form.lastSub'} =~ /^(lastonly|hdgrade)$/) {      if ($env{'form.lastSub'} =~ /^(lastonly|hdgrade)$/) {
  my ($string,$timestamp)= &get_last_submission(\%record);   my ($string,$timestamp)= &get_last_submission(\%record);
  my $lastsubonly=''.  
     ($$timestamp eq '' ? '' : '<b>Date Submitted:</b> '.   my $lastsubonly;
      $$timestamp)."</td></tr>\n";  
  if ($$timestamp eq '') {   if ($$timestamp eq '') {
     $lastsubonly.='<tr><td bgcolor="#ffffe6">'.$$string[0];       $lastsubonly.='<div class="LC_grade_submissions_body">'.$$string[0].'</div>'; 
  } else {   } else {
       $lastsubonly = '<div class="LC_grade_submissions_body"> <b>Date Submitted:</b> '.$$timestamp."\n";
   
     my %seenparts;      my %seenparts;
     my @part_response_id = &flatten_responseType($responseType);      my @part_response_id = &flatten_responseType($responseType);
     foreach my $part (@part_response_id) {      foreach my $part (@part_response_id) {
Line 1971  KEYWORDS Line 2044  KEYWORDS
  }   }
  my $responsetype = $responseType->{$partid}->{$respid};   my $responsetype = $responseType->{$partid}->{$respid};
  if (!exists($record{"resource.$partid.$respid.submission"})) {   if (!exists($record{"resource.$partid.$respid.submission"})) {
     $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part:</b> '.      $lastsubonly.="\n".'<div class="LC_grade_submission_part"><b>Part:</b> '.
  $display_part.' <span class="LC_internal_info">( ID '.$respid.   $display_part.' <span class="LC_internal_info">( ID '.$respid.
  ' )</span>&nbsp; &nbsp;'.   ' )</span>&nbsp; &nbsp;'.
  '<span class="LC_warning">Nothing submitted - no attempts</span><br /><br />';   '<span class="LC_warning">'.&mt('Nothing submitted - no attempts').'</span><br /><br /></div>';
     next;      next;
  }   }
  foreach (@$string) {   foreach my $submission (@$string) {
     my ($partid,$respid) = /^resource\.([^\.]*)\.([^\.]*)\.submission/;      my ($partid,$respid) = ($submission =~ /^resource\.([^\.]*)\.([^\.]*)\.submission/);
     if (join('_',@{$part}) ne ($partid.'_'.$respid)) { next; }      if (join('_',@{$part}) ne ($partid.'_'.$respid)) { next; }
     my ($ressub,$subval) = split(/:/,$_,2);      my ($ressub,$subval) = split(/:/,$submission,2);
     # Similarity check      # Similarity check
     my $similar='';      my $similar='';
     if($env{'form.checkPlag'}){      if($env{'form.checkPlag'}){
Line 2010  KEYWORDS Line 2083  KEYWORDS
  ($env{'form.lastSub'} eq 'hdgrade' &&    ($env{'form.lastSub'} eq 'hdgrade' && 
  $$handgrade{$$part[0].'_'.$$part[1]} eq 'yes')) {   $$handgrade{$$part[0].'_'.$$part[1]} eq 'yes')) {
  my $display_part=&get_display_part($partid,$symb);   my $display_part=&get_display_part($partid,$symb);
  $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part:</b> '.   $lastsubonly.='<div class="LC_grade_submission_part"><b>Part:</b> '.
     $display_part.' <span class="LC_internal_info">( ID '.$respid.      $display_part.' <span class="LC_internal_info">( ID '.$respid.
     ' )</span>&nbsp; &nbsp;';      ' )</span>&nbsp; &nbsp;';
  my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record);   my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record);
  if (@$files) {   if (@$files) {
     $lastsubonly.='<br /><span class="LC_warning">Like all files provided by users, this file may contain virusses</span><br />';      $lastsubonly.='<br /><span class="LC_warning">'.&mt('Like all files provided by users, this file may contain virusses').'</span><br />';
     my $file_counter = 0;      my $file_counter = 0;
     foreach my $file (@$files) {      foreach my $file (@$files) {
         $file_counter ++;          $file_counter++;
  &Apache::lonnet::allowuploaded('/adm/grades',$file);   &Apache::lonnet::allowuploaded('/adm/grades',$file);
  $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border=0"> '.$file.'</a>';   $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border=0"> '.$file.'</a>';
     }      }
     $lastsubonly.='<br />';      $lastsubonly.='<br />';
  }   }
  $lastsubonly.='<b>Submitted Answer: </b>'.   $lastsubonly.='<b>'.&mt('Submitted Answer:').' </b>'.
     &cleanRecord($subval,$responsetype,$symb,$partid,      &cleanRecord($subval,$responsetype,$symb,$partid,
  $respid,\%record,$order);   $respid,\%record,$order);
  if ($similar) {$lastsubonly.="<br /><br />$similar\n";}   if ($similar) {$lastsubonly.="<br /><br />$similar\n";}
    $lastsubonly.='</div>';
     }      }
  }   }
     }      }
       $lastsubonly.='</div>'."\n";
  }   }
  $lastsubonly.='</td></tr><tr bgcolor="#ffffff"><td>'."\n";  
  $request->print($lastsubonly);   $request->print($lastsubonly);
     } elsif ($env{'form.lastSub'} eq 'datesub') {     } elsif ($env{'form.lastSub'} eq 'datesub') {
  my (undef,$responseType,undef,$parts) = &showResourceInfo($symb);   my (undef,$responseType,undef,$parts) = &showResourceInfo($symb);
  $request->print(&displaySubByDates($symb,\%record,$parts,$responseType,$checkIcon,$uname,$udom));   $request->print(&displaySubByDates($symb,\%record,$parts,$responseType,$checkIcon,$uname,$udom));
     } elsif ($env{'form.lastSub'} =~ /^(last|all)$/) {      } elsif ($env{'form.lastSub'} =~ /^(last|all)$/) {
Line 2046  KEYWORDS Line 2120  KEYWORDS
   
     $request->print('<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':'      $request->print('<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':'
  .$udom.'" />'."\n");   .$udom.'" />'."\n");
       
     # return if view submission with no grading option      # return if view submission with no grading option
     if ($env{'form.showgrading'} eq '' || (!&canmodify($usec))) {      if ($env{'form.showgrading'} eq '' || (!&canmodify($usec))) {
  my $toGrade.='<input type="button" value="Grade Student" '.   my $toGrade.='<input type="button" value="Grade Student" '.
     'onClick="javascript:checksubmit(this.form,\'Grade Student\',\''      'onClick="javascript:checksubmit(this.form,\'Grade Student\',\''
     .$counter.'\');" target="_self" /> &nbsp;'."\n" if (&canmodify($usec));      .$counter.'\');" target="_self" /> &nbsp;'."\n" if (&canmodify($usec));
  $toGrade.='</td></tr></table></td></tr></table>'."\n";   $toGrade.='</div>'."\n";
  if (($env{'form.command'} eq 'submission') ||    if (($env{'form.command'} eq 'submission') || 
     ($env{'form.command'} eq 'processGroup' && $counter == $total)) {      ($env{'form.command'} eq 'processGroup' && $counter == $total)) {
     $toGrade.='</form>'.&show_grading_menu_form($symb);       $toGrade.='</form>'.&show_grading_menu_form($symb); 
Line 2060  KEYWORDS Line 2133  KEYWORDS
  $request->print($toGrade);   $request->print($toGrade);
  return;   return;
     } else {      } else {
  $request->print('</td></tr></table></td></tr></table>'."\n");   $request->print('</div>'."\n");
     }      }
   
     # essay grading message center      # essay grading message center
     if ($env{'form.handgrade'} eq 'yes') {      if ($env{'form.handgrade'} eq 'yes') {
    my $result='<div class="LC_grade_message_center">';
       
    $result.='<div class="LC_grade_message_center_header">'.
       &mt('Send Message').'</div><div class="LC_grade_message_center_body">';
  my ($lastname,$givenn) = split(/,/,$env{'form.fullname'});   my ($lastname,$givenn) = split(/,/,$env{'form.fullname'});
  my $msgfor = $givenn.' '.$lastname;   my $msgfor = $givenn.' '.$lastname;
  if (scalar(@col_fullnames) > 0) {   if (scalar(@$col_fullnames) > 0) {
     my $lastone = pop @col_fullnames;      my $lastone = pop(@$col_fullnames);
     $msgfor .= ', '.(join ', ',@col_fullnames).' and '.$lastone.'.';      $msgfor .= ', '.(join ', ',@$col_fullnames).' and '.$lastone.'.';
  }   }
  $msgfor =~ s/\'/\\'/g; #' stupid emacs - no! javascript   $msgfor =~ s/\'/\\'/g; #' stupid emacs - no! javascript
  $result='<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n".   $result.='<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n".
     '<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n";      '<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n";
  $result.='&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.   $result.='&nbsp;<a href="javascript:msgCenter(document.SCORE,'.$counter.
     ',\''.$msgfor.'\');" target="_self">'.      ',\''.$msgfor.'\');" target="_self">'.
     &mt('Compose message to student').(scalar(@col_fullnames) >= 1 ? 's' : '').'</a><label> ('.      &mt('Compose message to student').(scalar(@$col_fullnames) >= 1 ? 's' : '').'</a><label> ('.
     &mt('incl. grades').' <input type="checkbox" name="withgrades'.$counter.'" /></label>)'.      &mt('incl. grades').' <input type="checkbox" name="withgrades'.$counter.'" /></label>)'.
     '<img src="'.$request->dir_config('lonIconsURL').      '<img src="'.$request->dir_config('lonIconsURL').
     '/mailbkgrd.gif" width="14" height="10" name="mailicon'.$counter.'" />'."\n".      '/mailbkgrd.gif" width="14" height="10" name="mailicon'.$counter.'" />'."\n".
     '<br />&nbsp;('.      '<br />&nbsp;('.
     &mt('Message will be sent when you click on Save & Next below.').")\n";      &mt('Message will be sent when you click on Save &amp; Next below.').")\n";
    $result.='</div></div>';
  $request->print($result);   $request->print($result);
     }      }
     if ($perm{'vgr'}) {  
  $request->print('<br />'.  
     &Apache::loncommon::track_student_link(&mt('View recent activity'),  
    $uname,$udom,'check'));  
     }  
     if ($perm{'opa'}) {  
  $request->print('<br />'.  
     &Apache::loncommon::pprmlink(&mt('Set/Change parameters'),  
  $uname,$udom,$symb,'check'));  
     }  
   
     my %seen = ();      my %seen = ();
     my @partlist;      my @partlist;
     my @gradePartRespid;      my @gradePartRespid;
     my @part_response_id = &flatten_responseType($responseType);      my @part_response_id = &flatten_responseType($responseType);
       $request->print('<div class="LC_grade_assign">'.
       
       '<div class="LC_grade_assign_header">'.
       &mt('Assign Grades').'</div>'.
       '<div class="LC_grade_assign_body">');
     foreach my $part_response_id (@part_response_id) {      foreach my $part_response_id (@part_response_id) {
     my ($partid,$respid) = @{ $part_response_id };      my ($partid,$respid) = @{ $part_response_id };
  my $part_resp = join('_',@{ $part_response_id });   my $part_resp = join('_',@{ $part_response_id });
Line 2110  KEYWORDS Line 2183  KEYWORDS
  push @gradePartRespid,$partid.'.'.$respid;   push @gradePartRespid,$partid.'.'.$respid;
  $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record));   $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record));
     }      }
       $request->print('</div></div>');
   
       $request->print('<div class="LC_grade_info_links">');
       if ($perm{'vgr'}) {
    $request->print(
       &Apache::loncommon::track_student_link(&mt('View recent activity'),
      $uname,$udom,'check'));
       }
       if ($perm{'opa'}) {
    $request->print(
       &Apache::loncommon::pprmlink(&mt('Set/Change parameters'),
    $uname,$udom,$symb,'check'));
       }
       $request->print('</div>');
   
     $result='<input type="hidden" name="partlist'.$counter.      $result='<input type="hidden" name="partlist'.$counter.
  '" value="'.(join ":",@partlist).'" />'."\n";   '" value="'.(join ":",@partlist).'" />'."\n";
     $result.='<input type="hidden" name="gradePartRespid'.      $result.='<input type="hidden" name="gradePartRespid'.
Line 2120  KEYWORDS Line 2208  KEYWORDS
     $partlist[$ctr].'" />'."\n";      $partlist[$ctr].'" />'."\n";
  $ctr++;   $ctr++;
     }      }
     $request->print($result.'</td></tr></table></td></tr></table>'."\n");      $request->print($result.''."\n");
   
 # Done with printing info for one student  # Done with printing info for one student
   
     $request->print('</td></tr></table></p>');      $request->print('</div>');#LC_grade_show_user_body
       $request->print('</div>');#LC_grade_show_user
   
   
     # print end of form      # print end of form
Line 2154  KEYWORDS Line 2243  KEYWORDS
     return '';      return '';
 }  }
   
   sub check_collaborators {
       my ($symb,$uname,$udom,$record,$handgrade,$counter) = @_;
       my ($result,@col_fullnames);
       my ($classlist,undef,$fullname) = &getclasslist('all','0');
       foreach my $part (keys(%$handgrade)) {
    my $ncol = &Apache::lonnet::EXT('resource.'.$part.
    '.maxcollaborators',
    $symb,$udom,$uname);
    next if ($ncol <= 0);
    $part =~ s/\_/\./g;
    next if ($record->{'resource.'.$part.'.collaborators'} eq '');
    my (@good_collaborators, @bad_collaborators);
    foreach my $possible_collaborator
       (split(/,?\s+/,$record->{'resource.'.$part.'.collaborators'})) { 
       $possible_collaborator =~ s/[\$\^\(\)]//g;
       next if ($possible_collaborator eq '');
       my ($co_name,$co_dom) = split(/\@|:/,$possible_collaborator);
       $co_dom = $udom if (! defined($co_dom) || $co_dom =~ /^domain$/i);
       next if ($co_name eq $uname && $co_dom eq $udom);
       # Doing this grep allows 'fuzzy' specification
       my @matches = grep(/^\Q$co_name\E:\Q$co_dom\E$/i, 
          keys(%$classlist));
       if (! scalar(@matches)) {
    push(@bad_collaborators, $possible_collaborator);
       } else {
    push(@good_collaborators, @matches);
       }
    }
    if (scalar(@good_collaborators) != 0) {
       $result.='<br />'.&mt('Collaborators: ');
       foreach my $name (@good_collaborators) {
    my ($lastname,$givenn) = split(/,/,$$fullname{$name});
    push(@col_fullnames, $givenn.' '.$lastname);
    $result.=$fullname->{$name}.'&nbsp; &nbsp; &nbsp;';
       }
       $result.='<br />'."\n";
       my ($part)=split(/\./,$part);
       $result.='<input type="hidden" name="collaborator'.$counter.
    '" value="'.$part.':'.(join ':',@good_collaborators).'" />'.
    "\n";
    }
    if (scalar(@bad_collaborators) > 0) {
       $result.='<div class="LC_warning">';
       $result.=&mt('This student has submitted [quant,_1,invalid collaborator]: [_2]',scalar(@bad_collaborators),join(', ',@bad_collaborators));
       $result .= '</div>';
    }         
    if (scalar(@bad_collaborators > $ncol)) {
       $result .= '<div class="LC_warning">';
       $result .= &mt('This student has submitted too many '.
    'collaborators.  Maximum is [_1].',$ncol);
       $result .= '</div>';
    }
       }
       return ($result,$fullname,\@col_fullnames);
   }
   
 #--- Retrieve the last submission for all the parts  #--- Retrieve the last submission for all the parts
 sub get_last_submission {  sub get_last_submission {
     my ($returnhash)=@_;      my ($returnhash)=@_;
Line 2789  sub version_selected_portfile { Line 2934  sub version_selected_portfile {
     my $new_answer;      my $new_answer;
     $env{'form.copy'} = &Apache::lonnet::getfile("/uploaded/$domain/$stu_name/portfolio$directory$file_name");      $env{'form.copy'} = &Apache::lonnet::getfile("/uploaded/$domain/$stu_name/portfolio$directory$file_name");
     if($env{'form.copy'} eq '-1') {      if($env{'form.copy'} eq '-1') {
         &Apache::lonnet::logthis('problem getting file '.$file_name);  
         $new_answer = 'problem getting file';          $new_answer = 'problem getting file';
     } else {      } else {
         $new_answer = $answer_name.'.'.$version.'.'.$answer_ext;          $new_answer = $answer_name.'.'.$version.'.'.$answer_ext;
Line 3029  sub viewgrades { Line 3173  sub viewgrades {
  $sectionClass=&mt('Students in Section(s) [_1]',$section_display).'</h3>';   $sectionClass=&mt('Students in Section(s) [_1]',$section_display).'</h3>';
     }      }
     $result.='<h3>'.&mt('Assign Common Grade To [_1]',$sectionClass);      $result.='<h3>'.&mt('Assign Common Grade To [_1]',$sectionClass);
     $result.= '<table border=0><tr><td bgcolor="#777777">'."\n".      $result.= &Apache::loncommon::start_data_table();
  '<table border=0><tr bgcolor="#ffffdd"><td>';  
     #radio buttons/text box for assigning points for a section or class.      #radio buttons/text box for assigning points for a section or class.
     #handles different parts of a problem      #handles different parts of a problem
     my ($partlist,$handgrade,$responseType) = &response_type($symb);      my ($partlist,$handgrade,$responseType) = &response_type($symb);
     my %weight = ();      my %weight = ();
     my $ctsparts = 0;      my $ctsparts = 0;
     $result.='<table border="0">';  
     my %seen = ();      my %seen = ();
     my @part_response_id = &flatten_responseType($responseType);      my @part_response_id = &flatten_responseType($responseType);
     foreach my $part_response_id (@part_response_id) {      foreach my $part_response_id (@part_response_id) {
Line 3048  sub viewgrades { Line 3190  sub viewgrades {
  my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb);   my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb);
  $weight{$partid} = $wgt eq '' ? '1' : $wgt;   $weight{$partid} = $wgt eq '' ? '1' : $wgt;
   
    $result.=&Apache::loncommon::start_data_table_row().'<td>';
  $result.='<input type="hidden" name="partid_'.   $result.='<input type="hidden" name="partid_'.
     $ctsparts.'" value="'.$partid.'" />'."\n";      $ctsparts.'" value="'.$partid.'" />'."\n";
  $result.='<input type="hidden" name="weight_'.   $result.='<input type="hidden" name="weight_'.
     $partid.'" value="'.$weight{$partid}.'" />'."\n";      $partid.'" value="'.$weight{$partid}.'" />'."\n";
  my $display_part=&get_display_part($partid,$symb);   my $display_part=&get_display_part($partid,$symb);
  $result.='<tr><td><b>Part:</b> '.$display_part.'&nbsp; &nbsp;<b>Point:</b> </td><td>';   $result.=
       '<b>Part:</b> '.$display_part.'&nbsp; &nbsp;<b>Point:</b> </td><td>';
  $result.='<table border="0"><tr>';     $result.='<table border="0"><tr>';  
  my $ctr = 0;   my $ctr = 0;
  while ($ctr<=$weight{$partid}) { # display radio buttons in a nice table 10 across   while ($ctr<=$weight{$partid}) { # display radio buttons in a nice table 10 across
Line 3068  sub viewgrades { Line 3212  sub viewgrades {
     $partid.'" size="4" '.'onChange="javascript:writePoint(\''.      $partid.'" size="4" '.'onChange="javascript:writePoint(\''.
  $partid.'\','.$weight{$partid}.',\'textval\')" /> /'.   $partid.'\','.$weight{$partid}.',\'textval\')" /> /'.
     $weight{$partid}.' (problem weight)</td>'."\n";      $weight{$partid}.' (problem weight)</td>'."\n";
  $result.= '</td><td><select name="SELVAL_'.$partid.'"'.   $result.= '<td><select name="SELVAL_'.$partid.'"'.
     'onChange="javascript:writeRadText(\''.$partid.'\','.      'onChange="javascript:writeRadText(\''.$partid.'\','.
  $weight{$partid}.')"> '.   $weight{$partid}.')"> '.
     '<option selected="selected"> </option>'.      '<option selected="selected"> </option>'.
     '<option>excused</option>'.      '<option>excused</option>'.
     '<option>reset status</option></select></td>'.      '<option>reset status</option></select></td>'.
             '<td><label><input type="checkbox" name="FORCE_'.$partid.'" /> Override "Correct"</label></td></tr>'."\n";              '<td><label><input type="checkbox" name="FORCE_'.$partid.'" /> Override "Correct"</label></td>'.&Apache::loncommon::end_data_table_row()."\n";
  $ctsparts++;   $ctsparts++;
     }      }
     $result.='</table>'.'</td></tr></table>'.'</td></tr></table>'."\n".      $result.=&Apache::loncommon::end_data_table()."\n".
  '<input type="hidden" name="totalparts" value="'.$ctsparts.'" />';   '<input type="hidden" name="totalparts" value="'.$ctsparts.'" />';
     $result.='<input type="button" value="Revert to Default" '.      $result.='<input type="button" value="Revert to Default" '.
  'onClick="javascript:resetEntry('.$ctsparts.');" target="_self" />';   'onClick="javascript:resetEntry('.$ctsparts.');" />';
   
     #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 '.$sectionClass;      $result.= '<h3>Assign Grade to Specific Students in '.$sectionClass;
     $result.= '<table border=0><tr><td bgcolor="#777777">'."\n".      $result.= &Apache::loncommon::start_data_table().
  '<table border=0><tr bgcolor="#deffff"><td>&nbsp;<b>No.</b>&nbsp;</td>'.   &Apache::loncommon::start_data_table_header_row().
  '<td>'.&nameUserString('header')."</td>\n";   '<th>No.</th>'.
    '<th>'.&nameUserString('header')."</th>\n";
     my (@parts) = sort(&getpartlist($symb));      my (@parts) = sort(&getpartlist($symb));
     my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);      my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
     my @partids = ();      my @partids = ();
Line 3099  sub viewgrades { Line 3244  sub viewgrades {
         push(@partids, $partid);          push(@partids, $partid);
  my $display_part=&get_display_part($partid,$symb);   my $display_part=&get_display_part($partid,$symb);
  if ($display =~ /^Partial Credit Factor/) {   if ($display =~ /^Partial Credit Factor/) {
     $result.='<td><b>Score Part:</b> '.$display_part.      $result.='<th>Score Part: '.$display_part.
  ' <br /><b>(weight = '.$weight{$partid}.')</b></td>'."\n";   ' <br />(weight = '.$weight{$partid}.')</th>'."\n";
     next;      next;
  } else {   } else {
     $display =~s/\[Part: \Q$partid\E\]/Part:<\/b> $display_part/;      $display =~s/\[Part: \Q$partid\E\]/Part:<\/b> $display_part/;
  }   }
  $display =~ s|Problem Status|Grade Status<br />|;   $display =~ s|Problem Status|Grade Status<br />|;
  $result.='<td><b>'.$display.'</td>'."\n";   $result.='<th>'.$display.'</th>'."\n";
     }      }
     $result.='</tr>';      $result.=&Apache::loncommon::end_data_table_header_row();
   
     my %last_resets =       my %last_resets = 
  &get_last_resets($symb,$env{'request.course.id'},\@partids);   &get_last_resets($symb,$env{'request.course.id'},\@partids);
Line 3128  sub viewgrades { Line 3273  sub viewgrades {
  $result.=&viewstudentgrade($symb,$env{'request.course.id'},   $result.=&viewstudentgrade($symb,$env{'request.course.id'},
    $_,$$fullname{$_},\@parts,\%weight,$ctr,\%last_resets);     $_,$$fullname{$_},\@parts,\%weight,$ctr,\%last_resets);
     }      }
     $result.='</table></td></tr></table>';      $result.=&Apache::loncommon::end_data_table();
     $result.='<input type="hidden" name="total" value="'.$ctr.'" />'."\n";      $result.='<input type="hidden" name="total" value="'.$ctr.'" />'."\n";
     $result.='<input type="button" value="Save" '.      $result.='<input type="button" value="Save" '.
  'onClick="javascript:submit();" target="_self" /></form>'."\n";   'onClick="javascript:submit();" target="_self" /></form>'."\n";
Line 3151  sub viewstudentgrade { Line 3296  sub viewstudentgrade {
     my ($uname,$udom) = split(/:/,$student);      my ($uname,$udom) = split(/:/,$student);
     my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname);      my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname);
     my %aggregates = ();       my %aggregates = (); 
     my $result='<tr bgcolor="#ffffdd"><td align="right">'.      my $result=&Apache::loncommon::start_data_table_row().'<td align="right">'.
  '<input type="hidden" name="ctr'.($ctr-1).'" value="'.$student.'" />'.   '<input type="hidden" name="ctr'.($ctr-1).'" value="'.$student.'" />'.
  "\n".$ctr.'&nbsp;</td><td>&nbsp;'.   "\n".$ctr.'&nbsp;</td><td>&nbsp;'.
  '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.   '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom.
Line 3206  sub viewstudentgrade { Line 3351  sub viewstudentgrade {
  'value="'.$score.'" size="4" /></td>'."\n";   'value="'.$score.'" size="4" /></td>'."\n";
  }   }
     }      }
     $result.='</tr>';      $result.=&Apache::loncommon::end_data_table_row();
     return $result;      return $result;
 }  }
   
Line 3217  sub editgrades { Line 3362  sub editgrades {
   
     my $symb=&get_symb($request);      my $symb=&get_symb($request);
     my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));      my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));
     my $title='<h3><span class="LC_info">'.&mt('Current Grade Status').'</span></h3>';      my $title='<h2>'.&mt('Current Grade Status').'</h2>';
     $title.='<h4>'.&mt('<b>Current Resource: </b>[_1]',$env{'form.probTitle'}).'</h4><br />'."\n";      $title.='<h4>'.&mt('<b>Current Resource: </b>[_1]',$env{'form.probTitle'}).'</h4>'."\n";
     $title.='<h4>'.&mt('<b>Section: </b>[_1]',$section_display).'</h4>'."\n";      $title.='<h4>'.&mt('<b>Section: </b>[_1]',$section_display).'</h4>'."\n";
   
     my $result= '<table border="0"><tr><td bgcolor="#777777">'."\n";      my $result= &Apache::loncommon::start_data_table().
     $result.= '<table border="0"><tr bgcolor="#deffff">'.   &Apache::loncommon::start_data_table_header_row().
  '<td rowspan=2 valign="center">&nbsp;<b>No.</b>&nbsp;</td>'.   '<th rowspan="2" valign="middle">'.&mt('No.').'</th>'.
  '<td rowspan=2 valign="center">'.&nameUserString('header')."</td>\n";   '<th rowspan="2" valign="middle">'.&nameUserString('header')."</th>\n";
   
     my %scoreptr = (      my %scoreptr = (
     'correct'  =>'correct_by_override',      'correct'  =>'correct_by_override',
     'incorrect'=>'incorrect_by_override',      'incorrect'=>'incorrect_by_override',
Line 3250  sub editgrades { Line 3394  sub editgrades {
     }      }
     my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);      my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);
     foreach my $partid (@partid) {      foreach my $partid (@partid) {
  $header .= '<td align="center">&nbsp;<b>Old Score</b>&nbsp;</td>'.   $header .= '<th align="center">Old Score</th>'.
     '<td align="center">&nbsp;<b>New Score</b>&nbsp;</td>';      '<th align="center">New Score</th>';
  $columns{$partid}=2;   $columns{$partid}=2;
  foreach my $stores (@parts) {   foreach my $stores (@parts) {
     my ($part,$type) = &split_part_type($stores);      my ($part,$type) = &split_part_type($stores);
Line 3260  sub editgrades { Line 3404  sub editgrades {
     my $display=&Apache::lonnet::metadata($url,$stores.'.display');      my $display=&Apache::lonnet::metadata($url,$stores.'.display');
     $display =~ s/\[Part: (\w)+\]//;      $display =~ s/\[Part: (\w)+\]//;
     $display =~ s/Number of Attempts/Tries/;      $display =~ s/Number of Attempts/Tries/;
     $header .= '<td align="center">&nbsp;<b>Old '.$display.'</b>&nbsp;</td>'.      $header .= '<th align="center">Old '.$display.'</th>'.
  '<td align="center">&nbsp;<b>New '.$display.'</b>&nbsp;</td>';   '<th align="center">New '.$display.'</th>';
     $columns{$partid}+=2;      $columns{$partid}+=2;
  }   }
     }      }
     foreach my $partid (@partid) {      foreach my $partid (@partid) {
  my $display_part=&get_display_part($partid,$symb);   my $display_part=&get_display_part($partid,$symb);
  $result .= '<td colspan="'.$columns{$partid}.   $result .= '<th colspan="'.$columns{$partid}.
     '" align="center"><b>Part:</b> '.$display_part.      '" align="center">Part: '.$display_part.
     ' (Weight = '.$weight{$partid}.')</td>';      ' (Weight = '.$weight{$partid}.')</th>';
   
     }      }
     $result .= '</tr><tr bgcolor="#deffff">';      $result .= &Apache::loncommon::end_data_table_header_row().
     $result .= $header;   &Apache::loncommon::start_data_table_header_row().
     $result .= '</tr>'."\n";   $header.
     my $noupdate;   &Apache::loncommon::end_data_table_header_row();
       my @noupdate;
     my ($updateCtr,$noupdateCtr) = (1,1);      my ($updateCtr,$noupdateCtr) = (1,1);
     for ($i=0; $i<$env{'form.total'}; $i++) {      for ($i=0; $i<$env{'form.total'}; $i++) {
  my $line;   my $line;
Line 3287  sub editgrades { Line 3432  sub editgrades {
  my $usec=$classlist->{"$uname:$udom"}[5];   my $usec=$classlist->{"$uname:$udom"}[5];
  if (!&canmodify($usec)) {   if (!&canmodify($usec)) {
     my $numcols=scalar(@partid)*4+2;      my $numcols=scalar(@partid)*4+2;
     $noupdate.=$line."<td colspan=\"$numcols\"><span class=\"LC_warning\">Not allowed to modify student</span></td></tr>";      push(@noupdate,
    $line."<td colspan=\"$numcols\"><span class=\"LC_warning\">Not allowed to modify student</span></td></tr>");
     next;      next;
  }   }
         my %aggregate = ();          my %aggregate = ();
Line 3356  sub editgrades { Line 3502  sub editgrades {
     '<td align="center">'.$awarded.'&nbsp;</td>';      '<td align="center">'.$awarded.'&nbsp;</td>';
     }      }
  }   }
  $line.='</tr>'."\n";   $line.="\n";
   
  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'};
Line 3389  sub editgrades { Line 3535  sub editgrades {
  }   }
     }      }
   
     $result.='<tr bgcolor="#ffffde"><td align="right">&nbsp;'.$updateCtr.'&nbsp;</td>'.$line;      $result.=&Apache::loncommon::start_data_table_row().
    '<td align="right">&nbsp;'.$updateCtr.'&nbsp;</td>'.$line.
    &Apache::loncommon::end_data_table_row();
     $updateCtr++;      $updateCtr++;
  } else {   } else {
     $noupdate.='<tr bgcolor="#ffffde"><td align="right">&nbsp;'.$noupdateCtr.'&nbsp;</td>'.$line;      push(@noupdate,
    '<td align="right">&nbsp;'.$noupdateCtr.'&nbsp;</td>'.$line);
     $noupdateCtr++;      $noupdateCtr++;
  }   }
         if ($aggregateflag) {          if ($aggregateflag) {
Line 3400  sub editgrades { Line 3549  sub editgrades {
   $cdom,$cnum);    $cdom,$cnum);
         }          }
     }      }
     if ($noupdate) {      if (@noupdate) {
 # my $numcols=(scalar(@partid)*(scalar(@parts)-1)*2)+3;  # my $numcols=(scalar(@partid)*(scalar(@parts)-1)*2)+3;
  my $numcols=scalar(@partid)*4+2;   my $numcols=scalar(@partid)*4+2;
  $result .= '<tr bgcolor="#ffffff"><td align="center" colspan="'.$numcols.'">No Changes Occurred For the Students Below</td></tr><tr bgcolor="#ffffde">'.$noupdate;   $result .= &Apache::loncommon::start_data_table_row('LC_empty_row').
       '<td align="center" colspan="'.$numcols.'">No Changes Occurred For the Students Below</td>'.
       &Apache::loncommon::end_data_table_row();
    foreach my $line (@noupdate) {
       $result.=
    &Apache::loncommon::start_data_table_row().
    $line.
    &Apache::loncommon::end_data_table_row();
    }
     }      }
     $result .= '</table></td></tr></table>'."\n".      $result .= &Apache::loncommon::end_data_table().
  &show_grading_menu_form ($symb);   &show_grading_menu_form($symb);
     my $msg = '<br /><b>Number of records updated = '.$rec_update.      my $msg = '<p><b>Number of records updated = '.$rec_update.
  ' for '.$count.' student'.($count <= 1 ? '' : 's').'.</b><br />'.   ' for '.$count.' student'.($count <= 1 ? '' : 's').'.</b><br />'.
  '<b>Total number of students = '.$env{'form.total'}.'</b><br />';   '<b>Total number of students = '.$env{'form.total'}.'</b></p>';
     return $title.$msg.$result;      return $title.$msg.$result;
 }  }
   
Line 3801  sub csvuploadassign { Line 3958  sub csvuploadassign {
                 if ($wgt) {                  if ($wgt) {
                     $entries{$fields{$dest}}=~s/\s//g;                      $entries{$fields{$dest}}=~s/\s//g;
                     my $pcr=$entries{$fields{$dest}} / $wgt;                      my $pcr=$entries{$fields{$dest}} / $wgt;
                     my $award='correct_by_override';                      my $award=($pcr == 0) ? 'incorrect_by_override'
                                             : 'correct_by_override';
                     $grades{"resource.$part.awarded"}=$pcr;                      $grades{"resource.$part.awarded"}=$pcr;
                     $grades{"resource.$part.solved"}=$award;                      $grades{"resource.$part.solved"}=$award;
                     $points{$part}=1;                      $points{$part}=1;
Line 3823  sub csvuploadassign { Line 3981  sub csvuploadassign {
  }   }
  if (! %grades) { push(@skipped,"$username:$domain no data to save"); }   if (! %grades) { push(@skipped,"$username:$domain no data to save"); }
  $grades{"resource.regrader"}="$env{'user.name'}:$env{'user.domain'}";   $grades{"resource.regrader"}="$env{'user.name'}:$env{'user.domain'}";
 # &Apache::lonnet::logthis(" storing ".(join('-',%grades)));  
  my $result=&Apache::lonnet::cstore(\%grades,$symb,   my $result=&Apache::lonnet::cstore(\%grades,$symb,
    $env{'request.course.id'},     $env{'request.course.id'},
    $domain,$username);     $domain,$username);
Line 4153  sub displaySubByDates { Line 4310  sub displaySubByDates {
     my $isCODE=0;      my $isCODE=0;
     my $isTask = ($symb =~/\.task$/);      my $isTask = ($symb =~/\.task$/);
     if (exists($record->{'resource.CODE'})) { $isCODE=1; }      if (exists($record->{'resource.CODE'})) { $isCODE=1; }
     my $studentTable='<table border="0" width="100%"><tr><td bgcolor="#777777">'.      my $studentTable=&Apache::loncommon::start_data_table().
  '<table border="0" width="100%"><tr bgcolor="#e6ffff">'.   &Apache::loncommon::start_data_table_header_row().
  '<td><b>Date/Time</b></td>'.   '<th>'.&mt('Date/Time').'</th>'.
  ($isCODE?'<td><b>CODE</b></td>':'').   ($isCODE?'<th>'.&mt('CODE').'</th>':'').
  '<td><b>Submission</b></td>'.   '<th>'.&mt('Submission').'</th>'.
  '<td><b>Status&nbsp;</b></td></tr>';   '<th>'.&mt('Status').'</th>'.
    &Apache::loncommon::end_data_table_header_row();
     my ($version);      my ($version);
     my %mark;      my %mark;
     my %orders;      my %orders;
     $mark{'correct_by_student'} = $checkIcon;      $mark{'correct_by_student'} = $checkIcon;
     if (!exists($$record{'1:timestamp'})) {      if (!exists($$record{'1:timestamp'})) {
  return '<br />&nbsp;<span class="LC_warning">Nothing submitted - no attempts</span><br />';   return '<br />&nbsp;<span class="LC_warning">'.&mt('Nothing submitted - no attempts').'</span><br />';
     }      }
   
     my $interaction;      my $interaction;
     for ($version=1;$version<=$$record{'version'};$version++) {      for ($version=1;$version<=$$record{'version'};$version++) {
  my $timestamp = scalar(localtime($$record{$version.':timestamp'}));   my $timestamp = 
       &Apache::lonlocal::locallocaltime($$record{$version.':timestamp'});
  if (exists($$record{$version.':resource.0.version'})) {   if (exists($$record{$version.':resource.0.version'})) {
     $interaction = $$record{$version.':resource.0.version'};      $interaction = $$record{$version.':resource.0.version'};
  }   }
   
  my $where = ($isTask ? "$version:resource.$interaction"   my $where = ($isTask ? "$version:resource.$interaction"
              : "$version:resource");               : "$version:resource");
  #&Apache::lonnet::logthis(" got $where");   $studentTable.=&Apache::loncommon::start_data_table_row().
  $studentTable.='<tr bgcolor="#ffffff" valign="top"><td>'.$timestamp.'</td>';      '<td>'.$timestamp.'</td>';
  if ($isCODE) {   if ($isCODE) {
     $studentTable.='<td>'.$record->{$version.':resource.CODE'}.'</td>';      $studentTable.='<td>'.$record->{$version.':resource.CODE'}.'</td>';
  }   }
Line 4196  sub displaySubByDates { Line 4355  sub displaySubByDates {
   
     my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/)      my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/)
                : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/));                 : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/));
     #&Apache::lonnet::logthis("match $matchKey $responseId (".$$record{$version.':'.$matchKey});      $displaySub[0].='<b>'.&mt('Part:').'</b>&nbsp;'.$display_part.'&nbsp;';
     $displaySub[0].='<b>Part:</b>&nbsp;'.$display_part.'&nbsp;';      $displaySub[0].='<span class="LC_internal_info">('.&mt('ID').'&nbsp;'.
     $displaySub[0].='<span class="LC_internal_info">(ID&nbsp;'.  
  $responseId.')</span>&nbsp;<b>';   $responseId.')</span>&nbsp;<b>';
     if ($$record{"$where.$partid.tries"} eq '') {      if ($$record{"$where.$partid.tries"} eq '') {
  $displaySub[0].='Trial&nbsp;not&nbsp;counted';   $displaySub[0].=&mt('Trial&nbsp;not&nbsp;counted');
     } else {      } else {
  $displaySub[0].='Trial&nbsp;'.   $displaySub[0].=&mt('Trial&nbsp;[_1]',
     $$record{"$where.$partid.tries"};      $$record{"$where.$partid.tries"});
     }      }
     my $responseType=($isTask ? 'Task'      my $responseType=($isTask ? 'Task'
                                               : $responseType->{$partid}->{$responseId});                                                : $responseType->{$partid}->{$responseId});
Line 4244  sub displaySubByDates { Line 4402  sub displaySubByDates {
  }   }
  $studentTable.='<td>'.$displaySub[0].'&nbsp;</td><td>'.$displaySub[1];   $studentTable.='<td>'.$displaySub[0].'&nbsp;</td><td>'.$displaySub[1];
  if ($displaySub[2]) {   if ($displaySub[2]) {
     $studentTable.='Manually graded by '.$displaySub[2];      $studentTable.=&mt('Manually graded by [_1]',$displaySub[2]);
  }   }
  $studentTable.='&nbsp;</td></tr>';   $studentTable.='&nbsp;</td>'.
           &Apache::loncommon::end_data_table_row();
     }      }
     $studentTable.='</table></td></tr></table>';      $studentTable.=&Apache::loncommon::end_data_table();
     return $studentTable;      return $studentTable;
 }  }
   
Line 4465  the homework problem. Line 4623  the homework problem.
   
 =over 4  =over 4
   
 =cut  
   
   
 =pod   
   
 =item defaultFormData  =item defaultFormData
   
Line 4481  the homework problem. Line 4636  the homework problem.
   
 sub defaultFormData {  sub defaultFormData {
     my ($symb)=@_;      my ($symb)=@_;
     return '      return '<input type="hidden" name="symb"    value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n".
       <input type="hidden" name="symb"    value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n".  
      '<input type="hidden" name="saveState" value="'.$env{'form.saveState'}.'" />'."\n".       '<input type="hidden" name="saveState" value="'.$env{'form.saveState'}.'" />'."\n".
      '<input type="hidden" name="probTitle" value="'.$env{'form.probTitle'}.'" />'."\n";       '<input type="hidden" name="probTitle" value="'.$env{'form.probTitle'}.'" />'."\n";
 }  }
   
   
 =pod   =pod 
   
 =item getSequenceDropDown  =item getSequenceDropDown
Line 4788  SCANTRONFORM Line 4943  SCANTRONFORM
     </tr>      </tr>
 SCANTRONFORM  SCANTRONFORM
   
     $r->print(<<SCANTRONFORM);      $r->print('<tr><td bgcolor="#777777">');
   </table>      &Apache::lonpickcode::code_list($r,2);
 $grading_menu_button      $r->print('</td></tr></table>');
 SCANTRONFORM      $r->print($grading_menu_button);
   
     return      return
 }  }
   
Line 5076  sub scan_data { Line 5230  sub scan_data {
   
      if just_header was not true these key may also exist       if just_header was not true these key may also exist
   
        missingerror - a list of bubbled line numbers that had a blank bubble         missingerror - a list of bubble ranges that are considered to be answers
                       that is considered an error (if the operator had already                        to a single question that don't have any bubbles filled in.
                       okayed a blank bubble line as really being blank then                        Of the form questionnumber:firstbubblenumber:count.
                       that bubble line number won't appear here.         doubleerror  - a list of bubble ranges that are considered to be answers
        doubleerror  - a list of bubbled line numbers that had more than one                        to a single question that have more than one bubble filled in.
                       bubble filled in and has not been corrected by the                        Of the form questionnumber::firstbubblenumber:count
                       operator     
                   In the above, count is the number of bubble responses in the
                   input line needed to represent the possible answers to the question.
                   e.g. a radioresponse with 15 choices in an answer sheet with 10 choices
                   per line would have count = 2.
   
        maxquest     - the number of the last bubble line that was parsed         maxquest     - the number of the last bubble line that was parsed
   
        (<number> starts at 1)         (<number> starts at 1)
Line 5097  sub scan_data { Line 5256  sub scan_data {
   
 sub scantron_parse_scanline {  sub scantron_parse_scanline {
     my ($line,$whichline,$scantron_config,$scan_data,$just_header)=@_;      my ($line,$whichline,$scantron_config,$scan_data,$just_header)=@_;
   
     my %record;      my %record;
     my $questions=substr($line,$$scantron_config{'Qstart'}-1);  # Answers      my $questions=substr($line,$$scantron_config{'Qstart'}-1);  # Answers
     my $data=substr($line,0,$$scantron_config{'Qstart'}-1);     # earlier stuff      my $data=substr($line,0,$$scantron_config{'Qstart'}-1);     # earlier stuff
Line 5133  sub scantron_parse_scanline { Line 5293  sub scantron_parse_scanline {
   
     my @alphabet=('A'..'Z');      my @alphabet=('A'..'Z');
     my $questnum=0;      my $questnum=0;
     while ($questions) {      my $ansnum  =1; # Multiple 'answer lines'/question.
   
       chomp($questions); # Get rid of any trailing \n.
       $questions =~ s/\r$//;      # Get rid of trailing \r too (MAC or Win uploads).
       while (length($questions)) {
    my $answers_needed = $bubble_lines_per_response{$questnum};
    my $answer_length  = $$scantron_config{'Qlength'} * $answers_needed;
   
   
   
  $questnum++;   $questnum++;
  my $currentquest=substr($questions,0,$$scantron_config{'Qlength'});   my $currentquest = substr($questions,0,$answer_length);
  substr($questions,0,$$scantron_config{'Qlength'})='';   $questions       = substr($questions,0,$answer_length)='';
  if (length($currentquest) < $$scantron_config{'Qlength'}) { next; }   if (length($currentquest) < $answer_length) { next; }
   
    # Qon letter implies for each slot in currentquest we have:
    #    ? or * for doubles a letter in A-Z for a bubble and
           #    about anything else (esp. a value of Qoff for missing
    #    bubbles.
   
   
  if ($$scantron_config{'Qon'} eq 'letter') {   if ($$scantron_config{'Qon'} eq 'letter') {
     if ($currentquest eq '?'  
  || $currentquest eq '*') {      if ($currentquest =~ /\?/
    || $currentquest =~ /\*/
    || (&occurence_count($currentquest, "[A-Z]") > 1)) {
  push(@{$record{'scantron.doubleerror'}},$questnum);   push(@{$record{'scantron.doubleerror'}},$questnum);
  $record{"scantron.$questnum.answer"}='';   for (my $ans = 0; $ans < $answers_needed; $ans++) { 
       my $bubble = substr($currentquest, $ans, 1);
       if ($bubble =~ /[A-Z]/ ) {
    $record{"scantron.$ansnum.answer"} = $bubble;
       } else {
    $record{"scantron.$ansnum.answer"}='';
       }
       $ansnum++;
    }
   
     } elsif (!defined($currentquest)      } elsif (!defined($currentquest)
      || $currentquest eq $$scantron_config{'Qoff'}       || (&occurence_count($currentquest, $$scantron_config{'Qoff'}) == length($currentquest))
      || $currentquest !~ /^[A-Z]$/) {       || (&occurence_count($currentquest, "[A-Z]") == 0)) {
  $record{"scantron.$questnum.answer"}='';   for (my $ans = 0; $ans < $answers_needed; $ans++ ) {
       $record{"scantron.$ansnum.answer"}='';
       $ansnum++;
   
    }
  if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) {   if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) {
     push(@{$record{"scantron.missingerror"}},$questnum);      push(@{$record{"scantron.missingerror"}},$questnum);
      #  $ansnum += $answers_needed;
  }   }
     } else {      } else {
  $record{"scantron.$questnum.answer"}=$currentquest;   for (my $ans = 0; $ans < $answers_needed; $ans++) {
       $record{"scantron.$ansnum.answer"} = substr($currentquest, $ans, 1);
       $ansnum++;
    }
     }      }
   
    # Qon 'number' implies each slot gives a digit that indexes the
    #    the bubbles filled or Qoff or a non number for unbubbled lines.
           #    and *? for double bubbles on a line.
    #    these answers are also stored as letters.
   
  } elsif ($$scantron_config{'Qon'} eq 'number') {   } elsif ($$scantron_config{'Qon'} eq 'number') {
     if ($currentquest eq '?'      if ($currentquest =~ /\?/
  || $currentquest eq '*') {   || $currentquest =~ /\*/
    || (&occurence_count($currentquest, '\d') > 1)) {
  push(@{$record{'scantron.doubleerror'}},$questnum);   push(@{$record{'scantron.doubleerror'}},$questnum);
  $record{"scantron.$questnum.answer"}='';   for (my $ans = 0; $ans < $answers_needed; $ans++) {
       my $bubble = substr($currentquest, $ans, 1);
       if ($bubble =~ /\d/) {
    $record{"scantron.$ansnum.answer"} = $alphabet[$bubble];
       } else {
    $record{"scantron.$ansnum.answer"}=' ';
       }
       $ansnum++;
    }
   
     } elsif (!defined($currentquest)      } elsif (!defined($currentquest)
      || $currentquest eq $$scantron_config{'Qoff'}        || (&occurence_count($currentquest,$$scantron_config{'Qoff'}) == length($currentquest)) 
      || $currentquest !~ /^\d$/) {       || (&occurence_count($currentquest, '\d') == 0)) {
  $record{"scantron.$questnum.answer"}='';   for (my $ans = 0; $ans < $answers_needed; $ans++ ) {
       $record{"scantron.$ansnum.answer"}='';
       $ansnum++;
   
    }
  if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) {   if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) {
     push(@{$record{"scantron.missingerror"}},$questnum);      push(@{$record{"scantron.missingerror"}},$questnum);
       $ansnum += $answers_needed;
  }   }
   
     } else {      } else {
  # wrap zero back to J   $currentquest = &digits_to_letters($currentquest);
  if ($currentquest eq '0') {   for (my $ans =0; $ans < $answers_needed; $ans++) {
     $record{"scantron.$questnum.answer"}=      $record{"scantron.$ansnum.answer"} = substr($currentquest, $ans, 1);
  $alphabet[9];      $ansnum++;
  } else {  
     $record{"scantron.$questnum.answer"}=  
  $alphabet[$currentquest-1];  
  }   }
     }      }
  } else {   } else {
   
       # Otherwise there's a positional notation;
       # each bubble line requires Qlength items, and there are filled in
       # bubbles for each case where there 'Qon' characters.
       #
   
     my @array=split($$scantron_config{'Qon'},$currentquest,-1);      my @array=split($$scantron_config{'Qon'},$currentquest,-1);
     if (length($array[0]) eq $$scantron_config{'Qlength'}) {  
  $record{"scantron.$questnum.answer"}='';      # If the split only  giveas us one element.. the full length of the
       # answser string, no bubbles are filled in:
   
       if (length($array[0]) eq $$scantron_config{'Qlength'}*$answers_needed) {
    for (my $ans = 0; $ans < $answers_needed; $ans++ ) {
       $record{"scantron.$ansnum.answer"}='';
       $ansnum++;
   
    }
  if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) {   if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) {
     push(@{$record{"scantron.missingerror"}},$questnum);      push(@{$record{"scantron.missingerror"}},$questnum);
  }   }
     } else {      } elsif (scalar(@array) lt 2) {
  $record{"scantron.$questnum.answer"}=  
     $alphabet[length($array[0])];   my $location      = length($array[0]);
    my $line_num      = $location / $$scantron_config{'Qlength'};
    my $bubble        = $alphabet[$location % $$scantron_config{'Qlength'}];
   
    for (my $ans = 0; $ans < $answers_needed; $ans++) {
       if ($ans eq $line_num) {
    $record{"scantron.$ansnum.answer"} = $bubble;
       } else {
    $record{"scantron.$ansnum.answer"} = ' ';
       }
       $ansnum++;
    }
     }      }
     if (scalar(@array) gt 2) {      #  If there's more than one instance of a bubble character
       #  That's a double bubble; with positional notation we can
       #  record all the bubbles filled in as well as the 
       #  fact this response consists of multiple bubbles.
       #
       else {
  push(@{$record{'scantron.doubleerror'}},$questnum);   push(@{$record{'scantron.doubleerror'}},$questnum);
   
    my $first_answer = $ansnum;
    for (my $ans =0; $ans < $answers_needed; $ans++) {
       my $item = $first_answer+$ans;
       $record{"scantron.$item.answer"} = '';
    }
   
  my @ans=@array;   my @ans=@array;
  my $i=length($ans[0]);shift(@ans);   my $i=0;
    my $increment = 0;
  while ($#ans) {   while ($#ans) {
     $i+=length($ans[0])+1;      $i+=length($ans[0]) + $increment;
     $record{"scantron.$questnum.answer"}.=$alphabet[$i];      my $line   = int($i/$$scantron_config{'Qlength'} + $first_answer);
       my $bubble = $i%$$scantron_config{'Qlength'};
       $record{"scantron.$line.answer"}.=$alphabet[$bubble];
     shift(@ans);      shift(@ans);
       $increment = 1;
  }   }
    $ansnum += $answers_needed;
     }      }
  }   }
     }      }
Line 5551  sub scantron_form_start { Line 5807  sub scantron_form_start {
   <input type="hidden" name="scantron_options_ignore" value="$env{'form.scantron_options_ignore'}" />    <input type="hidden" name="scantron_options_ignore" value="$env{'form.scantron_options_ignore'}" />
   <input type="hidden" name="scantron_options_hidden" value="$env{'form.scantron_options_hidden'}" />    <input type="hidden" name="scantron_options_hidden" value="$env{'form.scantron_options_hidden'}" />
 SCANTRONFORM  SCANTRONFORM
   
     my $line = 0;
       while (defined($env{"form.scantron.bubblelines.$line"})) {
          my $chunk =
      '<input type="hidden" name="scantron.bubblelines.'.$line.'" value="'.$env{"form.scantron.bubblelines.$line"}.'" />'."\n";
          $chunk .=
      '<input type="hidden" name="scantron.first_bubble_line.'.$line.'" value="'.$env{"form.scantron.first_bubble_line.$line"}.'" />'."\n";
          $result .= $chunk;
          $line++;
      }
     return $result;      return $result;
 }  }
   
Line 5609  sub scantron_validate_file { Line 5875  sub scantron_validate_file {
     }      }
     my $currentphase=$env{'form.validatepass'};      my $currentphase=$env{'form.validatepass'};
   
   
     my $stop=0;      my $stop=0;
     while (!$stop && $currentphase < scalar(@validate_phases)) {      while (!$stop && $currentphase < scalar(@validate_phases)) {
  $r->print("<p> Validating ".$validate_phases[$currentphase]."</p>");   $r->print("<p> Validating ".$validate_phases[$currentphase]."</p>");
Line 6032  sub scantron_validate_ID { Line 6299  sub scantron_validate_ID {
     #get scantron line setup      #get scantron line setup
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
       
       &scantron_get_maxbubble(); # parse needs the bubble_lines.. array.
   
     my %found=('ids'=>{},'usernames'=>{});      my %found=('ids'=>{},'usernames'=>{});
     for (my $i=0;$i<=$scanlines->{'count'};$i++) {      for (my $i=0;$i<=$scanlines->{'count'};$i++) {
Line 6117  sub scantron_validate_ID { Line 6386  sub scantron_validate_ID {
 sub scantron_get_correction {  sub scantron_get_correction {
     my ($r,$i,$scan_record,$scan_config,$line,$error,$arg)=@_;      my ($r,$i,$scan_record,$scan_config,$line,$error,$arg)=@_;
   
 #FIXME in the case of a duplicated ID the previous line, probaly need  #FIXME in the case of a duplicated ID the previous line, probably need
 #to show both the current line and the previous one and allow skipping  #to show both the current line and the previous one and allow skipping
 #the previous one or the current one  #the previous one or the current one
   
Line 6216  ENDSCRIPT Line 6485  ENDSCRIPT
  $r->print($message);   $r->print($message);
  $r->print("<p>Please indicate which bubble should be used for grading</p>");   $r->print("<p>Please indicate which bubble should be used for grading</p>");
  foreach my $question (@{$arg}) {   foreach my $question (@{$arg}) {
     my $selected=$$scan_record{"scantron.$question.answer"};      my $selected  = &get_response_bubbles($scan_record, $question);
       my @select_array = split(/:/,$selected);
     &scantron_bubble_selector($r,$scan_config,$question,      &scantron_bubble_selector($r,$scan_config,$question,
       split('',$selected));        @select_array);
  }   }
     } elsif ($error eq 'missingbubble') {      } elsif ($error eq 'missingbubble') {
  $r->print("<p>There have been <b>no</b> bubbles scanned for some question(s)</p>\n");   $r->print("<p>There have been <b>no</b> bubbles scanned for some question(s)</p>\n");
Line 6228  ENDSCRIPT Line 6498  ENDSCRIPT
  $r->print('<input type="hidden" name="scantron_questions" value="'.   $r->print('<input type="hidden" name="scantron_questions" value="'.
   join(',',@{$arg}).'" />');    join(',',@{$arg}).'" />');
  foreach my $question (@{$arg}) {   foreach my $question (@{$arg}) {
     my $selected=$$scan_record{"scantron.$question.answer"};      my $selected = &get_response_bubbles($scan_record, $question);
     &scantron_bubble_selector($r,$scan_config,$question);      my @select_array = split(/:/,$selected); # ought to be an array of empties.
       &scantron_bubble_selector($r,$scan_config,$question, @select_array);
  }   }
     } else {      } else {
  $r->print("\n<ul>");   $r->print("\n<ul>");
Line 6249  ENDSCRIPT Line 6520  ENDSCRIPT
     $r           - Apache request object      $r           - Apache request object
     $scan_config - hash from &get_scantron_config()      $scan_config - hash from &get_scantron_config()
     $quest       - number of the bubble line to make a corrector for      $quest       - number of the bubble line to make a corrector for
     $selected    - array of letters of previously selected bubbles      @lines       - array of answer lines.
     $lines       - if present, number of bubble lines to show  
   
 =cut  =cut
   
 sub scantron_bubble_selector {  sub scantron_bubble_selector {
     my ($r,$scan_config,$quest,@selected, $lines)=@_;      my ($r,$scan_config,$quest,@lines)=@_;
     my $max=$$scan_config{'Qlength'};      my $max=$$scan_config{'Qlength'};
   
   
     my $scmode=$$scan_config{'Qon'};      my $scmode=$$scan_config{'Qon'};
   
       my $bubble_length = scalar(@lines);
   
   
     if ($scmode eq 'number' || $scmode eq 'letter') { $max=10; }           if ($scmode eq 'number' || $scmode eq 'letter') { $max=10; }     
   
       my $response = $quest-1;
       my $lines = $bubble_lines_per_response{$response};
   
     if (!defined($lines)) {  
  $lines = 1;  
     }  
     my $total_lines = $lines*2;      my $total_lines = $lines*2;
     my @alphabet=('A'..'Z');      my @alphabet=('A'..'Z');
     $r->print("<table border='1'><tr><td rowspan='".$total_lines."'>$quest</td>");      $r->print("<table border='1'><tr><td rowspan='".$total_lines."'>$quest</td>");
Line 6273  sub scantron_bubble_selector { Line 6547  sub scantron_bubble_selector {
  if ($l != 0) {   if ($l != 0) {
     $r->print('<tr>');      $r->print('<tr>');
  }   }
    my @selected = split(//,$lines[$l]);
  # FIXME:  This loop probably has to be considerably more clever for  
  #  multiline bubbles: User can multibubble by having bubbles in  
  #  several lines.  User can skip lines legitimately etc. etc.  
   
  for (my $i=0;$i<$max;$i++) {   for (my $i=0;$i<$max;$i++) {
     $r->print("\n".'<td align="center">');      $r->print("\n".'<td align="center">');
     if ($selected[0] eq $alphabet[$i]) {       if ($selected[0] eq $alphabet[$i]) { 
Line 6438  sub scantron_validate_CODE { Line 6708  sub scantron_validate_CODE {
   
     my %allcodes=&get_codes();      my %allcodes=&get_codes();
   
       &scantron_get_maxbubble(); # parse needs the lines per response array.
   
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
     for (my $i=0;$i<=$scanlines->{'count'};$i++) {      for (my $i=0;$i<=$scanlines->{'count'};$i++) {
  my $line=&scantron_get_line($scanlines,$scan_data,$i);   my $line=&scantron_get_line($scanlines,$scan_data,$i);
Line 6490  sub scantron_validate_doublebubble { Line 6762  sub scantron_validate_doublebubble {
     #get scantron line setup      #get scantron line setup
     my %scantron_config=&get_scantron_config($env{'form.scantron_format'});      my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
     my ($scanlines,$scan_data)=&scantron_getfile();      my ($scanlines,$scan_data)=&scantron_getfile();
   
       &scantron_get_maxbubble(); # parse needs the bubble line array.
   
     for (my $i=0;$i<=$scanlines->{'count'};$i++) {      for (my $i=0;$i<=$scanlines->{'count'};$i++) {
  my $line=&scantron_get_line($scanlines,$scan_data,$i);   my $line=&scantron_get_line($scanlines,$scan_data,$i);
  if ($line=~/^[\s\cz]*$/) { next; }   if ($line=~/^[\s\cz]*$/) { next; }
Line 6513  sub scantron_validate_doublebubble { Line 6788  sub scantron_validate_doublebubble {
    resource and then checking &Apache::lonxml::get_problem_counter()     resource and then checking &Apache::lonxml::get_problem_counter()
    for what the current value of the problem counter is.     for what the current value of the problem counter is.
   
    Caches the result to $env{'form.scantron_maxbubble'}     Caches the results to $env{'form.scantron_maxbubble'},
      $env{'form.scantron.bubble_lines.n'} and 
      $env{'form.scantron.first_bubble_line.n'}
      which are the total number of bubble, lines, the number of bubble
      lines for reponse n and number of the first bubble line for response n.
   
 =cut  =cut
   
 sub scantron_get_maxbubble {      sub scantron_get_maxbubble {    
   
     if (defined($env{'form.scantron_maxbubble'}) &&      if (defined($env{'form.scantron_maxbubble'}) &&
  $env{'form.scantron_maxbubble'}) {   $env{'form.scantron_maxbubble'}) {
    &restore_bubble_lines();
  return $env{'form.scantron_maxbubble'};   return $env{'form.scantron_maxbubble'};
     }      }
   
     my $navmap=Apache::lonnavmaps::navmap->new();      my (undef, undef, $sequence) =
     my (undef,undef,$sequence)=  
  &Apache::lonnet::decode_symb($env{'form.selectpage'});   &Apache::lonnet::decode_symb($env{'form.selectpage'});
   
       my $navmap=Apache::lonnavmaps::navmap->new();
     my $map=$navmap->getResourceByUrl($sequence);      my $map=$navmap->getResourceByUrl($sequence);
     my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);      my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
   
Line 6538  sub scantron_get_maxbubble { Line 6817  sub scantron_get_maxbubble {
     my $cid         = $env{'request.course.id'};      my $cid         = $env{'request.course.id'};
     my $total_lines = 0;      my $total_lines = 0;
     %bubble_lines_per_response = ();      %bubble_lines_per_response = ();
       %first_bubble_line         = ();
   
     
       my $response_number = 0;
       my $bubble_line     = 0;
     foreach my $resource (@resources) {      foreach my $resource (@resources) {
  my $symb = $resource->symb();   my $symb = $resource->symb();
    &Apache::lonxml::clear_bubble_lines_for_part();
  my $result=&Apache::lonnet::ssi($resource->src(),   my $result=&Apache::lonnet::ssi($resource->src(),
  ('symb' => $resource->symb()),   ('symb' => $resource->symb()),
  ('grade_target' => 'analyze'),   ('grade_target' => 'analyze'),
Line 6555  sub scantron_get_maxbubble { Line 6839  sub scantron_get_maxbubble {
   
   
  foreach my $part_id (@{$analysis{'parts'}}) {   foreach my $part_id (@{$analysis{'parts'}}) {
     my $bubble_lines = $analysis{"$part_id.bubble_lines"}[0];  
     if (!$bubble_lines) {  
  $bubble_lines = 1;      my $lines = $analysis{"$part_id.bubble_lines"};;
     }  
     $bubble_lines_per_response{"$symb.$part_id"} = $bubble_lines;      # TODO - make this a persistent hash not an array.
     $total_lines = $total_lines + $bubble_lines;  
   
       $first_bubble_line{$response_number}           = $bubble_line;
       $bubble_lines_per_response{$response_number}   = $lines;
       $response_number++;
   
       $bubble_line +=  $lines;
       $total_lines +=  $lines;
  }   }
   
     }      }
     &Apache::lonnet::delenv('scantron\.');      &Apache::lonnet::delenv('scantron\.');
   
       &save_bubble_lines();
     $env{'form.scantron_maxbubble'} =      $env{'form.scantron_maxbubble'} =
  $total_lines;   $total_lines;
     return $env{'form.scantron_maxbubble'};      return $env{'form.scantron_maxbubble'};
Line 6575  sub scantron_get_maxbubble { Line 6868  sub scantron_get_maxbubble {
 =item scantron_validate_missingbubbles  =item scantron_validate_missingbubbles
   
    Validates all scanlines in the selected file to not have any     Validates all scanlines in the selected file to not have any
    bubble lines with missing bubbles that haven't been verified as missing.      answers that don't have bubbles that have not been verified
       to be bubble free.
   
 =cut  =cut
   
Line 6597  sub scantron_validate_missingbubbles { Line 6891  sub scantron_validate_missingbubbles {
  $scan_data);   $scan_data);
  if (!defined($$scan_record{'scantron.missingerror'})) { next; }   if (!defined($$scan_record{'scantron.missingerror'})) { next; }
  my @to_correct;   my @to_correct;
   
    # Probably here's where the error is...
   
  foreach my $missing (@{$$scan_record{'scantron.missingerror'}}) {   foreach my $missing (@{$$scan_record{'scantron.missingerror'}}) {
     if ($missing > $max_bubble) { next; }      if ($missing > $max_bubble) { next; }
     push(@to_correct,$missing);      push(@to_correct,$missing);
Line 6669  SCANTRONFORM Line 6966  SCANTRONFORM
     my $start=&Time::HiRes::time();      my $start=&Time::HiRes::time();
     my $i=-1;      my $i=-1;
     my ($uname,$udom,$started);      my ($uname,$udom,$started);
   
       &scantron_get_maxbubble(); # Need the bubble lines array to parse.
   
     while ($i<$scanlines->{'count'}) {      while ($i<$scanlines->{'count'}) {
   ($uname,$udom)=('','');    ($uname,$udom)=('','');
   $i++;    $i++;
Line 6719  SCANTRONFORM Line 7019  SCANTRONFORM
     }      }
     my $result=&Apache::lonnet::ssi($resource->src(),%form);      my $result=&Apache::lonnet::ssi($resource->src(),%form);
     if ($result ne '') {      if ($result ne '') {
  &Apache::lonnet::logthis("scantron grading error -> $result");  
  &Apache::lonnet::logthis("scantron grading error info name $uname domain $udom course $env{'request.course.id'} url ".$resource->src());  
     }      }
     if (&Apache::loncommon::connection_aborted($r)) { last; }      if (&Apache::loncommon::connection_aborted($r)) { last; }
  }   }
Line 6952  sub grading_menu { Line 7250  sub grading_menu {
     my $probTitle = &Apache::lonnet::gettitle($symb);      my $probTitle = &Apache::lonnet::gettitle($symb);
     my ($table,undef,$hdgrade) = &showResourceInfo($symb,$probTitle);      my ($table,undef,$hdgrade) = &showResourceInfo($symb,$probTitle);
   
     #  
     # Define menu data  
     $env{'form.probTitle'} = &Apache::lonnet::gettitle($symb);  
     my ($table) = &showResourceInfo($symb,$env{'form.probTitle'});  
     $request->print($table);      $request->print($table);
     my %fields = ('symb'=>&Apache::lonenc::check_encrypt($symb),      my %fields = ('symb'=>&Apache::lonenc::check_encrypt($symb),
                   'handgrade'=>$hdgrade,                    'handgrade'=>$hdgrade,
Line 6985  sub grading_menu { Line 7279  sub grading_menu {
     $fields{'command'} = 'scantron_selectphase';      $fields{'command'} = 'scantron_selectphase';
     $url = &Apache::lonhtmlcommon::build_url('grades/',\%fields);      $url = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
     push (@menu, { url => $url,      push (@menu, { url => $url,
                    name => &mt('Grade Scantron Forms'),                     name => &mt('Grade/Manage Scantron Forms'),
                    short_description =>                      short_description => 
             &mt('')});              &mt('')});
     $fields{'command'} = 'verify';      $fields{'command'} = 'verify';
     $url = &Apache::lonhtmlcommon::build_url('grades/',\%fields);      $url = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
     push (@menu, { url => "",      push (@menu, { url => "",
                    jscript => ' onClick="javascript:checkChoice2(document.forms.gradingMenu,\'5\',\'verify\')" ',  
                    name => &mt('Verify Receipt'),                     name => &mt('Verify Receipt'),
                    short_description =>                      short_description => 
             &mt('')});              &mt('')});
     $fields{'command'} = 'manage';  
     $url = &Apache::lonhtmlcommon::build_url('/adm/helper/resettimes.helper',\%fields);  
     push (@menu, { url => $url,  
                    name => &mt('Manage Access Times'),  
                    short_description =>   
             &mt('')});  
     $fields{'command'} = 'view';  
     $url = &Apache::lonhtmlcommon::build_url('/adm/pickcode',\%fields);  
     push (@menu, { url => $url,  
                    name => &mt('View Saved CODEs'),  
                    short_description =>   
             &mt('')});  
   
     #      #
     # Create the menu      # Create the menu
     my $Str;      my $Str;
Line 7016  sub grading_menu { Line 7296  sub grading_menu {
     $Str .= '<input type="hidden" name="command" value="" />'.      $Str .= '<input type="hidden" name="command" value="" />'.
     '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n".      '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n".
  '<input type="hidden" name="handgrade"   value="'.$hdgrade.'" />'."\n".   '<input type="hidden" name="handgrade"   value="'.$hdgrade.'" />'."\n".
  '<input type="hidden" name="probTitle"   value="'.$probTitle.'" ue="" />'."\n".   '<input type="hidden" name="probTitle"   value="'.$probTitle.'" />'."\n".
  '<input type="hidden" name="saveState"   value="" />'."\n".   '<input type="hidden" name="saveState"   value="" />'."\n".
  '<input type="hidden" name="gradingMenu" value="1" />'."\n".   '<input type="hidden" name="gradingMenu" value="1" />'."\n".
  '<input type="hidden" name="showgrading" value="yes" />'."\n";   '<input type="hidden" name="showgrading" value="yes" />'."\n";
Line 7029  sub grading_menu { Line 7309  sub grading_menu {
                 $menudata->{'url'}.'" >'.                  $menudata->{'url'}.'" >'.
                 $menudata->{'name'}."</a></h3>\n";                  $menudata->{'name'}."</a></h3>\n";
         } else {          } else {
             $Str .='    <h3><a '.              $Str .='    <h3><input type="button" value="Verify Receipt" '.
                 $menudata->{'jscript'}.                  $menudata->{'jscript'}.
                 ' href="javascript:checkChoice2(document.forms.gradingMenu,\'5\',\'verify\')" >'.                  ' onClick="javascript:checkChoice(document.forms.gradingMenu,\'5\',\'verify\')" '.
                 $menudata->{'name'}."</a></h3>\n";                  ' /></h3>';
             $Str .= ('&nbsp;'x8).              $Str .= ('&nbsp;'x8).
                     ' receipt: '.&Apache::lonnet::recprefix($env{'request.course.id'}).                      ' receipt: '.&Apache::lonnet::recprefix($env{'request.course.id'}).
                     '-<input type="text" name="receipt" size="4" onChange="javascript:checkReceiptNo(this.form,\'OK\')" />';                      '-<input type="text" name="receipt" size="4" onChange="javascript:checkReceiptNo(this.form,\'OK\')" />';
Line 7040  sub grading_menu { Line 7320  sub grading_menu {
         $Str .= '    '.('&nbsp;'x8).$menudata->{'short_description'}.          $Str .= '    '.('&nbsp;'x8).$menudata->{'short_description'}.
             "\n";              "\n";
     }      }
     $Str .="</dl>\n";  
     $Str .="</form>\n";      $Str .="</form>\n";
     $request->print(<<GRADINGMENUJS);      $request->print(<<GRADINGMENUJS);
 <script type="text/javascript" language="javascript">  <script type="text/javascript" language="javascript">
Line 7053  sub grading_menu { Line 7332  sub grading_menu {
     cmdsave = 'submission';      cmdsave = 'submission';
  }   }
  formname.command.value = cmd;   formname.command.value = cmd;
  formname.saveState.value = "saveCmd="+cmdsave+":saveSec="+pullDownSelection(formname.section)+  
     ":saveSub="+pullDownSelection(formname.submitonly)+":saveStatus="+pullDownSelection(formname.Status);  
  if (val < 5) formname.submit();   if (val < 5) formname.submit();
  if (val == 5) {   if (val == 5) {
     if (!checkReceiptNo(formname,'notOK')) { return false;}      if (!checkReceiptNo(formname,'notOK')) { 
     formname.submit();          return false;
  }      } else {
  if (val < 7) formname.submit();          formname.submit();
     }      }
     function checkChoice2(formname,val,cmdx) {  
  if (val <= 2) {  
     var cmd = radioSelection(formname.radioChoice);  
     var cmdsave = cmd;  
  } else {  
     cmd = cmdx;  
     cmdsave = 'submission';  
  }  
  formname.command.value = cmd;  
  if (val < 5) formname.submit();  
  if (val == 5) {  
     if (!checkReceiptNo(formname,'notOK')) { return false;}  
     formname.submit();  
  }   }
  if (val < 7) formname.submit();  
     }      }
   
     function checkReceiptNo(formname,nospace) {      function checkReceiptNo(formname,nospace) {
Line 7095  sub grading_menu { Line 7358  sub grading_menu {
 </script>  </script>
 GRADINGMENUJS  GRADINGMENUJS
     &commonJSfunctions($request);      &commonJSfunctions($request);
     my $result='<h3>&nbsp;<span class="LC_info">Manual Grading/View Submission</span></h3>';  
     $result.=$table;  
     my (undef,$sections) = &getclasslist('all','0');  
     my $savedState = &savedState();  
     my $saveCmd = ($$savedState{'saveCmd'} eq '' ? 'submission' : $$savedState{'saveCmd'});  
     my $saveSec = ($$savedState{'saveSec'} eq '' ? 'all' : $$savedState{'saveSec'});  
     my $saveSub = ($$savedState{'saveSub'} eq '' ? 'all' : $$savedState{'saveSub'});  
     my $saveStatus = ($$savedState{'saveStatus'} eq '' ? 'Active' : $$savedState{'saveStatus'});  
   
     $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n".  
  '<input type="hidden" name="symb"        value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n".  
  '<input type="hidden" name="handgrade"   value="'.$hdgrade.'" />'."\n".  
  '<input type="hidden" name="probTitle"   value="'.$probTitle.'" ue="" />'."\n".  
  '<input type="hidden" name="saveState"   value="" />'."\n".  
  '<input type="hidden" name="gradingMenu" value="1" />'."\n".  
  '<input type="hidden" name="showgrading" value="yes" />'."\n";  
   
     $result.='<table width="100%" border="0"><tr><td bgcolor=#777777>'."\n".  
  '<table width="100%" border="0"><tr bgcolor="#e6ffff"><td colspan="2">'."\n".  
  '&nbsp;<b>Select a Grading/Viewing Option</b></td></tr>'."\n".  
  '<tr bgcolor="#ffffe6" valign="top"><td>'."\n";  
   
     $result.='<table width="100%" border="0">';  
     $result.='<tr bgcolor="#ffffe6" valign="top">'."\n";  
     $result.='<td><b>'.&mt('Sections').'</b></td>';  
 #    $result.='<td>Groups</td>';  
     $result.='<td><b>'.&mt('Access Status').'</td>'."\n";  
     $result.='</tr>';  
     $result.='<tr bgcolor="#ffffe6" valign="top"><td>'."\n".  
  '&nbsp;<select name="section" multiple="multiple" size="3">'."\n";  
     if (ref($sections)) {  
  foreach (sort (@$sections)) {  
     $result.='<option value="'.$_.'" '.  
  ($saveSec eq $_ ? 'selected="selected"':'').'>'.$_.'</option>'."\n";  
  }  
     }  
     $result.= '<option value="all" '.($saveSec eq 'all' ? 'selected="selected"' : ''). '>all</option></select> &nbsp; ';  
     return $Str;          return $Str;    
 }  }
   
Line 7180  sub submit_options { Line 7406  sub submit_options {
 </script>  </script>
 GRADINGMENUJS  GRADINGMENUJS
     &commonJSfunctions($request);      &commonJSfunctions($request);
     my $result='<h3>&nbsp;<span class="LC_info">Manual Grading/View Submission</span></h3>';  
     my ($table,undef,$hdgrade) = &showResourceInfo($symb,$probTitle);      my ($table,undef,$hdgrade) = &showResourceInfo($symb,$probTitle);
     $result.=$table;      my $result;
     my (undef,$sections) = &getclasslist('all','0');      my (undef,$sections) = &getclasslist('all','0');
     my $savedState = &savedState();      my $savedState = &savedState();
     my $saveCmd = ($$savedState{'saveCmd'} eq '' ? 'submission' : $$savedState{'saveCmd'});      my $saveCmd = ($$savedState{'saveCmd'} eq '' ? 'submission' : $$savedState{'saveCmd'});
Line 7199  GRADINGMENUJS Line 7424  GRADINGMENUJS
  '<input type="hidden" name="gradingMenu" value="1" />'."\n".   '<input type="hidden" name="gradingMenu" value="1" />'."\n".
  '<input type="hidden" name="showgrading" value="yes" />'."\n";   '<input type="hidden" name="showgrading" value="yes" />'."\n";
   
     $result.='<table border="0"><tr><td bgcolor=#777777>'."\n".      $result.='
  '<table width="100%" border="0"><tr bgcolor="#e6ffff"><td>'."\n".      <div class="LC_grade_select_mode">
  '&nbsp;<b>Select a Grading/Viewing Option</b></td></tr>'."\n".        <div class="LC_grade_select_mode_current">
  '<tr bgcolor="#ffffe6" valign="top"><td>'."\n";          <h2>
             '.&mt('Grade Current Resource').'
     $result.='<table width="100%" border="0">';          </h2>
     $result.='<tr bgcolor="#ffffe6" valign="top">'."\n";          <div class="LC_grade_select_mode_body">
     $result.='<td><b>'.&mt('Sections').'</b></td>';            <div class="LC_grades_resource_info">
     $result.='<td><b>'.&mt('Groups').'</b></td>';             '.$table.'
     $result.='<td><b>'.&mt('Access Status').'</td>'."\n";            </div>
     $result.='</tr>';            <div class="LC_grade_select_mode_selector">
     $result.='<tr bgcolor="#ffffe6" valign="top"><td>'."\n".               <div class="LC_grade_select_mode_selector_header">
  '&nbsp;<select name="section" multiple="multiple" size="3">'."\n";                  '.&mt('Sections').'
                </div>
                <div class="LC_grade_select_mode_selector_body">
          <select name="section" multiple="multiple" size="5">'."\n";
     if (ref($sections)) {      if (ref($sections)) {
  foreach (sort (@$sections)) {   foreach my $section (sort (@$sections)) {
     $result.='<option value="'.$_.'" '.      $result.='<option value="'.$section.'" '.
  ($saveSec eq $_ ? 'selected="selected"':'').'>'.$_.'</option>'."\n";   ($saveSec eq $section ? 'selected="selected"':'').'>'.$section.'</option>'."\n";
  }   }
     }      }
     $result.= '<option value="all" '.($saveSec eq 'all' ? 'selected="selected"' : ''). '>all</option></select> &nbsp; ';      $result.= '<option value="all" '.($saveSec eq 'all' ? 'selected="selected"' : ''). '>all</option></select> &nbsp; ';
     $result.= '</td><td>'."\n";      $result.='
     $result.= &Apache::lonstatistics::GroupSelect('group','multiple',3);               </div>
     $result.='</td><td>'."\n";            </div>
     $result.=&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,3,undef,'mult');            <div class="LC_grade_select_mode_selector">
                <div class="LC_grade_select_mode_selector_header">
     $result.='</td></tr>';                  '.&mt('Groups').'
                </div>
     $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="3"><label>'.               <div class="LC_grade_select_mode_selector_body">
  '<input type="radio" name="radioChoice" value="submission" '.                  '.&Apache::lonstatistics::GroupSelect('group','multiple',5).'
  ($saveCmd eq 'submission' ? 'checked="checked"' : '').' /> '.'<b>'.&mt('Current Resource').':</b> '.&mt('For one or more students').               </div>
  '</label> <select name="submitonly">'.            </div>
  '<option value="yes" '.            <div class="LC_grade_select_mode_selector">
  ($saveSub eq 'yes' ? 'selected="selected"' : '').'>'.&mt('with submissions').'</option>'.               <div class="LC_grade_select_mode_selector_header">
  '<option value="queued" '.                  '.&mt('Access Status').'
  ($saveSub eq 'queued' ? 'selected="selected"' : '').'>'.&mt('in grading queue').'</option>'.               </div>
  '<option value="graded" '.               <div class="LC_grade_select_mode_selector_body">
  ($saveSub eq 'graded' ? 'selected="selected"' : '').'>'.&mt('with ungraded submissions').'</option>'.                  '.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,5,undef,'mult').'
  '<option value="incorrect" '.               </div>
  ($saveSub eq 'incorrect' ? 'selected="selected"' : '').'>'.&mt('with incorrect submissions').'</option>'.            </div>
  '<option value="all" '.            <div class="LC_grade_select_mode_selector">
  ($saveSub eq 'all' ? 'selected="selected"' : '').'>'.&mt('with any status').'</option></select></td></tr>'."\n";               <div class="LC_grade_select_mode_selector_header">
                   '.&mt('Submission Status').'
     $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'.               </div>
  '<label><input type="radio" name="radioChoice" value="viewgrades" '.               <div class="LC_grade_select_mode_selector_body">
  ($saveCmd eq 'viewgrades' ? 'checked="checked"' : '').' /> '.                 <select name="submitonly" size="5">
  '<b>Current Resource:</b> For all students in selected section or course</label></td></tr>'."\n";           <option value="yes" '.      ($saveSub eq 'yes'       ? 'selected="selected"' : '').'>'.&mt('with submissions').'</option>
            <option value="queued" '.   ($saveSub eq 'queued'    ? 'selected="selected"' : '').'>'.&mt('in grading queue').'</option>
     $result.='<tr bgcolor="#ffffe6" valign="top"><td colspan="2">'.           <option value="graded" '.   ($saveSub eq 'graded'    ? 'selected="selected"' : '').'>'.&mt('with ungraded submissions').'</option>
  '<label><input type="radio" name="radioChoice" value="pickStudentPage" '.           <option value="incorrect" '.($saveSub eq 'incorrect' ? 'selected="selected"' : '').'>'.&mt('with incorrect submissions').'</option>
  ($saveCmd eq 'pickStudentPage' ? 'checked="checked"' : '').' /> '.                   <option value="all" '.      ($saveSub eq 'all'       ? 'selected="selected"' : '').'>'.&mt('with any status').'</option>
  'The <b>complete</b> set/page/sequence: For one student</label></td></tr>'."\n";                 </select>
                </div>
     $result.='<tr bgcolor="#ffffe6"><td colspan="2"><br />'.            </div>
  '<input type="button" onClick="javascript:checkChoice(this.form,\'2\');" value="Next->" />'.            <div class="LC_grade_select_mode_type_body">
  '</td></tr></table>'."\n";              <div class="LC_grade_select_mode_type">
                 <label>
     $result.='</td>'; #<td valign="top">';                  <input type="radio" name="radioChoice" value="submission" '.
                     ($saveCmd eq 'submission' ? 'checked="checked"' : '').' /> '.
 #    $result.='<table width="100%" border="0">';               &mt('Select individual students to grade and view submissions.').'
 #    $result.='<tr bgcolor="#ffffe6"><td>'.        </label> 
 # '<input type="button" onClick="javascript:checkChoice(this.form,\'3\',\'csvform\');" value="'.&mt('Upload').'" />'.              </div>
 # ' '.&mt('scores from file').' </td></tr>'."\n";              <div class="LC_grade_select_mode_type">
 #        <label>
 #    $result.='<tr bgcolor="#ffffe6"><td>'.                  <input type="radio" name="radioChoice" value="viewgrades" '.
 #        '<input type="button" onClick="javascript:checkChoice(this.form,\'6\',\'processclicker\');" value="'.&mt('Process').'" />'.                    ($saveCmd eq 'viewgrades' ? 'checked="checked"' : '').' /> '.
 #        ' '.&mt('clicker file').' </td></tr>'."\n";                      &mt('Grade all selected students in a grading table.').'
 #                </label>
 #    $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'.              </div>
 # '<input type="button" onClick="javascript:checkChoice(this.form,\'4\',\'scantron_selectphase\');'.              <div class="LC_grade_select_mode_type">
 # '" value="'.&mt('Grade').'" /> scantron forms</td></tr>'."\n";        <input type="button" onClick="javascript:checkChoice(this.form,\'2\');" value="'.&mt('Next-&gt;').'" />
 #              </div>
 #    if ((&Apache::lonnet::allowed('mgr',$env{'request.course.id'})) && ($symb)) {            </div>
 # $result.='<tr bgcolor="#ffffe6"valign="top"><td>'.          </div>
 #    '<input type="button" onClick="javascript:checkChoice(this.form,\'5\',\'verify\');" value="'.&mt('Verify').'" />'.        </div>
 #    ' '.&mt('receipt').': '.        <div class="LC_grade_select_mode_page">
 #    &Apache::lonnet::recprefix($env{'request.course.id'}).          <h2>
 #    '-<input type="text" name="receipt" size="4" onChange="javascript:checkReceiptNo(this.form,\'OK\')" />'.           '.&mt('Grade Complete Folder for One Student').'
 #    '</td></tr>'."\n";          </h2>
 #    }           <div class="LC_grades_select_mode_body">
 #    $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'.            <div class="LC_grade_select_mode_type_body">
 # '<input type="button" onClick="javascript:this.form.action=\'/adm/helper/resettimes.helper\';this.form.submit();'.              <div class="LC_grade_select_mode_type">
 # '" value="'.&mt('Manage').'" /> access times.</td></tr>'."\n";                <label>
 #    $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'.                  <input type="radio" name="radioChoice" value="pickStudentPage" '.
 # '<input type="button" onClick="javascript:this.form.command.value=\'codelist\';this.form.action=\'/adm/pickcode\';this.form.submit();'.    ($saveCmd eq 'pickStudentPage' ? 'checked="checked"' : '').' /> '.
 # '" value="'.&mt('View').'" /> saved CODEs.</td></tr>'."\n";    &mt('The <b>complete</b> page/sequence/folder: For one student').'
 #                </label>
 #    $result.='</table>'."\n".'</td>';              </div>
     $result.= '</tr></table>'."\n".              <div class="LC_grade_select_mode_type">
  '</td></tr></table></form>'."\n";        <input type="button" onClick="javascript:checkChoice(this.form,\'2\');" value="'.&mt('Next-&gt;').'" />
               </div>
             </div>
           </div>
         </div>
       </div>
     </form>';
     return $result;      return $result;
 }  }
   
Line 7461  function sanitycheck() { Line 7695  function sanitycheck() {
 <input type="hidden" name="saveState"  value="$env{'form.saveState'}" />  <input type="hidden" name="saveState"  value="$env{'form.saveState'}" />
 <input type="file" name="upfile" size="50" />  <input type="file" name="upfile" size="50" />
 <br /><label>$type: $selectform</label>  <br /><label>$type: $selectform</label>
 <br /><label>$attendance: <input type="radio" name="gradingmechanism" value="attendance" $checked{'attendance'} onClick="sanitycheck()" /></label>  <br /><label><input type="radio" name="gradingmechanism" value="attendance" $checked{'attendance'} onClick="sanitycheck()" />$attendance </label>
 <br /><label>$personnel: <input type="radio" name="gradingmechanism" value="personnel" $checked{'personnel'} onClick="sanitycheck()" /></label>  <br /><label><input type="radio" name="gradingmechanism" value="personnel" $checked{'personnel'} onClick="sanitycheck()" />$personnel</label>
 <br /><label>$specific: <input type="radio" name="gradingmechanism" value="specific" $checked{'specific'} onClick="sanitycheck()" /></label>  <br /><label><input type="radio" name="gradingmechanism" value="specific" $checked{'specific'} onClick="sanitycheck()" />$specific </label>
 <input type="text" name="specificid" value="$env{'form.specificid'}" size="20" />  <input type="text" name="specificid" value="$env{'form.specificid'}" size="20" />
 <input type="hidden" name="waschecked" value="$env{'form.gradingmechanism'}" />  <input type="hidden" name="waschecked" value="$env{'form.gradingmechanism'}" />
 <br /><label>$pcorrect: <input type="text" name="pcorrect" size="4" value="$env{'form.pcorrect'}" onChange="sanitycheck()" /></label>  <br /><label>$pcorrect: <input type="text" name="pcorrect" size="4" value="$env{'form.pcorrect'}" onChange="sanitycheck()" /></label>
Line 7810  sub handler { Line 8044  sub handler {
     my $symb=&get_symb($request,1);      my $symb=&get_symb($request,1);
     my @commands=&Apache::loncommon::get_env_multiple('form.command');      my @commands=&Apache::loncommon::get_env_multiple('form.command');
     my $command=$commands[0];      my $command=$commands[0];
   
     if ($#commands > 0) {      if ($#commands > 0) {
  &Apache::lonnet::logthis("grades got multiple commands ".join(':',@commands));   &Apache::lonnet::logthis("grades got multiple commands ".join(':',@commands));
     }      }
   
   
     $request->print(&Apache::loncommon::start_page('Grading'));      $request->print(&Apache::loncommon::start_page('Grading'));
     if ($symb eq '' && $command eq '') {      if ($symb eq '' && $command eq '') {
  if ($env{'user.adv'}) {   if ($env{'user.adv'}) {

Removed from v.1.446  
changed lines
  Added in v.1.477


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