--- loncom/homework/grades.pm 2013/06/29 16:27:39 1.596.2.12.2.17 +++ loncom/homework/grades.pm 2012/08/09 23:25:48 1.596.2.13 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.596.2.12.2.17 2013/06/29 16:27:39 raeburn Exp $ +# $Id: grades.pm,v 1.596.2.13 2012/08/09 23:25:48 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -125,16 +125,13 @@ sub getpartlist { # --- Get the symbolic name of a problem and the url sub get_symb { my ($request,$silent) = @_; - my $symb=$env{'form.symb'}; - unless ($symb) { - (my $url=$env{'form.url'}) =~ s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--; - $symb = &Apache::lonnet::symbread($url); - if ($symb eq '') { - if (!$silent) { - $request->print(&mt("Unable to handle ambiguous references: [_1].",$url)); - return (); - } - } + (my $url=$env{'form.url'}) =~ s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--; + my $symb=($env{'form.symb'} ne '' ? $env{'form.symb'} : (&Apache::lonnet::symbread($url))); + if ($symb eq '') { + if (!$silent) { + $request->print(&mt("Unable to handle ambiguous references: [_1].",$url)); + return (); + } } &Apache::lonenc::check_decrypt(\$symb); return ($symb); @@ -253,7 +250,7 @@ sub showResourceInfo { $result.=''.$display_part.'' .''.''.$resID.'' .''.&mt($responsetype).'' -# .''.&mt('Handgrade: [_1]',$handgrade).'' +# .''.&mt('Handgrade: [_1]',$handgrade).'' .&Apache::loncommon::end_data_table_row(); } } @@ -277,7 +274,7 @@ sub reset_caches { } sub get_analyze { - my ($symb,$uname,$udom,$no_increment,$add_to_hash,$type,$trial,$rndseed,$bubbles_per_row)=@_; + my ($symb,$uname,$udom,$no_increment,$add_to_hash,$type,$trial,$rndseed)=@_; my $key = "$symb\0$uname\0$udom"; if ($type eq 'randomizetry') { if ($trial ne '') { @@ -311,9 +308,6 @@ sub reset_caches { 'grade_courseid' => $env{'request.course.id'}, 'grade_username' => $uname, 'grade_noincrement' => $no_increment); - if ($bubbles_per_row ne '') { - $form{'bubbles_per_row'} = $bubbles_per_row; - } if ($type eq 'randomizetry') { $form{'grade_questiontype'} = $type; if ($rndseed ne '') { @@ -354,7 +348,7 @@ sub reset_caches { } sub scantron_partids_tograde { - my ($resource,$cid,$uname,$udom,$check_for_randomlist,$bubbles_per_row) = @_; + my ($resource,$cid,$uname,$udom,$check_for_randomlist) = @_; my (%analysis,@parts); if (ref($resource)) { my $symb = $resource->symb(); @@ -362,9 +356,7 @@ sub reset_caches { if ($check_for_randomlist) { $add_to_form = { 'check_parts_withrandomlist' => 1,}; } - my $analyze = - &get_analyze($symb,$uname,$udom,undef,$add_to_form, - undef,undef,undef,$bubbles_per_row); + my $analyze = &get_analyze($symb,$uname,$udom,undef,$add_to_form); if (ref($analyze) eq 'HASH') { %analysis = %{$analyze}; } @@ -1619,15 +1611,17 @@ INNERJS function savedMsgHeader(Nmsg,usrctr,fullname) { var height = 70*Nmsg+250; + var scrollbar = "no"; if (height > 600) { height = 600; + scrollbar = "yes"; } var xpos = (screen.width-600)/2; xpos = (xpos < 0) ? '0' : xpos; var ypos = (screen.height-height)/2-30; ypos = (ypos < 0) ? '0' : ypos; - pWin = window.open('', 'MessageCenter', 'resizable=yes,toolbar=no,location=no,scrollbars=yes,screenx='+xpos+',screeny='+ypos+',width=700,height='+height); + pWin = window.open('', 'MessageCenter', 'resizable=yes,toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=700,height='+height); pWin.focus(); pDoc = pWin.document; pDoc.$docopen; @@ -1837,6 +1831,7 @@ sub gradeBox { $line.=''."\n"; + #&mt('Part:[_1]Points:[_2]or[_3]',$display_part,$radio,$line); $result .= ''.$display_part.''.$radio.''.&mt('or').''.$line.''; $result.=&Apache::loncommon::end_data_table_row(); @@ -1923,27 +1918,14 @@ sub show_problem { $companswer=~s|||g; $companswer=~s|name="submit"|name="would_have_been_submit"|g; } - my $renderheading = &mt('View of the problem'); - my $answerheading = &mt('Correct answer'); - if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) { - my $stu_fullname = $env{'form.fullname'}; - if ($stu_fullname eq '') { - $stu_fullname = &Apache::loncommon::plainname($uname,$udom,'lastname'); - } - my $forwhom = &nameUserString(undef,$stu_fullname,$uname,$udom); - if ($forwhom ne '') { - $renderheading = &mt('View of the problem for[_1]',$forwhom); - $answerheading = &mt('Correct answer for[_1]',$forwhom); - } - } $rendered= '
' - .'

'.$renderheading.'

' + .'

'.&mt('View of the problem').'

' .$rendered .'
'; $companswer= '
' - .'

'.$answerheading.'

' + .'

'.&mt('Correct answer').'

' .$companswer .'
'; my $result; @@ -2014,7 +1996,7 @@ sub submission { $udom = ($udom eq '' ? $env{'user.domain'} : $udom); #has form.userdom changed for a student? my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'}); $env{'form.fullname'} = &Apache::loncommon::plainname($uname,$udom,'lastname') if $env{'form.fullname'} eq ''; - my ($symb) = &get_symb($request); + my $symb = &get_symb($request); if ($symb eq '') { $request->print("Unable to handle ambiguous references:."); return ''; } if (!&canview($usec)) { @@ -2148,7 +2130,7 @@ KEYWORDS my ($adom,$aname,$apath)=($essayurl=~/^($LONCAPA::domain_re)\/($LONCAPA::username_re)\/(.*)$/); $apath=&escape($apath); $apath=~s/\W/\_/gs; - &init_old_essays($symb,$apath,$adom,$aname); + &init_old_essays($symb,$apath,$adom,$aname); } } @@ -2617,187 +2599,10 @@ sub keywords_highlight { return $string; } -# For Tasks provide a mechanism to display previous version for one specific student - -sub show_previous_task_version { - my ($request,$symb) = @_; - if ($symb eq '') { - $request->print("Unable to handle ambiguous references."); - - return ''; - } - my ($uname,$udom) = ($env{'form.student'},$env{'form.userdom'}); - my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'}); - if (!&canview($usec)) { - $request->print('Unable to view previous version for requested student.('. - $uname.':'.$udom.' in section '.$usec.' in course id '. - $env{'request.course.id'}.')'); - return; - } - my $mode = 'both'; - my $isTask = ($symb =~/\.task$/); - if ($isTask) { - if ($env{'form.previousversion'} =~ /^\d+$/) { - if ($env{'form.fullname'} eq '') { - $env{'form.fullname'} = - &Apache::loncommon::plainname($uname,$udom,'lastname'); - } - my $probtitle=&Apache::lonnet::gettitle($symb); - $request->print("\n\n". - '
'. - '

'.&nameUserString(undef,$env{'form.fullname'},$uname,$udom). - '

'."\n"); - &Apache::lonxml::clear_problem_counter(); - $request->print(&show_problem($request,$symb,$uname,$udom,1,1,$mode, - {'previousversion' => $env{'form.previousversion'} })); - $request->print("\n
"); - } - } - return; -} - -sub choose_task_version_form { - my ($symb,$uname,$udom,$nomenu) = @_; - my $isTask = ($symb =~/\.task$/); - my ($current,$version,$result,$js,$displayed,$rowtitle); - if ($isTask) { - my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'}, - $udom,$uname); - if (($record{'resource.0.version'} eq '') || - ($record{'resource.0.version'} < 2)) { - return ($record{'resource.0.version'}, - $record{'resource.0.version'},$result,$js); - } else { - $current = $record{'resource.0.version'}; - } - if ($env{'form.previousversion'}) { - $displayed = $env{'form.previousversion'}; - $rowtitle = &mt('Choose another version:') - } else { - $displayed = $current; - $rowtitle = &mt('Show earlier version:'); - } - $result = '
'; - my $list; - my $numversions = 0; - for (my $i=1; $i<=$record{'resource.0.version'}; $i++) { - if ($i == $current) { - if (!$env{'form.previousversion'} || $nomenu) { - next; - } else { - $list .= ''."\n"; - $numversions ++; - } - } elsif (defined($record{'resource.'.$i.'.0.status'})) { - unless ($i == $env{'form.previousversion'}) { - $numversions ++; - } - $list .= ''."\n"; - } - } - if ($numversions) { - $symb = &HTML::Entities::encode($symb,'<>"&'); - $result .= - '
'. - &Apache::loncommon::start_data_table(). - &Apache::loncommon::start_data_table_row(). - ''.$rowtitle.''. - ''. - &Apache::loncommon::end_data_table_row(); - unless ($nomenu) { - $result .= &Apache::loncommon::start_data_table_row(). - ''.&mt('Open in new window').''. - ''. - ''. - ''. - ''. - &Apache::loncommon::end_data_table_row(); - } - $result .= - &Apache::loncommon::start_data_table_row(). - ' '. - ''. - ''. - ''. - &Apache::loncommon::end_data_table_row(). - &Apache::loncommon::end_data_table(). - '
'; - $js = &previous_display_javascript($nomenu,$current); - } elsif ($displayed && $nomenu) { - $result .= ''.&mt('Close window').''; - } else { - $result .= &mt('No previous versions to show for this student'); - } - $result .= '
'; - } - return ($current,$displayed,$result,$js); -} - -sub previous_display_javascript { - my ($nomenu,$current) = @_; - my $js = <<"JSONE"; - -ENDJS - -} - #--- Called from submission routine sub processHandGrade { my ($request) = shift; - my ($symb) = &get_symb($request); + my $symb = &get_symb($request); my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb); my $button = $env{'form.gradeOpt'}; my $ngrade = $env{'form.NCT'}; @@ -3202,11 +3007,9 @@ sub handback_files { &file_name_version_ext($answer_file); my ($portfolio_path) = ($directory =~ /^.+$stuname\/portfolio(.*)/); my $getpropath = 1; - my ($dir_list,$listerror) = - &Apache::lonnet::dirlist($portfolio_root.$portfolio_path, - $domain,$stuname,$getpropath); - my $version = &get_next_version($answer_name,$answer_ext,$dir_list); - # fix filename + 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}\/(.*)/); my $result=&Apache::lonnet::finishuserfileupload($stuname,$domain, $newflg.'_'.$part_resp.'_returndoc'.$counter, @@ -3226,7 +3029,7 @@ sub handback_files { $file_msg.=''.$save_file_name."
"; } - $request->print('
'.&mt('[_1] will be the uploaded filename [_2]',''.$fname.'',''.$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter}.'')); + $request->print('
'.&mt('[_1] will be the uploaded file name [_2]',''.$fname.'',''.$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter}.'')); } } } @@ -3365,11 +3168,9 @@ sub version_portfiles { my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*)$/); my ($answer_name,$answer_ver,$answer_ext) = &file_name_version_ext($answer_file); - my $getpropath = 1; - my ($dir_list,$listerror) = - &Apache::lonnet::dirlist($portfolio_root.$directory,$domain, - $stu_name,$getpropath); - my $version = &get_next_version($answer_name,$answer_ext,$dir_list); + 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') { push(@versioned_portfiles, $directory.$new_answer); @@ -3388,24 +3189,21 @@ sub version_portfiles { sub get_next_version { my ($answer_name, $answer_ext, $dir_list) = @_; my $version; - if (ref($dir_list) eq 'ARRAY') { - foreach my $row (@{$dir_list}) { - my ($file) = split(/\&/,$row,2); - my ($file_name,$file_version,$file_ext) = - &file_name_version_ext($file); - if (($file_name eq $answer_name) && - ($file_ext eq $answer_ext)) { - # gets here if filename and extension match, - # regardless of version + foreach my $row (@$dir_list) { + my ($file) = split(/\&/,$row,2); + my ($file_name,$file_version,$file_ext) = + &file_name_version_ext($file); + if (($file_name eq $answer_name) && + ($file_ext eq $answer_ext)) { + # gets here if filename and extension match, regardless of version if ($file_version ne '') { - # a versioned file is found so save it for later - if ($file_version > $version) { - $version = $file_version; - } + # a versioned file is found so save it for later + if ($file_version > $version) { + $version = $file_version; } } } - } + } $version ++; return($version); } @@ -3865,7 +3663,7 @@ sub viewstudentgrade { sub editgrades { my ($request) = @_; - my ($symb)=&get_symb($request); + my $symb=&get_symb($request); my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section')); my $title='

'.&mt('Current Grade Status').'

'; $title.='

'.&mt('Current Resource: [_1]',$env{'form.probTitle'}).'

'."\n"; @@ -4810,8 +4608,8 @@ sub displayPage { &Apache::loncommon::start_data_table_row(). ''.$prob. (scalar(@{$parts}) == 1 ? '' - : '
('.&mt('[_1]parts', - scalar(@{$parts}).' ').')' + : '
('.&mt('[_1]parts)', + scalar(@{$parts}).' ') ). ''; $studentTable.=''; @@ -4893,7 +4691,6 @@ sub displaySubByDates { &Apache::loncommon::start_data_table_header_row(). ''.&mt('Date/Time').''. ($isCODE?''.&mt('CODE').'':''). - ($isTask?''.&mt('Version').'':''). ''.&mt('Submission').''. ''.&mt('Status').''. &Apache::loncommon::end_data_table_header_row(); @@ -4914,9 +4711,7 @@ sub displaySubByDates { if (exists($$record{$version.':resource.0.version'})) { $interaction = $$record{$version.':resource.0.version'}; } - if ($isTask && $env{'form.previousversion'}) { - next unless ($interaction == $env{'form.previousversion'}); - } + my $where = ($isTask ? "$version:resource.$interaction" : "$version:resource"); $studentTable.=&Apache::loncommon::start_data_table_row(). @@ -4924,9 +4719,6 @@ sub displaySubByDates { if ($isCODE) { $studentTable.=''.$record->{$version.':resource.CODE'}.''; } - if ($isTask) { - $studentTable.=''.$interaction.''; - } my @versionKeys = split(/\:/,$$record{$version.':keys'}); my @displaySub = (); foreach my $partid (@{$parts}) { @@ -4946,7 +4738,7 @@ sub displaySubByDates { my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/) : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/)); - $displaySub[0].=''; + $displaySub[0].='' .' ' .'('.&mt('Response ID: [_1]',$responseId).')' @@ -5308,11 +5100,6 @@ my %subdivided_bubble_lines; # no. my %responsetype_per_response; # responsetype for each response -my %masterseq_id_responsenum; # src_id (e.g., 12.3_0.11 etc.) for each - # numbered response. Needed when randomorder - # or randompick are in use. Key is ID, value - # is response number. - # Save and restore the bubble lines array to the form env. @@ -5326,17 +5113,12 @@ sub save_bubble_lines { $env{"form.scantron.responsetype.$line"} = $responsetype_per_response{$line}; } - foreach my $resid (keys(%masterseq_id_responsenum)) { - my $line = $masterseq_id_responsenum{$resid}; - $env{"form.scantron.residpart.$line"} = $resid; - } } sub restore_bubble_lines { my $line = 0; %bubble_lines_per_response = (); - %masterseq_id_responsenum = (); while ($env{"form.scantron.bubblelines.$line"}) { my $value = $env{"form.scantron.bubblelines.$line"}; $bubble_lines_per_response{$line} = $value; @@ -5346,12 +5128,28 @@ sub restore_bubble_lines { $env{"form.scantron.sub_bubblelines.$line"}; $responsetype_per_response{$line} = $env{"form.scantron.responsetype.$line"}; - my $id = $env{"form.scantron.residpart.$line"}; - $masterseq_id_responsenum{$id} = $line; $line++; } } +# Given the parsed scanline, get the response for +# 'answer' number n: + +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}; + + my $selected = ""; + + for (my $bline = 0; $bline < $bubble_lines; $bline++) { + $selected .= $$parsed_line{"scantron.$bubble_line.answer"}.":"; + $bubble_line++; + } + return $selected; +} + =pod =item scantron_filenames @@ -5364,16 +5162,14 @@ 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 ($dirlist,$listerror) = &Apache::lonnet::dirlist('userfiles',$cdom, - $cname,$getpropath); + my @files=&Apache::lonnet::dirlist('userfiles',$cdom,$cname, + $getpropath); my @possiblenames; - if (ref($dirlist) eq 'ARRAY') { - foreach my $filename (sort(@{$dirlist})) { - ($filename)=split(/&/,$filename); - if ($filename!~/^scantron_orig_/) { next ; } - $filename=~s/^scantron_orig_//; - push(@possiblenames,$filename); - } + foreach my $filename (sort(@files)) { + ($filename)=split(/&/,$filename); + if ($filename!~/^scantron_orig_/) { next ; } + $filename=~s/^scantron_orig_//; + push(@possiblenames,$filename); } return @possiblenames; } @@ -5771,8 +5567,6 @@ sub scantron_selectphase { LastName - column that the last name starts in LastNameLength - number of columns that the last name spans - BubblesPerRow - number of bubbles available in each row used to - bubble an answer. (If not specified, 10 assumed). =cut @@ -5803,7 +5597,6 @@ sub get_scantron_config { $config{'FirstNamelength'}=$config[14]; $config{'LastName'}=$config[15]; $config{'LastNamelength'}=$config[16]; - $config{'BubblesPerRow'}=$config[17]; last; } return %config; @@ -6015,27 +5808,6 @@ sub digits_to_letters { (see scantron_getfile for more information) just_header - True if should not process question answers but only the stuff to the left of the answers. - randomorder - True if randomorder in use - randompick - True if randompick in use - sequence - Exam folder URL - master_seq - Ref to array containing symbs in exam folder - symb_to_resource - Ref to hash of symbs for resources in exam folder - (corresponding values are resource objects) - partids_by_symb - Ref to hash of symb -> array ref of partIDs - orderedforcode - Ref to hash of arrays. keys are CODEs and values - are refs to an array of resource objects, ordered - according to order used for CODE, when randomorder - and or randompick are in use. - respnumlookup - Ref to hash mapping question numbers in bubble lines - for current line to question number used for same question - in "Master Sequence" (as seen by Course Coordinator). - startline - Ref to hash where key is question number (0 is first) - and value is number of first bubble line for current - student or code-based randompick and/or randomorder. - totalref - Ref of scalar used to score total number of bubble - lines needed for responses in a scan line (used when - randompick in use. - Returns: Hash containing the result of parsing the scanline @@ -6080,12 +5852,12 @@ sub digits_to_letters { =cut sub scantron_parse_scanline { - my ($line,$whichline,$scantron_config,$scan_data,$just_header,$idmap, - $randomorder,$randompick,$sequence,$master_seq,$symb_to_resource, - $partids_by_symb,$orderedforcode,$respnumlookup,$startline,$totalref)=@_; + my ($line,$whichline,$scantron_config,$scan_data,$just_header)=@_; my %record; - my $data=substr($line,0,$$scantron_config{'Qstart'}-1); # stuff before answers + my $lastpos = $env{'form.scantron_maxbubble'}*$$scantron_config{'Qlength'}; + my $questions=substr($line,$$scantron_config{'Qstart'}-1,$lastpos); # Answers + my $data=substr($line,0,$$scantron_config{'Qstart'}-1); # earlier stuff if (!($$scantron_config{'CODElocation'} eq 0 || $$scantron_config{'CODElocation'} eq 'none')) { if ($$scantron_config{'CODElocation'} < 0 || @@ -6121,29 +5893,10 @@ sub scantron_parse_scanline { my $questnum=0; my $ansnum =1; # Multiple 'answer lines'/question. - my $lastpos = $env{'form.scantron_maxbubble'}*$$scantron_config{'Qlength'}; - if ($randompick || $randomorder) { - my $total = &get_respnum_lookups($sequence,$scan_data,$idmap,$line,\%record, - $master_seq,$symb_to_resource, - $partids_by_symb,$orderedforcode, - $respnumlookup,$startline); - if ($total) { - $lastpos = $total*$$scantron_config{'Qlength'}; - } - if (ref($totalref)) { - $$totalref = $total; - } - } - my $questions=substr($line,$$scantron_config{'Qstart'}-1,$lastpos); # Answers chomp($questions); # Get rid of any trailing \n. $questions =~ s/\r$//; # Get rid of trailing \r too (MAC or Win uploads). while (length($questions)) { - my $answers_needed; - if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) { - $answers_needed = $bubble_lines_per_response{$respnumlookup->{$questnum}}; - } else { - $answers_needed = $bubble_lines_per_response{$questnum}; - } + my $answers_needed = $bubble_lines_per_response{$questnum}; my $answer_length = ($$scantron_config{'Qlength'} * $answers_needed) || 1; $questnum++; @@ -6152,16 +5905,11 @@ sub scantron_parse_scanline { $questions = substr($questions,$answer_length); if (length($currentquest) < $answer_length) { next; } - my $subdivided; - if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) { - $subdivided = $subdivided_bubble_lines{$respnumlookup->{$questnum-1}}; - } else { - $subdivided = $subdivided_bubble_lines{$questnum-1}; - } - if ($subdivided =~ /,/) { + if ($subdivided_bubble_lines{$questnum-1} =~ /,/) { my $subquestnum = 1; my $subquestions = $currentquest; - my @subanswers_needed = split(/,/,$subdivided); + my @subanswers_needed = + split(/,/,$subdivided_bubble_lines{$questnum-1}); foreach my $subans (@subanswers_needed) { my $subans_length = ($$scantron_config{'Qlength'} * $subans) || 1; @@ -6172,13 +5920,10 @@ sub scantron_parse_scanline { ($$scantron_config{'Qon'} eq 'number')) { $ansnum = &scantron_validator_lettnum($ansnum, $questnum,$quest_id,$subans,$currsubquest,$whichline, - \@alphabet,\%record,$scantron_config,$scan_data, - $randomorder,$randompick,$respnumlookup); + \@alphabet,\%record,$scantron_config,$scan_data); } else { $ansnum = &scantron_validator_positional($ansnum, - $questnum,$quest_id,$subans,$currsubquest,$whichline, - \@alphabet,\%record,$scantron_config,$scan_data, - $randomorder,$randompick,$respnumlookup); + $questnum,$quest_id,$subans,$currsubquest,$whichline, \@alphabet,\%record,$scantron_config,$scan_data); } $subquestnum ++; } @@ -6187,13 +5932,11 @@ sub scantron_parse_scanline { ($$scantron_config{'Qon'} eq 'number')) { $ansnum = &scantron_validator_lettnum($ansnum,$questnum, $quest_id,$answers_needed,$currentquest,$whichline, - \@alphabet,\%record,$scantron_config,$scan_data, - $randomorder,$randompick,$respnumlookup); + \@alphabet,\%record,$scantron_config,$scan_data); } else { $ansnum = &scantron_validator_positional($ansnum,$questnum, $quest_id,$answers_needed,$currentquest,$whichline, - \@alphabet,\%record,$scantron_config,$scan_data, - $randomorder,$randompick,$respnumlookup); + \@alphabet,\%record,$scantron_config,$scan_data); } } } @@ -6201,66 +5944,9 @@ sub scantron_parse_scanline { return \%record; } -sub get_master_seq { - my ($resources,$master_seq,$symb_to_resource) = @_; - return unless ((ref($resources) eq 'ARRAY') && (ref($master_seq) eq 'ARRAY') && - (ref($symb_to_resource) eq 'HASH')); - my $resource_error; - foreach my $resource (@{$resources}) { - my $ressymb; - if (ref($resource)) { - $ressymb = $resource->symb(); - push(@{$master_seq},$ressymb); - $symb_to_resource->{$ressymb} = $resource; - } else { - $resource_error = 1; - last; - } - } - return $resource_error; -} - -sub get_respnum_lookups { - my ($sequence,$scan_data,$idmap,$line,$record,$master_seq,$symb_to_resource, - $partids_by_symb,$orderedforcode,$respnumlookup,$startline) = @_; - return unless ((ref($record) eq 'HASH') && (ref($master_seq) eq 'ARRAY') && - (ref($symb_to_resource) eq 'HASH') && (ref($partids_by_symb) eq 'HASH') && - (ref($orderedforcode) eq 'HASH') && (ref($respnumlookup) eq 'HASH') && - (ref($startline) eq 'HASH')); - my ($user,$scancode); - if ((exists($record->{'scantron.CODE'})) && - (&Apache::lonnet::validCODE($record->{'scantron.CODE'}))) { - $scancode = $record->{'scantron.CODE'}; - } else { - $user = &scantron_find_student($record,$scan_data,$idmap,$line); - } - my @mapresources = - &users_order($user,$scancode,$sequence,$master_seq,$symb_to_resource, - $orderedforcode); - my $total = 0; - my $count = 0; - foreach my $resource (@mapresources) { - my $id = $resource->id(); - my $symb = $resource->symb(); - if (ref($partids_by_symb->{$symb}) eq 'ARRAY') { - foreach my $partid (@{$partids_by_symb->{$symb}}) { - my $respnum = $masterseq_id_responsenum{$id.'_'.$partid}; - if ($respnum ne '') { - $respnumlookup->{$count} = $respnum; - $startline->{$count} = $total; - $total += $bubble_lines_per_response{$respnum}; - $count ++; - } - } - } - } - return $total; -} - sub scantron_validator_lettnum { my ($ansnum,$questnum,$quest_id,$answers_needed,$currquest,$whichline, - $alphabet,$record,$scantron_config,$scan_data,$randomorder, - $randompick,$respnumlookup) = @_; + $alphabet,$record,$scantron_config,$scan_data) = @_; # Qon 'letter' implies for each slot in currquest we have: # ? or * for doubles, a letter in A-Z for a bubble, and @@ -6279,23 +5965,19 @@ sub scantron_validator_lettnum { $matchon = '\d'; } my $occurrences = 0; - my $responsenum = $questnum-1; - if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) { - $responsenum = $respnumlookup->{$questnum-1} - } - if (($responsetype_per_response{$responsenum} eq 'essayresponse') || - ($responsetype_per_response{$responsenum} eq 'formularesponse') || - ($responsetype_per_response{$responsenum} eq 'stringresponse') || - ($responsetype_per_response{$responsenum} eq 'imageresponse') || - ($responsetype_per_response{$responsenum} eq 'reactionresponse') || - ($responsetype_per_response{$responsenum} eq 'organicresponse')) { + if (($responsetype_per_response{$questnum-1} eq 'essayresponse') || + ($responsetype_per_response{$questnum-1} eq 'formularesponse') || + ($responsetype_per_response{$questnum-1} eq 'stringresponse') || + ($responsetype_per_response{$questnum-1} eq 'imageresponse') || + ($responsetype_per_response{$questnum-1} eq 'reactionresponse') || + ($responsetype_per_response{$questnum-1} eq 'organicresponse')) { my @singlelines = split('',$currquest); foreach my $entry (@singlelines) { $occurrences = &occurence_count($entry,$matchon); if ($occurrences > 1) { last; } - } + } } else { $occurrences = &occurence_count($currquest,$matchon); } @@ -6343,8 +6025,7 @@ sub scantron_validator_lettnum { sub scantron_validator_positional { my ($ansnum,$questnum,$quest_id,$answers_needed,$currquest, - $whichline,$alphabet,$record,$scantron_config,$scan_data, - $randomorder,$randompick,$respnumlookup) = @_; + $whichline,$alphabet,$record,$scantron_config,$scan_data) = @_; # Otherwise there's a positional notation; # each bubble line requires Qlength items, and there are filled in @@ -6386,16 +6067,12 @@ sub scantron_validator_positional { # record all the bubbles filled in as well as the # fact this response consists of multiple bubbles. # - my $responsenum = $questnum-1; - if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) { - $responsenum = $respnumlookup->{$questnum-1} - } - if (($responsetype_per_response{$responsenum} eq 'essayresponse') || - ($responsetype_per_response{$responsenum} eq 'formularesponse') || - ($responsetype_per_response{$responsenum} eq 'stringresponse') || - ($responsetype_per_response{$responsenum} eq 'imageresponse') || - ($responsetype_per_response{$responsenum} eq 'reactionresponse') || - ($responsetype_per_response{$responsenum} eq 'organicresponse')) { + if (($responsetype_per_response{$questnum-1} eq 'essayresponse') || + ($responsetype_per_response{$questnum-1} eq 'formularesponse') || + ($responsetype_per_response{$questnum-1} eq 'stringresponse') || + ($responsetype_per_response{$questnum-1} eq 'imageresponse') || + ($responsetype_per_response{$questnum-1} eq 'reactionresponse') || + ($responsetype_per_response{$questnum-1} eq 'organicresponse')) { my $doubleerror = 0; while (($currquest >= $$scantron_config{'Qlength'}) && (!$doubleerror)) { @@ -6704,12 +6381,6 @@ sub scantron_warning_screen { ''.&mt('List of CODES to validate against:').''. $env{'form.scantron_CODElist'}.''; } - my $lastbubblepoints; - if ($env{'form.scantron_lastbubblepoints'} ne '') { - $lastbubblepoints = - ''.&mt('Hand-graded items: points from last bubble in row').''. - $env{'form.scantron_lastbubblepoints'}.''; - } return ('

@@ -6718,11 +6389,11 @@ sub scantron_warning_screen { -'.$CODElist.$lastbubblepoints.' +'.$CODElist.'
'.&mt('Sequence to be Graded:').''.$title.'
'.&mt('Data File that will be used:').''.$env{'form.scantron_selectfile'}.'

-

'.&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.").'

+

'.&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.').'


'); @@ -6758,9 +6429,8 @@ sub scantron_do_warning { } } else { my $warning=&scantron_warning_screen('Grading: Validate Records'); - my $bubbledbyhand=&hand_bubble_option(); $r->print(' -'.$warning.$bubbledbyhand.' +'.$warning.' '); @@ -6802,11 +6472,9 @@ SCANTRONFORM ''."\n"; $chunk .= ''."\n"; - $chunk .= - ''."\n"; $result .= $chunk; $line++; - } + } return $result; } @@ -6852,16 +6520,12 @@ sub scantron_validate_file { #get the student pick code ready $r->print(&Apache::loncommon::studentbrowser_javascript()); my $nav_error; - my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); - my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config); + my $max_bubble=&scantron_get_maxbubble(\$nav_error); if ($nav_error) { $r->print(&navmap_errormsg()); return ''; } my $result=&scantron_form_start($max_bubble).$default_form_data; - if ($env{'form.scantron_lastbubblepoints'} ne '') { - $result .= ''; - } $r->print($result); my @validate_phases=( 'sequence', @@ -6879,7 +6543,6 @@ sub scantron_validate_file { while (!$stop && $currentphase < scalar(@validate_phases)) { $r->print(&mt('Validating '.$validate_phases[$currentphase]).'
'); $r->rflush(); - my $which="scantron_validate_".$validate_phases[$currentphase]; { no strict 'refs'; @@ -7288,12 +6951,7 @@ sub scantron_validate_sequence { my @resources= $navmap->retrieveResources($map,\&scantron_filter_not_exam,1,0); if (@resources) { - $r->print('

' - .&mt('Some resources in the sequence currently are not set to' - .' exam mode. Grading these resources currently may not' - .' work correctly.') - .'

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

".&mt('Some resources in the sequence currently are not set to exam mode. Grading these resources currently may not work correctly.')."

"); return (1,$currentphase); } } @@ -7315,7 +6973,7 @@ sub scantron_validate_ID { my ($scanlines,$scan_data)=&scantron_getfile(); my $nav_error; - &scantron_get_maxbubble(\$nav_error,\%scantron_config); # parse needs the bubble_lines.. array. + &scantron_get_maxbubble(\$nav_error); # parse needs the bubble_lines.. array. if ($nav_error) { $r->print(&navmap_errormsg()); return(1,$currentphase); @@ -7374,8 +7032,7 @@ sub scantron_validate_ID { sub scantron_get_correction { - my ($r,$i,$scan_record,$scan_config,$line,$error,$arg, - $randomorder,$randompick,$respnumlookup,$startline)=@_; + my ($r,$i,$scan_record,$scan_config,$line,$error,$arg)=@_; #FIXME in the case of a duplicated ID the previous line, probably need #to show both the current line and the previous one and allow skipping #the previous one or the current one @@ -7425,7 +7082,7 @@ sub scantron_get_correction { $r->print(&Apache::loncommon::selectstudent_link('scantronupload', 'scantron_username','scantron_domain')); $r->print(": "); - $r->print("\n:\n". + $r->print("\n@". &Apache::loncommon::select_dom_form($env{'request.role.domain'},'scantron_domain')); $r->print(''); @@ -7511,8 +7168,7 @@ ENDSCRIPT # 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,$randomorder,$randompick, - $respnumlookup,$startline); + my $line_list = &questions_to_line_list($arg); $r->print(''); @@ -7520,9 +7176,7 @@ ENDSCRIPT $r->print("

".&mt("Please indicate which bubble should be used for grading")."

"); foreach my $question (@{$arg}) { my @linenums = &prompt_for_corrections($r,$question,$scan_config, - $scan_record, $error, - $randomorder,$randompick, - $respnumlookup,$startline); + $scan_record, $error); push(@lines_to_correct,@linenums); } $r->print(&verify_bubbles_checked(@lines_to_correct)); @@ -7536,16 +7190,13 @@ ENDSCRIPT # a list of question numbers. Therefore: # - my $line_list = &questions_to_line_list($arg,$randomorder,$randompick, - $respnumlookup,$startline); + my $line_list = &questions_to_line_list($arg); $r->print(''); foreach my $question (@{$arg}) { my @linenums = &prompt_for_corrections($r,$question,$scan_config, - $scan_record, $error, - $randomorder,$randompick, - $respnumlookup,$startline); + $scan_record, $error); push(@lines_to_correct,@linenums); } $r->print(&verify_bubbles_checked(@lines_to_correct)); @@ -7598,20 +7249,12 @@ used to fill in the scantron_questions f Arguments: questions - Reference to an array of questions. - randomorder - True if randomorder in use. - randompick - True if randompick in use. - respnumlookup - Reference to HASH mapping question numbers in bubble lines - for current line to question number used for same question - in "Master Seqence" (as seen by Course Coordinator). - startline - Reference to hash where key is question number (0 is first) - and key is number of first bubble line for current student - or code-based randompick and/or randomorder. =cut sub questions_to_line_list { - my ($questions,$randomorder,$randompick,$respnumlookup,$startline) = @_; + my ($questions) = @_; my @lines; foreach my $item (@{$questions}) { @@ -7620,16 +7263,8 @@ sub questions_to_line_list { if ($item =~ /^(\d+)\.(\d+)$/) { $question = $1; my $subquestion = $2; - my $responsenum = $question-1; - if (($randomorder || $randompick) && (ref($respnumlookup) eq 'HASH')) { - $responsenum = $respnumlookup->{$question-1}; - if (ref($startline) eq 'HASH') { - $first = $startline->{$question-1} + 1; - } - } else { - $first = $first_bubble_line{$responsenum} + 1; - } - my @subans = split(/,/,$subdivided_bubble_lines{$responsenum}); + $first = $first_bubble_line{$question-1} + 1; + my @subans = split(/,/,$subdivided_bubble_lines{$question-1}); my $subcount = 1; while ($subcount<$subquestion) { $first += $subans[$subcount-1]; @@ -7637,16 +7272,8 @@ sub questions_to_line_list { } $count = $subans[$subquestion-1]; } else { - my $responsenum = $question-1; - if (($randomorder || $randompick) && (ref($respnumlookup) eq 'HASH')) { - $responsenum = $respnumlookup->{$question-1}; - if (ref($startline) eq 'HASH') { - $first = $startline->{$question-1} + 1; - } - } else { - $first = $first_bubble_line{$responsenum} + 1; - } - $count = $bubble_lines_per_response{$responsenum}; + $first = $first_bubble_line{$question-1} + 1; + $count = $bubble_lines_per_response{$question-1}; } $last = $first+$count-1; push(@lines, ($first..$last)); @@ -7668,14 +7295,6 @@ for multi and missing bubble cases). $scan_config - The scantron file configuration hash. $scan_record - Reference to the hash that has the the parsed scanlines. $error - Type of error - $randomorder - True if randomorder in use. - $randompick - True if randompick in use. - $respnumlookup - Reference to HASH mapping question numbers in bubble lines - for current line to question number used for same question - in "Master Seqence" (as seen by Course Coordinator). - $startline - Reference to hash where key is question number (0 is first) - and value is number of first bubble line for current student - or code-based randompick and/or randomorder. Implicit inputs: %bubble_lines_per_response - Starting line numbers for each question. @@ -7700,26 +7319,15 @@ for multi and missing bubble cases). =cut sub prompt_for_corrections { - my ($r, $question, $scan_config, $scan_record, $error, $randomorder, - $randompick, $respnumlookup, $startline) = @_; + my ($r, $question, $scan_config, $scan_record, $error) = @_; my ($current_line,$lines); my @linenums; my $questionnum = $question; - my ($first,$responsenum); if ($question =~ /^(\d+)\.(\d+)$/) { $question = $1; + $current_line = $first_bubble_line{$question-1} + 1 ; my $subquestion = $2; - if (($randomorder || $randompick) && (ref($respnumlookup) eq 'HASH')) { - $responsenum = $respnumlookup->{$question-1}; - if (ref($startline) eq 'HASH') { - $first = $startline->{$question-1}; - } - } else { - $responsenum = $question-1; - $first = $first_bubble_line{$responsenum} + 1; - } - $current_line = $first + 1 ; - my @subans = split(/,/,$subdivided_bubble_lines{$responsenum}); + my @subans = split(/,/,$subdivided_bubble_lines{$question-1}); my $subcount = 1; while ($subcount<$subquestion) { $current_line += $subans[$subcount-1]; @@ -7727,34 +7335,25 @@ sub prompt_for_corrections { } $lines = $subans[$subquestion-1]; } else { - if (($randomorder || $randompick) && (ref($respnumlookup) eq 'HASH')) { - $responsenum = $respnumlookup->{$question-1}; - if (ref($startline) eq 'HASH') { - $first = $startline->{$question-1}; - } - } else { - $responsenum = $question-1; - $first = $first_bubble_line{$responsenum}; - } - $current_line = $first + 1; - $lines = $bubble_lines_per_response{$responsenum}; + $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 (($responsetype_per_response{$responsenum} eq 'essayresponse') || - ($responsetype_per_response{$responsenum} eq 'formularesponse') || - ($responsetype_per_response{$responsenum} eq 'stringresponse') || - ($responsetype_per_response{$responsenum} eq 'imageresponse') || - ($responsetype_per_response{$responsenum} eq 'reactionresponse') || - ($responsetype_per_response{$responsenum} eq 'organicresponse')) { - $r->print(&mt("Although this particular question type requires handgrading, the instructions for this question in the bubblesheet exam directed students to leave [quant,_1,line] blank on their bubblesheets.",$lines).'

'.&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.').'
'.&mt('The score for this question will be a sum of the numeric values for the selected bubbles from each line, where A=1 point, B=2 points etc.').'
'.&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.").'

'); + if (($responsetype_per_response{$question-1} eq 'essayresponse') || + ($responsetype_per_response{$question-1} eq 'formularesponse') || + ($responsetype_per_response{$question-1} eq 'stringresponse') || + ($responsetype_per_response{$question-1} eq 'imageresponse') || + ($responsetype_per_response{$question-1} eq 'reactionresponse') || + ($responsetype_per_response{$question-1} eq 'organicresponse')) { + $r->print(&mt("Although this particular question type requires handgrading, the instructions for this question in the exam directed students to leave [quant,_1,line] blank on their bubblesheets.",$lines).'

'.&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.').'
'.&mt('The score for this question will be a sum of the numeric values for the selected bubbles from each line, where A=1 point, B=2 points etc.').'
'.&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.").'

'); } else { $r->print(&mt("Select at most one bubble in a single line and select 'No Bubble' in all the other lines. ")."
"); } } for (my $i =0; $i < $lines; $i++) { my $selected = $$scan_record{"scantron.$current_line.answer"}; - &scantron_bubble_selector($r,$scan_config,$current_line, + &scantron_bubble_selector($r,$scan_config,$current_line, $questionnum,$error,split('', $selected)); push(@linenums,$current_line); $current_line++; @@ -7787,19 +7386,7 @@ sub scantron_bubble_selector { my $max=$$scan_config{'Qlength'}; my $scmode=$$scan_config{'Qon'}; - if ($scmode eq 'number' || $scmode eq 'letter') { - if (($$scan_config{'BubblesPerRow'} =~ /^\d+$/) && - ($$scan_config{'BubblesPerRow'} > 0)) { - $max=$$scan_config{'BubblesPerRow'}; - if (($scmode eq 'number') && ($max > 10)) { - $max = 10; - } elsif (($scmode eq 'letter') && $max > 26) { - $max = 26; - } - } else { - $max = 10; - } - } + if ($scmode eq 'number' || $scmode eq 'letter') { $max=10; } my @alphabet=('A'..'Z'); $r->print(&Apache::loncommon::start_data_table(). @@ -7954,7 +7541,7 @@ sub scantron_validate_CODE { my %allcodes=&get_codes(); my $nav_error; - &scantron_get_maxbubble(\$nav_error,\%scantron_config); # parse needs the lines per response array. + &scantron_get_maxbubble(\$nav_error); # parse needs the lines per response array. if ($nav_error) { $r->print(&navmap_errormsg()); return(1,$currentphase); @@ -8008,43 +7595,12 @@ sub scantron_validate_doublebubble { #get student info my $classlist=&Apache::loncoursedata::get_classlist(); my %idmap=&username_to_idmap($classlist); - my (undef,undef,$sequence)= - &Apache::lonnet::decode_symb($env{'form.selectpage'}); #get scantron line setup my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); my ($scanlines,$scan_data)=&scantron_getfile(); - - my $navmap = Apache::lonnavmaps::navmap->new(); - unless (ref($navmap)) { - $r->print(&navmap_errormsg()); - return(1,$currentphase); - } - my $map=$navmap->getResourceByUrl($sequence); - my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); - my ($randomorder,$randompick,@master_seq,%symb_to_resource,%grader_partids_by_symb, - %grader_randomlists_by_symb,%orderedforcode,%respnumlookup,%startline); - my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config); - my $nav_error; - if (ref($map)) { - $randomorder = $map->randomorder(); - $randompick = $map->randompick(); - if ($randomorder || $randompick) { - $nav_error = &get_master_seq(\@resources,\@master_seq,\%symb_to_resource); - if ($nav_error) { - $r->print(&navmap_errormsg()); - return(1,$currentphase); - } - &graders_resources_pass(\@resources,\%grader_partids_by_symb, - \%grader_randomlists_by_symb,$bubbles_per_row); - } - } else { - $r->print(&navmap_errormsg()); - return(1,$currentphase); - } - - &scantron_get_maxbubble(\$nav_error,\%scantron_config); # parse needs the bubble line array. + &scantron_get_maxbubble(\$nav_error); # parse needs the bubble line array. if ($nav_error) { $r->print(&navmap_errormsg()); return(1,$currentphase); @@ -8054,15 +7610,11 @@ sub scantron_validate_doublebubble { my $line=&scantron_get_line($scanlines,$scan_data,$i); if ($line=~/^[\s\cz]*$/) { next; } my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config, - $scan_data,undef,\%idmap,$randomorder, - $randompick,$sequence,\@master_seq, - \%symb_to_resource,\%grader_partids_by_symb, - \%orderedforcode,\%respnumlookup,\%startline); + $scan_data); if (!defined($$scan_record{'scantron.doubleerror'})) { next; } &scantron_get_correction($r,$i,$scan_record,\%scantron_config,$line, 'doublebubble', - $$scan_record{'scantron.doubleerror'}, - $randomorder,$randompick,\%respnumlookup,\%startline); + $$scan_record{'scantron.doubleerror'}); return (1,$currentphase); } return (0,$currentphase+1); @@ -8070,7 +7622,7 @@ sub scantron_validate_doublebubble { sub scantron_get_maxbubble { - my ($nav_error,$scantron_config) = @_; + my ($nav_error) = @_; if (defined($env{'form.scantron_maxbubble'}) && $env{'form.scantron_maxbubble'}) { &restore_bubble_lines(); @@ -8089,7 +7641,6 @@ sub scantron_get_maxbubble { } my $map=$navmap->getResourceByUrl($sequence); my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); - my $bubbles_per_row = &bubblesheet_bubbles_per_row($scantron_config); &Apache::lonxml::clear_problem_counter(); @@ -8101,14 +7652,11 @@ sub scantron_get_maxbubble { %first_bubble_line = (); %subdivided_bubble_lines = (); %responsetype_per_response = (); - %masterseq_id_responsenum = (); my $response_number = 0; my $bubble_line = 0; foreach my $resource (@resources) { - my $resid = $resource->id(); - my ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname, - $udom,undef,$bubbles_per_row); + my ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname,$udom); if ((ref($analysis) eq 'HASH') && (ref($parts) eq 'ARRAY')) { foreach my $part_id (@{$parts}) { my $lines; @@ -8137,10 +7685,9 @@ sub scantron_get_maxbubble { if (ref($analysis->{$part_id.'.shown'}) eq 'ARRAY') { $numshown = scalar(@{$analysis->{$part_id.'.shown'}}); } - my $bubbles_per_row = - &bubblesheet_bubbles_per_row($scantron_config); - my $inner_bubble_lines = int($numbub/$bubbles_per_row); - if (($numbub % $bubbles_per_row) != 0) { + my $bubbles_per_line = 10; + 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++) { @@ -8151,13 +7698,12 @@ sub scantron_get_maxbubble { $lines = $numshown * $inner_bubble_lines; } else { $lines = $analysis->{"$part_id.bubble_lines"}; - } + } $first_bubble_line{$response_number} = $bubble_line; $bubble_lines_per_response{$response_number} = $lines; $responsetype_per_response{$response_number} = $analysis->{$part_id.'.type'}; - $masterseq_id_responsenum{$resid.'_'.$part_id} = $response_number; $response_number++; $bubble_line += $lines; @@ -8173,76 +7719,26 @@ sub scantron_get_maxbubble { return $env{'form.scantron_maxbubble'}; } -sub bubblesheet_bubbles_per_row { - my ($scantron_config) = @_; - my $bubbles_per_row; - if (ref($scantron_config) eq 'HASH') { - $bubbles_per_row = $scantron_config->{'BubblesPerRow'}; - } - if ((!$bubbles_per_row) || ($bubbles_per_row < 1)) { - $bubbles_per_row = 10; - } - return $bubbles_per_row; -} - sub scantron_validate_missingbubbles { my ($r,$currentphase) = @_; #get student info my $classlist=&Apache::loncoursedata::get_classlist(); my %idmap=&username_to_idmap($classlist); - my (undef,undef,$sequence)= - &Apache::lonnet::decode_symb($env{'form.selectpage'}); #get scantron line setup my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); my ($scanlines,$scan_data)=&scantron_getfile(); - - my $navmap = Apache::lonnavmaps::navmap->new(); - unless (ref($navmap)) { - $r->print(&navmap_errormsg()); - return(1,$currentphase); - } - - my $map=$navmap->getResourceByUrl($sequence); - my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); - my ($randomorder,$randompick,@master_seq,%symb_to_resource,%grader_partids_by_symb, - %grader_randomlists_by_symb,%orderedforcode,%respnumlookup,%startline); - my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config); - my $nav_error; - if (ref($map)) { - $randomorder = $map->randomorder(); - $randompick = $map->randompick(); - if ($randomorder || $randompick) { - $nav_error = &get_master_seq(\@resources,\@master_seq,\%symb_to_resource); - if ($nav_error) { - $r->print(&navmap_errormsg()); - return(1,$currentphase); - } - &graders_resources_pass(\@resources,\%grader_partids_by_symb, - \%grader_randomlists_by_symb,$bubbles_per_row); - } - } else { - $r->print(&navmap_errormsg()); - return(1,$currentphase); - } - - - my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config); + my $max_bubble=&scantron_get_maxbubble(\$nav_error); if ($nav_error) { - $r->print(&navmap_errormsg()); return(1,$currentphase); } - if (!$max_bubble) { $max_bubble=2**31; } for (my $i=0;$i<=$scanlines->{'count'};$i++) { my $line=&scantron_get_line($scanlines,$scan_data,$i); if ($line=~/^[\s\cz]*$/) { next; } - my $scan_record = - &scantron_parse_scanline($line,$i,\%scantron_config,$scan_data,undef,\%idmap, - $randomorder,$randompick,$sequence,\@master_seq, - \%symb_to_resource,\%grader_partids_by_symb, - \%orderedforcode,\%respnumlookup,\%startline); + my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config, + $scan_data); if (!defined($$scan_record{'scantron.missingerror'})) { next; } my @to_correct; @@ -8251,45 +7747,28 @@ sub scantron_validate_missingbubbles { foreach my $missing (@{$$scan_record{'scantron.missingerror'}}) { my $lastbubble; if ($missing =~ /^(\d+)\.(\d+)$/) { - my $question = $1; - my $subquestion = $2; - my ($first,$responsenum); - if ($randomorder || $randompick) { - $responsenum = $respnumlookup{$question-1}; - $first = $startline{$question-1}; - } else { - $responsenum = $question-1; - $first = $first_bubble_line{$responsenum}; - } - if (!defined($first)) { next; } - my @subans = split(/,/,$subdivided_bubble_lines{$responsenum}); - my $subcount = 1; - while ($subcount<$subquestion) { - $first += $subans[$subcount-1]; - $subcount ++; - } - my $count = $subans[$subquestion-1]; - $lastbubble = $first + $count; + my $question = $1; + my $subquestion = $2; + if (!defined($first_bubble_line{$question -1})) { next; } + my $first = $first_bubble_line{$question-1}; + my @subans = split(/,/,$subdivided_bubble_lines{$question-1}); + my $subcount = 1; + while ($subcount<$subquestion) { + $first += $subans[$subcount-1]; + $subcount ++; + } + my $count = $subans[$subquestion-1]; + $lastbubble = $first + $count; } else { - my ($first,$responsenum); - if ($randomorder || $randompick) { - $responsenum = $respnumlookup{$missing-1}; - $first = $startline{$missing-1}; - } else { - $responsenum = $missing-1; - $first = $first_bubble_line{$responsenum}; - } - if (!defined($first)) { next; } - $lastbubble = $first + $bubble_lines_per_response{$responsenum}; + if (!defined($first_bubble_line{$missing - 1})) { next; } + $lastbubble = $first_bubble_line{$missing - 1} + $bubble_lines_per_response{$missing - 1}; } if ($lastbubble > $max_bubble) { next; } push(@to_correct,$missing); } if (@to_correct) { &scantron_get_correction($r,$i,$scan_record,\%scantron_config, - $line,'missingbubble',\@to_correct, - $randomorder,$randompick,\%respnumlookup, - \%startline); + $line,'missingbubble',\@to_correct); return (1,$currentphase); } @@ -8297,41 +7776,6 @@ sub scantron_validate_missingbubbles { return (0,$currentphase+1); } -sub hand_bubble_option { - my (undef, undef, $sequence) = - &Apache::lonnet::decode_symb($env{'form.selectpage'}); - return if ($sequence eq ''); - my $navmap = Apache::lonnavmaps::navmap->new(); - unless (ref($navmap)) { - return; - } - my $needs_hand_bubbles; - my $map=$navmap->getResourceByUrl($sequence); - my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); - foreach my $res (@resources) { - if (ref($res)) { - if ($res->is_problem()) { - my $partlist = $res->parts(); - foreach my $part (@{ $partlist }) { - my @types = $res->responseType($part); - if (grep(/^(chem|essay|image|formula|math|string|functionplot)$/,@types)) { - $needs_hand_bubbles = 1; - last; - } - } - } - } - } - if ($needs_hand_bubbles) { - my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); - my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config); - return &mt('The sequence to be graded contains response types which are handgraded.').'

'. - &mt('If you have already graded these by bubbling sheets to indicate points awarded, [_1]what point value is assigned to a filled last bubble in each row?','
'). - ' '.&mt('or').' '. - '

'; - } - return; -} sub scantron_process_students { my ($r) = @_; @@ -8344,7 +7788,6 @@ sub scantron_process_students { my $default_form_data=&defaultFormData($symb); my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); - my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config); my ($scanlines,$scan_data)=&scantron_getfile(); my $classlist=&Apache::loncoursedata::get_classlist(); my %idmap=&username_to_idmap($classlist); @@ -8352,29 +7795,36 @@ sub scantron_process_students { unless (ref($navmap)) { $r->print(&navmap_errormsg()); return ''; - } + } my $map=$navmap->getResourceByUrl($sequence); - my ($randomorder,$randompick,@master_seq,%symb_to_resource,%grader_partids_by_symb, - %grader_randomlists_by_symb); - if (ref($map)) { - $randomorder = $map->randomorder(); - $randompick = $map->randompick(); - } else { - $r->print(&navmap_errormsg()); - return ''; - } - my $nav_error; my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); - my (%grader_partids_by_symb,%grader_randomlists_by_symb,%ordered); - if ($randomorder || $randompick) { - $nav_error = &get_master_seq(\@resources,\@master_seq,\%symb_to_resource); - if ($nav_error) { - $r->print(&navmap_errormsg()); - return ''; + my (%grader_partids_by_symb,%grader_randomlists_by_symb); + &graders_resources_pass(\@resources,\%grader_partids_by_symb, + \%grader_randomlists_by_symb); + my $resource_error; + foreach my $resource (@resources) { + my $ressymb; + if (ref($resource)) { + $ressymb = $resource->symb(); + } else { + $resource_error = 1; + last; + } + my ($analysis,$parts) = + &scantron_partids_tograde($resource,$env{'request.course.id'}, + $env{'user.name'},$env{'user.domain'},1); + $grader_partids_by_symb{$ressymb} = $parts; + if (ref($analysis) eq 'HASH') { + if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') { + $grader_randomlists_by_symb{$ressymb} = + $analysis->{'parts_withrandomlist'}; + } } } - &graders_resources_pass(\@resources,\%grader_partids_by_symb, - \%grader_randomlists_by_symb,$bubbles_per_row); + if ($resource_error) { + $r->print(&navmap_errormsg()); + return ''; + } my ($uname,$udom); my $result= <print('
'); @@ -8397,7 +7849,8 @@ SCANTRONFORM my $i=-1; my $started; - &scantron_get_maxbubble(\$nav_error,\%scantron_config); # Need the bubble lines array to parse. + my $nav_error; + &scantron_get_maxbubble(\$nav_error); # Need the bubble lines array to parse. if ($nav_error) { $r->print(&navmap_errormsg()); return ''; @@ -8416,7 +7869,6 @@ SCANTRONFORM my %lettdig = &letter_to_digits(); my $numletts = scalar(keys(%lettdig)); - my %orderedforcode; while ($i<$scanlines->{'count'}) { ($uname,$udom)=('',''); @@ -8428,15 +7880,8 @@ SCANTRONFORM 'last student'); } $started=1; - my %respnumlookup = (); - my %startline = (); - my $total; my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config, - $scan_data,undef,\%idmap,$randomorder, - $randompick,$sequence,\@master_seq, - \%symb_to_resource,\%grader_partids_by_symb, - \%orderedforcode,\%respnumlookup,\%startline, - \$total); + $scan_data); unless ($uname=&scantron_find_student($scan_record,$scan_data, \%idmap,$i)) { &scantron_add_delay(\@delayqueue,$line, @@ -8448,26 +7893,10 @@ SCANTRONFORM 'Student '.$uname.' has multiple sheets',2); next; } - my $usec = $classlist->{$uname}->[&Apache::loncoursedata::CL_SECTION]; - my $user = $uname.':'.$usec; ($uname,$udom)=split(/:/,$uname); - my $scancode; - if ((exists($scan_record->{'scantron.CODE'})) && - (&Apache::lonnet::validCODE($scan_record->{'scantron.CODE'}))) { - $scancode = $scan_record->{'scantron.CODE'}; - } else { - $scancode = ''; - } - - my @mapresources = @resources; - if ($randomorder || $randompick) { - @mapresources = - &users_order($user,$scancode,$sequence,\@master_seq,\%symb_to_resource, - \%orderedforcode); - } my (%partids_by_symb,$res_error); - foreach my $resource (@mapresources) { + foreach my $resource (@resources) { my $ressymb; if (ref($resource)) { $ressymb = $resource->symb(); @@ -8478,8 +7907,7 @@ SCANTRONFORM if ((exists($grader_randomlists_by_symb{$ressymb})) || (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) { my ($analysis,$parts) = - &scantron_partids_tograde($resource,$env{'request.course.id'}, - $uname,$udom,undef,$bubbles_per_row); + &scantron_partids_tograde($resource,$env{'request.course.id'},$uname,$udom); $partids_by_symb{$ressymb} = $parts; } else { $partids_by_symb{$ressymb} = $grader_partids_by_symb{$ressymb}; @@ -8499,11 +7927,16 @@ SCANTRONFORM &scantron_putfile($scanlines,$scan_data); } + my $scancode; + if ((exists($scan_record->{'scantron.CODE'})) && + (&Apache::lonnet::validCODE($scan_record->{'scantron.CODE'}))) { + $scancode = $scan_record->{'scantron.CODE'}; + } else { + $scancode = ''; + } + if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode, - \@mapresources,\%partids_by_symb, - $bubbles_per_row,$randomorder,$randompick, - \%respnumlookup,\%startline) - eq 'ssi_error') { + \@resources,\%partids_by_symb) eq 'ssi_error') { $ssi_error = 0; # So end of handler error message does not trigger. $r->print(""); &ssi_print_error($r); @@ -8512,43 +7945,26 @@ SCANTRONFORM return ''; # Why return ''? Beats me. } - if (($scancode) && ($randomorder || $randompick)) { - my $parmresult = - &Apache::lonparmset::storeparm_by_symb($symb, - '0_examcode',2,$scancode, - 'string_examcode',$uname, - $udom); - } $completedstudents{$uname}={'line'=>$line}; if ($env{'form.verifyrecord'}) { my $lastpos = $env{'form.scantron_maxbubble'}*$scantron_config{'Qlength'}; - if ($randompick) { - if ($total) { - $lastpos = $total*$scantron_config{'Qlength'}; - } - } - my $studentdata = substr($line,$scantron_config{'Qstart'}-1,$lastpos); chomp($studentdata); $studentdata =~ s/\r$//; my $studentrecord = ''; my $counter = -1; - foreach my $resource (@mapresources) { + 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{$ressymb}, - \%scantron_config,\%lettdig,$numletts,$randomorder, - $randompick,\%respnumlookup,\%startline); + \%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, - \@mapresources,\%partids_by_symb, - $bubbles_per_row,$randomorder,$randompick, - \%respnumlookup,\%startline) - eq 'ssi_error') { + \@resources,\%partids_by_symb) eq 'ssi_error') { $ssi_error = 0; # So end of handler error message does not trigger. $r->print(""); &ssi_print_error($r); @@ -8559,14 +7975,12 @@ SCANTRONFORM } $counter = -1; $studentrecord = ''; - foreach my $resource (@mapresources) { + 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{$ressymb}, - \%scantron_config,\%lettdig,$numletts, - $randomorder,$randompick,\%respnumlookup, - \%startline); + \%scantron_config,\%lettdig,$numletts); $studentrecord .= $recording; } if ($studentrecord ne $studentdata) { @@ -8615,16 +8029,14 @@ SCANTRONFORM } sub graders_resources_pass { - my ($resources,$grader_partids_by_symb,$grader_randomlists_by_symb, - $bubbles_per_row) = @_; + my ($resources,$grader_partids_by_symb,$grader_randomlists_by_symb) = @_; if ((ref($resources) eq 'ARRAY') && (ref($grader_partids_by_symb)) && (ref($grader_randomlists_by_symb) eq 'HASH')) { foreach my $resource (@{$resources}) { my $ressymb = $resource->symb(); my ($analysis,$parts) = &scantron_partids_tograde($resource,$env{'request.course.id'}, - $env{'user.name'},$env{'user.domain'}, - 1,$bubbles_per_row); + $env{'user.name'},$env{'user.domain'},1); $grader_partids_by_symb->{$ressymb} = $parts; if (ref($analysis) eq 'HASH') { if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') { @@ -8637,67 +8049,8 @@ sub graders_resources_pass { return; } -=pod - -=item users_order - - Returns array of resources in current map, ordered based on either CODE, - if this is a CODEd exam, or based on student's identity if this is a - "NAMEd" exam. - - Should be used when randomorder and/or randompick applied when the - corresponding exam was printed, prior to students completing bubblesheets - for the version of the exam the student received. - -=cut - -sub users_order { - my ($user,$scancode,$mapurl,$master_seq,$symb_to_resource,$orderedforcode) = @_; - my @mapresources; - unless ((ref($master_seq) eq 'ARRAY') && (ref($symb_to_resource) eq 'HASH')) { - return @mapresources; - } - if ($scancode) { - if ((ref($orderedforcode) eq 'HASH') && (ref($orderedforcode->{$scancode}) eq 'ARRAY')) { - @mapresources = @{$orderedforcode->{$scancode}}; - } else { - $env{'form.CODE'} = $scancode; - my $actual_seq = - &Apache::lonprintout::master_seq_to_person_seq($mapurl, - $master_seq, - $user,$scancode,1); - if (ref($actual_seq) eq 'ARRAY') { - @mapresources = map { $symb_to_resource->{$_}; } @{$actual_seq}; - if (ref($orderedforcode) eq 'HASH') { - if (@mapresources > 0) { - $orderedforcode->{$scancode} = \@mapresources; - } - } - } - delete($env{'form.CODE'}); - } - } else { - my $actual_seq = - &Apache::lonprintout::master_seq_to_person_seq($mapurl, - $master_seq, - $user,undef,1); - if (ref($actual_seq) eq 'ARRAY') { - @mapresources = - map { $symb_to_resource->{$_}; } @{$actual_seq}; - } - } - return @mapresources; -} - sub grade_student_bubbles { - my ($r,$uname,$udom,$scan_record,$scancode,$resources,$parts,$bubbles_per_row, - $randomorder,$randompick,$respnumlookup,$startline) = @_; - my $uselookup = 0; - if (($randomorder || $randompick) && (ref($respnumlookup) eq 'HASH') && - (ref($startline) eq 'HASH')) { - $uselookup = 1; - } - + my ($r,$uname,$udom,$scan_record,$scancode,$resources,$parts) = @_; if (ref($resources) eq 'ARRAY') { my $count = 0; foreach my $resource (@{$resources}) { @@ -8710,21 +8063,11 @@ sub grade_student_bubbles { 'grade_symb' => $ressymb, 'CODE' => $scancode ); - if ($bubbles_per_row ne '') { - $form{'bubbles_per_row'} = $bubbles_per_row; - } - if ($env{'form.scantron_lastbubblepoints'} ne '') { - $form{'scantron_lastbubblepoints'} = $env{'form.scantron_lastbubblepoints'}; - } if (ref($parts) eq 'HASH') { if (ref($parts->{$ressymb}) eq 'ARRAY') { foreach my $part (@{$parts->{$ressymb}}) { - if ($uselookup) { - $form{'scantron_questnum_start.'.$part} = $startline->{$count} + 1; - } else { - $form{'scantron_questnum_start.'.$part} = - 1+$env{'form.scantron.first_bubble_line.'.$count}; - } + $form{'scantron_questnum_start.'.$part} = + 1+$env{'form.scantron.first_bubble_line.'.$count}; $count++; } } @@ -8746,9 +8089,8 @@ sub scantron_upload_scantron_data { 'domainid', 'coursename',$dom); my $syllabuslink = ''.&mt('Syllabus').''. - (' 'x2).&mt('(shows course personnel)'); - my ($symb) = &get_symb($r,1); - my $default_form_data=&defaultFormData($symb); + (' 'x2).&mt('(shows course personnel)'); + my $default_form_data=&defaultFormData(&get_symb($r,1)); my $nofile_alert = &mt('Please use the browse button to select a file from your local directory.'); my $nocourseid_alert = &mt("Please use the 'Select Course' link to open a separate window where you can search for a course to which a file can be uploaded."); $r->print(' @@ -8953,18 +8295,17 @@ sub valid_file { sub scantron_download_scantron_data { my ($r)=@_; - my ($symb) = &get_symb($r,1); - my $default_form_data=&defaultFormData($symb); + my $default_form_data=&defaultFormData(&get_symb($r,1)); my $cname=$env{'course.'.$env{'request.course.id'}.'.num'}; my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'}; my $file=$env{'form.scantron_selectfile'}; if (! &valid_file($file)) { $r->print('

- '.&mt('The requested filename was invalid.').' + '.&mt('The requested file name was invalid.').'

'); - $r->print(&show_grading_menu_form($symb)); + $r->print(&show_grading_menu_form(&get_symb($r,1))); return; } my $orig='/uploaded/'.$cdom.'/'.$cname.'/scantron_orig_'.$file; @@ -8987,7 +8328,7 @@ sub scantron_download_scantron_data { '','').'

'); - $r->print(&show_grading_menu_form($symb)); + $r->print(&show_grading_menu_form(&get_symb($r,1))); return ''; } @@ -9005,7 +8346,6 @@ sub checkscantron_results { my %record; my %scantron_config = &Apache::grades::get_scantron_config($env{'form.scantron_format'}); - my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config); my ($scanlines,$scan_data)=&Apache::grades::scantron_getfile(); my $classlist=&Apache::loncoursedata::get_classlist(); my %idmap=&Apache::grades::username_to_idmap($classlist); @@ -9015,20 +8355,10 @@ sub checkscantron_results { return ''; } my $map=$navmap->getResourceByUrl($sequence); - my ($randomorder,$randompick,@master_seq,%symb_to_resource,%grader_partids_by_symb, - %grader_randomlists_by_symb,%orderedforcode); - if (ref($map)) { - $randomorder=$map->randomorder(); - $randompick=$map->randompick(); - } my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); - my $nav_error = &get_master_seq(\@resources,\@master_seq,\%symb_to_resource); - if ($nav_error) { - $r->print(&navmap_errormsg()); - return ''; - } - &graders_resources_pass(\@resources,\%grader_partids_by_symb, - \%grader_randomlists_by_symb,$bubbles_per_row); + my (%grader_partids_by_symb,%grader_randomlists_by_symb); + &graders_resources_pass(\@resources,\%grader_partids_by_symb, \%grader_randomlists_by_symb); + my ($uname,$udom); my (%scandata,%lastname,%bylast); $r->print(' @@ -9037,10 +8367,13 @@ sub checkscantron_results { my @delayqueue; my %completedstudents; - my $count=&get_todo_count($scanlines,$scan_data); - my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,$count); - my ($username,$domain,$started,%ordered); - &scantron_get_maxbubble(\$nav_error,\%scantron_config); # Need the bubble lines array to parse. + my $count=&Apache::grades::get_todo_count($scanlines,$scan_data); + my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Bubblesheet/Submissions Comparison Status', + 'Progress of Bubblesheet Data/Submission Records Comparison',$count, + 'inline',undef,'checkscantron'); + my ($username,$domain,$started); + my $nav_error; + &scantron_get_maxbubble(\$nav_error); # Need the bubble lines array to parse. if ($nav_error) { $r->print(&navmap_errormsg()); return ''; @@ -9064,8 +8397,8 @@ sub checkscantron_results { my $scan_record= &Apache::grades::scantron_parse_scanline($line,$i,\%scantron_config, $scan_data); - unless ($uname=&scantron_find_student($scan_record,$scan_data, - \%idmap,$i)) { + unless ($uname=&Apache::grades::scantron_find_student($scan_record,$scan_data, + \%idmap,$i)) { &Apache::grades::scantron_add_delay(\@delayqueue,$line, 'Unable to find a student that matches',1); next; @@ -9078,57 +8411,26 @@ sub checkscantron_results { my $pid = $scan_record->{'scantron.ID'}; $lastname{$pid} = $scan_record->{'scantron.LastName'}; push(@{$bylast{$lastname{$pid}}},$pid); - my $usec = $classlist->{$uname}->[&Apache::loncoursedata::CL_SECTION]; - my $user = $uname.':'.$usec; - ($username,$domain)=split(/:/,$uname); - - my $scancode; - if ((exists($scan_record->{'scantron.CODE'})) && - (&Apache::lonnet::validCODE($scan_record->{'scantron.CODE'}))) { - $scancode = $scan_record->{'scantron.CODE'}; - } else { - $scancode = ''; - } - - my @mapresources = @resources; my $lastpos = $env{'form.scantron_maxbubble'}*$scantron_config{'Qlength'}; - my %respnumlookup=(); - my %startline=(); - if ($randomorder || $randompick) { - @mapresources = - &users_order($user,$scancode,$sequence,\@master_seq,\%symb_to_resource, - \%orderedforcode); - my $total = &get_respnum_lookups($sequence,$scan_data,\%idmap,$line, - $scan_record,\@master_seq,\%symb_to_resource, - \%grader_partids_by_symb,\%orderedforcode, - \%respnumlookup,\%startline); - if ($randompick && $total) { - $lastpos = $total*$scantron_config{'Qlength'}; - } - } $scandata{$pid} = substr($line,$scantron_config{'Qstart'}-1,$lastpos); chomp($scandata{$pid}); $scandata{$pid} =~ s/\r$//; - + ($username,$domain)=split(/:/,$uname); my $counter = -1; - foreach my $resource (@mapresources) { + foreach my $resource (@resources) { my $parts; my $ressymb = $resource->symb(); if ((exists($grader_randomlists_by_symb{$ressymb})) || (ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) { (my $analysis,$parts) = - &scantron_partids_tograde($resource,$env{'request.course.id'}, - $username,$domain,undef, - $bubbles_per_row); + &scantron_partids_tograde($resource,$env{'request.course.id'},$username,$domain); } else { $parts = $grader_partids_by_symb{$ressymb}; } ($counter,my $recording) = &verify_scantron_grading($resource,$domain,$username,$cid,$counter, $scandata{$pid},$parts, - \%scantron_config,\%lettdig,$numletts, - $randomorder,$randompick, - \%respnumlookup,\%startline); + \%scantron_config,\%lettdig,$numletts); $record{$pid} .= $recording; } } @@ -9174,11 +8476,7 @@ sub checkscantron_results { $env{'form.scantron_maxbubble'}). '

' ); - $r->print('

' - .&mt('Exact matches for [_1][quant,_2,student][_3].','',$passed,'') - .'
' - .&mt('Discrepancies detected for [_1][quant,_2,student][_3].','',$failed,'') - .'

'); + $r->print('

'.&mt('Exact matches for [quant,_1,student].',$passed).'
'.&mt('Discrepancies detected for [quant,_1,student].',$failed).'

'); if ($passed) { $r->print(&mt('Students with exact correspondence between bubblesheet data and submissions are as follows:').'

'); $r->print(&Apache::loncommon::start_data_table()."\n". @@ -9204,8 +8502,7 @@ sub checkscantron_results { sub verify_scantron_grading { my ($resource,$domain,$username,$cid,$counter,$scandata,$partids, - $scantron_config,$lettdig,$numletts,$randomorder,$randompick, - $respnumlookup,$startline) = @_; + $scantron_config,$lettdig,$numletts) = @_; my ($record,%expected,%startpos); return ($counter,$record) if (!ref($resource)); return ($counter,$record) if (!$resource->is_problem()); @@ -9214,21 +8511,15 @@ sub verify_scantron_grading { foreach my $part_id (@{$partids}) { $counter ++; $expected{$part_id} = 0; - my $respnum = $counter; - if ($randomorder || $randompick) { - $respnum = $respnumlookup->{$counter}; - $startpos{$part_id} = $startline->{$counter} + 1; - } else { - $startpos{$part_id} = $env{"form.scantron.first_bubble_line.$counter"}; - } - if ($env{"form.scantron.sub_bubblelines.$respnum"}) { - my @sub_lines = split(/,/,$env{"form.scantron.sub_bubblelines.$respnum"}); + if ($env{"form.scantron.sub_bubblelines.$counter"}) { + my @sub_lines = split(/,/,$env{"form.scantron.sub_bubblelines.$counter"}); foreach my $item (@sub_lines) { $expected{$part_id} += $item; } } else { - $expected{$part_id} = $env{"form.scantron.bubblelines.$respnum"}; + $expected{$part_id} = $env{"form.scantron.bubblelines.$counter"}; } + $startpos{$part_id} = $env{"form.scantron.first_bubble_line.$counter"}; } if ($symb) { my %recorded; @@ -9324,7 +8615,7 @@ sub verify_scantron_grading { return ($counter,$record); } -sub letter_to_digits { +sub letter_to_digits { my %lettdig = ( A => 1, B => 2, @@ -9371,13 +8662,6 @@ sub savedState { return \%savedState; } -#--- Href with symb and command --- - -sub href_symb_cmd { - my ($symb,$cmd)=@_; - return '/adm/grades?symb='.&HTML::Entities::encode(&Apache::lonenc::check_encrypt($symb),'<>&"').'&command='.$cmd; -} - sub grading_menu { my ($request) = @_; my ($symb)=&get_symb($request); @@ -9801,8 +9085,7 @@ sub process_clicker { my $pincorrect=&mt("Percentage points for incorrect solution"); my $selectform=&Apache::loncommon::select_form($env{'form.upfiletype'},'upfiletype', {'iclicker' => 'i>clicker', - 'interwrite' => 'interwrite PRS', - 'turning' => 'Turning Technologies'}); + 'interwrite' => 'interwrite PRS'}); $symb = &Apache::lonenc::check_encrypt($symb); $result.=< @@ -9975,9 +9258,6 @@ ENDHEADER if ($env{'form.upfiletype'} eq 'interwrite') { ($errormsg,$number)=&interwrite_eval(\@questiontitles,\%responses); } - if ($env{'form.upfiletype'} eq 'turning') { - ($errormsg,$number)=&turning_eval(\@questiontitles,\%responses); - } $result.='
'.&mt('Found [_1] question(s)',$number).'
'. ''. &mt('Awarding [_1] percent for correct and [_2] percent for incorrect responses', @@ -10109,31 +9389,6 @@ sub interwrite_eval { return ($errormsg,$number); } -sub turning_eval { - my ($questiontitles,$responses)=@_; - my $number=0; - my $errormsg=''; - foreach my $line (split(/[\n\r]/,$env{'form.upfile'})) { - my %components=&Apache::loncommon::record_sep($line); - my @entries=map {$components{$_}} (sort(keys(%components))); - if ($#entries>$number) { $number=$#entries; } - my $id=$entries[0]; - my @idresponses; - $id=~s/^[\#0]+//; - unless ($id) { next; } - for (my $idx=1;$idx<=$#entries;$idx++) { - $entries[$idx]=~s/\,/\;/g; - $entries[$idx]=~s/[^a-zA-Z0-9\.\*\-\+\;]+//g; - push(@idresponses,$entries[$idx]); - } - $$responses{$id}=join(',',@idresponses); - } - for (my $i=1; $i<=$number; $i++) { - $$questiontitles[$i]=&mt('Question [_1]',$i); - } - return ($errormsg,$number); -} - sub assign_clicker_grades { my ($r)=@_; my ($symb)=&get_symb($r); @@ -10275,19 +9530,6 @@ sub navmap_errormsg { ''; } -sub startpage { - my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$js) = @_; - if ($nomenu) { - $r->print(&Apache::loncommon::start_page("Student's Version",$js,{'only_body' => '1'})); - } else { - $r->print(&Apache::loncommon::start_page('Grading',$js, - {'bread_crumbs' => $crumbs})); - } - unless ($nodisplayflag) { - $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp)); - } -} - sub handler { my $request=$_[0]; &reset_caches(); @@ -10309,7 +9551,7 @@ sub handler { $ssi_error = 0; my $brcrum = [{href=>"/adm/grades",text=>"Grading"}]; my $start_page = &Apache::loncommon::start_page('Grading',undef, - {'bread_crumbs' => $brcrum}); + {'bread_crumbs' => $brcrum}); if ($symb eq '' && $command eq '') { if ($env{'user.adv'}) { &Apache::loncommon::content_type($request,'text/html'); @@ -10342,7 +9584,6 @@ sub handler { &init_perm(); if (!%perm) { $request->internal_redirect('/adm/quickgrades'); - return OK; } else { &Apache::loncommon::content_type($request,'text/html'); $request->send_http_header; @@ -10363,33 +9604,9 @@ sub handler { } &Apache::loncommon::content_type($request,'text/html'); $request->send_http_header; - unless ((($command eq 'submission' || $command eq 'versionsub')) && ($perm{'vgr'})) { - $request->print($start_page); - } + $request->print($start_page); if ($command eq 'submission' && $perm{'vgr'}) { - my ($stuvcurrent,$stuvdisp,$versionform,$js); - if (($env{'form.student'} ne '') && ($env{'form.userdom'} ne '')) { - ($stuvcurrent,$stuvdisp,$versionform,$js) = - &choose_task_version_form($symb,$env{'form.student'}, - $env{'form.userdom'}); - } - &startpage($request,$symb,[{href=>"", text=>"Student Submissions"}],undef,undef,$stuvcurrent,$stuvdisp,undef,$js); - if ($versionform) { - $request->print($versionform); - } - $request->print('
'); ($env{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0)); - } elsif ($command eq 'versionsub' && $perm{'vgr'}) { - my ($stuvcurrent,$stuvdisp,$versionform,$js) = - &choose_task_version_form($symb,$env{'form.student'}, - $env{'form.userdom'}, - $env{'form.inhibitmenu'}); - &startpage($request,$symb,[{href=>"", text=>"Previous Student Version"}],undef,undef,$stuvcurrent,$stuvdisp,$env{'form.inhibitmenu'},$js); - if ($versionform) { - $request->print($versionform); - } - $request->print('
'); - $request->print(&show_previous_task_version($request,$symb)); } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) { &pickStudentPage($request); } elsif ($command eq 'displayPage' && $perm{'vgr'}) { @@ -10560,16 +9777,6 @@ ssi_with_retries() - missingbubble - array ref of the bubble lines that have missing bubble errors - $randomorder - True if exam folder has randomorder set - $randompick - True if exam folder has randompick set - $respnumlookup - Reference to HASH mapping question numbers in bubble lines - for current line to question number used for same question - in "Master Seqence" (as seen by Course Coordinator). - $startline - Reference to hash where key is question number (0 is first) - and value is number of first bubble line for current student - or code-based randompick and/or randomorder. - - =item scantron_get_maxbubble() : Arguments: @@ -10579,8 +9786,6 @@ ssi_with_retries() calling routine should trap the error condition and display the warning found in &navmap_errormsg(). - $scantron_config - Reference to bubblesheet format configuration hash. - 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() @@ -10590,7 +9795,7 @@ ssi_with_retries() $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 + 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.