Diff for /loncom/homework/grades.pm between versions 1.754 and 1.761

version 1.754, 2019/01/27 14:39:55 version 1.761, 2019/03/06 15:45:29
Line 48  use Apache::lonquickgrades; Line 48  use Apache::lonquickgrades;
 use Apache::bridgetask();  use Apache::bridgetask();
 use Apache::lontexconvert();  use Apache::lontexconvert();
 use String::Similarity;  use String::Similarity;
   use HTML::Parser();
   use File::MMagic;
 use LONCAPA;  use LONCAPA;
   
 use POSIX qw(floor);  use POSIX qw(floor);
Line 4923  LISTJAVASCRIPT Line 4925  LISTJAVASCRIPT
     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 $result='<h3><span class="LC_info">&nbsp;'.      my $result='<h3><span class="LC_info">&nbsp;'.
  &mt('Manual Grading by Page or Sequence').'</span></h3>';   &mt('Manual Grading by Page or Sequence').'</span></h3>';
Line 5012  LISTJAVASCRIPT Line 5015  LISTJAVASCRIPT
  '<th>'.&nameUserString('header').'</th>'.   '<th>'.&nameUserString('header').'</th>'.
  &Apache::loncommon::end_data_table_header_row();   &Apache::loncommon::end_data_table_header_row();
     
     my (undef,undef,$fullname) = &getclasslist($getsec,'1');      my (undef,undef,$fullname) = &getclasslist($getsec,'1',$getgroup);
     my $ptr = 1;      my $ptr = 1;
     foreach my $student (sort       foreach my $student (sort 
  {   {
Line 5902  sub scantron_selectphase { Line 5905  sub scantron_selectphase {
   
         $r->print('          $r->print('
     <br />');      <br />');
     my $default_form_data=&defaultFormData($symb);  
     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 $alertmsg = &mt('Please use the browse button to select a file from your local directory.');      my $alertmsg = &mt('Please use the browse button to select a file from your local directory.');
Line 5915  sub scantron_selectphase { Line 5917  sub scantron_selectphase {
     return false;      return false;
  }   }
  formname.submit();   formname.submit();
     }'.$formatjs));      }'."\n".$formatjs));
     $r->print('      $r->print('
               <form enctype="multipart/form-data" action="/adm/grades" name="rules" method="post">                <form enctype="multipart/form-data" action="/adm/grades" name="rules" method="post">
                 '.$default_form_data.'                  '.$default_form_data.'
Line 8684  SCANTRONFORM Line 8686  SCANTRONFORM
  return ''; # Dunno why the other returns return '' rather than just returning.   return ''; # Dunno why the other returns return '' rather than just returning.
     }      }
   
     my %lettdig = &letter_to_digits();      my %lettdig = &Apache::lonnet::letter_to_digits();
     my $numletts = scalar(keys(%lettdig));      my $numletts = scalar(keys(%lettdig));
     my %orderedforcode;      my %orderedforcode;
   
Line 9099  END Line 9101  END
             if (keys(%{$domconfig{'scantron'}{'config'}}) > 1) {              if (keys(%{$domconfig{'scantron'}{'config'}}) > 1) {
                 if (($domconfig{'scantron'}{'config'}{'dat'}) &&                  if (($domconfig{'scantron'}{'config'}{'dat'}) &&
                     (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH')) {                      (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH')) {
                     if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}})) {                      if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {  
                         my ($onclick,$formatextra,$singleline);                          if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}})) {
                         my @lines = &Apache::lonnet::get_scantronformat_file();                              my ($onclick,$formatextra,$singleline);
                         my $count = 0;                              my @lines = &Apache::lonnet::get_scantronformat_file();
                         foreach my $line (@lines) {                              my $count = 0;
                             next if ($line =~ /^#/);                              foreach my $line (@lines) {
                             $singleline = $line;                                  next if ($line =~ /^#/);
                             $count ++;                                  $singleline = $line;
                         }                                  $count ++;
                         if ($count > 1) {                              }
                             $formatextra = '<div style="display:none" id="bubbletype">'.                              if ($count > 1) {
                                            &scantron_scantab().'</div>';                                  $formatextra = '<div style="display:none" id="bubbletype">'.
                             $onclick = ' onclick="toggleScantab(this.form);"';                                                 '<span class="LC_nobreak">'.
                             $formatjs = <<"END";                                                 &mt('Bubblesheet type:').'&nbsp;'.
                                                  &scantron_scantab().'</span></div>';
                                   $onclick = ' onclick="toggleScantab(this.form);"';
                                   $formatjs = <<"END";
 function toggleScantab(form) {  function toggleScantab(form) {
     var divid = 'bubbletype';      var divid = 'bubbletype';
     if (document.getElementById(divid)) {      if (document.getElementById(divid)) {
Line 9125  function toggleScantab(form) { Line 9130  function toggleScantab(form) {
                     if (chosen == 'dat') {                      if (chosen == 'dat') {
                         document.getElementById(divid).style.display = 'none';                          document.getElementById(divid).style.display = 'none';
                     } else if (chosen == 'csv') {                      } else if (chosen == 'csv') {
                         document.getElementById(divid).style.display = 'inline-block';                          document.getElementById(divid).style.display = 'block';
                     }                      }
                 }                  }
             }              }
Line 9135  function toggleScantab(form) { Line 9140  function toggleScantab(form) {
 }  }
   
 END  END
                         } elsif ($count == 1) {                              } elsif ($count == 1) {
                             my $formatname = (split(/:/,$singleline,2))[0];                                  my $formatname = (split(/:/,$singleline,2))[0];
                             $formatextra = '<input type="hidden" name="scantron_format" value="'.$formatname.'" />';                                  $formatextra = '<input type="hidden" name="scantron_format" value="'.$formatname.'" />';
                               }
                               $formattitle = &mt('File format');
                               $formatoptions = '<label><input name="fileformat" type="radio" value="dat" checked="checked"'.$onclick.' />'.
                                                &mt('Plain Text (no delimiters)').
                                                '</label>'.('&nbsp;'x2).
                                                '<label><input name="fileformat" type="radio" value="csv"'.$onclick.' />'.
                                                &mt('Comma separated values').'</label>'.$formatextra;
                         }                          }
                         $formattitle = &mt('File format');  
                         $formatoptions = '<label><input name="fileformat" type="radio" value="dat" checked="checked"'.$onclick.' />'.  
                                          &mt('Plain Text (no delimiters)').  
                                          '</label>'.('&nbsp;'x2).  
                                          '<label><input name="fileformat" type="radio" value="csv"'.$onclick.' />'.  
                                          &mt('Comma separated values').'</label>'.$formatextra;  
                     }                      }
                 }                  }
             } elsif (keys(%{$domconfig{'scantron'}{'config'}}) == 1) {              } elsif (keys(%{$domconfig{'scantron'}{'config'}}) == 1) {
                 if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}})) {                  if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
                     $formattitle = &mt('Format of bubblesheet data file:');                      if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}})) {
                     $formatoptions = &scantron_scantab();                          $formattitle = &mt('Bubblesheet type');
                           $formatoptions = &scantron_scantab();
                       }
                 }                  }
             }              }
         }          }
Line 9192  sub scantron_upload_scantron_data_save { Line 9200  sub scantron_upload_scantron_data_save {
                 if (@possibles > 1) {                  if (@possibles > 1) {
                     if ($env{'form.fileformat'} eq 'csv') {                      if ($env{'form.fileformat'} eq 'csv') {
                         if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {                          if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {
                             if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}}) > 1) {                              if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
                                 $is_csv = 1;                                  if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}}) > 1) {
                                       $is_csv = 1;
                                   }
                             }                              }
                         }                          }
                     }                      }
                 } elsif (@possibles == 1) {                  } elsif (@possibles == 1) {
                     if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {                      if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {
                         if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}}) > 1) {                          if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
                             $is_csv = 1;                              if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}}) > 1) {
                                   $is_csv = 1;
                               }
                         }                          }
                     }                      }
                 }                  }
Line 9396  sub checkscantron_results { Line 9408  sub checkscantron_results {
     my ($r,$symb) = @_;      my ($r,$symb) = @_;
     if (!$symb) {return '';}      if (!$symb) {return '';}
     my $cid = $env{'request.course.id'};      my $cid = $env{'request.course.id'};
     my %lettdig = &letter_to_digits();      my %lettdig = &Apache::lonnet::letter_to_digits();
     my $numletts = scalar(keys(%lettdig));      my $numletts = scalar(keys(%lettdig));
     my $cnum = $env{'course.'.$cid.'.num'};      my $cnum = $env{'course.'.$cid.'.num'};
     my $cdom = $env{'course.'.$cid.'.domain'};      my $cdom = $env{'course.'.$cid.'.domain'};
Line 9727  sub verify_scantron_grading { Line 9739  sub verify_scantron_grading {
     return ($counter,$record);      return ($counter,$record);
 }  }
   
 sub letter_to_digits {  
     my %lettdig = (  
                     A => 1,  
                     B => 2,  
                     C => 3,  
                     D => 4,  
                     E => 5,  
                     F => 6,  
                     G => 7,  
                     H => 8,  
                     I => 9,  
                     J => 0,  
                   );  
     return %lettdig;  
 }  
   
   
 #-------- end of section for handling grading scantron forms -------  #-------- end of section for handling grading scantron forms -------
 #  #
Line 10302  sub process_clicker_file { Line 10298  sub process_clicker_file {
                         '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'),1);                          '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'),1);
         return $result;          return $result;
     }      }
       my $mimetype;
       if ($env{'form.upfiletype'} eq 'iclicker') {
           my $mm = new File::MMagic;
           $mimetype = $mm->checktype_contents($env{'form.upfile'});
           unless (($mimetype eq 'text/plain') || ($mimetype eq 'text/html')) {
               $result.= '<p>'.
                   &Apache::lonhtmlcommon::confirm_success(
                       &mt('File format is neither csv (iclicker 6) nor xml (iclicker 7)'),1).'</p>';
               return $result;
           }
       } elsif (($env{'form.upfiletype'} ne 'interwrite') && ($env{'form.upfiletype'} ne 'turning')) {
           $result .= '<p>'.
               &Apache::lonhtmlcommon::confirm_success(
                   &mt('Invalid clicker type: choose one of: i>clicker, Interwrite PRS, or Turning Technologies.'),1).'</p>';
           return $result;
       }
   
 # Were able to get all the info needed, now analyze the file  # Were able to get all the info needed, now analyze the file
   
Line 10328  ENDHEADER Line 10340  ENDHEADER
     my $errormsg='';      my $errormsg='';
     my $number=0;      my $number=0;
     if ($env{'form.upfiletype'} eq 'iclicker') {      if ($env{'form.upfiletype'} eq 'iclicker') {
  ($errormsg,$number)=&iclicker_eval(\@questiontitles,\%responses);          if ($mimetype eq 'text/plain') {
     }              ($errormsg,$number)=&iclicker_eval(\@questiontitles,\%responses);
     if ($env{'form.upfiletype'} eq 'interwrite') {          } elsif ($mimetype eq 'text/html') {
               ($errormsg,$number)=&iclickerxml_eval(\@questiontitles,\%responses);
           }
       } elsif ($env{'form.upfiletype'} eq 'interwrite') {
         ($errormsg,$number)=&interwrite_eval(\@questiontitles,\%responses);          ($errormsg,$number)=&interwrite_eval(\@questiontitles,\%responses);
     }      } elsif ($env{'form.upfiletype'} eq 'turning') {
     if ($env{'form.upfiletype'} eq 'turning') {  
         ($errormsg,$number)=&turning_eval(\@questiontitles,\%responses);          ($errormsg,$number)=&turning_eval(\@questiontitles,\%responses);
     }      }
     $result.='<br />'.&mt('Found [_1] question(s)',$number).'<br />'.      $result.='<br />'.&mt('Found [_1] question(s)',$number).'<br />'.
Line 10441  sub iclicker_eval { Line 10455  sub iclicker_eval {
     return ($errormsg,$number);      return ($errormsg,$number);
 }  }
   
   sub iclickerxml_eval {
       my ($questiontitles,$responses)=@_;
       my $number=0;
       my $errormsg='';
       my @state;
       my %respbyid;
       my $p = HTML::Parser->new
       (
           xml_mode => 1,
           start_h =>
               [sub {
                    my ($tagname,$attr) = @_;
                    push(@state,$tagname);
                    if ("@state" eq "ssn p") {
                        my $title = $attr->{qn};
                        $title =~ s/(^\s+|\s+$)//g;
                        $questiontitles->[$number]=$title;
                    } elsif ("@state" eq "ssn p v") {
                        my $id = $attr->{id};
                        my $entry = $attr->{ans};
                        $id=~s/^[\#0]+//;
                        $entry =~s/[^a-zA-Z0-9\.\*\-\+]+//g;
                        $respbyid{$id}[$number] = $entry;
                    }
               }, "tagname, attr"],
            end_h =>
                  [sub {
                      my ($tagname) = @_;
                      if ("@state" eq "ssn p") {
                          $number++;
                      }
                      pop(@state);
                   }, "tagname"],
       );
   
       $p->parse($env{'form.upfile'});
       $p->eof;
       foreach my $id (keys(%respbyid)) {
           $responses->{$id}=join(',',@{$respbyid{$id}});
       }
       return ($errormsg,$number);
   }
   
 sub interwrite_eval {  sub interwrite_eval {
     my ($questiontitles,$responses)=@_;      my ($questiontitles,$responses)=@_;
     my $number=0;      my $number=0;
Line 10645  sub startpage { Line 10702  sub startpage {
     }      }
     if ($nomenu) {      if ($nomenu) {
         $args{'only_body'} = 1;           $args{'only_body'} = 1; 
         $r->print(&Apache::loncommon::start_page("Student's Version",$js,\%args);          $r->print(&Apache::loncommon::start_page("Student's Version",$js,\%args));
     } else {      } else {
         unshift(@$crumbs,{href=>&href_symb_cmd($symb,'gradingmenu'),text=>"Grading"});          unshift(@$crumbs,{href=>&href_symb_cmd($symb,'gradingmenu'),text=>"Grading"});
         $args{'bread_crumbs'} = $crumbs;          $args{'bread_crumbs'} = $crumbs;
Line 10653  sub startpage { Line 10710  sub startpage {
         &Apache::lonquickgrades::startGradeScreen($r,($env{'form.symb'}?'probgrading':'grading'));          &Apache::lonquickgrades::startGradeScreen($r,($env{'form.symb'}?'probgrading':'grading'));
     }      }
     unless ($nodisplayflag) {      unless ($nodisplayflag) {
        $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp));          $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp));
     }      }
 }  }
   
Line 11032  Side Effects: None. Line 11089  Side Effects: None.
     $r           - Apache request object      $r           - Apache request object
     $i           - number of the current scanline      $i           - number of the current scanline
     $scan_record - hash ref as returned from &scantron_parse_scanline()      $scan_record - hash ref as returned from &scantron_parse_scanline()
     $scan_config - hash ref as returned from &get_scantron_config()      $scan_config - hash ref as returned from &Apache::lonnet::get_scantron_config()
     $line        - full contents of the current scanline      $line        - full contents of the current scanline
     $error       - error condition, valid values are      $error       - error condition, valid values are
                    'incorrectCODE', 'duplicateCODE',                     'incorrectCODE', 'duplicateCODE',

Removed from v.1.754  
changed lines
  Added in v.1.761


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