--- loncom/homework/grades.pm 2004/03/19 03:47:09 1.181 +++ loncom/homework/grades.pm 2004/04/20 06:11:49 1.186 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.181 2004/03/19 03:47:09 albertel Exp $ +# $Id: grades.pm,v 1.186 2004/04/20 06:11:49 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -511,7 +511,7 @@ sub verifyreceipt { my $request = shift; my $courseid = $ENV{'request.course.id'}; - my $receipt = unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}).'-'. + my $receipt = &Apache::lonnet::recprefix($courseid).'-'. $ENV{'form.receipt'}; $receipt =~ s/[^\-\d]//g; my $url = $ENV{'form.url'}; @@ -3445,6 +3445,30 @@ sub scantron_scantab { return $result; } +sub scantron_CODElist { + my $cdom = $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; + my $cnum = $ENV{'course.'.$ENV{'request.course.id'}.'.num'}; + my @names=&Apache::lonnet::getkeys('CODEs',$cdom,$cnum); + my $namechoice='<option></option>'; + foreach my $name (@names) { + $namechoice.='<option value="'.$name.'">'.$name.'</option>'; + } + $namechoice='<select name="scantron_CODElist">'.$namechoice.'</select>'; + return $namechoice; +} + +sub scantron_CODEunique { + my $result='<nobr> + <input type="radio" name="scantron_CODEunique" + value="Yes" checked="on" /> Yes + </nobr> + <nobr> + <input type="radio" name="scantron_CODEunique" + value="No" /> No + </nobr>'; + return $result; +} + sub scantron_selectphase { my ($r) = @_; my ($symb,$url)=&get_symb_and_url($r); @@ -3454,6 +3478,8 @@ sub scantron_selectphase { my $grading_menu_button=&show_grading_menu_form($symb,$url); my $file_selector=&scantron_uploads(); my $format_selector=&scantron_scantab(); + my $CODE_selector=&scantron_CODElist(); + my $CODE_unique=&scantron_CODEunique(); my $result; #FIXME allow instructor to be able to download the scantron file # and to upload it, @@ -3480,6 +3506,12 @@ sub scantron_selectphase { <td> Format of data file: </td><td> $format_selector </td> </tr> <tr bgcolor="#ffffe6"> + <td> Saved CODEs to validate against: </td><td> $CODE_selector</td> + </tr> + <tr bgcolor="#ffffe6"> + <td> Each CODE is only to be used once:</td><td> $CODE_unique </td> + </tr> + <tr bgcolor="#ffffe6"> <td> <!-- FIXME this is lazy, a single parse of the set should let me know what this is --> Last line to expect an answer on: </td><td> @@ -3603,7 +3635,7 @@ sub scantron_fixup_scanline { my ($scantron_config,$scan_data,$line,$whichline,$field,$args)=@_; if ($field eq 'ID') { if (length($args->{'newid'}) > $$scantron_config{'IDlength'}) { - return ($line,1,'New value to large'); + return ($line,1,'New value too large'); } if (length($args->{'newid'}) < $$scantron_config{'IDlength'}) { $args->{'newid'}=sprintf('%-'.$$scantron_config{'IDlength'}.'s', @@ -3615,6 +3647,19 @@ sub scantron_fixup_scanline { &scan_data($scan_data,"$whichline.user", $args->{'username'}.':'.$args->{'domain'}); } + } elsif ($field eq 'CODE') { + if (length($args->{'CODE'}) > $$scantron_config{'CODElength'}) { + return ($line,1,'New CODE value too large'); + } + if (length($args->{'CODE'}) < $$scantron_config{'CODElength'}) { + $args->{'CODE'}=sprintf('%-'.$$scantron_config{'CODElength'}.'s', + $args->{'CODE'}); + } + substr($line,$$scantron_config{'CODEstart'}-1, + $$scantron_config{'CODElength'})=$args->{'CODE'}; + if ($args->{'CODE'}=~/^\s*$/) { + &scan_data($scan_data,"$whichline.CODE",$args->{'CODE'}); + } } elsif ($field eq 'answer') { my $length=$scantron_config->{'Qlength'}; my $off=$scantron_config->{'Qoff'}; @@ -3748,6 +3793,11 @@ sub scantron_process_corrections { 'ID',{'newid'=>$newid, 'username'=>$ENV{'form.scantron_username'}, 'domain'=>$ENV{'form.scantron_domain'}}); + } elsif ($ENV{'form.scantron_corrections'} =~ /^(duplicate|incorrect)CODE$/) { + my $newCODE=$ENV{'form.scantron_CODE'}; + ($line,$err,$errmsg)= + &scantron_fixup_scanline(\%scantron_config,$scan_data,$line,$which, + 'CODE',{'CODE'=>$newCODE}); } elsif ($ENV{'form.scantron_corrections'} =~ /^(missing|double)bubble$/) { foreach my $question (split(',',$ENV{'form.scantron_questions'})) { ($line,$err,$errmsg)= @@ -3941,7 +3991,7 @@ sub scantron_validate_ID { $line,'duplicateID',$username); return(1); } - #FIXME store away line we prviously saw the ID on to use above + #FIXME store away line we previously saw the ID on to use above $found{'ids'}{$found}++; $found{'usernames'}{$username}++; } else { @@ -3988,7 +4038,7 @@ sub scantron_get_correction { $r->print('<input type="hidden" name="scantron_corrections" value="'.$error.'" />'."\n"); $r->print('<input type="hidden" name="scantron_line" value="'.$i.'" />'."\n"); if ($error =~ /ID$/) { - if ($error eq 'unknownID') { + if ($error eq 'incorrectID') { $r->print("The encoded ID is not in the classlist</p>\n"); } elsif ($error eq 'duplicateID') { $r->print("The encoded ID has also been used by a previous paper $arg</p>\n"); @@ -4006,9 +4056,23 @@ sub scantron_get_correction { 'scantron_username','scantron_domain')); $r->print(": <input type='text' name='scantron_username' value='' />"); $r->print("\n@". - &Apache::loncommon::select_dom_form($ENV{'request.role..domain'},'scantron_domain')); + &Apache::loncommon::select_dom_form($ENV{'request.role.domain'},'scantron_domain')); $r->print('</li>'); + } elsif ($error =~ /CODE$/) { + if ($error eq 'incorrectCODE') { + $r->print("The encoded CODE is not in the list of possible CODEs</p>\n"); + } elsif ($error eq 'duplicateCODE') { + $r->print("The encoded CODE has also been used by a previous paper $arg, and CODEs were supposed to be unique</p>\n"); + } + $r->print("<p>The ID on the form is <tt>". + $$scan_record{'scantron.ID'}."</tt><br />\n"); + $r->print("The name on the paper is ". + $$scan_record{'scantron.LastName'}.",". + $$scan_record{'scantron.FirstName'}."</p>"); + $r->print("<p>How should I handle this? <br /> \n"); + $r->print("\n<ul><li> "); + $r->print('</li>'); } elsif ($error eq 'doublebubble') { #FIXME Need to print out who this is along with the paper info $r->print("<p>There have been multiple bubbles scanned for a some question(s)</p>\n"); @@ -4060,6 +4124,48 @@ sub scantron_bubble_selector { sub scantron_validate_CODE { my ($r,$currentphase) = @_; #FIXME doesn't do anything yet + my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'}); + if ($scantron_config{'CODElocation'} && + $scantron_config{'CODEstart'} && + $scantron_config{'CODElength'}) { + if (!$ENV{'form.scantron_CODElist'}) { + &FIXME_blow_up() + } + } else { + &Apache::lonnet::logthis(" CODE stuf $scantron_config{'CODElocation'}:$scantron_config{'CODEstart'}:$scantron_config{'CODElength'}"); + return (0,$currentphase+1); + } + + my %usedCODEs; + + my $old_name=$ENV{'form.scantron_CODElist'}; + my $cdom =$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; + my $cnum =$ENV{'course.'.$ENV{'request.course.id'}.'.num'}; + my %result=&Apache::lonnet::get('CODEs',[$old_name],$cdom,$cnum); + my %allcodes=map {($_,1)} split(',',$result{$old_name}); + + my ($scanlines,$scan_data)=&scantron_getfile(); + for (my $i=0;$i<=$scanlines->{'count'};$i++) { + my $line=&scantron_get_line($scanlines,$i); + if ($line=~/^[\s\cz]*$/) { next; } + my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config, + $scan_data); + my $CODE=$$scan_record{'scantron.CODE'}; + my $error=0; + if (!exists($allcodes{$CODE})) { + &scantron_get_correction($r,$i,$scan_record, + \%scantron_config, + $line,'incorrectCODE',$CODE); + return(1); + } + if (exists($usedCODEs{$CODE}) && $ENV{'form.scantron_CODEunique'}) { + &scantron_get_correction($r,$i,$scan_record, + \%scantron_config, + $line,'duplicateCODE',$CODE); + return(1); + } + $usedCODEs{$CODE}++; + } return (0,$currentphase+1); } @@ -4238,11 +4344,21 @@ UPLOAD sub scantron_upload_scantron_data_save { my($r)=@_; + my ($symb,$url)=&get_symb_and_url($r,1); + my $doanotherupload= + '<br /><form action="/adm/grades" method="post">'."\n". + '<input type="hidden" name="command" value="scantronupload" />'."\n". + '<input type="submit" name="submit" value="Do Another Upload" />'."\n". + '</form>'."\n"; if (!&Apache::lonnet::allowed('usc',$ENV{'form.domainid'}) && !&Apache::lonnet::allowed('usc', $ENV{'form.domainid'}.'_'.$ENV{'form.courseid'})) { $r->print("You are not allowed to upload Scantron data to the requested course.<br />"); - $r->print(&show_grading_menu_form(&get_symb_and_url($r))); + if ($symb) { + $r->print(&show_grading_menu_form($symb,$url)); + } else { + $r->print($doanotherupload); + } return ''; } $r->print("Doing upload to ".$ENV{'form.courseid'}." <br />"); @@ -4263,17 +4379,20 @@ sub scantron_upload_scantron_data_save { # See if there is anything left unless ($fname) { return 'error: no uploaded file'; } $fname='scantron_orig_'.$fname; - $r->print(&Apache::lonnet::finishuserfileupload($ENV{'form.courseid'}, - $ENV{'form.domainid'}, - $home,'upfile',$fname)); - my ($symb,$url)=&get_symb_and_url($r); + if (length($ENV{'form.upfile'}) < 2) { + $r->print("<font color='red'>Error:</font> The file you attempted to upload, <tt>".&HTML::Entities::encode($ENV{'form.upfile.filename'},'<>&"')."</tt>, contained no information. Please check that you entered the correct filename."); + } else { + my $result=&Apache::lonnet::finishuserfileupload($ENV{'form.courseid'},$ENV{'form.domainid'},$home,'upfile',$fname); + if ($result =~ m|^/uploaded/|) { + $r->print("<font color='green'>Success:</font> Successfully uploaded ".(length($ENV{'form.upfile'})-1)." bytes of data into location <tt>".$result."</tt>"); + } else { + $r->print("<font color='red'>Error:</font> An error (".$result.") occured when attempting to upload the file, <tt>".&HTML::Entities::encode($ENV{'form.upfile.filename'},'<>&"')."</tt>"); + } + } if ($symb) { - $r->print(&show_grading_menu_form(&get_symb_and_url($r))); + $r->print(&show_grading_menu_form($symb,$url)); } else { - $r->print('<br /><form action="/adm/grades" method="post">'."\n". - '<input type="hidden" name="command" value="scantronupload" />'."\n". - '<input type="submit" name="submit" value="Do Another Upload" />'."\n". - '</form>'."\n"); + $r->print($doanotherupload); } return ''; } @@ -4428,17 +4547,18 @@ GRADINGMENUJS $result.='<table width="100%" border=0>'; $result.='<tr bgcolor="#ffffe6"><td>'. - '<input type="button" onClick="javascript:checkChoice(this.form,\'3\',\'csvform\');" value="Upload" />'. - ' scores from file </td></tr>'."\n"; + '<input type="button" onClick="javascript:checkChoice(this.form,\'3\',\'csvform\');" value="'.&mt('Upload').'" />'. + ' '.&mt('scores from file').' </td></tr>'."\n"; $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'. '<input type="button" onClick="javascript:checkChoice(this.form,\'4\',\'scantron_selectphase\');'. - '" value="Grade" /> scantron forms</td></tr>'."\n"; + '" value="'.&mt('Grade').'" /> scantron forms</td></tr>'."\n"; if ((&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'})) && ($symb)) { $result.='<tr bgcolor="#ffffe6"valign="top"><td>'. - '<input type="button" onClick="javascript:checkChoice(this.form,\'5\',\'verify\');" value="Verify" />'. - ' submission Receipt no: '.unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}). + '<input type="button" onClick="javascript:checkChoice(this.form,\'5\',\'verify\');" value="'.&mt('Verify').'" />'. + ' '.&mt('receipt').': '. + &Apache::lonnet::recprefix($ENV{'request.course.id'}). '-<input type="text" name="receipt" size="4" onChange="javascript:checkReceiptNo(this.form,\'OK\')">'. '</td></tr>'."\n"; }