--- loncom/homework/grades.pm 2004/04/29 07:21:16 1.192 +++ loncom/homework/grades.pm 2004/05/06 06:49:48 1.195 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.192 2004/04/29 07:21:16 albertel Exp $ +# $Id: grades.pm,v 1.195 2004/05/06 06:49:48 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -3729,7 +3729,7 @@ sub scan_data { } sub scantron_parse_scanline { - my ($line,$whichline,$scantron_config,$scan_data,$justCODE)=@_; + my ($line,$whichline,$scantron_config,$scan_data,$justHeader)=@_; my %record; my $questions=substr($line,$$scantron_config{'Qstart'}-1); my $data=substr($line,0,$$scantron_config{'Qstart'}-1); @@ -3748,7 +3748,6 @@ sub scantron_parse_scanline { #FIXME interpret first N questions } } - if ($justCODE) { return \%record; } $record{'scantron.ID'}=substr($data,$$scantron_config{'IDstart'}-1, $$scantron_config{'IDlength'}); $record{'scantron.PaperID'}= @@ -3760,6 +3759,8 @@ sub scantron_parse_scanline { $record{'scantron.LastName'}= substr($data,$$scantron_config{'LastName'}-1, $$scantron_config{'LastNamelength'}); + if ($justHeader) { return \%record; } + my @alphabet=('A'..'Z'); my $questnum=0; while ($questions) { @@ -3850,6 +3851,8 @@ sub scantron_process_corrections { $newCODE=$ENV{'form.scantron_CODE_selectedvalue'}; } elsif ($resolution eq 'use_typed') { $newCODE=$ENV{'form.scantron_CODE_newvalue'}; + } elsif ($resolution =~ /^use_closest_(\d+)/) { + $newCODE=$ENV{"form.scantron_CODE_closest_$1"}; } if ($ENV{'form.scantron_corrections'} eq 'duplicateCODE') { $args{'CODE_ignore_dup'}=1; @@ -3884,7 +3887,6 @@ sub scantron_validate_file { my $default_form_data=&defaultFormData($symb,$url); if ($ENV{'form.scantron_options_ignore'} eq 'ignore_corrections') { my $result=&scantron_remove('corrected'); - &Apache::lonnet::logthis("result was $result"); if ($result ne 'ok' && $result ne 'not_found' ) { $r->print("An error occured ($result) when trying to Remove the existing corrections."); } @@ -3916,14 +3918,10 @@ SCANTRONFORM 'doublebubble', 'missingbubbles'); if (!$ENV{'form.validatepass'}) { - $ENV{'form.valiadatepass'} = 0; + $ENV{'form.validatepass'} = 0; } - my $currentphase=$ENV{'form.valiadatepass'}; + my $currentphase=$ENV{'form.validatepass'}; - if ($ENV{'form.scantron_selectfile'}=~m-^/-) { - #first pass copy file to classdir - - } my $stop=0; while (!$stop && $currentphase < scalar(@validate_phases)) { $r->print("<p> Validating ".$validate_phases[$currentphase]."</p>"); @@ -3964,20 +3962,15 @@ sub scantron_remove { return 'refused'; } $file.=$ENV{'form.scantron_selectfile'}; - &Apache::lonnet::logthis("removeing $file"); my $result=&Apache::lonnet::removeuserfile($cname,$cdom,$file); my @keys=&Apache::lonnet::getkeys('nohist_scantrondata',$cdom,$cname); - &Apache::lonnet::logthis('got keys '.join(':',@keys)); - &Apache::lonnet::logthis("cdom $cdom cname $cname"); my @todelete; my $filename=$ENV{'form.scantron_selectfile'}; - &Apache::lonnet::logthis('filename '.$filename); foreach my $key (@keys) { if ($key=~/^\Q$filename\E_/) { push(@todelete,$key); } } - &Apache::lonnet::logthis('todelete '.join(':',@todelete)); if (@todelete) { &Apache::lonnet::del('nohist_scantrondata',\@todelete,$cdom,$cname); } @@ -4089,11 +4082,11 @@ sub scantron_validate_ID { if ($found{'ids'}{$found}) { &scantron_get_correction($r,$i,$scan_record,\%scantron_config, $line,'duplicateID',$found); - return(1); + return(1,$currentphase); } elsif ($found{'usernames'}{$username}) { &scantron_get_correction($r,$i,$scan_record,\%scantron_config, $line,'duplicateID',$username); - return(1); + return(1,$currentphase); } #FIXME store away line we previously saw the ID on to use above $found{'ids'}{$found}++; @@ -4105,18 +4098,18 @@ sub scantron_validate_ID { &scantron_get_correction($r,$i,$scan_record, \%scantron_config, $line,'duplicateID',$username); - return(1); + return(1,$currentphase); } elsif (!defined($username)) { &scantron_get_correction($r,$i,$scan_record, \%scantron_config, $line,'incorrectID'); - return(1); + return(1,$currentphase); } $found{'usernames'}{$username}++; } else { &scantron_get_correction($r,$i,$scan_record,\%scantron_config, $line,'incorrectID'); - return(1); + return(1,$currentphase); } } } @@ -4167,7 +4160,7 @@ sub scantron_get_correction { if ($error eq 'incorrectCODE') { $r->print("</p><p>The encoded CODE is not in the list of possible CODEs</p>\n"); } elsif ($error eq 'duplicateCODE') { - $r->print("</p><p>The encoded CODE has also been used by a previous paper $arg, and CODEs were supposed to be unique</p>\n"); + $r->print("</p><p>The encoded CODE has also been used by a previous paper ".join(', ',@{$arg}).", and CODEs are supposed to be unique</p>\n"); } $r->print("<p>The CODE on the form is <tt>". $$scan_record{'scantron.CODE'}."</tt><br />\n"); @@ -4178,8 +4171,21 @@ sub scantron_get_correction { $$scan_record{'scantron.FirstName'}."</p>"); $r->print("<p>How should I handle this? <br /> \n"); $r->print("\n<br /> "); - $r->print("<input type='radio' name='scantron_CODE_resolution' value='use_unfound' checked='on' /> Use the CODE <b><tt>".$$scan_record{'scantron.CODE'}."</tt></b> that is was on the paper, ignoring the error."); + my $i=0; + if ($error eq 'incorrectCODE') { + my ($max,$closest)=&scantron_get_closely_matching_CODEs($arg,$$scan_record{'scantron.CODE'}); + foreach my $testcode (@{$closest}) { + my $checked=''; + if (!$i) { $checked=' checked="on" '; } + $r->print("<input type='radio' name='scantron_CODE_resolution' value='use_closest_$i' $checked /> Use the similar CODE <b><tt>".$testcode."</tt></b> instead.<input type='hidden' name='scantron_CODE_closest_$i' value='$testcode' />"); + $r->print("\n<br />"); + $i++; + } + } + my $checked; if (!$i) { $checked=' checked="on" '; } + $r->print("<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."); $r->print("\n<br />"); + $r->print(<<ENDSCRIPT); <script type="text/javascript"> function change_radio(field) { @@ -4202,7 +4208,6 @@ ENDSCRIPT $r->print("<input type='radio' name='scantron_CODE_resolution' value='use_typed' /> Use <input type='text' size='8' name='scantron_CODE_newvalue' onfocus=\"javascript:change_radio('use_typed')\" onkeypress=\"javascript:change_radio('use_typed')\" /> as the CODE."); $r->print("\n<br /><br />"); } 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"); $r->print('<input type="hidden" name="scantron_questions" value="'. join(',',@{$arg}).'" />'); @@ -4249,9 +4254,38 @@ sub scantron_bubble_selector { $r->print('</tr></table>'); } +sub num_matches { + my ($orig,$code) = @_; + my @code=split(//,$code); + my @orig=split(//,$orig); + my $same=0; + for (my $i=0;$i<scalar(@code);$i++) { + if ($code[$i] eq $orig[$i]) { $same++; } + } + return $same; +} + +sub scantron_get_closely_matching_CODEs { + my ($allcodes,$CODE)=@_; + my @CODEs; + foreach my $testcode (sort(keys(%{$allcodes}))) { + push(@{$CODEs[&num_matches($CODE,$testcode)]},$testcode); + } + + return ($#CODEs,$CODEs[-1]); +} + +sub get_codes { + 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 {(&Apache::lonprintout::num_to_letters($_),1)} split(',',$result{$old_name}); + return %allcodes; +} + 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'} && @@ -4265,11 +4299,7 @@ sub scantron_validate_CODE { 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 {(&Apache::lonprintout::num_to_letters($_),1)} split(',',$result{$old_name}); + my %allcodes=&get_codes(); my ($scanlines,$scan_data)=&scantron_getfile(); for (my $i=0;$i<=$scanlines->{'count'};$i++) { @@ -4282,17 +4312,17 @@ sub scantron_validate_CODE { if (!exists($allcodes{$CODE}) && !$$scan_record{'scantron.useCODE'}) { &scantron_get_correction($r,$i,$scan_record, \%scantron_config, - $line,'incorrectCODE',$CODE); - return(1); + $line,'incorrectCODE',\%allcodes); + return(1,$currentphase); } if (exists($usedCODEs{$CODE}) && $ENV{'form.scantron_CODEunique'} && !$$scan_record{'scantron.CODE_ignore_dup'}) { &scantron_get_correction($r,$i,$scan_record, \%scantron_config, - $line,'duplicateCODE',$CODE); - return(1); + $line,'duplicateCODE',$usedCODEs{$CODE}); + return(1,$currentphase); } - $usedCODEs{$CODE}++; + push (@{$usedCODEs{$CODE}},$$scan_record{'scantron.PaperID'}); } return (0,$currentphase+1); } @@ -4403,7 +4433,8 @@ SCANTRONFORM my %completedstudents; my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Scantron Status', - 'Scantron Progress',$scanlines->{'count'}); + 'Scantron Progress',$scanlines->{'count'}, + 'inline',undef,'scantronupload'); &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state, 'Processing first student'); my $start=&Time::HiRes::time(); @@ -4434,13 +4465,18 @@ SCANTRONFORM my $i=0; foreach my $resource (@resources) { $i++; - my $result=&Apache::lonnet::ssi($resource->src(), - ('submitted' =>'scantron', - 'grade_target' =>'grade', - 'grade_username'=>$uname, - 'grade_domain' =>$udom, - 'grade_courseid'=>$ENV{'request.course.id'}, - 'grade_symb' =>$resource->symb())); + my %form=('submitted' =>'scantron', + 'grade_target' =>'grade', + 'grade_username'=>$uname, + 'grade_domain' =>$udom, + 'grade_courseid'=>$ENV{'request.course.id'}, + 'grade_symb' =>$resource->symb()); + if (exists($scan_record->{'scantron.CODE'}) && + $scan_record->{'scantron.CODE'}) { + $form{'CODE'}=$scan_record->{'scantron.CODE'}; + } + my $result=&Apache::lonnet::ssi($resource->src(),%form); + } $completedstudents{$uname}={'line'=>$line}; } continue {