Diff for /loncom/homework/grades.pm between versions 1.399.2.1 and 1.415

version 1.399.2.1, 2007/06/13 17:20:12 version 1.415, 2007/06/16 23:00:09
Line 41  use Apache::Constants qw(:common); Line 41  use Apache::Constants qw(:common);
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonenc;  use Apache::lonenc;
 use String::Similarity;  use String::Similarity;
 use lib '/home/httpd/lib/perl';  
 use LONCAPA;  use LONCAPA;
   
 use POSIX qw(floor);  use POSIX qw(floor);
Line 180  sub showResourceInfo { Line 179  sub showResourceInfo {
  if (exists($partsseen{$partID})) {   if (exists($partsseen{$partID})) {
     $result.="<td>&nbsp;</td>";      $result.="<td>&nbsp;</td>";
  } else {   } else {
     $result.="<td><input type='checkbox' name='vPart' value='$partID' checked='on' /></td>";      $result.="<td><input type='checkbox' name='vPart' value='$partID' checked='checked' /></td>";
  }   }
  $partsseen{$partID}=1;   $partsseen{$partID}=1;
     }      }
Line 708  LISTJAVASCRIPT Line 707  LISTJAVASCRIPT
     &commonJSfunctions($request);      &commonJSfunctions($request);
     $request->print($result);      $request->print($result);
   
     my $checkhdgrade = ($env{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1 ) ? 'checked' : '';      my $checkhdgrade = ($env{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1 ) ? 'checked="checked"' : '';
     my $checklastsub = $checkhdgrade eq '' ? 'checked' : '';      my $checklastsub = $checkhdgrade eq '' ? 'checked="checked"' : '';
     my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'.      my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'.
  "\n".$table.   "\n".$table.
  '&nbsp;<b>View Problem Text: </b><label><input type="radio" name="vProb" value="no" checked="on" /> no </label>'."\n".   '&nbsp;<b>View Problem Text: </b><label><input type="radio" name="vProb" value="no" checked="checked" /> no </label>'."\n".
  '<label><input type="radio" name="vProb" value="yes" /> one student </label>'."\n".   '<label><input type="radio" name="vProb" value="yes" /> one student </label>'."\n".
  '<label><input type="radio" name="vProb" value="all" /> all students </label><br />'."\n".   '<label><input type="radio" name="vProb" value="all" /> all students </label><br />'."\n".
  '&nbsp;<b>View Answer: </b><label><input type="radio" name="vAns" value="no"  /> no </label>'."\n".   '&nbsp;<b>View Answer: </b><label><input type="radio" name="vAns" value="no"  /> no </label>'."\n".
  '<label><input type="radio" name="vAns" value="yes" /> one student </label>'."\n".   '<label><input type="radio" name="vAns" value="yes" /> one student </label>'."\n".
  '<label><input type="radio" name="vAns" value="all" checked="on" /> all students </label><br />'."\n".   '<label><input type="radio" name="vAns" value="all" checked="checked" /> all students </label><br />'."\n".
  '&nbsp;<b>Submissions: </b>'."\n";   '&nbsp;<b>Submissions: </b>'."\n";
     if ($env{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1) {      if ($env{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1) {
  $gradeTable.='<label><input type="radio" name="lastSub" value="hdgrade" '.$checkhdgrade.' /> essay part only </label>'."\n";   $gradeTable.='<label><input type="radio" name="lastSub" value="hdgrade" '.$checkhdgrade.' /> essay part only </label>'."\n";
Line 763  LISTJAVASCRIPT Line 762  LISTJAVASCRIPT
  'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n".   'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n".
  'value="Next->" /> <br />'."\n";   'value="Next->" /> <br />'."\n";
     $gradeTable.=&check_buttons();      $gradeTable.=&check_buttons();
     $gradeTable.='<label><input type="checkbox" name="checkPlag" checked="on" />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');
     $gradeTable.='<table border="0"><tr><td bgcolor="#777777">'.      $gradeTable.='<table border="0"><tr><td bgcolor="#777777">'.
  '<table border="0"><tr bgcolor="#e6ffff">';   '<table border="0"><tr bgcolor="#e6ffff">';
Line 1501  sub gradeBox { Line 1500  sub gradeBox {
  $result.= '<td><span style="white-space: nowrap;"><label><input type="radio" name="RADVAL'.$counter.'_'.$partid.'" '.   $result.= '<td><span style="white-space: nowrap;"><label><input type="radio" name="RADVAL'.$counter.'_'.$partid.'" '.
     'onclick="javascript:writeBox(this.form,\''.$counter.'_'.$partid.'\','.      'onclick="javascript:writeBox(this.form,\''.$counter.'_'.$partid.'\','.
     $thisweight.')" value="'.$thisweight.'" '.      $thisweight.')" value="'.$thisweight.'" '.
     ($score eq $thisweight ? 'checked':'').' /> '.$thisweight."</label></span></td>\n";      ($score eq $thisweight ? 'checked="checked"':'').' /> '.$thisweight."</label></span></td>\n";
  $result.=(($ctr+1)%10 == 0 ? '</tr><tr>' : '');   $result.=(($ctr+1)%10 == 0 ? '</tr><tr>' : '');
         $thisweight += $increment;          $thisweight += $increment;
  $ctr++;   $ctr++;
Line 1519  sub gradeBox { Line 1518  sub gradeBox {
  'onChange="javascript:clearRadBox(this.form,\''.$counter.'_'.$partid.'\')" >'."\n";   'onChange="javascript:clearRadBox(this.form,\''.$counter.'_'.$partid.'\')" >'."\n";
     if ($$record{'resource.'.$partid.'.solved'} eq 'excused') {      if ($$record{'resource.'.$partid.'.solved'} eq 'excused') {
  $result.='<option></option>'.   $result.='<option></option>'.
     '<option selected="on">excused</option>';      '<option selected="selected">excused</option>';
     } else {      } else {
  $result.='<option selected="on"></option>'.   $result.='<option selected="selected"></option>'.
     '<option>excused</option>';      '<option>excused</option>';
     }      }
     $result.='<option>reset status</option></select>'."\n";      $result.='<option>reset status</option></select>'."\n";
Line 2082  KEYWORDS Line 2081  KEYWORDS
     '<option>3</option><option>5</option>'.      '<option>3</option><option>5</option>'.
     '<option>7</option><option>10</option></select>'."\n";      '<option>7</option><option>10</option></select>'."\n";
  my $nsel = ($env{'form.NTSTU'} ne '' ? $env{'form.NTSTU'} : '1');   my $nsel = ($env{'form.NTSTU'} ne '' ? $env{'form.NTSTU'} : '1');
  $ntstu =~ s/<option>$nsel</<option selected="on">$nsel</;   $ntstu =~ s/<option>$nsel</<option selected="selected">$nsel</;
  $endform.=$ntstu.'student(s) &nbsp;&nbsp;';   $endform.=$ntstu.'student(s) &nbsp;&nbsp;';
  $endform.='<input type="button" value="Previous" '.   $endform.='<input type="button" value="Previous" '.
     'onClick="javascript:checksubmit(this.form,\'Previous\');" TARGET=_self> &nbsp;'."\n".      'onClick="javascript:checksubmit(this.form,\'Previous\');" TARGET=_self> &nbsp;'."\n".
Line 2565  sub handback_files { Line 2564  sub handback_files {
                                            $newflg.'_'.$part_resp.'_returndoc'.$file_counter,                                             $newflg.'_'.$part_resp.'_returndoc'.$file_counter,
                                            $save_file_name);                                             $save_file_name);
                     if ($result !~ m|^/uploaded/|) {                      if ($result !~ m|^/uploaded/|) {
                         $request->print('<span class="LC_error">An errror occured ('.$result.                          $request->print('<span class="LC_error">An error occurred ('.$result.
                         ') while trying to upload '.$newflg.'_'.$part_resp.'_returndoc'.$file_counter.'</span><br />');                          ') while trying to upload '.$newflg.'_'.$part_resp.'_returndoc'.$file_counter.'</span><br />');
                     } else {                      } else {
                         # mark the file as read only                          # mark the file as read only
Line 3028  sub viewgrades { Line 3027  sub viewgrades {
  $result.= '</td><td><select name="SELVAL_'.$partid.'"'.   $result.= '</td><td><select name="SELVAL_'.$partid.'"'.
     'onChange="javascript:writeRadText(\''.$partid.'\','.      'onChange="javascript:writeRadText(\''.$partid.'\','.
  $weight{$partid}.')"> '.   $weight{$partid}.')"> '.
     '<option selected="on"> </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></tr>'."\n";
Line 3146  sub viewstudentgrade { Line 3145  sub viewstudentgrade {
     $result.='&nbsp;<select name="'.      $result.='&nbsp;<select name="'.
  'GD_'.$student.'_'.$part.'_solved" '.   'GD_'.$student.'_'.$part.'_solved" '.
  'onChange="javascript:changeOneScore(\''.$part.'\',\''.$student.'\')" >'."\n";   'onChange="javascript:changeOneScore(\''.$part.'\',\''.$student.'\')" >'."\n";
     $result.= (($status eq 'excused') ? '<option> </option><option selected="on">excused</option>'       $result.= (($status eq 'excused') ? '<option> </option><option selected="selected">excused</option>' 
  : '<option selected="on"> </option><option>excused</option>')."\n";   : '<option selected="selected"> </option><option>excused</option>')."\n";
     $result.='<option>reset status</option>';      $result.='<option>reset status</option>';
     $result.="</select>&nbsp;</td>\n";      $result.="</select>&nbsp;</td>\n";
  } else {   } else {
Line 3848  LISTJAVASCRIPT Line 3847  LISTJAVASCRIPT
     foreach (@$titles) {      foreach (@$titles) {
  my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);   my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
  $result.='<option value="'.$ctr.'" '.   $result.='<option value="'.$ctr.'" '.
     ($$symbx{$_} =~ /$curpage$/ ? 'selected="on"' : '').      ($$symbx{$_} =~ /$curpage$/ ? 'selected="selected"' : '').
     '>'.$showtitle.'</option>'."\n";      '>'.$showtitle.'</option>'."\n";
  $ctr++;   $ctr++;
     }      }
Line 3863  LISTJAVASCRIPT Line 3862  LISTJAVASCRIPT
     $result.='<input type="hidden" name="page" />'."\n".      $result.='<input type="hidden" name="page" />'."\n".
  '<input type="hidden" name="title" />'."\n";   '<input type="hidden" name="title" />'."\n";
   
     $result.='&nbsp;<b>View Problems Text: </b><label><input type="radio" name="vProb" value="no" checked="on" /> no </label>'."\n".      $result.='&nbsp;<b>View Problems Text: </b><label><input type="radio" name="vProb" value="no" checked="checked" /> no </label>'."\n".
  '<label><input type="radio" name="vProb" value="yes" /> yes </label>'."<br />\n";   '<label><input type="radio" name="vProb" value="yes" /> yes </label>'."<br />\n";
   
     $result.='&nbsp;<b>Submission Details: </b>'.      $result.='&nbsp;<b>Submission Details: </b>'.
  '<label><input type="radio" name="lastSub" value="none" /> none</label>'."\n".   '<label><input type="radio" name="lastSub" value="none" /> none</label>'."\n".
  '<label><input type="radio" name="lastSub" value="datesub" checked /> by dates and submissions</label>'."\n".   '<label><input type="radio" name="lastSub" value="datesub" checked="checked" /> by dates and submissions</label>'."\n".
  '<label><input type="radio" name="lastSub" value="all" /> all details</label>'."\n";   '<label><input type="radio" name="lastSub" value="all" /> all details</label>'."\n";
   
     $result.='<input type="hidden" name="section"     value="'.$getsec.'" />'."\n".      $result.='<input type="hidden" name="section"     value="'.$getsec.'" />'."\n".
Line 4384  sub getSequenceDropDown { Line 4383  sub getSequenceDropDown {
     foreach (@$titles) {      foreach (@$titles) {
  my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);   my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
  $result.='<option value="'.$$symbx{$_}.'" '.   $result.='<option value="'.$$symbx{$_}.'" '.
     ($$symbx{$_} =~ /$curpage$/ ? 'selected="on"' : '').      ($$symbx{$_} =~ /$curpage$/ ? 'selected="selected"' : '').
     '>'.$showtitle.'</option>'."\n";      '>'.$showtitle.'</option>'."\n";
  $ctr++;   $ctr++;
     }      }
Line 4412  sub scantron_uploads { Line 4411  sub scantron_uploads {
     my $result= '<select name="scantron_selectfile">';      my $result= '<select name="scantron_selectfile">';
     $result.="<option></option>";      $result.="<option></option>";
     foreach my $filename (sort(&scantron_filenames())) {      foreach my $filename (sort(&scantron_filenames())) {
  $result.="<option".($filename eq $file2grade ? ' selected="on"':'').">$filename</option>\n";   $result.="<option".($filename eq $file2grade ? ' selected="selected"':'').">$filename</option>\n";
     }      }
     $result.="</select>";      $result.="</select>";
     return $result;      return $result;
Line 4963  sub remember_current_skipped { Line 4962  sub remember_current_skipped {
 sub check_for_error {  sub check_for_error {
     my ($r,$result)=@_;      my ($r,$result)=@_;
     if ($result ne 'ok' && $result ne 'not_found' ) {      if ($result ne 'ok' && $result ne 'not_found' ) {
  $r->print("An error occured ($result) when trying to Remove the existing corrections.");   $r->print("An error occurred ($result) when trying to Remove the existing corrections.");
     }      }
 }  }
   
Line 5425  sub scantron_get_correction { Line 5424  sub scantron_get_correction {
     if ($closest > 0) {      if ($closest > 0) {
  foreach my $testcode (@{$closest}) {   foreach my $testcode (@{$closest}) {
     my $checked='';      my $checked='';
     if (!$i) { $checked=' checked="on" '; }      if (!$i) { $checked=' checked="checked" '; }
     $r->print("<label><input type='radio' name='scantron_CODE_resolution' value='use_closest_$i' $checked /> Use the similar CODE <b><tt>".$testcode."</tt></b> instead.</label><input type='hidden' name='scantron_CODE_closest_$i' value='$testcode' />");      $r->print("<label><input type='radio' name='scantron_CODE_resolution' value='use_closest_$i' $checked /> Use the similar CODE <b><tt>".$testcode."</tt></b> instead.</label><input type='hidden' name='scantron_CODE_closest_$i' value='$testcode' />");
     $r->print("\n<br />");      $r->print("\n<br />");
     $i++;      $i++;
Line 5433  sub scantron_get_correction { Line 5432  sub scantron_get_correction {
     }      }
  }   }
  if ($$scan_record{'scantron.CODE'}=~/\S/ ) {   if ($$scan_record{'scantron.CODE'}=~/\S/ ) {
     my $checked; if (!$i) { $checked=' checked="on" '; }      my $checked; if (!$i) { $checked=' checked="checked" '; }
     $r->print("<label><input type='radio' name='scantron_CODE_resolution' value='use_unfound' $checked /> Use the CODE <b><tt>".$$scan_record{'scantron.CODE'}."</tt></b> that is was on the paper, ignoring the error.</label>");      $r->print("<label><input type='radio' name='scantron_CODE_resolution' value='use_unfound' $checked /> Use the CODE <b><tt>".$$scan_record{'scantron.CODE'}."</tt></b> that is was on the paper, ignoring the error.</label>");
     $r->print("\n<br />");      $r->print("\n<br />");
  }   }
Line 6033  GRADINGMENUJS Line 6032  GRADINGMENUJS
     if (ref($sections)) {      if (ref($sections)) {
  foreach (sort (@$sections)) {   foreach (sort (@$sections)) {
     $result.='<option value="'.$_.'" '.      $result.='<option value="'.$_.'" '.
  ($saveSec eq $_ ? 'selected="on"':'').'>'.$_.'</option>'."\n";   ($saveSec eq $_ ? 'selected="selected"':'').'>'.$_.'</option>'."\n";
  }   }
     }      }
     $result.= '<option value="all" '.($saveSec eq 'all' ? 'selected="on"' : ''). '>all</option></select> &nbsp; ';      $result.= '<option value="all" '.($saveSec eq 'all' ? 'selected="selected"' : ''). '>all</option></select> &nbsp; ';
   
     $result.=&mt('Student Status').':</b>'.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,undef);      $result.=&mt('Student Status').':'.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,undef);
   
     $result.='</td></tr>';      $result.='</td></tr>';
   
     $result.='<tr bgcolor="#ffffe6"valign="top"><td><label>'.      $result.='<tr bgcolor="#ffffe6"valign="top"><td><label>'.
  '<input type="radio" name="radioChoice" value="submission" '.   '<input type="radio" name="radioChoice" value="submission" '.
  ($saveCmd eq 'submission' ? 'checked' : '').' /> '.'<b>'.&mt('Current Resource').':</b> '.&mt('For one or more students').   ($saveCmd eq 'submission' ? 'checked="checked"' : '').' /> '.'<b>'.&mt('Current Resource').':</b> '.&mt('For one or more students').
  '</label> <select name="submitonly">'.   '</label> <select name="submitonly">'.
  '<option value="yes" '.   '<option value="yes" '.
  ($saveSub eq 'yes' ? 'selected="on"' : '').' />'.&mt('with submissions').'</option>'.   ($saveSub eq 'yes' ? 'selected="selected"' : '').'>'.&mt('with submissions').'</option>'.
  '<option value="queued" '.   '<option value="queued" '.
  ($saveSub eq 'queued' ? 'selected="on"' : '').' />'.&mt('in grading queue').'</option>'.   ($saveSub eq 'queued' ? 'selected="selected"' : '').'>'.&mt('in grading queue').'</option>'.
  '<option value="graded" '.   '<option value="graded" '.
  ($saveSub eq 'graded' ? 'selected="on"' : '').' />'.&mt('with ungraded submissions').'</option>'.   ($saveSub eq 'graded' ? 'selected="selected"' : '').'>'.&mt('with ungraded submissions').'</option>'.
  '<option value="incorrect" '.   '<option value="incorrect" '.
  ($saveSub eq 'incorrect' ? 'selected="on"' : '').' />'.&mt('with incorrect submissions').'</option>'.   ($saveSub eq 'incorrect' ? 'selected="selected"' : '').'>'.&mt('with incorrect submissions').'</option>'.
  '<option value="all" '.   '<option value="all" '.
  ($saveSub eq 'all' ? 'selected="on"' : '').' />'.&mt('with any status').'</option></select></td></tr>'."\n";   ($saveSub eq 'all' ? 'selected="selected"' : '').'>'.&mt('with any status').'</option></select></td></tr>'."\n";
   
     $result.='<tr bgcolor="#ffffe6"valign="top"><td>'.      $result.='<tr bgcolor="#ffffe6"valign="top"><td>'.
  '<label><input type="radio" name="radioChoice" value="viewgrades" '.   '<label><input type="radio" name="radioChoice" value="viewgrades" '.
  ($saveCmd eq 'viewgrades' ? 'checked' : '').' /> '.   ($saveCmd eq 'viewgrades' ? 'checked="checked"' : '').' /> '.
  '<b>Current Resource:</b> For all students in selected section or course</label></td></tr>'."\n";   '<b>Current Resource:</b> For all students in selected section or course</label></td></tr>'."\n";
   
     $result.='<tr bgcolor="#ffffe6" valign="top"><td>'.      $result.='<tr bgcolor="#ffffe6" valign="top"><td>'.
  '<label><input type="radio" name="radioChoice" value="pickStudentPage" '.   '<label><input type="radio" name="radioChoice" value="pickStudentPage" '.
  ($saveCmd eq 'pickStudentPage' ? 'checked' : '').' /> '.   ($saveCmd eq 'pickStudentPage' ? 'checked="checked"' : '').' /> '.
  'The <b>complete</b> set/page/sequence: For one student</label></td></tr>'."\n";   'The <b>complete</b> set/page/sequence: For one student</label></td></tr>'."\n";
   
     $result.='<tr bgcolor="#ffffe6"><td><br />'.      $result.='<tr bgcolor="#ffffe6"><td><br />'.
Line 6078  GRADINGMENUJS Line 6077  GRADINGMENUJS
  '<input type="button" onClick="javascript:checkChoice(this.form,\'3\',\'csvform\');" value="'.&mt('Upload').'" />'.   '<input type="button" onClick="javascript:checkChoice(this.form,\'3\',\'csvform\');" value="'.&mt('Upload').'" />'.
  ' '.&mt('scores from file').' </td></tr>'."\n";   ' '.&mt('scores from file').' </td></tr>'."\n";
   
       $result.='<tr bgcolor="#ffffe6"><td>'.
           '<input type="button" onClick="javascript:checkChoice(this.form,\'6\',\'processclicker\');" value="'.&mt('Process').'" />'.
           ' '.&mt('clicker file').' </td></tr>'."\n";
   
     $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'.      $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'.
  '<input type="button" onClick="javascript:checkChoice(this.form,\'4\',\'scantron_selectphase\');'.   '<input type="button" onClick="javascript:checkChoice(this.form,\'4\',\'scantron_selectphase\');'.
  '" value="'.&mt('Grade').'" /> scantron forms</td></tr>'."\n";   '" value="'.&mt('Grade').'" /> scantron forms</td></tr>'."\n";
Line 6097  GRADINGMENUJS Line 6100  GRADINGMENUJS
  '<input type="button" onClick="javascript:this.form.command.value=\'codelist\';this.form.action=\'/adm/pickcode\';this.form.submit();'.   '<input type="button" onClick="javascript:this.form.command.value=\'codelist\';this.form.action=\'/adm/pickcode\';this.form.submit();'.
  '" value="'.&mt('View').'" /> saved CODEs.</td></tr>'."\n";   '" value="'.&mt('View').'" /> saved CODEs.</td></tr>'."\n";
   
     $result.='</form></td></tr></table>'."\n".      $result.='</table>'."\n".
  '</td></tr></table>'."\n".   '</td></tr></table>'."\n".
  '</td></tr></table>'."\n";   '</td></tr></table></form>'."\n";
     return $result;      return $result;
 }  }
   
Line 6125  sub init_perm { Line 6128  sub init_perm {
     }      }
 }  }
   
   sub gather_clicker_ids {
       my %clicker_ids;
   
       my $classlist = &Apache::loncoursedata::get_classlist();
   
       # Set up a couple variables.
       my $username_idx = &Apache::loncoursedata::CL_SNAME();
       my $domain_idx   = &Apache::loncoursedata::CL_SDOM();
   
       foreach my $student (keys(%$classlist)) {
   
           my $username = $classlist->{$student}->[$username_idx];
           my $domain   = $classlist->{$student}->[$domain_idx];
           my $clickers =
       (&Apache::lonnet::userenvironment($domain,$username,'clickers'))[1];
           foreach my $id (split(/\,/,$clickers)) {
               $id=~s/^[\#0]+//;
               if (exists($clicker_ids{$id})) {
    $clicker_ids{$id}.=','.$username.':'.$domain;
               } else {
    $clicker_ids{$id}=$username.':'.$domain;
               }
           }
       }
       return %clicker_ids;
   }
   
   sub gather_adv_clicker_ids {
       my %clicker_ids;
       my $cnum=$env{'course.'.$env{'request.course.id'}.'.num'};
       my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
       my %coursepersonnel=&Apache::lonnet::get_course_adv_roles($cdom.'/'.$cnum);
       foreach my $element (sort(keys(%coursepersonnel))) {
           foreach my $person (split(/\,/,$coursepersonnel{$element})) {
               my ($puname,$pudom)=split(/\:/,$person);
               my $clickers =
    (&Apache::lonnet::userenvironment($pudom,$puname,'clickers'))[1];
               foreach my $id (split(/\,/,$clickers)) {
    $id=~s/^[\#0]+//;
    if (exists($clicker_ids{$id})) {
       $clicker_ids{$id}.=','.$puname.':'.$pudom;
    } else {
       $clicker_ids{$id}=$puname.':'.$pudom;
    }
               }
           }
       }
       return %clicker_ids;
   }
   
   sub clicker_grading_parameters {
       return ('gradingmechanism' => 'scalar',
               'upfiletype' => 'scalar',
               'specificid' => 'scalar',
               'pcorrect' => 'scalar',
               'pincorrect' => 'scalar');
   }
   
   sub process_clicker {
       my ($r)=@_;
       my ($symb)=&get_symb($r);
       if (!$symb) {return '';}
       my $result=&checkforfile_js();
       $env{'form.probTitle'} = &Apache::lonnet::gettitle($symb);
       my ($table) = &showResourceInfo($symb,$env{'form.probTitle'});
       $result.=$table;
       $result.='<br /><table width="100%" border="0"><tr><td bgcolor="#777777">'."\n";
       $result.='<table width="100%" border="0"><tr bgcolor="#e6ffff"><td>'."\n";
       $result.='&nbsp;<b>'.&mt('Specify a file containing the clicker information for this resource').
           '.</b></td></tr>'."\n";
       $result.='<tr bgcolor=#ffffe6><td>'."\n";
   # Attempt to restore parameters from last session, set defaults if not present
       my %Saveable_Parameters=&clicker_grading_parameters();
       &Apache::loncommon::restore_course_settings('grades_clicker',
                                                    \%Saveable_Parameters);
       if (!$env{'form.pcorrect'}) { $env{'form.pcorrect'}=100; }
       if (!$env{'form.pincorrect'}) { $env{'form.pincorrect'}=100; }
       if (!$env{'form.gradingmechanism'}) { $env{'form.gradingmechanism'}='attendance'; }
       if (!$env{'form.upfiletype'}) { $env{'form.upfiletype'}='iclicker'; }
   
       my %checked;
       foreach my $gradingmechanism ('attendance','personnel','specific') {
          if ($env{'form.gradingmechanism'} eq $gradingmechanism) {
             $checked{$gradingmechanism}="checked='checked'";
          }
       }
   
       my $upload=&mt("Upload File");
       my $type=&mt("Type");
       my $attendance=&mt("Award points just for participation");
       my $personnel=&mt("Correctness determined from response by course personnel");
       my $specific=&mt("Correctness determined from response with clicker ID(s)"); 
       my $pcorrect=&mt("Percentage points for correct solution");
       my $pincorrect=&mt("Percentage points for incorrect solution");
       my $selectform=&Apache::loncommon::select_form($env{'form.upfiletype'},'upfiletype',
      ('iclicker' => 'i>clicker'));
   
       $result.=<<ENDUPFORM;
   <script type="text/javascript">
   function sanitycheck() {
   // Accept only integer percentages
      document.forms.gradesupload.pcorrect.value=Math.round(document.forms.gradesupload.pcorrect.value);
      document.forms.gradesupload.pincorrect.value=Math.round(document.forms.gradesupload.pincorrect.value);
   // Find out grading choice
      for (i=0; i<document.forms.gradesupload.gradingmechanism.length; i++) {
         if (document.forms.gradesupload.gradingmechanism[i].checked) {
            gradingchoice=document.forms.gradesupload.gradingmechanism[i].value;
         }
      }
   // By default, new choice equals user selection
      newgradingchoice=gradingchoice;
   // Not good to give more points for false answers than correct ones
      if (Math.round(document.forms.gradesupload.pcorrect.value)<Math.round(document.forms.gradesupload.pincorrect.value)) {
         document.forms.gradesupload.pcorrect.value=document.forms.gradesupload.pincorrect.value;
      }
   // If new choice is attendance only, and old choice was correctness-based, restore defaults
      if ((gradingchoice=='attendance') && (document.forms.gradesupload.waschecked.value!='attendance')) {
         document.forms.gradesupload.pcorrect.value=100;
         document.forms.gradesupload.pincorrect.value=100;
      }
   // If the values are different, cannot be attendance only
      if ((Math.round(document.forms.gradesupload.pcorrect.value)!=Math.round(document.forms.gradesupload.pincorrect.value)) &&
          (gradingchoice=='attendance')) {
          newgradingchoice='personnel';
      }
   // Change grading choice to new one
      for (i=0; i<document.forms.gradesupload.gradingmechanism.length; i++) {
         if (document.forms.gradesupload.gradingmechanism[i].value==newgradingchoice) {
            document.forms.gradesupload.gradingmechanism[i].checked=true;
         } else {
            document.forms.gradesupload.gradingmechanism[i].checked=false;
         }
      }
   // Remember the old state
      document.forms.gradesupload.waschecked.value=newgradingchoice;
   }
   </script>
   <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
   <input type="hidden" name="symb" value="$symb" />
   <input type="hidden" name="command" value="processclickerfile" />
   <input type="hidden" name="probTitle" value="$env{'form.probTitle'}" />
   <input type="hidden" name="saveState"  value="$env{'form.saveState'}" />
   <input type="file" name="upfile" size="50" />
   <br /><label>$type: $selectform</label>
   <br /><label>$attendance: <input type="radio" name="gradingmechanism" value="attendance" $checked{'attendance'} onClick="sanitycheck()" /></label>
   <br /><label>$personnel: <input type="radio" name="gradingmechanism" value="personnel" $checked{'personnel'} onClick="sanitycheck()" /></label>
   <br /><label>$specific: <input type="radio" name="gradingmechanism" value="specific" $checked{'specific'} onClick="sanitycheck()" /></label>
   <input type="text" name="specificid" value="$env{'form.specificid'}" size="20" />
   <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>$pincorrect: <input type="text" name="pincorrect" size="4" value="$env{'form.pincorrect'}" onChange="sanitycheck()" /></label>
   <br /><input type="button" onClick="javascript:checkUpload(this.form);" value="$upload" />
   </form>
   ENDUPFORM
       $result.='</td></tr></table>'."\n".
                '</td></tr></table><br /><br />'."\n";
       $result.=&show_grading_menu_form($symb);
       return $result;
   }
   
   sub process_clicker_file {
       my ($r)=@_;
       my ($symb)=&get_symb($r);
       if (!$symb) {return '';}
   
       my %Saveable_Parameters=&clicker_grading_parameters();
       &Apache::loncommon::store_course_settings('grades_clicker',
                                                 \%Saveable_Parameters);
   
       my ($result) = &showResourceInfo($symb,$env{'form.probTitle'});
       if (($env{'form.gradingmechanism'} eq 'specific') && ($env{'form.specificid'}!~/\w/)) {
    $result.='<span class="LC_error">'.&mt('You need to specify a clicker ID for the correct answer').'</span>';
    return $result.&show_grading_menu_form($symb);
       }
       my %clicker_ids=&gather_clicker_ids();
       my %correct_ids;
       if ($env{'form.gradingmechanism'} eq 'personnel') {
    %correct_ids=&gather_adv_clicker_ids();
       }
       if ($env{'form.gradingmechanism'} eq 'specific') {
    foreach my $correct_id (split(/[\s\,]/,$env{'form.specificid'})) {;
      $correct_id=~tr/a-z/A-Z/;
      $correct_id=~s/\s//gs;
      $correct_id=~s/^[\#0]+//;
              if ($correct_id) {
         $correct_ids{$correct_id}='specified';
              }
           }
       }
       if ($env{'form.gradingmechanism'} eq 'attendance') {
    $result.=&mt('Score based on attendance only');
       } else {
    my $number=0;
    $result.='<p><b>'.&mt('Correctness determined by the following IDs').'</b>';
    foreach my $id (sort(keys(%correct_ids))) {
       $result.='<br /><tt>'.$id.'</tt> - ';
       if ($correct_ids{$id} eq 'specified') {
    $result.=&mt('specified');
       } else {
    my ($uname,$udom)=split(/\:/,$correct_ids{$id});
    $result.=&Apache::loncommon::plainname($uname,$udom);
       }
       $number++;
    }
           $result.="</p>\n";
    if ($number==0) {
       $result.='<span class="LC_error">'.&mt('No IDs found to determine correct answer').'</span>';
       return $result.&show_grading_menu_form($symb);
    }
       }
       if (length($env{'form.upfile'}) < 2) {
           $result.=&mt('[_1] Error: [_2] The file you attempted to upload, [_3] contained no information. Please check that you entered the correct filename.',
        '<span class="LC_error">',
        '</span>',
        '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>');
           return $result.&show_grading_menu_form($symb);
       }
   
   # Were able to get all the info needed, now analyze the file
   
       $result.=&Apache::loncommon::studentbrowser_javascript();
       my $heading=&mt('Scanning clicker file');
       $result.=(<<ENDHEADER);
   <br /><table width="100%" border="0"><tr><td bgcolor="#777777">
   <table width="100%" border="0"><tr bgcolor="#e6ffff"><td>
   <b>$heading</b></td></tr><tr bgcolor=#ffffe6><td>
   <form method="post" action="/adm/grades" name="clickeranalysis">
   <input type="hidden" name="symb" value="$symb" />
   <input type="hidden" name="command" value="assignclickergrades" />
   <input type="hidden" name="probTitle" value="$env{'form.probTitle'}" />
   <input type="hidden" name="saveState"  value="$env{'form.saveState'}" />
   <input type="hidden" name="gradingmechanism" value="$env{'form.gradingmechanism'}" />
   <input type="hidden" name="pcorrect" value="$env{'form.pcorrect'}" />
   <input type="hidden" name="pincorrect" value="$env{'form.pincorrect'}" />
   ENDHEADER
       my %responses;
       my @questiontitles;
       my $errormsg='';
       my $number=0;
       if ($env{'form.upfiletype'} eq 'iclicker') {
    ($errormsg,$number)=&iclicker_eval(\@questiontitles,\%responses);
       }
       $result.='<br />'.&mt('Found [_1] question(s)',$number).'<br />'.
                '<input type="hidden" name="number" value="'.$number.'" />'.
                &mt('Awarding [_1] percent for correct and [_2] percent for incorrect responses',
                    $env{'form.pcorrect'},$env{'form.pincorrect'}).
                '<br />';
   # Remember Question Titles
   # FIXME: Possibly need delimiter other than ":"
       for (my $i=0;$i<$number;$i++) {
           $result.='<input type="hidden" name="question:'.$i.'" value="'.
                    &HTML::Entities::encode($questiontitles[$i],'"&<>').'" />';
       }
       my $correct_count=0;
       my $student_count=0;
       my $unknown_count=0;
   # Match answers with usernames
   # FIXME: Possibly need delimiter other than ":"
       foreach my $id (keys(%responses)) {
          if ($correct_ids{$id}) {
             $result.="\n".'<input type="hidden" name="correct:'.$correct_count.':'.$correct_ids{$id}.'" value="'.$responses{$id}.'" />';
             $correct_count++;
          } elsif ($clicker_ids{$id}) {
             $result.="\n".'<input type="hidden" name="student:'.$clicker_ids{$id}.'" value="'.$responses{$id}.'" />';
             $student_count++;
          } else {
             $result.="\n<hr />".&mt('Unregistered Clicker')." <tt>".$id."</tt><br />";
             $result.="\n".'<input type="hidden" name="unknown:'.$id.'" value="'.$responses{$id}.'" />'.
                      "\n".&mt("Username").": <input type='text' name='uname".$id."' />&nbsp;".
                      "\n".&mt("Domain").": ".
                      &Apache::loncommon::select_dom_form($env{'course.'.$env{'request.course.id'}.'.domain'},'udom'.$id).'&nbsp;'.
                      &Apache::loncommon::selectstudent_link('clickeranalysis','uname'.$id,'udom'.$id);
             $unknown_count++;
          }
       }
       $result.='<hr />'.
                &mt('Found [_1] registered and [_2] unregistered clickers.',$student_count,$unknown_count);
       if ($env{'form.gradingmechanism'} ne 'attendance') {
          if ($correct_count==0) {
             $errormsg.="Found no correct answers answers for grading!";
          } elsif ($correct_count>1) {
             $result.='<br /><span class="LC_warning">'.&mt("Found [_1] entries for grading!",$correct_count).'</span>';
          }
       }
       if ($errormsg) {
          $result.='<br /><span class="LC_error">'.&mt($errormsg).'</span>';
       } else {
          $result.='<br /><input type="submit" name="finalize" value="'.&mt('Finalize Grading').'" />';
       }
       $result.='</form></td></tr></table>'."\n".
                '</td></tr></table><br /><br />'."\n";
       return $result.&show_grading_menu_form($symb);
   }
   
   sub iclicker_eval {
       my ($questiontitles,$responses)=@_;
       my $number=0;
       my $errormsg='';
       foreach my $line (split(/[\n\r]/,$env{'form.upfile'})) {
           my %components=&Apache::loncommon::record_sep($line);
           my @entries=map {$components{$_}} (sort(keys(%components)));
    if ($entries[0] eq 'Question') {
       for (my $i=3;$i<$#entries;$i+=6) {
    $$questiontitles[$number]=$entries[$i];
    $number++;
       }
    }
    if ($entries[0]=~/^\#/) {
       my $id=$entries[0];
       my @idresponses;
       $id=~s/^[\#0]+//;
       for (my $i=0;$i<$number;$i++) {
    my $idx=3+$i*6;
    push(@idresponses,$entries[$idx]);
       }
       $$responses{$id}=join(',',@idresponses);
    }
       }
       return ($errormsg,$number);
   }
   
   sub assign_clicker_grades {
       my ($r)=@_;
       my ($symb)=&get_symb($r);
       if (!$symb) {return '';}
       my ($result) = &showResourceInfo($symb,$env{'form.probTitle'});
       my $heading=&mt('Assigning grades based on clicker file');
       $result.=(<<ENDHEADER);
   <br /><table width="100%" border="0"><tr><td bgcolor="#777777">
   <table width="100%" border="0"><tr bgcolor="#e6ffff"><td>
   <b>$heading</b></td></tr><tr bgcolor=#ffffe6><td>
   ENDHEADER
   # Get correct result
   # FIXME: Possibly need delimiter other than ":"
       my @correct=();
       my $gradingmechanism=$env{'form.gradingmechanism'};
       my $number=$env{'form.number'};
       if ($gradingmechanism ne 'attendance') {
          foreach my $key (keys(%env)) {
             if ($key=~/^form\.correct\:/) {
                my @input=split(/\,/,$env{$key});
                for (my $i=0;$i<=$#input;$i++) {
                    if (($correct[$i]) && ($input[$i]) &&
                        ($correct[$i] ne $input[$i])) {
                       $result.='<br /><span class="LC_warning">'.
                                &mt('More than one correct result given for question "[_1]": [_2] versus [_3].',
                                    $env{'form.question:'.$i},$correct[$i],$input[$i]).'</span>';
                    } elsif ($input[$i]) {
                       $correct[$i]=$input[$i];
                    }
                }
             }
          }
          for (my $i=0;$i<$number;$i++) {
             if (!$correct[$i]) {
                $result.='<br /><span class="LC_error">'.
                         &mt('No correct result given for question "[_1]"!',
                             $env{'form.question:'.$i}).'</span>';
             }
          }
          $result.='<br />'.&mt("Correct answer: [_1]",join(', ',map { ($_?$_:'-') } @correct));
       }
   # Start grading
       my $pcorrect=$env{'form.pcorrect'};
       my $pincorrect=$env{'form.pincorrect'};
       foreach my $key (keys(%env)) {
          if ($key=~/^form\.student\:(.*)$/) {
             my $user=$1;
             my @answer=split(/\,/,$env{$key});
             my $sum=0;
             for (my $i=0;$i<$number;$i++) {
                if ($answer[$i]) {
                   if ($gradingmechanism eq 'attendance') {
                      $sum+=$pcorrect;
                   } else {
                      if ($answer[$i] eq $correct[$i]) {
                         $sum+=$pcorrect;
                      } else {
                         $sum+=$pincorrect;
                      }
                   }
                }
             }
             my $ave=$sum/$number;
             $result.='<br />'.$user.' - '.$env{$key}.': '.$ave;
          }
       }
   # We are done
       $result.='</td></tr></table>'."\n".
                '</td></tr></table><br /><br />'."\n";
       return $result.&show_grading_menu_form($symb);
   }
   
 sub handler {  sub handler {
     my $request=$_[0];      my $request=$_[0];
   
Line 6192  sub handler { Line 6588  sub handler {
     $request->print(&editgrades($request));      $request->print(&editgrades($request));
  } elsif ($command eq 'verify' && $perm{'vgr'}) {   } elsif ($command eq 'verify' && $perm{'vgr'}) {
     $request->print(&verifyreceipt($request));      $request->print(&verifyreceipt($request));
           } elsif ($command eq 'processclicker' && $perm{'mgr'}) {
               $request->print(&process_clicker($request));
           } elsif ($command eq 'processclickerfile' && $perm{'mgr'}) {
               $request->print(&process_clicker_file($request));
           } elsif ($command eq 'assignclickergrades' && $perm{'mgr'}) {
               $request->print(&assign_clicker_grades($request));
  } elsif ($command eq 'csvform' && $perm{'mgr'}) {   } elsif ($command eq 'csvform' && $perm{'mgr'}) {
     $request->print(&upcsvScores_form($request));      $request->print(&upcsvScores_form($request));
  } elsif ($command eq 'csvupload' && $perm{'mgr'}) {   } elsif ($command eq 'csvupload' && $perm{'mgr'}) {

Removed from v.1.399.2.1  
changed lines
  Added in v.1.415


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