--- loncom/homework/grades.pm 2009/02/24 17:12:19 1.553 +++ loncom/homework/grades.pm 2009/03/06 16:13:29 1.554 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.553 2009/02/24 17:12:19 biermanm Exp $ +# $Id: grades.pm,v 1.554 2009/03/06 16:13:29 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -274,6 +274,28 @@ sub reset_caches { } } } + + sub scantron_partids_tograde { + my ($resource,$cid,$uname,$udom) = @_; + my (%analysis,@parts); + if (ref($resource)) { + my $symb = $resource->symb(); + my $analyze = &get_analyze($symb,$uname,$udom); + if (ref($analyze) eq 'HASH') { + %analysis = %{$analyze}; + } + if (ref($analysis{'parts'}) eq 'ARRAY') { + foreach my $part (@{$analysis{'parts'}}) { + my ($id,$respid) = split(/\./,$part); + if (!&Apache::loncommon::check_if_partid_hidden($id,$symb,$udom,$uname)) { + push(@parts,$part); + } + } + } + } + return (\%analysis,\@parts); + } + } #--- Clean response type for display @@ -4728,7 +4750,7 @@ sub getSequenceDropDown { } my %bubble_lines_per_response; # no. bubble lines for each response. - # index is "symb.part_id" + # key is zero-based index - 0, 1, 2 ... my %first_bubble_line; # First bubble line no. for each bubble. @@ -4769,7 +4791,6 @@ sub restore_bubble_lines { $env{"form.scantron.responsetype.$line"}; $line++; } - } # Given the parsed scanline, get the response for @@ -4778,7 +4799,6 @@ sub restore_bubble_lines { sub get_response_bubbles { my ($parsed_line, $response) = @_; - my $bubble_line = $first_bubble_line{$response-1} +1; my $bubble_lines= $bubble_lines_per_response{$response-1}; @@ -7243,7 +7263,7 @@ sub scantron_get_maxbubble { %first_bubble_line = (); %subdivided_bubble_lines = (); %responsetype_per_response = (); - + my $response_number = 0; my $bubble_line = 0; foreach my $resource (@resources) { @@ -7310,33 +7330,6 @@ sub scantron_get_maxbubble { return $env{'form.scantron_maxbubble'}; } -sub scantron_partids_tograde { - my ($resource,$cid,$uname,$udom) = @_; - my (%analysis,@parts); - - if (ref($resource)) { - my $symb = $resource->symb(); - my $result=&ssi_with_retries($resource->src(), $ssi_retries, - ('symb' => $symb, - 'grade_target' => 'analyze', - 'grade_courseid' => $cid, - 'grade_domain' => $udom, - 'grade_username' => $uname)); - my (undef, $an) = split(/_HASH_REF__/,$result, 2); - %analysis = &Apache::lonnet::str2hash($an); - - if (ref($analysis{'parts'}) eq 'ARRAY') { - foreach my $part (@{$analysis{'parts'}}) { - my ($id,$respid) = split(/\./,$part); - if (!&Apache::loncommon::check_if_partid_hidden($id,$symb,$udom,$uname)) { - push(@parts,$part); - } - } - } - } - return (\%analysis,\@parts); -} - sub scantron_validate_missingbubbles { my ($r,$currentphase) = @_; #get student info @@ -7408,15 +7401,8 @@ sub scantron_process_students { my $navmap=Apache::lonnavmaps::navmap->new(); my $map=$navmap->getResourceByUrl($sequence); my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); - - my ($uname,$udom,%partids_by_symb); - foreach my $resource (@resources) { - my $ressymb = $resource->symb(); - my ($analysis,$parts) = - &scantron_partids_tograde($resource,$env{'request.course.id'},$uname,$udom); - $partids_by_symb{$ressymb} = $parts; - } # $r->print("geto ".scalar(@resources)."
"); + my ($uname,$udom); my $result= < @@ -7440,7 +7426,6 @@ SCANTRONFORM my $started; &scantron_get_maxbubble(); # Need the bubble lines array to parse. - # If an ssi failed in scantron_get_maxbubble, put an error message out to # the user and return. @@ -7481,6 +7466,13 @@ SCANTRONFORM } ($uname,$udom)=split(/:/,$uname); + my %partids_by_symb; + foreach my $resource (@resources) { + my $ressymb = $resource->symb(); + my ($analysis,$parts) = + &scantron_partids_tograde($resource,$env{'request.course.id'},$uname,$udom); $partids_by_symb{$ressymb} = $parts; + } + &Apache::lonxml::clear_problem_counter(); &Apache::lonnet::appenv($scan_record); @@ -7497,7 +7489,7 @@ SCANTRONFORM } if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode, - @resources) eq 'ssi_error') { + \@resources,\%partids_by_symb) eq 'ssi_error') { $ssi_error = 0; # So end of handler error message does not trigger. $r->print(""); &ssi_print_error($r); @@ -7515,19 +7507,32 @@ SCANTRONFORM my $studentrecord = ''; my $counter = -1; foreach my $resource (@resources) { + my $ressymb = $resource->symb(); ($counter,my $recording) = &verify_scantron_grading($resource,$udom,$uname,$env{'request.course.id'}, - $counter,$studentdata,\%partids_by_symb, + $counter,$studentdata,$partids_by_symb{$ressymb}, \%scantron_config,\%lettdig,$numletts); $studentrecord .= $recording; } if ($studentrecord ne $studentdata) { + &Apache::lonxml::clear_problem_counter(); + if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode, + \@resources,\%partids_by_symb) eq 'ssi_error') { + $ssi_error = 0; # So end of handler error message does not trigger. + $r->print(""); + &ssi_print_error($r); + $r->print(&show_grading_menu_form($symb)); + &Apache::lonnet::remove_lock($lock); + delete($completedstudents{$uname}); + return ''; + } $counter = -1; $studentrecord = ''; foreach my $resource (@resources) { + my $ressymb = $resource->symb(); ($counter,my $recording) = &verify_scantron_grading($resource,$udom,$uname,$env{'request.course.id'}, - $counter,$studentdata,\%partids_by_symb, + $counter,$studentdata,$partids_by_symb{$ressymb}, \%scantron_config,\%lettdig,$numletts); $studentrecord .= $recording; } @@ -7577,18 +7582,32 @@ SCANTRONFORM } sub grade_student_bubbles { - my ($r,$uname,$udom,$scan_record,$scancode,@resources) = @_; - foreach my $resource (@resources) { - my %form = ('submitted' => 'scantron', - 'grade_target' => 'grade', - 'grade_username'=> $uname, - 'grade_domain' => $udom, - 'grade_courseid'=> $env{'request.course.id'}, - 'grade_symb' => $resource->symb(), - 'CODE' => $scancode); - my $result=&ssi_with_retries($resource->src(),$ssi_retries,%form); - return 'ssi_error' if ($ssi_error); - last if (&Apache::loncommon::connection_aborted($r)); + my ($r,$uname,$udom,$scan_record,$scancode,$resources,$parts) = @_; + if (ref($resources) eq 'ARRAY') { + my $count = 0; + foreach my $resource (@{$resources}) { + my $ressymb = $resource->symb(); + my %form = ('submitted' => 'scantron', + 'grade_target' => 'grade', + 'grade_username' => $uname, + 'grade_domain' => $udom, + 'grade_courseid' => $env{'request.course.id'}, + 'grade_symb' => $ressymb, + 'CODE' => $scancode + ); + if (ref($parts) eq 'HASH') { + if (ref($parts->{$ressymb}) eq 'ARRAY') { + foreach my $part (@{$parts->{$ressymb}}) { + $form{'scantron_questnum_start.'.$part} = + 1+$env{'form.scantron.first_bubble_line.'.$count}; + $count++; + } + } + } + my $result=&ssi_with_retries($resource->src(),$ssi_retries,%form); + return 'ssi_error' if ($ssi_error); + last if (&Apache::loncommon::connection_aborted($r)); + } } return; } @@ -7761,13 +7780,7 @@ sub checkscantron_results { my $navmap=Apache::lonnavmaps::navmap->new(); my $map=$navmap->getResourceByUrl($sequence); my @resources=$navmap->retrieveResources($map,undef,1,0); - my ($uname,$udom,%partids_by_symb); - foreach my $resource (@resources) { - my $ressymb = $resource->symb(); - my ($analysis,$parts) = - &scantron_partids_tograde($resource,$env{'request.course.id'},$uname,$udom); - $partids_by_symb{$ressymb} = $parts; - } + my ($uname,$udom); my (%scandata,%lastname,%bylast); $r->print('
'."\n"); @@ -7822,9 +7835,12 @@ sub checkscantron_results { ($username,$domain)=split(/:/,$uname); my $counter = -1; foreach my $resource (@resources) { + my $ressymb = $resource->symb(); + my ($analysis,$parts) = + &scantron_partids_tograde($resource,$env{'request.course.id'},$username,$domain); ($counter,my $recording) = &verify_scantron_grading($resource,$domain,$username,$cid,$counter, - $scandata{$pid},\%partids_by_symb, + $scandata{$pid},$parts, \%scantron_config,\%lettdig,$numletts); $record{$pid} .= $recording; } @@ -7889,15 +7905,14 @@ sub checkscantron_results { } sub verify_scantron_grading { - my ($resource,$domain,$username,$cid,$counter,$scandata,$partids_by_symb, + my ($resource,$domain,$username,$cid,$counter,$scandata,$partids, $scantron_config,$lettdig,$numletts) = @_; my ($record,%expected,%startpos); return ($counter,$record) if (!ref($resource)); return ($counter,$record) if (!$resource->is_problem()); my $symb = $resource->symb(); - return ($counter,$record) if (ref($partids_by_symb) ne 'HASH'); - return ($counter,$record) if (ref($partids_by_symb->{$symb}) ne 'ARRAY'); - foreach my $part_id (@{$partids_by_symb->{$symb}}) { + return ($counter,$record) if (ref($partids) ne 'ARRAY'); + foreach my $part_id (@{$partids}) { $counter ++; $expected{$part_id} = 0; if ($env{"form.scantron.sub_bubblelines.$counter"}) { @@ -7990,7 +8005,7 @@ sub verify_scantron_grading { } } } - foreach my $part_id (@{$partids_by_symb->{$symb}}) { + foreach my $part_id (@{$partids}) { if ($recorded{$part_id} eq '') { for (my $i=0; $i<$expected{$part_id}; $i++) { for (my $j=0; $j<$scantron_config->{'Qlength'}; $j++) {