--- loncom/homework/grades.pm 2007/11/08 20:47:56 1.487
+++ loncom/homework/grades.pm 2008/12/10 21:30:38 1.528.2.1
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Grading handler
#
-# $Id: grades.pm,v 1.487 2007/11/08 20:47:56 albertel Exp $
+# $Id: grades.pm,v 1.528.2.1 2008/12/10 21:30:38 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -47,88 +47,89 @@ use LONCAPA;
use POSIX qw(floor);
-my %perm=();
-my %bubble_lines_per_response = (); # no. bubble lines for each response.
- # index is "symb.part_id"
-
-my %first_bubble_line = (); # First bubble line no. for each bubble.
-
-# Save and restore the bubble lines array to the form env.
-
-
-sub save_bubble_lines {
- foreach my $line (keys(%bubble_lines_per_response)) {
- $env{"form.scantron.bubblelines.$line"} = $bubble_lines_per_response{$line};
- $env{"form.scantron.first_bubble_line.$line"} =
- $first_bubble_line{$line};
- }
-}
-
-sub restore_bubble_lines {
- my $line = 0;
- %bubble_lines_per_response = ();
- while ($env{"form.scantron.bubblelines.$line"}) {
- my $value = $env{"form.scantron.bubblelines.$line"};
- $bubble_lines_per_response{$line} = $value;
- $first_bubble_line{$line} =
- $env{"form.scantron.first_bubble_line.$line"};
- $line++;
- }
+my %perm=();
-}
+# These variables are used to recover from ssi errors
-# Given the parsed scanline, get the response for
-# 'answer' number n:
+my $ssi_retries = 5;
+my $ssi_error;
+my $ssi_error_resource;
+my $ssi_error_message;
-sub get_response_bubbles {
- my ($parsed_line, $response) = @_;
+# Do an ssi with retries:
+# While I'd love to factor out this with the vesrion in lonprintout,
+# that would either require a data coupling between modules, which I refuse to perpetuate
+# (there's quite enough of that already), or would require the invention of another infrastructure
+# I'm not quite ready to invent (e.g. an ssi_with_retry object).
+#
+# At least the logic that drives this has been pulled out into loncommon.
- my $bubble_line = $first_bubble_line{$response-1} +1;
- my $bubble_lines= $bubble_lines_per_response{$response-1};
-
- my $selected = "";
- for (my $bline = 0; $bline < $bubble_lines; $bline++) {
- $selected .= $$parsed_line{"scantron.$bubble_line.answer"}.":";
- $bubble_line++;
+#
+# ssi_with_retries - Does the server side include of a resource.
+# if the ssi call returns an error we'll retry it up to
+# the number of times requested by the caller.
+# If we still have a proble, no text is appended to the
+# output and we set some global variables.
+# to indicate to the caller an SSI error occurred.
+# All of this is supposed to deal with the issues described
+# in LonCAPA BZ 5631 see:
+# http://bugs.lon-capa.org/show_bug.cgi?id=5631
+# by informing the user that this happened.
+#
+# Parameters:
+# resource - The resource to include. This is passed directly, without
+# interpretation to lonnet::ssi.
+# form - The form hash parameters that guide the interpretation of the resource
+#
+# retries - Number of retries allowed before giving up completely.
+# Returns:
+# On success, returns the rendered resource identified by the resource parameter.
+# Side Effects:
+# The following global variables can be set:
+# ssi_error - If an unrecoverable error occurred this becomes true.
+# It is up to the caller to initialize this to false
+# if desired.
+# ssi_error_resource - If an unrecoverable error occurred, this is the value
+# of the resource that could not be rendered by the ssi
+# call.
+# ssi_error_message - The error string fetched from the ssi response
+# in the event of an error.
+#
+sub ssi_with_retries {
+ my ($resource, $retries, %form) = @_;
+ my ($content, $response) = &Apache::loncommon::ssi_with_retries($resource, $retries, %form);
+ if ($response->is_error) {
+ $ssi_error = 1;
+ $ssi_error_resource = $resource;
+ $ssi_error_message = $response->code . " " . $response->message;
}
- return $selected;
-}
-
-# ----- These first few routines are general use routines.----
-
-# Return the number of occurences of a pattern in a string.
-
-sub occurence_count {
- my ($string, $pattern) = @_;
-
- my @matches = ($string =~ /$pattern/g);
+ return $content;
- return scalar(@matches);
}
+#
+# Prodcuces an ssi retry failure error message to the user:
+#
-
-# Take a string known to have digits and convert all the
-# digits into letters in the range J,A..I.
-
-sub digits_to_letters {
- my ($input) = @_;
-
- my @alphabet = ('J', 'A'..'I');
-
- my @input = split(//, $input);
- my $output ='';
- for (my $i = 0; $i < scalar(@input); $i++) {
- if ($input[$i] =~ /\d/) {
- $output .= $alphabet[$input[$i]];
- } else {
- $output .= $input[$i];
- }
- }
- return $output;
+sub ssi_print_error {
+ my ($r) = @_;
+ my $helpurl = &Apache::loncommon::top_nav_help('Helpdesk');
+ $r->print('
+
+
+'.&mt('Unable to retrieve a resource from a server:').'
+'.&mt('Resource:').' '.$ssi_error_resource.'
+'.&mt('Error:').' '.$ssi_error_message.'
+
'.
+&mt('It is recommended that you try again later, as this error may mean the server was just temporarily unavailable, or is down for maintenance.').'
'.
+&mt('If the error persists, please contact the [_1] for assistance.',$helpurl).
+'
\n"; @@ -1841,9 +1843,9 @@ sub download_all_link { join("\n",&Apache::loncommon::get_env_multiple('form.vPart')); my $identifier = &Apache::loncommon::get_cgi_id(); - &Apache::lonnet::appenv('cgi.'.$identifier.'.students' => $all_students, - 'cgi.'.$identifier.'.symb' => $symb, - 'cgi.'.$identifier.'.parts' => $parts,); + &Apache::lonnet::appenv({'cgi.'.$identifier.'.students' => $all_students, + 'cgi.'.$identifier.'.symb' => $symb, + 'cgi.'.$identifier.'.parts' => $parts,}); $r->print(''. &mt('Download All Submitted Documents').''); return @@ -2224,8 +2226,8 @@ KEYWORDS $seen{$partid}++; next if ($$handgrade{$part_resp} ne 'yes' && $env{'form.lastSub'} eq 'hdgrade'); - push @partlist,$partid; - push @gradePartRespid,$partid.'.'.$respid; + push(@partlist,$partid); + push(@gradePartRespid,$partid.'.'.$respid); $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record)); } $request->print(''); @@ -2552,7 +2554,7 @@ sub processHandGrade { my (@parsedlist,@nextlist); my ($nextflg) = 0; - foreach (sort + foreach my $item (sort { if (lc($$fullname{$a}) ne lc($$fullname{$b})) { return (lc($$fullname{$a}) cmp lc($$fullname{$b})); @@ -2560,12 +2562,12 @@ sub processHandGrade { return $a cmp $b; } (keys(%$fullname))) { if ($nextflg == 1 && $button =~ /Next$/) { - push @parsedlist,$_; + push(@parsedlist,$item); } - $nextflg = 1 if ($_ eq $laststu); + $nextflg = 1 if ($item eq $laststu); if ($button eq 'Previous') { - last if ($_ eq $firststu); - push @parsedlist,$_; + last if ($item eq $firststu); + push(@parsedlist,$item); } } $ctr = 0; @@ -2588,11 +2590,11 @@ sub processHandGrade { my $submitted = 0; my $ungraded = 0; my $incorrect = 0; - foreach (keys(%status)) { - $submitted = 1 if ($status{$_} ne 'nothing'); - $ungraded = 1 if ($status{$_} =~ /^ungraded/); - $incorrect = 1 if ($status{$_} =~ /^incorrect/); - my ($foo,$partid,$foo1) = split(/\./,$_); + foreach my $item (keys(%status)) { + $submitted = 1 if ($status{$item} ne 'nothing'); + $ungraded = 1 if ($status{$item} =~ /^ungraded/); + $incorrect = 1 if ($status{$item} =~ /^incorrect/); + my ($foo,$partid,$foo1) = split(/\./,$item); if ($status{'resource.'.$partid.'.submitted_by'} ne '') { $submitted = 0; } @@ -2603,7 +2605,7 @@ sub processHandGrade { next if (!$ungraded && ($submitonly eq 'graded')); next if (!$incorrect && $submitonly eq 'incorrect'); } - push @nextlist,$student if ($ctr < $ntstu); + push(@nextlist,$student) if ($ctr < $ntstu); last if ($ctr == $ntstu); $ctr++; } @@ -2611,7 +2613,7 @@ sub processHandGrade { $ctr = 0; my $total = scalar(@nextlist)-1; - foreach (sort @nextlist) { + foreach (sort(@nextlist)) { my ($uname,$udom,$submitter) = split(/:/); $env{'form.student'} = $uname; $env{'form.userdom'} = $udom; @@ -2657,7 +2659,7 @@ sub saveHandGrade { } } elsif ($dropMenu eq 'reset status' && exists($record{'resource.'.$new_part.'.solved'})) { #don't bother if no old records -> no attempts - foreach my $key (keys (%record)) { + foreach my $key (keys(%record)) { if ($key=~/^resource\.\Q$new_part\E\./) { $newrecord{$key} = ''; } } $newrecord{'resource.'.$new_part.'.regrader'}= @@ -2692,7 +2694,7 @@ sub saveHandGrade { &handback_files($request,$symb,$stuname,$domain,$newflg,$new_part,\%newrecord); next; } else { - push @parts_graded, $new_part; + push(@parts_graded,$new_part); } if ($record{'resource.'.$new_part.'.awarded'} ne $partial) { $newrecord{'resource.'.$new_part.'.awarded'} = $partial; @@ -2719,7 +2721,7 @@ sub saveHandGrade { $record{'resource.'.$new_part.'.solved'} eq 'incorrect_by_override' || $dropMenu eq 'reset status') { - push (@version_parts,$new_part); + push(@version_parts,$new_part); } } my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; @@ -2767,7 +2769,7 @@ sub check_and_remove_from_queue { sub handback_files { my ($request,$symb,$stuname,$domain,$newflg,$new_part,$newrecord) = @_; - my $portfolio_root = &propath($domain,$stuname).'/userfiles/portfolio'; + my $portfolio_root = '/userfiles/portfolio'; my ($partlist,$handgrade,$responseType) = &response_type($symb); my @part_response_id = &flatten_responseType($responseType); @@ -2785,7 +2787,8 @@ sub handback_files { my ($answer_name,$answer_ver,$answer_ext) = &file_name_version_ext($answer_file); my ($portfolio_path) = ($directory =~ /^.+$stuname\/portfolio(.*)/); - my @dir_list = &Apache::lonnet::dirlist($portfolio_path,$domain,$stuname,$portfolio_root); + my $getpropath = 1; + my @dir_list = &Apache::lonnet::dirlist($portfolio_root.$portfolio_path,$domain,$stuname,$getpropath); my $version = &get_next_version($answer_name, $answer_ext, \@dir_list); # fix file name my ($save_file_name) = (($directory.$answer_name.".$version.".$answer_ext) =~ /^.+\/${stuname}\/(.*)/); @@ -2891,7 +2894,7 @@ sub decrement_aggs { if ($aggtries == $totaltries) { $decrement{'users'} = 1; } - foreach my $type (keys (%decrement)) { + foreach my $type (keys(%decrement)) { $$aggregate{$symb."\0".$part."\0".$type} = -$decrement{$type}; } return; @@ -2921,8 +2924,7 @@ sub version_portfiles { my $version_parts = join('|',@$v_flag); my @returned_keys; my $parts = join('|', @$parts_graded); - my $portfolio_root = &propath($domain,$stu_name). - '/userfiles/portfolio'; + my $portfolio_root = '/userfiles/portfolio'; foreach my $key (keys(%$record)) { my $new_portfiles; if ($key =~ /^resource\.($version_parts)\./ && $key =~ /\.portfiles$/ ) { @@ -2933,7 +2935,8 @@ sub version_portfiles { my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*)$/); my ($answer_name,$answer_ver,$answer_ext) = &file_name_version_ext($answer_file); - my @dir_list = &Apache::lonnet::dirlist($directory,$domain,$stu_name,$portfolio_root); + my $getpropath = 1; + my @dir_list = &Apache::lonnet::dirlist($portfolio_root.$directory,$domain,$stu_name,$getpropath); my $version = &get_next_version($answer_name, $answer_ext, \@dir_list); my $new_answer = &version_selected_portfile($domain, $stu_name, $directory, $answer_file, $version); if ($new_answer ne 'problem getting file') { @@ -3292,7 +3295,7 @@ sub viewgrades { $display =~ s|^Number of Attempts|Tries | '.
@@ -3446,7 +3449,7 @@ sub editgrades {
my $header;
while ($ctr < $env{'form.totalparts'}) {
my $partid = $env{'form.partid_'.$ctr};
- push @partid,$partid;
+ push(@partid,$partid);
$weight{$partid} = $env{'form.weight_'.$partid};
$ctr++;
}
@@ -4042,31 +4045,31 @@ sub csvuploadassign {
$grades{$store_key}=$entries{$fields{$dest}};
}
}
- if (! %grades) { push(@skipped,"$username:$domain no data to save"); }
- $grades{"resource.regrader"}="$env{'user.name'}:$env{'user.domain'}";
- my $result=&Apache::lonnet::cstore(\%grades,$symb,
+ if (! %grades) {
+ push(@skipped,&mt("[_1]: no data to save","$username:$domain"));
+ } else {
+ $grades{"resource.regrader"}="$env{'user.name'}:$env{'user.domain'}";
+ my $result=&Apache::lonnet::cstore(\%grades,$symb,
$env{'request.course.id'},
$domain,$username);
- if ($result eq 'ok') {
- $request->print('.');
- } else {
- $request->print(" - - Failed to save student $username:$domain. - Message when trying to save was ($result) - - " ); - } - $request->rflush(); - $countdone++; + if ($result eq 'ok') { + $request->print('.'); + } else { + $request->print("". + &mt("Failed to save data for student [_1]. Message when trying to save was: [_2]", + "$username:$domain",$result)." "); + } + $request->rflush(); + $countdone++; + } } - $request->print("Saved $countdone students\n"); + $request->print(' '.&mt("Saved [_1] students",$countdone)."\n"); if (@skipped) { - $request->print(' Skipped Students'); + $request->print(''.&mt('Skipped Students').' '); foreach my $student (@skipped) { $request->print("$student\n"); } } if (@notallowed) { - $request->print(' Students Not Allowed to Modify '); + $request->print(''.&mt('Students Not Allowed to Modify').' '); foreach my $student (@notallowed) { $request->print("$student\n"); } } $request->print(" \n"); @@ -4256,7 +4259,8 @@ sub displayPage { my $result=' '.$env{'form.title'}.''; $result.=''.&mt('Student: [_1]',&nameUserString(undef,$$fullname{$env{'form.student'}},$uname,$udom)). ''."\n"; - if (&Apache::lonnet::validCODE($env{'form.CODE'})) { + $env{'form.CODE'} = uc($env{'form.CODE'}); + if (&Apache::lonnet::validCODE(uc($env{'form.CODE'}))) { $result.=''.&mt('CODE: [_1]',$env{'form.CODE'}).''."\n"; } else { delete($env{'form.CODE'}); @@ -4407,6 +4411,7 @@ sub displaySubByDates { } my $interaction; + my $no_increment = 1; for ($version=1;$version<=$$record{'version'};$version++) { my $timestamp = &Apache::lonlocal::locallocaltime($$record{$version.':timestamp'}); @@ -4450,7 +4455,8 @@ sub displaySubByDates { if (!exists($orders{$partid})) { $orders{$partid}={}; } if (!exists($orders{$partid}->{$responseId})) { $orders{$partid}->{$responseId}= - &get_order($partid,$responseId,$symb,$uname,$udom); + &get_order($partid,$responseId,$symb,$uname,$udom, + $no_increment); } $displaySub[0].=' '. &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:",$uname,$udom).''; @@ -4503,12 +4509,12 @@ sub updateGradeByPage { my ($uname,$udom) = split(/:/,$env{'form.student'}); my $usec=$classlist->{$env{'form.student'}}[5]; if (!&canmodify($usec)) { - $request->print('Unable to modify requested student.('.$env{'form.student'}.''); + $request->print(''.&mt('Unable to modify requested student ([_1])',$env{'form.student'}).''); $request->print(&show_grading_menu_form($env{'form.symb'})); return; } my $result=' '.$env{'form.title'}.''; - $result.=' Student: '.&nameUserString(undef,$env{'form.fullname'},$uname,$udom).
+ $result.='('.&mt('[quant,_1, parts]',scalar(@{$parts})) - ).')
- |
-
|
- $default_form_data
-
-
|
- + '.&mt('Download a scoring office file').' + | + '.&Apache::loncommon::end_data_table_header_row().' + '.&Apache::loncommon::start_data_table_row().' + '.&mt('Filename of scoring office file: [_1]',$file_selector).'
+ + + '.&Apache::loncommon::end_data_table_row().' + '.&Apache::loncommon::end_data_table().' + + +'); - $r->print(' | ||
---|---|---|---|---|---|---|---|
'); &Apache::lonpickcode::code_list($r,2); - $r->print(' |
Sequence to be Graded: | $title |
Data File that will be used: | $env{'form.scantron_selectfile'} |
'.&mt('Sequence to be Graded:').' | '.$title.' |
'.&mt('Data File that will be used:').' | '.$env{'form.scantron_selectfile'}.' |
If this information is correct, please click on '$button_text'.
-If something is incorrect, please click the 'Grading Menu' button to start over.
+'.&mt('If this information is correct, please click on \'[_1]\'.',&mt($button_text)).'
+'.&mt('If something is incorrect, please click the \'Grading Menu\' button to start over.').'
You have forgetten to specify some information. Please go Back and try again.
"); + $r->print("".&mt('You have forgetten to specify some information. Please go Back and try again.')."
"); if ( $env{'form.selectpage'} eq '') { - $r->print('You have not selected a Sequence to grade
'); + $r->print(''.&mt('You have not selected a Sequence to grade').'
'); } if ( $env{'form.scantron_selectfile'} eq '') { - $r->print('You have not selected a file that contains the student\'s response data.
'); + $r->print(''.&mt('You have not selected a file that contains the student\'s response data.').'
'); } if ( $env{'form.scantron_format'} eq '') { - $r->print('You have not selected a the format of the student\'s response data.
'); + $r->print(''.&mt('You have not selected a the format of the student\'s response data.').'
'); } } else { my $warning=&scantron_warning_screen('Grading: Validate Records'); - $r->print(<Gathering necessary info.
");$r->rflush(); + $r->print(''.&mt('Gathering necessary information.').'
');$r->rflush(); #get the student pick code ready $r->print(&Apache::loncommon::studentbrowser_javascript()); my $max_bubble=&scantron_get_maxbubble(); @@ -6001,7 +6203,7 @@ sub scantron_validate_file { my $stop=0; while (!$stop && $currentphase < scalar(@validate_phases)) { - $r->print("Validating ".$validate_phases[$currentphase]."
"); + $r->print(&mt('Validating '.$validate_phases[$currentphase]).'Or click the 'Grading Menu' button to start over.
"); + $r->print("".&mt("Or click the 'Grading Menu' button to start over.")."
"); } else { - $r->print(''); - $r->print(' using corrected infoAn error was detected ($error)"); if ( $$scan_record{'scantron.PaperID'} =~ /\S/) { - $r->print(" for PaperID ". - $$scan_record{'scantron.PaperID'}." \n"); + $r->print("
".&mt("An error was detected ($error)". + " for PaperID [_1]", + $$scan_record{'scantron.PaperID'})."
\n"); } else { - $r->print(" in scanline $i". - $line."\n"); - } - my $message="
The ID on the form is ".
- $$scan_record{'scantron.ID'}."
\n".
- "The name on the paper is ".
- $$scan_record{'scantron.LastName'}.",".
- $$scan_record{'scantron.FirstName'}."
".&mt("An error was detected ($error)". + " in scanline [_1]
[_2]", + $i,$line)." \n"); + } + my $message="
".&mt("The ID on the form is [_1]
".
+ "The name on the paper is [_2],[_3]",
+ $$scan_record{'scantron.ID'},
+ $$scan_record{'scantron.LastName'},
+ $$scan_record{'scantron.FirstName'})."
".&mt("The encoded ID is not in the classlist"). + "
\n"); } elsif ($error eq 'duplicateID') { - $r->print("The encoded ID has also been used by a previous paper $arg\n"); + $r->print("".&mt("The encoded ID has also been used by a previous paper [_1]",$arg)."
\n"); } $r->print($message); - $r->print("How should I handle this?
\n");
+ $r->print("
".&mt("How should I handle this?")."
\n");
$r->print("\n
The encoded CODE is not in the list of possible CODEs
\n"); + $r->print("".&mt("The encoded CODE is not in the list of possible CODEs.")."
\n"); } elsif ($error eq 'duplicateCODE') { - $r->print("The encoded CODE has also been used by a previous paper ".join(', ',@{$arg}).", and CODEs are supposed to be unique
\n"); + $r->print("".&mt("The encoded CODE has also been used by a previous paper [_1], and CODEs are supposed to be unique.",join(', ',@{$arg}))."
\n"); } - $r->print("The CODE on the form is '".
- $$scan_record{'scantron.CODE'}."'
\n");
+ $r->print("
".&mt("The CODE on the form is '[_1]'",
+ $$scan_record{'scantron.CODE'})."
\n");
$r->print($message);
- $r->print("
How should I handle this?
\n");
+ $r->print("
".&mt("How should I handle this?")."
\n");
$r->print("\n
");
my $i=0;
if ($error eq 'incorrectCODE'
@@ -6566,7 +6779,13 @@ sub scantron_get_correction {
foreach my $testcode (@{$closest}) {
my $checked='';
if (!$i) { $checked=' checked="checked" '; }
- $r->print("
");
$i++;
}
@@ -6574,7 +6793,12 @@ sub scantron_get_correction {
}
if ($$scan_record{'scantron.CODE'}=~/\S/ ) {
my $checked; if (!$i) { $checked=' checked="checked" '; }
- $r->print("
");
}
@@ -6596,118 +6820,274 @@ ENDSCRIPT
"&curCODE=".&escape($$scan_record{'scantron.CODE'}).
"&scantron_selectfile=".&escape($env{'form.scantron_selectfile'});
if ($env{'form.scantron_CODElist'} =~ /\S/) {
- $r->print("
");
}
- $r->print("
");
} elsif ($error eq 'doublebubble') {
- $r->print("
There have been multiple bubbles scanned for a some question(s)
\n"); + $r->print("".&mt("There have been multiple bubbles scanned for some question(s)")."
\n"); + + # The form field scantron_questions is acutally a list of line numbers. + # represented by this form so: + + my $line_list = &questions_to_line_list($arg); + $r->print(''); + $line_list.'" />'); $r->print($message); - $r->print("Please indicate which bubble should be used for grading
"); + $r->print("".&mt("Please indicate which bubble should be used for grading")."
"); foreach my $question (@{$arg}) { - my $selected = &get_response_bubbles($scan_record, $question); - my @select_array = split(/:/,$selected); - &scantron_bubble_selector($r,$scan_config,$question, - @select_array); + my @linenums = &prompt_for_corrections($r,$question,$scan_config, + $scan_record, $error); + push(@lines_to_correct,@linenums); } + $r->print(&verify_bubbles_checked(@lines_to_correct)); } elsif ($error eq 'missingbubble') { - $r->print("There have been no bubbles scanned for some question(s)
\n"); + $r->print("".&mt("There have been no bubbles scanned for some question(s)")."
\n"); $r->print($message); - $r->print("Please indicate which bubble should be used for grading
"); - $r->print("Some questions have no scanned bubbles\n"); + $r->print("".&mt("Please indicate which bubble should be used for grading.")."
"); + $r->print(&mt("Some questions have no scanned bubbles.")."\n"); + + # The form field scantron_questions is actually a list of line numbers not + # a list of question numbers. Therefore: + # + + my $line_list = &questions_to_line_list($arg); + $r->print(''); + $line_list.'" />'); foreach my $question (@{$arg}) { - my $selected = &get_response_bubbles($scan_record, $question); - my @select_array = split(/:/,$selected); # ought to be an array of empties. - &scantron_bubble_selector($r,$scan_config,$question, @select_array); + my @linenums = &prompt_for_corrections($r,$question,$scan_config, + $scan_record, $error); + push(@lines_to_correct,@linenums); } + $r->print(&verify_bubbles_checked(@lines_to_correct)); } else { $r->print("\n$quest | "); +sub prompt_for_corrections { + my ($r, $question, $scan_config, $scan_record, $error) = @_; + my ($current_line,$lines); + my @linenums; + my $questionnum = $question; + if ($question =~ /^(\d+)\.(\d+)$/) { + $question = $1; + $current_line = $first_bubble_line{$question-1} + 1 ; + my $subquestion = $2; + my @subans = split(/,/,$subdivided_bubble_lines{$question-1}); + my $subcount = 1; + while ($subcount<$subquestion) { + $current_line += $subans[$subcount-1]; + $subcount ++; + } + $lines = $subans[$subquestion-1]; + } else { + $current_line = $first_bubble_line{$question-1} + 1 ; + $lines = $bubble_lines_per_response{$question-1}; + } + if ($lines > 1) { + $r->print(&mt('The group of bubble lines below responds to a single question.').'|
'); - if ($selected[0] eq $alphabet[$i]) { - $r->print('X'); - shift(@selected) ; - } else { - $r->print(' '); - } - $r->print(' | '); - - } +=pod - if ($l == 0) { - my $lspan = $total_lines * 2; # 2 table rows per bubble line. +=item scantron_bubble_selector + + Generates the html radiobuttons to correct a single bubble line + possibly showing the existing the selected bubbles if known - $r->print('|
took $lasttime
"); @@ -7179,7 +7677,7 @@ sub scantron_upload_scantron_data { my $domsel=&Apache::loncommon::select_dom_form($env{'request.role.domain'}, 'domainid'); my $default_form_data=&defaultFormData(&get_symb($r,1)); - $r->print(<$select_link | |
Course ID: | |
Course Name: | |
Domain: | $domsel |
File to upload: | |
'.$select_link.' | |
'.&mt('Course ID:').' | +|
'.&mt('Course Name:').' | +|
'.&mt('Domain:').' | +'.$domsel.' |
'.&mt('File to upload:').' | +
- The requested file name was invalid. + '.&mt('The requested file name was invalid.').'
-ERROR +'); $r->print(&show_grading_menu_form(&get_symb($r,1))); return; } @@ -7317,21 +7824,289 @@ ERROR &Apache::lonnet::allowuploaded('/adm/grades',$orig); &Apache::lonnet::allowuploaded('/adm/grades',$corrected); &Apache::lonnet::allowuploaded('/adm/grades',$skipped); - $r->print(<- Original file as uploaded by the scantron office. + '.&mt('[_1]Original[_2] file as uploaded by the scantron office.', + '','').'
- Corrections, a file of corrected records that were used in grading. + '.&mt('[_1]Corrections[_2], a file of corrected records that were used in grading.', + '','').'
- Skipped, a file of records that were skipped. + '.&mt('[_1]Skipped[_2], a file of records that were skipped.', + '','').'
-DOWNLOAD +'); $r->print(&show_grading_menu_form(&get_symb($r,1))); 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(' +'.&mt('Comparison of scantron data (including corrections) with corresponding submission records (most recent submission) for [quant,_1,student] ([_2] scantron lines/student).',$numstudents,$env{'form.scantron_maxbubble'}).'
'); + $r->print(''.&mt('Exact matches for [quant,_1,student].',$passed).'
'.&mt('Discrepancies detected for [quant,_1,student].',$failed).'
'.&mt('Correctness determined by the following IDs').'';
@@ -7914,6 +8708,9 @@ sub process_clicker_file {
ENDHEADER
+ if ($env{'form.gradingmechanism'} eq 'given') {
+ $result.='';
+ }
my %responses;
my @questiontitles;
my $errormsg='';
@@ -7926,11 +8723,13 @@ ENDHEADER
}
$result.='
'.&mt('Found [_1] question(s)',$number).'
'.
''.
- &mt('Awarding [_1] percent for corrion(s)',$number).'
'.
- ''.
&mt('Awarding [_1] percent for correct and [_2] percent for incorrect responses',
$env{'form.pcorrect'},$env{'form.pincorrect'}).
'
';
+ if (($env{'form.gradingmechanism'} eq 'given') && ($number!=$foundgiven)) {
+ $result.=''.&mt('Number of given answers does not agree with number of questions in file.').'';
+ return $result.&show_grading_menu_form($symb);
+ }
# Remember Question Titles
# FIXME: Possibly need delimiter other than ":"
for (my $i=0;$i<$number;$i++) {
@@ -7974,7 +8773,7 @@ ENDHEADER
}
$result.='