Diff for /loncom/homework/grades.pm between versions 1.130.2.1.2.6 and 1.130.2.1.2.7

version 1.130.2.1.2.6, 2003/09/29 21:31:30 version 1.130.2.1.2.7, 2003/09/30 06:35:20
Line 3276  sub username_to_idmap { Line 3276  sub username_to_idmap {
 }  }
   
 sub scantron_fixup_scanline {  sub scantron_fixup_scanline {
     my ($scantron_config,$scan_data,$line,$whichline,$field,$newvalue,$arg)=@_;      my ($scantron_config,$scan_data,$line,$whichline,$field,$args)=@_;
     if ($field eq 'ID') {      if ($field eq 'ID') {
  if ($newvalue > $$scantron_config{'IDlength'}) {   if (length($args->{'newid'}) > $$scantron_config{'IDlength'}) {
     return ($line,1,'New value to large');      return ($line,1,'New value to large');
  }   }
  if ($newvalue < $$scantron_config{'IDlength'}) {   if (length($args->{'newid'}) < $$scantron_config{'IDlength'}) {
     $newvalue=sprintf('%-'.$$scantron_config{'IDlength'}.'s',      $args->{'newid'}=sprintf('%-'.$$scantron_config{'IDlength'}.'s',
       $newvalue);       $args->{'newid'});
  }   }
  substr($line,$$scantron_config{'IDstart'}-1,   substr($line,$$scantron_config{'IDstart'}-1,
        $$scantron_config{'IDlength'})=$newvalue;         $$scantron_config{'IDlength'})=$args->{'newid'};
    if ($args->{'newid'}=~/^\s*$/) {
       &scan_data($scan_data,"$whichline.user",
          $args->{'username'}.':'.$args->{'domain'});
    }
     } elsif ($field eq 'answer') {      } elsif ($field eq 'answer') {
  my $length=$scantron_config->{'Qlength'};   my $length=$scantron_config->{'Qlength'};
  my $off=$scantron_config->{'Qoff'};   my $off=$scantron_config->{'Qoff'};
  my $on=$scantron_config->{'Qon'};   my $on=$scantron_config->{'Qon'};
  my $answer=${off}x$length;   my $answer=${off}x$length;
  if ($arg eq 'none') {   if ($args->{'response'} eq 'none') {
     &scan_data($scan_data,"$whichline.no_bubble.$newvalue",'1');      &scan_data($scan_data,
          "$whichline.no_bubble.".$args->{'question'},'1');
  } else {   } else {
     substr($answer,$arg,1)=$on;      substr($answer,$args->{'response'},1)=$on;
     &scan_data($scan_data,"$whichline.no_bubble.$newvalue",undef,'1');      &scan_data($scan_data,
          "$whichline.no_bubble.".$args->{'question'},undef,'1');
  }   }
  my $where=$length*($newvalue-1)+$scantron_config->{'Qstart'};   my $where=$length*($args->{'question'}-1)+$scantron_config->{'Qstart'};
  Apache->request->print("where $where arg $arg ");  
  Apache->request->print('b:<pre>'.$line.'</pre>');  
  substr($line,$where-1,$length)=$answer;   substr($line,$where-1,$length)=$answer;
  Apache->request->print('a:<pre>'.$line.'</pre>');  
     }      }
     return $line;      return $line;
 }  }
Line 3358  sub scantron_parse_scanline { Line 3361  sub scantron_parse_scanline {
     $record{"scantron.$questnum.answer"}=$alphabet[length($array[0])];      $record{"scantron.$questnum.answer"}=$alphabet[length($array[0])];
  }   }
  if (scalar(@array) gt 2) {   if (scalar(@array) gt 2) {
       Apache->request->print("snippet is <pre>$currentquest</pre>");
     push(@{$record{'scantron.doubleerror'}},$questnum);      push(@{$record{'scantron.doubleerror'}},$questnum);
     my @ans=@array;      my @ans=@array;
     my $i=length($ans[0]);shift(@ans);      my $i=length($ans[0]);shift(@ans);
     while (@ans) {      while ($#ans) {
  $i+=length($ans[0])+1;   $i+=length($ans[0])+1;
  $record{"scantron.$questnum.answer"}.=$alphabet[$i];   $record{"scantron.$questnum.answer"}.=$alphabet[$i];
  shift(@ans);   shift(@ans);
Line 3382  sub scantron_add_delay { Line 3386  sub scantron_add_delay {
 }  }
   
 sub scantron_find_student {  sub scantron_find_student {
     my ($scantron_record,$idmap)=@_;      my ($scantron_record,$scan_data,$idmap,$line)=@_;
     my $scanID=$$scantron_record{'scantron.ID'};      my $scanID=$$scantron_record{'scantron.ID'};
       if ($scanID =~ /^\s*$/) {
    return &scan_data($scan_data,"$line.user");
       }
     foreach my $id (keys(%$idmap)) {      foreach my $id (keys(%$idmap)) {
  #Apache->request->print('<pre>checking studnet -'.$id.'- againt -'.$scanID.'- </pre>');   #Apache->request->print('<pre>checking studnet -'.$id.'- againt -'.$scanID.'- </pre>');
  if (lc($id) eq lc($scanID)) {   if (lc($id) eq lc($scanID)) {
Line 3402  sub scantron_filter { Line 3409  sub scantron_filter {
     return 0;      return 0;
 }  }
   
 #FIXME I think I am doing this in the wrong order, I think it would be  
 #better to make a several passes analyzing all of the lines in the  
 #file for common errors wrong/invalid PID/username duplicated  
 #PID/username, missing bubbles, double bubbles, missing/invalid CODE  
 #and then get the instructor to fix all of these errors, then grade  
 #the corrected one, I'll still need to catch error conditions, but  
 #maybe most will taken care even before we start  
   
 sub scantron_process_corrections {  sub scantron_process_corrections {
     my ($r) = @_;      my ($r) = @_;
     my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'});      my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'});
Line 3426  sub scantron_process_corrections { Line 3425  sub scantron_process_corrections {
  my $newid=$classlist->{$newstudent}->[&Apache::loncoursedata::CL_ID];   my $newid=$classlist->{$newstudent}->[&Apache::loncoursedata::CL_ID];
  ($line,$err,$errmsg)=   ($line,$err,$errmsg)=
     &scantron_fixup_scanline(\%scantron_config,$scan_data,$line,$which,      &scantron_fixup_scanline(\%scantron_config,$scan_data,$line,$which,
      'ID',$newid);       'ID',{'newid'=>$newid,
       'username'=>$ENV{'form.scantron_username'},
       'domain'=>$ENV{'form.scantron_domain'}});
     } elsif ($ENV{'form.scantron_corrections'} =~ /^(missing|double)bubble$/) {      } elsif ($ENV{'form.scantron_corrections'} =~ /^(missing|double)bubble$/) {
  foreach my $question (split(',',$ENV{'form.scantron_questions'})) {   foreach my $question (split(',',$ENV{'form.scantron_questions'})) {
     ($line,$err,$errmsg)=      ($line,$err,$errmsg)=
  &scantron_fixup_scanline(\%scantron_config,$scan_data,$line,   &scantron_fixup_scanline(\%scantron_config,$scan_data,$line,
  $which,'answer',$question,   $which,'answer',
     $ENV{"form.scantron_correct_Q_$question"});   { 'question'=>$question,
          'response'=>$ENV{"form.scantron_correct_Q_$question"}});
     if ($err) { last; }      if ($err) { last; }
  }   }
     }      }
Line 3458  sub scantron_validate_file { Line 3460  sub scantron_validate_file {
     $r->print(&Apache::loncommon::studentbrowser_javascript());      $r->print(&Apache::loncommon::studentbrowser_javascript());
     my $result= <<SCANTRONFORM;      my $result= <<SCANTRONFORM;
 <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantronupload">  <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantronupload">
   <input type="hidden" name="command" value="scantron_validate" />  
   <input type="hidden" name="selectpage" value="$ENV{'form.selectpage'}" />    <input type="hidden" name="selectpage" value="$ENV{'form.selectpage'}" />
   <input type="hidden" name="scantron_format" value="$ENV{'form.scantron_format'}" />    <input type="hidden" name="scantron_format" value="$ENV{'form.scantron_format'}" />
   <input type="hidden" name="scantron_selectfile" value="$ENV{'form.scantron_selectfile'}" />    <input type="hidden" name="scantron_selectfile" value="$ENV{'form.scantron_selectfile'}" />
Line 3482  SCANTRONFORM Line 3483  SCANTRONFORM
     }      }
     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->rflush();
  my $which="scantron_validate_".$validate_phases[$currentphase];   my $which="scantron_validate_".$validate_phases[$currentphase];
  {   {
     no strict 'refs';      no strict 'refs';
     ($stop,$currentphase)=&$which($r,$currentphase);      ($stop,$currentphase)=&$which($r,$currentphase);
  }   }
     }      }
     $r->print("<input type='hidden' name='validatepass' value='".$currentphase."' />");      if (!$stop) {
    $r->print("Validation process complete, click 'Submit' to start proccssing");
    $r->print('<input type="hidden" name="command" value="scantron_process" />');
       } else {
    $r->print('<input type="hidden" name="command" value="scantron_validate" />');
    $r->print("<input type='hidden' name='validatepass' value='".$currentphase."' />");
       }
       $r->print('<input type="submit" name="submit" /></form></body></html>');
     return '';      return '';
 }  }
   
 sub scantron_getfile {  sub scantron_getfile {
     #my $scanlines=Apache::File->new($Apache::lonnet::perlvar{'lonScansDir'}."/$ENV{'form.scantron_selectfile'}");  
     #FIXME really would prefer a scantron directory but tokenwrapper      #FIXME really would prefer a scantron directory but tokenwrapper
     # doesn't allow access to subdirs of userfiles      # doesn't allow access to subdirs of userfiles
     my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};      my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'};
Line 3502  sub scantron_getfile { Line 3511  sub scantron_getfile {
     $lines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'.      $lines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'.
        'scantron_orig_'.$ENV{'form.scantron_selectfile'});         'scantron_orig_'.$ENV{'form.scantron_selectfile'});
     if ($lines eq '-1') {      if ($lines eq '-1') {
        #FIXME need to actually replicate file to course space   #FIXME need to actually replicate file to course space
    #FIXME when replicating strip CRLF to LF or CR to LF
     }      }
     my %scanlines;      my %scanlines;
     $scanlines{'orig'}=[split("\n",$lines)];      $scanlines{'orig'}=[(split("\n",$lines,-1))];
     my $temp=$scanlines{'orig'};      my $temp=$scanlines{'orig'};
     $scanlines{'count'}=$#$temp;      $scanlines{'count'}=$#$temp;
   
Line 3514  sub scantron_getfile { Line 3524  sub scantron_getfile {
     if ($lines eq '-1') {      if ($lines eq '-1') {
  $scanlines{'corrected'}=[];   $scanlines{'corrected'}=[];
     } else {      } else {
  $scanlines{'corrected'}=[split("\n",$lines)];   $scanlines{'corrected'}=[(split("\n",$lines,-1))];
     }      }
     $lines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'.      $lines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'.
        'scantron_skipped_'.$ENV{'form.scantron_selectfile'});         'scantron_skipped_'.$ENV{'form.scantron_selectfile'});
     if ($lines eq '-1') {      if ($lines eq '-1') {
  $scanlines{'skipped'}=[];   $scanlines{'skipped'}=[];
     } else {      } else {
  $scanlines{'skipped'}=[split("\n",$lines)];   $scanlines{'skipped'}=[(split("\n",$lines,-1))];
     }      }
     my @tmp=&Apache::lonnet::dump('scantrondata',$cdom,$cname);      my @tmp=&Apache::lonnet::dump('scantrondata',$cdom,$cname);
     if ($tmp[0] =~ /^(error:|no_such_host)/) { @tmp=(); }      if ($tmp[0] =~ /^(error:|no_such_host)/) { @tmp=(); }
Line 3567  sub scantron_get_line { Line 3577  sub scantron_get_line {
   
 sub scantron_put_line {  sub scantron_put_line {
     my ($scanlines,$i,$newline,$skip)=@_;      my ($scanlines,$i,$newline,$skip)=@_;
     if ($skip) { $scanlines->{'skipped'}[$i]=$newline;return; }      if ($skip) {
    $scanlines->{'skipped'}[$i]=$newline;
    return;
       }
     $scanlines->{'corrected'}[$i]=$newline;      $scanlines->{'corrected'}[$i]=$newline;
 }  }
   
Line 3589  sub scantron_validate_ID { Line 3602  sub scantron_validate_ID {
  my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,   my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,
  $scan_data);   $scan_data);
  my $id=$$scan_record{'scantron.ID'};   my $id=$$scan_record{'scantron.ID'};
  $r->print("<p>Checking ID ".$$scan_record{'scantron.ID'}.  # $r->print("<p>Checking ID ".$$scan_record{'scantron.ID'}.
   " on paper ID ".$$scan_record{'scantron.PaperID'}."</p>\n");  #  " on paper ID ".$$scan_record{'scantron.PaperID'}."</p>\n");
  my $found;   my $found;
  foreach my $checkid (keys(%idmap)) {   foreach my $checkid (keys(%idmap)) {
     if (lc($checkid) eq lc($id)) {      if (lc($checkid) eq lc($id)) {
  if ($checkid ne $id) {   if ($checkid ne $id) {
     $r->print("<p>Using $checkid for encoded $id</p>\n");      #$r->print("<p>Using $checkid for encoded $id</p>\n");
  }   }
  $found=$checkid;last;   $found=$checkid;last;
     }      }
  }   }
  if ($found) {   if ($found) {
       my $username=$idmap{$found};
     if ($found{'ids'}{$found}) {      if ($found{'ids'}{$found}) {
  #FIXME store away line we prviously saw the ID on  
  &scantron_get_correction($r,$i,$scan_record,\%scantron_config,   &scantron_get_correction($r,$i,$scan_record,\%scantron_config,
  $line,'duplicateID',$found);   $line,'duplicateID',$found);
  return(1);   return(1);
     } else {      } elsif ($found{'usernames'}{$username}) {
  $found{'ids'}{$found}++;   &scantron_get_correction($r,$i,$scan_record,\%scantron_config,
    $line,'duplicateID',$username);
    return(1);
     }      }
       #FIXME store away line we prviously saw the ID on to use above
       $found{'ids'}{$found}++;
       $found{'usernames'}{$username}++;
  } else {   } else {
     &scantron_get_correction($r,$i,$scan_record,\%scantron_config,      if ($id =~ /^\s*$/) {
      $line,'incorrectID');   my $username=&scan_data($scan_data,"$i.user");
     return(1);   if (defined($username) && $found{'usernames'}{$username}) {
       &scantron_get_correction($r,$i,$scan_record,
        \%scantron_config,
        $line,'duplicateID',$username);
       return(1);
    } elsif (!defined($username)) {
       &scantron_get_correction($r,$i,$scan_record,
        \%scantron_config,
        $line,'incorrectID');
       return(1);
    }
    $found{'usernames'}{$username}++;
       } else {
    &scantron_get_correction($r,$i,$scan_record,\%scantron_config,
    $line,'incorrectID');
    return(1);
       }
  }   }
     }      }
   
Line 3656  sub scantron_get_correction { Line 3690  sub scantron_get_correction {
       'scantron_username','scantron_domain'));        'scantron_username','scantron_domain'));
  $r->print('</li>');   $r->print('</li>');
     } elsif ($error eq 'doublebubble') {      } elsif ($error eq 'doublebubble') {
    $r->print("<pre>$line</pre>");
    $Apache::lonxml::debug=1;
    &Apache::lonhomework::showhashsubset($scan_record,'.');
    $Apache::lonxml::debug=0;
  $r->print("There have been multiple bubbles scanned for a single question\n");   $r->print("There have been multiple bubbles scanned for a single question\n");
  $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=$$scan_record{"scantron.$question.answer"};
     $r->print("<p> For question $question, selected bubbles were ".      $r->print("<p> For question $question, selected bubbles were ".
       join(" ",split('',$selected)).        join(" ",split('',$selected,-1)).
               " <br />Please pick which one should be used for grading<br />");                " <br />Please pick which one should be used for grading<br />");
     &scantron_bubble_selector($r,$scan_config,$question);      &scantron_bubble_selector($r,$scan_config,$question);
  }   }
Line 3680  sub scantron_get_correction { Line 3718  sub scantron_get_correction {
     }      }
     $r->print("<li>Skip this scanline saving it for later  ");      $r->print("<li>Skip this scanline saving it for later  ");
     $r->print("\n<input type='checkbox' name='scantron_skip_record' /> </li></ul>");      $r->print("\n<input type='checkbox' name='scantron_skip_record' /> </li></ul>");
     &scantron_end_validate_form($r);  
 }  }
   
 sub scantron_bubble_selector {  sub scantron_bubble_selector {
Line 3744  sub scantron_validate_missingbubbles { Line 3781  sub scantron_validate_missingbubbles {
  if (!defined($$scan_record{'scantron.missingerror'})) { next; }   if (!defined($$scan_record{'scantron.missingerror'})) { next; }
  my @to_correct;   my @to_correct;
  foreach my $missing (@{$$scan_record{'scantron.missingerror'}}) {   foreach my $missing (@{$$scan_record{'scantron.missingerror'}}) {
     if ($missing gt $max_bubble) { next; }      if ($missing > $max_bubble) { next; }
     push(@to_correct,$missing);      push(@to_correct,$missing);
  }   }
  if (@to_correct) {   if (@to_correct) {
Line 3757  sub scantron_validate_missingbubbles { Line 3794  sub scantron_validate_missingbubbles {
     return (0,$currentphase+1);      return (0,$currentphase+1);
 }  }
   
 sub scantron_end_validate_form {  
     my ($r) = @_;  
     $r->print('<input type="submit" name="submit" /></form></body></html>');  
 }  
   
 sub scantron_process_students {  sub scantron_process_students {
     my ($r) = @_;      my ($r) = @_;
     my (undef,undef,$sequence)=split(/___/,$ENV{'form.selectpage'});      my (undef,undef,$sequence)=split(/___/,$ENV{'form.selectpage'});
Line 3792  SCANTRONFORM Line 3824  SCANTRONFORM
     &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,      &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,
   'Processing first student');    'Processing first student');
     my $start=&Time::HiRes::time();      my $start=&Time::HiRes::time();
     my $i=0;      my $i=-1;
     while ($i<=$scanlines->{'count'}) {      while ($i<$scanlines->{'count'}) {
  $i++;   $i++;
  my $line=&scantron_get_line($scanlines,$i);   my $line=&scantron_get_line($scanlines,$i);
  if (!$line) { next; }  
  $r->print('<pre>line is'.$line.'</pre>');   $r->print('<pre>line is'.$line.'</pre>');
    if (!defined($line)) { 
       $r->print('skipping');
       next;
    }
  my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,   my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,
  $scan_data);   $scan_data);
  my ($uname,$udom);   my ($uname,$udom);
  unless ($uname=&scantron_find_student($scan_record,\%idmap)) {   unless ($uname=&scantron_find_student($scan_record,$scan_data,
         \%idmap,$i)) {
     &scantron_add_delay(\@delayqueue,$line,      &scantron_add_delay(\@delayqueue,$line,
  'Unable to find a student that matches',1);   'Unable to find a student that matches',1);
     next;      next;

Removed from v.1.130.2.1.2.6  
changed lines
  Added in v.1.130.2.1.2.7


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