');
+ pDoc.write('
'."\n";
- return $result.&show_grading_menu_form($symb);
+ return $result;
+}
+
+sub navmap_errormsg {
+ return ''.
+ &mt('An error occurred retrieving information about resources in the course.').' '.
+ &mt('It is recommended that you [_1]re-initialize the course[_2] and then return to this grading page.',' ','').
+ ' ';
+}
+
+sub startpage {
+ my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag) = @_;
+ unshift(@$crumbs,{href=>&href_symb_cmd($symb,'gradingmenu'),text=>"Grading"});
+ $r->print(&Apache::loncommon::start_page('Grading',undef,
+ {'bread_crumbs' => $crumbs}));
+ unless ($nodisplayflag) {
+ $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag));
+ }
}
sub handler {
@@ -8630,7 +9163,9 @@ sub handler {
$request->send_http_header;
return '' if $request->header_only;
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
- my $symb=&get_symb($request,1);
+
+# see what command we need to execute
+
my @commands=&Apache::loncommon::get_env_multiple('form.command');
my $command=$commands[0];
@@ -8638,104 +9173,144 @@ sub handler {
&Apache::lonnet::logthis("grades got multiple commands ".join(':',@commands));
}
+# see what the symb is
+
+ my $symb=$env{'form.symb'};
+ unless ($symb) {
+ (my $url=$env{'form.url'}) =~ s-^https*://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
+ $symb=&Apache::lonnet::symbread($url);
+ }
+ &Apache::lonenc::check_decrypt(\$symb);
+
$ssi_error = 0;
- $request->print(&Apache::loncommon::start_page('Grading'));
if ($symb eq '' && $command eq '') {
- if ($env{'user.adv'}) {
- if (($env{'form.codeone'}) && ($env{'form.codetwo'}) &&
- ($env{'form.codethree'})) {
- my $token=$env{'form.codeone'}.'*'.$env{'form.codetwo'}.'*'.
- $env{'form.codethree'};
- my ($tsymb,$tuname,$tudom,$tcrsid)=
- &Apache::lonnet::checkin($token);
- if ($tsymb) {
- my ($map,$id,$url)=&Apache::lonnet::decode_symb($tsymb);
- if (&Apache::lonnet::allowed('mgr',$tcrsid)) {
- $request->print(&ssi_with_retries('/res/'.$url, $ssi_retries,
- ('grade_username' => $tuname,
- 'grade_domain' => $tudom,
- 'grade_courseid' => $tcrsid,
- 'grade_symb' => $tsymb)));
- } else {
- $request->print('Not authorized: '.$token.'');
- }
- } else {
- $request->print('Not a valid DocID: '.$token.'');
- }
- } else {
- $request->print(&Apache::lonxml::tokeninputfield());
- }
- }
+#
+# Not called from a resource
+#
+
} else {
&init_perm();
if ($command eq 'submission' && $perm{'vgr'}) {
- ($env{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0));
+ &startpage($request,$symb,[{href=>"", text=>"Student Submissions"}]);
+ ($env{'form.student'} eq '' ? &listStudents($request,$symb) : &submission($request,0,0,$symb));
} elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {
- &pickStudentPage($request);
+ &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},
+ {href=>'',text=>'Select student'}],1,1);
+ &pickStudentPage($request,$symb);
} elsif ($command eq 'displayPage' && $perm{'vgr'}) {
- &displayPage($request);
+ &startpage($request,$symb,
+ [{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},
+ {href=>'',text=>'Select student'},
+ {href=>'',text=>'Grade student'}],1,1);
+ &displayPage($request,$symb);
} elsif ($command eq 'gradeByPage' && $perm{'mgr'}) {
- &updateGradeByPage($request);
+ &startpage($request,$symb);
+ &updateGradeByPage($request,$symb);
} elsif ($command eq 'processGroup' && $perm{'vgr'}) {
- &processGroup($request);
+ &startpage($request,$symb);
+ &processGroup($request,$symb);
} elsif ($command eq 'gradingmenu' && $perm{'vgr'}) {
- $request->print(&grading_menu($request));
- } elsif ($command eq 'submit_options' && $perm{'vgr'}) {
- $request->print(&submit_options($request));
+ &startpage($request,$symb);
+ $request->print(&grading_menu($request,$symb));
+ } elsif ($command eq 'individual' && $perm{'vgr'}) {
+ &startpage($request,$symb);
+ $request->print(&submit_options($request,$symb));
+ } elsif ($command eq 'ungraded' && $perm{'vgr'}) {
+ &startpage($request,$symb);
+ $request->print(&submit_options($request,$symb));
+ } elsif ($command eq 'table' && $perm{'vgr'}) {
+ &startpage($request,$symb,[{href=>"", text=>"Grading table"}]);
+ $request->print(&submit_options_table($request,$symb));
+ } elsif ($command eq 'all_for_one' && $perm{'vgr'}) {
+ &startpage($request,$symb,[{href=>'',text=>'Grade page/folder for one student'}],1,1);
+ $request->print(&submit_options_sequence($request,$symb));
} elsif ($command eq 'viewgrades' && $perm{'vgr'}) {
- $request->print(&viewgrades($request));
+ &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},{href=>'', text=>"Modify grades"}]);
+ $request->print(&viewgrades($request,$symb));
} elsif ($command eq 'handgrade' && $perm{'mgr'}) {
- $request->print(&processHandGrade($request));
+ &startpage($request,$symb);
+ $request->print(&processHandGrade($request,$symb));
} elsif ($command eq 'editgrades' && $perm{'mgr'}) {
- $request->print(&editgrades($request));
+ &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},
+ {href=>&href_symb_cmd($symb,'viewgrades').'&group=all§ion=all&Status=Active',
+ text=>"Modify grades"},
+ {href=>'', text=>"Store grades"}]);
+ $request->print(&editgrades($request,$symb));
+ } elsif ($command eq 'initialverifyreceipt' && $perm{'vgr'}) {
+ &startpage($request,$symb);
+ $request->print(&initialverifyreceipt($request,$symb));
} elsif ($command eq 'verify' && $perm{'vgr'}) {
- $request->print(&verifyreceipt($request));
+ &startpage($request,$symb);
+ $request->print(&verifyreceipt($request,$symb));
} elsif ($command eq 'processclicker' && $perm{'mgr'}) {
- $request->print(&process_clicker($request));
+ &startpage($request,$symb,[{href=>'', text=>'Process clicker'}]);
+ $request->print(&process_clicker($request,$symb));
} elsif ($command eq 'processclickerfile' && $perm{'mgr'}) {
- $request->print(&process_clicker_file($request));
+ &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'processclicker'), text=>'Process clicker'},
+ {href=>'', text=>'Process clicker file'}]);
+ $request->print(&process_clicker_file($request,$symb));
} elsif ($command eq 'assignclickergrades' && $perm{'mgr'}) {
- $request->print(&assign_clicker_grades($request));
+ &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'processclicker'), text=>'Process clicker'},
+ {href=>'', text=>'Process clicker file'},
+ {href=>'', text=>'Store grades'}]);
+ $request->print(&assign_clicker_grades($request,$symb));
} elsif ($command eq 'csvform' && $perm{'mgr'}) {
- $request->print(&upcsvScores_form($request));
+ &startpage($request,$symb);
+ $request->print(&upcsvScores_form($request,$symb));
} elsif ($command eq 'csvupload' && $perm{'mgr'}) {
- $request->print(&csvupload($request));
+ &startpage($request,$symb);
+ $request->print(&csvupload($request,$symb));
} elsif ($command eq 'csvuploadmap' && $perm{'mgr'} ) {
- $request->print(&csvuploadmap($request));
+ &startpage($request,$symb);
+ $request->print(&csvuploadmap($request,$symb));
} elsif ($command eq 'csvuploadoptions' && $perm{'mgr'}) {
if ($env{'form.associate'} ne 'Reverse Association') {
- $request->print(&csvuploadoptions($request));
+ &startpage($request,$symb);
+ $request->print(&csvuploadoptions($request,$symb));
} else {
if ( $env{'form.upfile_associate'} ne 'reverse' ) {
$env{'form.upfile_associate'} = 'reverse';
} else {
$env{'form.upfile_associate'} = 'forward';
}
- $request->print(&csvuploadmap($request));
+ &startpage($request,$symb);
+ $request->print(&csvuploadmap($request,$symb));
}
} elsif ($command eq 'csvuploadassign' && $perm{'mgr'} ) {
- $request->print(&csvuploadassign($request));
+ &startpage($request,$symb);
+ $request->print(&csvuploadassign($request,$symb));
} elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) {
- $request->print(&scantron_selectphase($request));
+ &startpage($request,$symb);
+ $request->print(&scantron_selectphase($request,undef,$symb));
} elsif ($command eq 'scantron_warning' && $perm{'mgr'}) {
- $request->print(&scantron_do_warning($request));
+ &startpage($request,$symb);
+ $request->print(&scantron_do_warning($request,$symb));
} elsif ($command eq 'scantron_validate' && $perm{'mgr'}) {
- $request->print(&scantron_validate_file($request));
+ &startpage($request,$symb);
+ $request->print(&scantron_validate_file($request,$symb));
} elsif ($command eq 'scantron_process' && $perm{'mgr'}) {
- $request->print(&scantron_process_students($request));
+ &startpage($request,$symb);
+ $request->print(&scantron_process_students($request,$symb));
} elsif ($command eq 'scantronupload' &&
(&Apache::lonnet::allowed('usc',$env{'request.role.domain'})||
&Apache::lonnet::allowed('usc',$env{'request.course.id'}))) {
- $request->print(&scantron_upload_scantron_data($request));
+ &startpage($request,$symb);
+ $request->print(&scantron_upload_scantron_data($request,$symb));
} elsif ($command eq 'scantronupload_save' &&
(&Apache::lonnet::allowed('usc',$env{'request.role.domain'})||
&Apache::lonnet::allowed('usc',$env{'request.course.id'}))) {
- $request->print(&scantron_upload_scantron_data_save($request));
+ &startpage($request,$symb);
+ $request->print(&scantron_upload_scantron_data_save($request,$symb));
} elsif ($command eq 'scantron_download' &&
&Apache::lonnet::allowed('usc',$env{'request.course.id'})) {
- $request->print(&scantron_download_scantron_data($request));
+ &startpage($request,$symb);
+ $request->print(&scantron_download_scantron_data($request,$symb));
+ } elsif ($command eq 'checksubmissions' && $perm{'vgr'}) {
+ &startpage($request,$symb);
+ $request->print(&checkscantron_results($request,$symb));
} elsif ($command) {
- $request->print("Access Denied ($command)");
+ &startpage($request,$symb);
+ $request->print(''.&mt('Access Denied ([_1])',$command).' ');
}
}
if ($ssi_error) {
@@ -8749,3 +9324,174 @@ sub handler {
1;
__END__;
+
+
+=head1 NAME
+
+Apache::grades
+
+=head1 SYNOPSIS
+
+Handles the viewing of grades.
+
+This is part of the LearningOnline Network with CAPA project
+described at http://www.lon-capa.org.
+
+=head1 OVERVIEW
+
+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.
+
+
+
+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.
+
+
+=head1 HANDLER SUBROUTINE
+
+ssi_with_retries()
+
+=head1 SUBROUTINES
+
+=over
+
+=item scantron_get_correction() :
+
+ Builds the interface screen to interact with the operator to fix a
+ specific error condition in a specific scanline
+
+ Arguments:
+ $r - Apache request object
+ $i - number of the current scanline
+ $scan_record - hash ref as returned from &scantron_parse_scanline()
+ $scan_config - hash ref as returned from &get_scantron_config()
+ $line - full contents of the current scanline
+ $error - error condition, valid values are
+ 'incorrectCODE', 'duplicateCODE',
+ 'doublebubble', 'missingbubble',
+ 'duplicateID', 'incorrectID'
+ $arg - extra information needed
+ For errors:
+ - duplicateID - paper number that this studentID was seen before on
+ - duplicateCODE - array ref of the paper numbers this CODE was
+ seen on before
+ - incorrectCODE - current incorrect CODE
+ - doublebubble - array ref of the bubble lines that have double
+ bubble errors
+ - missingbubble - array ref of the bubble lines that have missing
+ bubble errors
+
+=item scantron_get_maxbubble() :
+
+ Arguments:
+ $nav_error - Reference to scalar which is a flag to indicate a
+ failure to retrieve a navmap object.
+ if $nav_error is set to 1 by scantron_get_maxbubble(), the
+ calling routine should trap the error condition and display the warning
+ found in &navmap_errormsg().
+
+ Returns the maximum number of bubble lines that are expected to
+ occur. Does this by walking the selected sequence rendering the
+ resource and then checking &Apache::lonxml::get_problem_counter()
+ for what the current value of the problem counter is.
+
+ Caches the results to $env{'form.scantron_maxbubble'},
+ $env{'form.scantron.bubble_lines.n'},
+ $env{'form.scantron.first_bubble_line.n'} and
+ $env{"form.scantron.sub_bubblelines.n"}
+ which are the total number of bubble, lines, the number of bubble
+ lines for response n and number of the first bubble line for response n,
+ and a comma separated list of numbers of bubble lines for sub-questions
+ (for optionresponse, matchresponse, and rankresponse items), for response n.
+
+
+=item scantron_validate_missingbubbles() :
+
+ Validates all scanlines in the selected file to not have any
+ answers that don't have bubbles that have not been verified
+ to be bubble free.
+
+=item scantron_process_students() :
+
+ Routine that does the actual grading of the bubble sheet information.
+
+ The parsed scanline hash is added to %env
+
+ Then foreach unskipped scanline it does an &Apache::lonnet::ssi()
+ foreach resource , with the form data of
+
+ 'submitted' =>'scantron'
+ 'grade_target' =>'grade',
+ 'grade_username'=> username of student
+ 'grade_domain' => domain of student
+ 'grade_courseid'=> of course
+ 'grade_symb' => symb of resource to grade
+
+ This triggers a grading pass. The problem grading code takes care
+ of converting the bubbled letter information (now in %env) into a
+ valid submission.
+
+=item scantron_upload_scantron_data() :
+
+ Creates the screen for adding a new bubble sheet data file to a course.
+
+=item scantron_upload_scantron_data_save() :
+
+ Adds a provided bubble information data file to the course if user
+ has the correct privileges to do so.
+
+=item valid_file() :
+
+ Validates that the requested bubble data file exists in the course.
+
+=item scantron_download_scantron_data() :
+
+ Shows a list of the three internal files (original, corrected,
+ skipped) for a specific bubble sheet data file that exists in the
+ course.
+
+=item scantron_validate_ID() :
+
+ Validates all scanlines in the selected file to not have any
+ invalid or underspecified student/employee IDs
+
+=item navmap_errormsg() :
+
+ Returns HTML mark-up inside a with a link to re-initialize the course.
+ Should be called whenever the request to instantiate a navmap object fails.
+
+=back
+
+=cut
|