--- loncom/homework/grades.pm 2007/07/24 21:21:31 1.423 +++ loncom/homework/grades.pm 2007/07/25 00:00:23 1.424 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.423 2007/07/24 21:21:31 albertel Exp $ +# $Id: grades.pm,v 1.424 2007/07/25 00:00:23 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -4357,9 +4357,47 @@ sub updateGradeByPage { =head1 Bubble sheet grading routines - (For this documentation 'scanline' refers to the full line of characters - from the file that we are parsing 'bubble line' refers to the data - representing the line of bubbles that are on the physical bubble sheet) + For this documentation: + + 'scanline' refers to the full line of characters + from the file that we are parsing that represents one entire sheet + + 'bubble line' refers to the data + representing the line of bubbles that are on the physical bubble sheet + + +The overall process is that a scanned in bubble sheet data is uploaded +into a course. When a user wants to grade, they select a +sequence/folder of resources, a file of bubble sheet info, and pick +one of the predefined configurations for what each scanline looks +like. + +Next each scanline is checked for any errors of either 'missing +bubbles' (it's an error because it may have been missed scanned +because too light bubbling), 'double bubble' (each bubble line should +have no more that one letter picked), invalid or duplicated CODE, +invalid student ID + +If the CODE option is used that determines the randomization of the +homework problems, either way the student ID is looked up into a +username:domain. + +During the validation phase the instructor can choose to skip scanlines. + +After the validation phase, there is now 3 bubble sheet files + + scantron_original_filename (unmodified original file) + scantron_corrected_filename (file where the corrected information has replaced the original information) + scantron_skipped_filename (contains the exact text of scanlines that where skipped) + +Also there is a separate hash nohist_scantrondata that contains extra +correction information that isn't representable in the bubble sheet +file (see &scantron_getfile() for more information) + +After all scanlines are either valid, marked as valid or skipped, then +foreach line foreach problem in the picked sequence, an ssi request is +made that simulates a user submitting their selected letter(s) against +the homework problem. =over 4 @@ -4531,7 +4569,7 @@ sub scantron_CODEunique { Generates the initial screen to start the bubble sheet process. Allows for - starting a grading run. - - downloading exisiting scan data (original, corrected + - downloading existing scan data (original, corrected or skipped info) - uploading new scan data @@ -4589,7 +4627,7 @@ sub scantron_selectphase { Options:
-
+
@@ -4732,17 +4770,18 @@ SCANTRONFORM 'questions' start Qlength - number of columns comprising a single bubble line from the sheet. (usually either 1 or 10) - Qon - either a single charater representing the character used + Qon - either a single character representing the character used to signal a bubble was chosen in the positional setup, or the string 'letter' if the letter of the chosen bubble is in the final, or 'number' if a number representing the chosen bubble is in the file (1->A 0->J) - Qoff - the character used to represent that a buble was left blank + Qoff - the character used to represent that a bubble was + left blank PaperID - if the scanning process generates a unique number for each sheet scanned the column that this ID number starts in PaperIDlength - number of columns that comprise the unique ID number for the sheet of paper - FirstName - column that the firs tname starts in + FirstName - column that the first name starts in FirstNameLength - number of columns that the first name spans LastName - column that the last name starts in @@ -4793,7 +4832,7 @@ sub get_scantron_config { $classlist - reference to the class list hash. This is a hash keyed by student name:domain whose elements are references - to arrays containng various chunks of information + to arrays containing various chunks of information about the student. (See loncoursedata for more info). Returns @@ -4813,7 +4852,7 @@ sub username_to_idmap { =pod -=item scatron_fixup_scanline +=item scantron_fixup_scanline Process a requested correction to a scanline. @@ -4832,12 +4871,12 @@ sub username_to_idmap { $args - hash of additional info, - 'ID' 'newid' -> studentID to use in replacement - of exisiting one + of existing one - 'CODE' 'CODE_ignore_dup' - set to true if duplicates should be ignored. 'CODE' - is new code or 'use_unfound' - if the exisitng unfound code should + if the existing unfound code should be used as is - 'answer' 'response' - new answer or 'none' if blank @@ -4920,7 +4959,7 @@ sub scantron_fixup_scanline { Arguments: $scan_data - The hash (see scantron_getfile) $key - shorthand of the key to edit (actual key is - scatronfilename_key). + scantronfilename_key). $data - New value of the hash entry. $delete - If true, the entry is removed from the hash. @@ -5107,13 +5146,13 @@ sub scantron_parse_scanline { queue of messages to be shown after grading pass is complete Arguments: - $delayqueue - arrary ref of hash ref of erro messages + $delayqueue - arrary ref of hash ref of error messages $scanline - the scanline that caused the error $errormesage - the error message $errorcode - a numeric code for the error Side Effects: - updates the $dealyqueue to have a new hash ref of the error + updates the $delayqueue to have a new hash ref of the error =cut @@ -5129,6 +5168,18 @@ sub scantron_add_delay { =item scantron_find_student + Finds the username for the current scanline + + Arguments: + $scantron_record - hash result from scantron_parse_scanline + $scan_data - hash of correction information + (see &scantron_getfile() form more information) + $idmap - hash from &username_to_idmap() + $line - number of current scanline + + Returns: + Either 'username:domain' or undef if unknown + =cut sub scantron_find_student { @@ -5149,6 +5200,9 @@ sub scantron_find_student { =item scantron_filter + Filter sub for lonnavmaps, filters out hidden resources if ignore + hidden resources was selected + =cut sub scantron_filter { @@ -5171,6 +5225,9 @@ sub scantron_filter { =item scantron_process_corrections + Gets correction information out of submitted form data and corrects + the scanline + =cut sub scantron_process_corrections { @@ -5234,6 +5291,10 @@ sub scantron_process_corrections { =item reset_skipping_status + Forgets the current set of remember skipped scanlines (and thus + reverts back to considering all lines in the + scantron_skipped_ file) + =cut sub reset_skipping_status { @@ -5246,6 +5307,8 @@ sub reset_skipping_status { =item start_skipping + Marks a scanline to be skipped. + =cut sub start_skipping { @@ -5263,6 +5326,8 @@ sub start_skipping { =item should_be_skipped + Checks whether a scanline should be skipped. + =cut sub should_be_skipped { @@ -5284,6 +5349,9 @@ sub should_be_skipped { =item remember_current_skipped + Discovers what scanlines are in the scantron_skipped_ + file and remembers them into scan_data for later use. + =cut sub remember_current_skipped { @@ -5303,6 +5371,10 @@ sub remember_current_skipped { =item check_for_error + Checks if there was an error when attempting to remove a specific + scantron_.. bubble sheet data file. Prints out an error if + something went wrong. + =cut sub check_for_error { @@ -5316,6 +5388,9 @@ sub check_for_error { =item scantron_warning_screen + Interstitial screen to make sure the operator has selected the + correct options before we start the validation phase. + =cut sub scantron_warning_screen { @@ -5354,6 +5429,9 @@ STUFF =item scantron_do_warning + Check if the operator has picked something for all required + fields. Error out if something is missing. + =cut sub scantron_do_warning { @@ -5391,6 +5469,8 @@ STUFF =item scantron_form_start + html hidden input for remembering all selected grading options + =cut sub scantron_form_start { @@ -5414,6 +5494,12 @@ SCANTRONFORM =item scantron_validate_file + Dispatch routine for doing validation of a bubble sheet data file. + + Also processes any necessary information resets that need to + occur before validation begins (ignore previous corrections, + restarting the skipped records processing) + =cut sub scantron_validate_file { @@ -5423,7 +5509,7 @@ sub scantron_validate_file { my $default_form_data=&defaultFormData($symb); # do the detection of only doing skipped records first befroe we delete - # them when doing the corrections reset + # them when doing the corrections reset if ($env{'form.scantron_options_redo'} ne 'redo_skipped_ready') { &reset_skipping_status(); } @@ -5442,7 +5528,7 @@ sub scantron_validate_file { if ($env{'form.scantron_corrections'}) { &scantron_process_corrections($r); } - $r->print("

Gathering neccessary info.

");$r->rflush(); + $r->print("

Gathering necessary info.

");$r->rflush(); #get the student pick code ready $r->print(&Apache::loncommon::studentbrowser_javascript()); my $max_bubble=&scantron_get_maxbubble(); @@ -5504,6 +5590,10 @@ STUFF =item scantron_remove_file + Removes the requested bubble sheet data file, makes sure that + scantron_original_ is never removed + + =cut sub scantron_remove_file { @@ -5525,6 +5615,11 @@ sub scantron_remove_file { =item scantron_remove_scan_data + Removes all scan_data correction for the requested bubble sheet + data file. (In the case that both the are doing skipped records we need + to remember the old skipped lines for the time being so that element + persists for a while.) + =cut sub scantron_remove_scan_data { @@ -5554,6 +5649,24 @@ sub scantron_remove_scan_data { =item scantron_getfile + Fetches the requested bubble sheet data file (all 3 versions), and + the scan_data hash + + Arguments: + None + + Returns: + 2 hash references + + - first one has + orig - + corrected - + skipped - each of which points to an array ref of the specified + file broken up into individual lines + count - number of scanlines + + - second is the scan_data hash possible keys are + =cut sub scantron_getfile { @@ -5592,6 +5705,15 @@ sub scantron_getfile { =item lonnet_putfile + Wrapper routine to call &Apache::lonnet::finishuserfileupload + + Arguments: + $contents - data to store + $filename - filename to store $contents into + + Returns: + result value from &Apache::lonnet::finishuserfileupload + =cut sub lonnet_putfile { @@ -5607,6 +5729,16 @@ sub lonnet_putfile { =item scantron_putfile + Stores the current version of the bubble sheet data files, and the + scan_data hash. (Does not modify the original version only the + corrected and skipped versions. + + Arguments: + $scanlines - hash ref that looks like the first return value from + &scantron_getfile() + $scan_data - hash ref that looks like the second return value from + &scantron_getfile() + =cut sub scantron_putfile { @@ -5633,6 +5765,22 @@ sub scantron_putfile { =item scantron_get_line + Returns the correct version of the scanline + + Arguments: + $scanlines - hash ref that looks like the first return value from + &scantron_getfile() + $scan_data - hash ref that looks like the second return value from + &scantron_getfile() + $i - number of the requested line (starts at 0) + + Returns: + A scanline, (either the original or the corrected one if it + exists), or undef if the requested scanline should be + skipped. (Either because it's an skipped scanline, or it's an + unskipped scanline and we are not doing a 'do skipped scanlines' + pass. + =cut sub scantron_get_line { @@ -5647,6 +5795,17 @@ sub scantron_get_line { =item scantron_todo_count + Counts the number of scanlines that need processing. + + Arguments: + $scanlines - hash ref that looks like the first return value from + &scantron_getfile() + $scan_data - hash ref that looks like the second return value from + &scantron_getfile() + + Returns: + $count - number of scanlines to process + =cut sub get_todo_count { @@ -5664,6 +5823,19 @@ sub get_todo_count { =item scantron_put_line + Updates the 'corrected' or 'skipped' versions of the bubble sheet + data file. + + Arguments: + $scanlines - hash ref that looks like the first return value from + &scantron_getfile() + $scan_data - hash ref that looks like the second return value from + &scantron_getfile() + $i - line number to update + $newline - contents of the updated scanline + $skip - if true make the line for skipping and update the + 'skipped' file + =cut sub scantron_put_line { @@ -5680,6 +5852,15 @@ sub scantron_put_line { =item scantron_clear_skip + Remove a line from the 'skipped' file + + Arguments: + $scanlines - hash ref that looks like the first return value from + &scantron_getfile() + $scan_data - hash ref that looks like the second return value from + &scantron_getfile() + $i - line number to update + =cut sub scantron_clear_skip { @@ -5695,6 +5876,9 @@ sub scantron_clear_skip { =item scantron_filter_not_exam + Filter routine used by &Apache::lonnavmaps::retrieveResources(), to + filter out resources that are not marked as 'exam' mode + =cut sub scantron_filter_not_exam { @@ -5717,6 +5901,9 @@ sub scantron_filter_not_exam { =item scantron_validate_sequence + Validates the selected sequence, checking for resource that are + not set to exam mode. + =cut sub scantron_validate_sequence { @@ -5746,6 +5933,9 @@ sub scantron_validate_sequence { =item scantron_validate_ID + Validates all scanlines in the selected file to not have any + invalid or underspecified student IDs + =cut sub scantron_validate_ID { @@ -5814,6 +6004,30 @@ sub scantron_validate_ID { =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 + =cut sub scantron_get_correction { @@ -5945,7 +6159,7 @@ ENDSCRIPT =item scantron_bubble_selector Generates the html radiobuttons to correct a single bubble line - possibly showing the exisiting the selected bubbles if known + possibly showing the existing the selected bubbles if known Arguments: $r - Apache request object @@ -6021,6 +6235,16 @@ sub scantron_bubble_selector { =item num_matches + Counts the number of characters that are the same between the two arguments. + + Arguments: + $orig - CODE from the scanline + $code - CODE to match against + + Returns: + $count - integer count of the number of same characters between the + two arguments + =cut sub num_matches { @@ -6038,6 +6262,20 @@ sub num_matches { =item scantron_get_closely_matching_CODEs + Cycles through all CODEs and finds the set that has the greatest + number of same characters as the provided CODE + + Arguments: + $allcodes - hash ref returned by &get_codes() + $CODE - CODE from the current scanline + + Returns: + 2 element list + - first elements is number of how closely matching the best fit is + (5 means best set has 5 matching characters) + - second element is an arrary ref containing the set of valid CODEs + that best fit the passed in CODE + =cut sub scantron_get_closely_matching_CODEs { @@ -6054,6 +6292,17 @@ sub scantron_get_closely_matching_CODEs =item get_codes + Builds a hash which has keys of all of the valid CODEs from the selected + set of remembered CODEs. + + Arguments: + $old_name - name of the set of remembered CODEs + $cdom - domain of the course + $cnum - internal course name + + Returns: + %allcodes - keys are the valid CODEs, values are all 1 + =cut sub get_codes { @@ -6082,6 +6331,10 @@ sub get_codes { =item scantron_validate_CODE + Validates all scanlines in the selected file to not have any + invalid or underspecified CODEs and that none of the codes are + duplicated if this was requested. + =cut sub scantron_validate_CODE { @@ -6139,6 +6392,9 @@ sub scantron_validate_CODE { =item scantron_validate_doublebubble + Validates all scanlines in the selected file to not have any + bubble lines with multiple bubbles marked. + =cut sub scantron_validate_doublebubble { @@ -6168,6 +6424,13 @@ sub scantron_validate_doublebubble { =item scantron_get_maxbubble + 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 result to $env{'form.scantron_maxbubble'} + =cut sub scantron_get_maxbubble { @@ -6200,6 +6463,9 @@ sub scantron_get_maxbubble { =item scantron_validate_missingbubbles + Validates all scanlines in the selected file to not have any + bubble lines with missing bubbles that haven't been verified as missing. + =cut sub scantron_validate_missingbubbles { @@ -6474,7 +6740,7 @@ sub scantron_upload_scantron_data_save { =item valid_file - Vaildates that the requested bubble data file has exists in the course. + Validates that the requested bubble data file exists in the course. =cut