[LON-CAPA-cvs] cvs: loncom /homework grades.pm response.pm
raeburn
raeburn@source.lon-capa.org
Fri, 06 Mar 2009 16:13:29 -0000
This is a MIME encoded message
--raeburn1236356009
Content-Type: text/plain
raeburn Fri Mar 6 16:13:29 2009 EDT
Modified files:
/loncom/homework grades.pm response.pm
Log:
- Verification of Scantron grading for problems containing randomlists
- &scantron_partids_tograde()
- changed to use &get_analyze() to retrieve partIDs/responseIDs
- subroutine moved to be within scope of %analyze_cache.
- needs to be called for each user (randomlist -> possibly different responseIDs for different users).
- Robustness against changes to lonxml::counter being made by multitasking instructors.
- scantron_questnum_start.$part.$id form element passed in ssi call for scantron grading.
- where available, this value is used within response::getresponse() instead of lonxml::counter to determine starting column for scantron line.
- Second pass (if optional inbuilt verification enabled during scantron grading).
- Added missing call to repeat &grade_student_bubbles() when anomaly is detected during first pass.
****
Work-in-progress - possible performance hit - perhaps check if resource includes <randomlist></randomlist> before calling &scantron_partids_tograde() for each user?
--raeburn1236356009
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20090306161329.txt"
Index: loncom/homework/grades.pm
diff -u loncom/homework/grades.pm:1.553 loncom/homework/grades.pm:1.554
--- loncom/homework/grades.pm:1.553 Tue Feb 24 17:12:19 2009
+++ loncom/homework/grades.pm Fri Mar 6 16:13:29 2009
@@ -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 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 @@
}
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 @@
$env{"form.scantron.responsetype.$line"};
$line++;
}
-
}
# Given the parsed scanline, get the response for
@@ -4778,7 +4799,6 @@
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 @@
%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 @@
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 @@
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)."<br />");
+ my ($uname,$udom);
my $result= <<SCANTRONFORM;
<form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantronupload">
<input type="hidden" name="command" value="scantron_configphase" />
@@ -7440,7 +7426,6 @@
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 @@
}
($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 @@
}
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("</form>");
&ssi_print_error($r);
@@ -7515,19 +7507,32 @@
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("</form>");
+ &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 @@
}
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 @@
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('
<form method="post" enctype="multipart/form-data" action="/adm/grades" name="checkscantron">'."\n");
@@ -7822,9 +7835,12 @@
($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 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 @@
}
}
}
- 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++) {
Index: loncom/homework/response.pm
diff -u loncom/homework/response.pm:1.210 loncom/homework/response.pm:1.211
--- loncom/homework/response.pm:1.210 Tue Dec 23 18:09:36 2008
+++ loncom/homework/response.pm Fri Mar 6 16:13:29 2009
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# various response type definitons response definition
#
-# $Id: response.pm,v 1.210 2008/12/23 18:09:36 raeburn Exp $
+# $Id: response.pm,v 1.211 2009/03/06 16:13:29 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -948,13 +948,17 @@
my $id = $Apache::inputtags::response[-1];
my $line;
+ my $startline = $env{'form.scantron_questnum_start.'.$part.'.'.$id};
+ if (!$startline) {
+ $startline = $Apache::lonxml::counter;
+ }
for ($line = 0; $line < $lines; $line++) {
- my $theline = $Apache::lonxml::counter+$offset-1+$line;
+ my $theline = $startline+$offset-1+$line;
$response = $env{"scantron.$theline.answer"};
if ((defined($response)) && ($response ne "") && ($response ne " ")) {
last;
}
-
+
}
# save bubbled letter for later
--raeburn1236356009--