';
my %newrecord=();
@@ -4596,10 +4602,10 @@ sub updateGradeByPage {
}
my $display_part=&get_display_part($partid,$curRes->symb());
my $oldstatus = $env{'form.solved'.$question.'_'.$partid};
- $displayPts[0].=' Part: '.$display_part.' = '.
+ $displayPts[0].=' '.&mt('Part').': '.$display_part.' = '.
(($oldstatus eq 'excused') ? 'excused' : $oldpts).
' ';
- $displayPts[1].=' Part: '.$display_part.' = '.
+ $displayPts[1].=' '.&mt('Part').': '.$display_part.' = '.
(($score eq 'excused') ? 'excused' : $newpts).
' ';
$question++;
@@ -4648,9 +4654,9 @@ sub updateGradeByPage {
$studentTable.=&Apache::loncommon::end_data_table();
$studentTable.=&show_grading_menu_form($env{'form.symb'});
- my $grademsg=($changeflag == 0 ? 'No score was changed or updated.' :
- 'The scores were changed for '.
- $changeflag.' problem'.($changeflag == 1 ? '.' : 's.'));
+ my $grademsg=($changeflag == 0 ? &mt('No score was changed or updated.') :
+ &mt('The scores were changed for [quant,_1,problem].',
+ $changeflag));
$request->print($grademsg.$studentTable);
return '';
@@ -4834,8 +4840,9 @@ sub get_response_bubbles {
sub scantron_filenames {
my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
my $cname=$env{'course.'.$env{'request.course.id'}.'.num'};
+ my $getpropath = 1;
my @files=&Apache::lonnet::dirlist('userfiles',$cdom,$cname,
- &propath($cdom,$cname));
+ $getpropath);
my @possiblenames;
foreach my $filename (sort(@files)) {
($filename)=split(/&/,$filename);
@@ -4878,19 +4885,76 @@ sub scantron_uploads {
=cut
sub scantron_scantab {
- my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
my $result=''."\n";
-
return $result;
}
+=pod
+
+=item get_scantronformat_file
+
+ Returns an array containing lines from the scantron format file for
+ the domain of the course.
+
+ If a url for a custom.tab file is listed in domain's configuration.db,
+ lines are from this file.
+
+ Otherwise, if a default.tab has been published in RES space by the
+ domainconfig user, lines are from this file.
+
+ Otherwise, fall back to getting lines from the legacy file on the
+ local server: /home/httpd/lonTabs/default_scantronformat.tab
+
+=cut
+
+sub get_scantronformat_file {
+ my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my %domconfig = &Apache::lonnet::get_dom('configuration',['scantron'],$cdom);
+ my $gottab = 0;
+ my @lines;
+ if (ref($domconfig{'scantron'}) eq 'HASH') {
+ if ($domconfig{'scantron'}{'scantronformat'} ne '') {
+ my $formatfile = &Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonDocRoot'}.$domconfig{'scantron'}{'scantronformat'});
+ if ($formatfile ne '-1') {
+ @lines = split("\n",$formatfile,-1);
+ $gottab = 1;
+ }
+ }
+ }
+ if (!$gottab) {
+ my $confname = $cdom.'-domainconfig';
+ my $default = $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'.$cdom.'/'.$confname.'/default.tab';
+ my $formatfile = &Apache::lonnet::getfile($default);
+ if ($formatfile ne '-1') {
+ @lines = split("\n",$formatfile,-1);
+ $gottab = 1;
+ }
+ }
+ if (!$gottab) {
+ my @domains = &Apache::lonnet::current_machine_domains();
+ if (grep(/^\Q$cdom\E$/,@domains)) {
+ my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
+ @lines = <$fh>;
+ close($fh);
+ } else {
+ my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab');
+ @lines = <$fh>;
+ close($fh);
+ }
+ }
+ return @lines;
+}
+
=pod
=item scantron_CODElist
@@ -4923,11 +4987,11 @@ sub scantron_CODElist {
=cut
sub scantron_CODEunique {
- my $result='
+ my $result=''.&mt('Yes').'
-
+ '.&mt('No').' ';
@@ -5086,8 +5150,37 @@ sub scantron_selectphase {
');
&Apache::lonpickcode::code_list($r,2);
+
+ $r->print('
');
$r->print($grading_menu_button);
- return
+ return;
}
=pod
@@ -5149,10 +5242,10 @@ sub scantron_selectphase {
sub get_scantron_config {
my ($which) = @_;
- my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
+ my @lines = &get_scantronformat_file();
my %config;
#FIXME probably should move to XML it has already gotten a bit much now
- foreach my $line (<$fh>) {
+ foreach my $line (@lines) {
my ($name,$descrip)=split(/:/,$line);
if ($name ne $which ) { next; }
chomp($line);
@@ -6759,7 +6852,7 @@ ENDSCRIPT
foreach my $question (@{$arg}) {
my @linenums = &prompt_for_corrections($r,$question,$scan_config,
$scan_record, $error);
- push (@lines_to_correct,@linenums);
+ push(@lines_to_correct,@linenums);
}
$r->print(&verify_bubbles_checked(@lines_to_correct));
} elsif ($error eq 'missingbubble') {
@@ -6779,7 +6872,7 @@ ENDSCRIPT
foreach my $question (@{$arg}) {
my @linenums = &prompt_for_corrections($r,$question,$scan_config,
$scan_record, $error);
- push (@lines_to_correct,@linenums);
+ push(@lines_to_correct,@linenums);
}
$r->print(&verify_bubbles_checked(@lines_to_correct));
} else {
@@ -6937,7 +7030,7 @@ sub prompt_for_corrections {
my $selected = $$scan_record{"scantron.$current_line.answer"};
&scantron_bubble_selector($r,$scan_config,$current_line,
$questionnum,$error,split('', $selected));
- push (@linenums,$current_line);
+ push(@linenums,$current_line);
$current_line++;
}
if ($lines > 1) {
@@ -7153,7 +7246,7 @@ sub scantron_validate_CODE {
$line,'duplicateCODE',$usedCODEs{$CODE});
return(1,$currentphase);
}
- push (@{$usedCODEs{$CODE}},$$scan_record{'scantron.PaperID'});
+ push(@{$usedCODEs{$CODE}},$$scan_record{'scantron.PaperID'});
}
return (0,$currentphase+1);
}
@@ -7241,30 +7334,32 @@ sub scantron_get_maxbubble {
my $bubble_line = 0;
foreach my $resource (@resources) {
my $symb = $resource->symb();
+
+ my (@parts,@allparts,@possible_parts);
+
# Need to retrieve part IDs and response IDs because essayresponse,
# reactionresponse and organicresponse items are not included in
# $analysis{'parts'} from lonnet::ssi.
- my %possible_part_ids;
- if (ref($resource->parts()) eq 'ARRAY') {
+ if (ref($resource->parts()) eq 'ARRAY') {
foreach my $part (@{$resource->parts()}) {
if (!&Apache::loncommon::check_if_partid_hidden($part,$symb,$udom,$uname)) {
my @resp_ids = $resource->responseIds($part);
foreach my $id (@resp_ids) {
- $possible_part_ids{$part.'.'.$id} = 1;
+ my $part_id = $part.'.'.$id;
+ push(@possible_parts,$part_id);
}
}
}
}
- 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);
- my @parts;
+ 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);
my %analysis = &Apache::lonnet::str2hash($an);
@@ -7276,19 +7371,22 @@ sub scantron_get_maxbubble {
}
}
}
- # Add part_ids for any essayresponse items.
- foreach my $part_id (keys(%possible_part_ids)) {
- if (($analysis{$part_id.'.type'} eq 'essayresponse') ||
- ($analysis{$part_id.'.type'} eq 'reactionresponse') ||
- ($analysis{$part_id.'.type'} eq 'organicresponse')) {
- if (!grep(/^\Q$part_id\E$/,@parts)) {
- push (@parts,$part_id);
+ # Add part_ids for any essayresponse, reactionresponse or
+ # organicresponse items.
+ foreach my $part_id (@possible_parts) {
+ if (grep(/^\Q$part_id\E$/,@parts)) {
+ push(@allparts,$part_id);
+ } else {
+ if (($analysis{$part_id.'.type'} eq 'essayresponse') ||
+ ($analysis{$part_id.'.type'} eq 'reactionresponse') ||
+ ($analysis{$part_id.'.type'} eq 'organicresponse')) {
+ push(@allparts,$part_id);
}
}
}
- foreach my $part_id (@parts) {
- my $lines = $analysis{"$part_id.bubble_lines"};
+ foreach my $part_id (@allparts) {
+ my $lines;
# TODO - make this a persistent hash not an array.
@@ -7315,8 +7413,8 @@ sub scantron_get_maxbubble {
$numshown = scalar(@{$analysis{$part_id.'.shown'}});
}
my $bubbles_per_line = 10;
- my $inner_bubble_lines = int($numshown/$bubbles_per_line);
- if (($numshown % $bubbles_per_line) != 0) {
+ my $inner_bubble_lines = int($numbub/$bubbles_per_line);
+ if (($numbub % $bubbles_per_line) != 0) {
$inner_bubble_lines++;
}
for (my $i=0; $i<$numshown; $i++) {
@@ -7324,6 +7422,9 @@ sub scantron_get_maxbubble {
$inner_bubble_lines.',';
}
$subdivided_bubble_lines{$response_number} =~ s/,$//;
+ $lines = $numshown * $inner_bubble_lines;
+ } else {
+ $lines = $analysis{"$part_id.bubble_lines"};
}
$first_bubble_line{$response_number} = $bubble_line;
@@ -7460,6 +7561,7 @@ SCANTRONFORM
my @delayqueue;
my %completedstudents;
+ my $lock=&Apache::lonnet::set_lock(&mt('Grading bubblesheet exam'));
my $count=&get_todo_count($scanlines,$scan_data);
my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Scantron Status',
'Scantron Progress',$count,
@@ -7480,6 +7582,7 @@ SCANTRONFORM
$r->print("");
&ssi_print_error($r);
$r->print(&show_grading_menu_form($symb));
+ &Apache::lonnet::remove_lock($lock);
return ''; # Dunno why the other returns return '' rather than just returning.
}
@@ -7537,6 +7640,7 @@ SCANTRONFORM
$r->print("");
&ssi_print_error($r);
$r->print(&show_grading_menu_form($symb));
+ &Apache::lonnet::remove_lock($lock);
return ''; # Why return ''? Beats me.
}
@@ -7549,6 +7653,7 @@ SCANTRONFORM
&Apache::lonnet::delenv('scantron\.');
}
&Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
+ &Apache::lonnet::remove_lock($lock);
# my $lasttime = &Time::HiRes::time()-$start;
# $r->print("
took $lasttime
");
@@ -7739,6 +7844,271 @@ sub scantron_download_scantron_data {
return '';
}
+sub checkscantron_results {
+ my ($r) = @_;
+ my ($symb)=&get_symb($r);
+ if (!$symb) {return '';}
+ my $grading_menu_button=&show_grading_menu_form($symb);
+ my $cid = $env{'request.course.id'};
+ my %lettdig = (
+ A => 1,
+ B => 2,
+ C => 3,
+ D => 4,
+ E => 5,
+ F => 6,
+ G => 7,
+ H => 8,
+ I => 9,
+ J => 0,
+ );
+ my $numletts = scalar(keys(%lettdig));
+ my $cnum = $env{'course.'.$cid.'.num'};
+ my $cdom = $env{'course.'.$cid.'.domain'};
+ my (undef, undef, $sequence) = &Apache::lonnet::decode_symb($env{'form.selectpage'});
+ my %record;
+ my %scantron_config =
+ &Apache::grades::get_scantron_config($env{'form.scantron_format'});
+ my ($scanlines,$scan_data)=&Apache::grades::scantron_getfile();
+ my $classlist=&Apache::loncoursedata::get_classlist();
+ my %idmap=&Apache::grades::username_to_idmap($classlist);
+ my $navmap=Apache::lonnavmaps::navmap->new();
+ my $map=$navmap->getResourceByUrl($sequence);
+ my @resources=$navmap->retrieveResources($map,undef,1,0);
+ my (%scandata,%lastname,%bylast);
+ $r->print('
+ '.$grading_menu_button);
+ return;
+}
+
=pod
=back
@@ -7798,25 +8168,25 @@ sub grading_menu {
});
$fields{'command'} = 'csvform';
$url = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
- push (@menu, { url => $url,
+ push(@menu, { url => $url,
name => &mt('Upload Scores'),
short_description =>
&mt('Specify a file containing the class scores for current resource.')});
$fields{'command'} = 'processclicker';
$url = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
- push (@menu, { url => $url,
+ push(@menu, { url => $url,
name => &mt('Process Clicker'),
short_description =>
&mt('Specify a file containing the clicker information for this resource.')});
$fields{'command'} = 'scantron_selectphase';
$url = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
- push (@menu, { url => $url,
- name => &mt('Grade/Manage Scantron Forms'),
+ push(@menu, { url => $url,
+ name => &mt('Grade/Manage/Review Scantron Forms'),
short_description =>
- &mt('')});
+ &mt('Grade scantron exams, upload/download scantron data files, and review previously graded scantron exams.')});
$fields{'command'} = 'verify';
$url = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
- push (@menu, { url => "",
+ push(@menu, { url => "",
name => &mt('Verify Receipt'),
short_description =>
&mt('')});
@@ -7972,7 +8342,7 @@ GRADINGMENUJS