--- loncom/homework/grades.pm 2014/01/18 01:57:41 1.596.2.12.2.27 +++ 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.27 2014/01/18 01:57:41 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.='<td>'.$display_part.'</td>' .'<td>'.'<span class="LC_internal_info">'.$resID.'</span></td>' .'<td>'.&mt($responsetype).'</td>' -# .'<td><b>'.&mt('Handgrade: [_1]',$handgrade).'</b></td>' +# .'<td>'.&mt('<b>Handgrade: </b>[_1]',$handgrade).'</td>' .&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}; } @@ -811,7 +803,7 @@ sub verifyreceipt { '<h3><span class="LC_info">'. &mt('Verifying Receipt No. [_1]',$receipt). '</span></h3>'."\n". - '<h4>'.&mt('[_1]Resource: [_2]','<b>','</b>'.$env{'form.probTitle'}). + '<h4>'.&mt('<b>Resource: </b>[_1]',$env{'form.probTitle'}). '</h4>'."\n"; my ($string,$contents,$matches) = ('','',0); @@ -1162,7 +1154,7 @@ LISTJAVASCRIPT if ($submitonly eq 'graded' ) { $submissions = 'ungraded submissions'; } if ($submitonly eq 'queued' ) { $submissions = 'queued submissions'; } $gradeTable='<br /> <span class="LC_warning">'. - &mt('No '.$submissions.' found for this resource for any students. ([quant,_1,student] checked for '.$submissions.')', + &mt('No '.$submissions.' found for this resource for any students. ([_1] students checked for '.$submissions.')', $num_students). '</span><br />'; } @@ -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; @@ -1793,7 +1787,7 @@ sub gradeBox { $wgt = ($wgt > 0 ? $wgt : '1'); my $score = ($$record{'resource.'.$partid.'.awarded'} eq '' ? '' : &compute_points($$record{'resource.'.$partid.'.awarded'},$wgt)); - my $data_WGT='<input type="hidden" name="WGT'.$counter.'_'.$partid.'" value="'.$wgt.'" />'."\n"; + my $result='<input type="hidden" name="WGT'.$counter.'_'.$partid.'" value="'.$wgt.'" />'."\n"; my $display_part= &get_display_part($partid,$symb); my %last_resets = &get_last_resets($symb,$env{'request.course.id'}, [$partid]); @@ -1801,7 +1795,7 @@ sub gradeBox { if ($last_resets{$partid}) { $aggtries = &get_num_tries($record,$last_resets{$partid},$partid); } - my $result=&Apache::loncommon::start_data_table_row(); + $result.=&Apache::loncommon::start_data_table_row(); my $ctr = 0; my $thisweight = 0; my $increment = &get_increment(); @@ -1837,9 +1831,10 @@ sub gradeBox { $line.='<option value="reset status">'.&mt('reset status').'</option></select>'."\n"; + #&mt('<td><b>Part:</b></td><td>[_1]</td><td><b>Points:</b></td><td>[_2]</td><td>or</td><td>[_3]</td>',$display_part,$radio,$line); $result .= - '<td>'.$data_WGT.$display_part.'</td><td>'.$radio.'</td><td>'.&mt('or').'</td><td>'.$line.'</td>'; - $result.=&Apache::loncommon::end_data_table_row().'<td colspan="6">'; + '<td>'.$display_part.'</td><td>'.$radio.'</td><td>'.&mt('or').'</td><td>'.$line.'</td>'; + $result.=&Apache::loncommon::end_data_table_row(); $result.='<input type="hidden" name="stores'.$counter.'_'.$partid.'" value="" />'."\n". '<input type="hidden" name="oldpts'.$counter.'_'.$partid.'" value="'.$score.'" />'."\n". '<input type="hidden" name="solved'.$counter.'_'.$partid.'" value="'. @@ -1850,7 +1845,6 @@ sub gradeBox { $aggtries.'" />'."\n"; my $res_error; $result.=&handback_box($symb,$uname,$udom,$counter,$partid,$record,\$res_error); - $result.='</td>'.&Apache::loncommon::end_data_table_row(); if ($res_error) { return &navmap_errormsg(); } @@ -1924,27 +1918,14 @@ sub show_problem { $companswer=~s|</form>||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= '<div class="LC_Box">' - .'<h3 class="LC_hcell">'.$renderheading.'</h3>' + .'<h3 class="LC_hcell">'.&mt('View of the problem').'</h3>' .$rendered .'</div>'; $companswer= '<div class="LC_Box">' - .'<h3 class="LC_hcell">'.$answerheading.'</h3>' + .'<h3 class="LC_hcell">'.&mt('Correct answer').'</h3>' .$companswer .'</div>'; my $result; @@ -2015,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)) { @@ -2044,7 +2025,7 @@ sub submission { &download_all_link($request, $symb); } $request->print('<h3> <span class="LC_info">'.&mt('Submission Record').'</span></h3>'."\n". - '<h4> '.&mt('[_1]Resource: [_2]','<b>','</b>'.$env{'form.probTitle'}).'</h4>'."\n"); + '<h4> '.&mt('<b>Resource: </b> [_1]',$env{'form.probTitle'}).'</h4>'."\n"); # option to display problem, only once else it cause problems # with the form later since the problem has a form. @@ -2061,7 +2042,7 @@ sub submission { $request->print(&show_problem($request,$symb,$uname,$udom,0,1,$mode)); } - # kwclr is the only variable that is guaranteed not to be blank + # kwclr is the only variable that is guaranteed to be non blank # if this subroutine has been called once. my %keyhash = (); if ($env{'form.kwclr'} eq '' && $env{'form.handgrade'} eq 'yes') { @@ -2139,7 +2120,7 @@ sub submission { <b>$lt{'keyw'}:</b> <a href="javascript:keywords(document.SCORE);" target="_self">$lt{'list'}</a> <a href="#" onmousedown="javascript:getSel(); return false" - class="page">$lt{'past'}</a> + CLASS="page">$lt{'past'}</a> <a href="javascript:kwhighlight();" target="_self">$lt{'high'}</a><br /><br /> KEYWORDS # @@ -2149,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); } } @@ -2166,7 +2147,7 @@ KEYWORDS if ($perm{'vgr'}) { $request->print( &Apache::loncommon::track_student_link( - 'View recent activity', + &mt('View recent activity'), $uname,$udom,'check') .' ' ); @@ -2230,7 +2211,7 @@ KEYWORDS # (for multi-response type part) # (3) Last submission plus the parts info # (4) The whole record for this student - + if ($env{'form.lastSub'} =~ /^(lastonly|hdgrade)$/) { my ($string,$timestamp)= &get_last_submission(\%record); my $lastsubonly; @@ -2253,14 +2234,13 @@ KEYWORDS if ($env{"form.$uname:$udom:$partid:submitted_by"}) { if (exists($seenparts{$partid})) { next; } $seenparts{$partid}=1; - $request->print( - '<b>'.&mt('Part: [_1]',$display_part).'</b>'. - ' <b>'.&mt('Collaborative submission by: [_1]', - '<a href="javascript:viewSubmitter(\''. - $env{"form.$uname:$udom:$partid:submitted_by"}. - '\');" target="_self">'. - $$fullname{$env{"form.$uname:$udom:$partid:submitted_by"}}.'</a>'). - '<br />'); + my $submitby='<b>Part:</b> '.$display_part. + ' <b>Collaborative submission by:</b> '. + '<a href="javascript:viewSubmitter(\''. + $env{"form.$uname:$udom:$partid:submitted_by"}. + '\');" target="_self">'. + $$fullname{$env{"form.$uname:$udom:$partid:submitted_by"}}.'</a><br />'; + $request->print($submitby); next; } my $responsetype = $responseType->{$partid}->{$respid}; @@ -2285,7 +2265,7 @@ KEYWORDS $trial = $record{"resource.$partid.tries"}; $rndseed = $record{"resource.$partid.rndseed"}; } - if ($env{'form.checkPlag'}) { + if($env{'form.checkPlag'}){ my ($oname,$odom,$ocrsid,$oessay,$osim)= &most_similar($uname,$udom,$symb,$subval); if ($osim) { @@ -2313,8 +2293,9 @@ KEYWORDS } my $order=&get_order($partid,$respid,$symb,$uname,$udom, undef,$type,$trial,$rndseed); - if ($env{'form.lastSub'} eq 'lastonly' || $env{'form.lastSub'} eq 'datesub' || $env{'form.lastSub'} =~ /^(last|all)$/ || ($env{'form.lastSub'} eq 'hdgrade' && - $$handgrade{$$part[0].'_'.$$part[1]} eq 'yes')) { + if ($env{'form.lastSub'} eq 'lastonly' || + ($env{'form.lastSub'} eq 'hdgrade' && + $$handgrade{$$part[0].'_'.$$part[1]} eq 'yes')) { my $display_part=&get_display_part($partid,$symb); $lastsubonly.='<div class="LC_grade_submission_part">'. '<b>'.&mt('Part: [_1]',$display_part).'</b>'. @@ -2326,26 +2307,18 @@ KEYWORDS if ($hide eq 'anon') { $lastsubonly.='<br />'.&mt('[quant,_1,file] uploaded to this anonymous survey',scalar(@{$files})); } else { - $lastsubonly.='<br /><br />'.'<b>'.&mt('Submitted Files:').'</b>' - .'<br /><span class="LC_warning">'; - if(@$files == 1) { - $lastsubonly .= &mt('Like all files provided by users, this file may contain viruses!'); - } else { - $lastsubonly .= &mt('Like all files provided by users, these files may contain viruses!'); - } - $lastsubonly .= '</span>'; - + $lastsubonly.='<br /><span class="LC_warning">'.&mt('Like all files provided by users, this file may contain viruses').'</span><br />'; foreach my $file (@$files) { &Apache::lonnet::allowuploaded('/adm/grades',$file); - $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0" alt="" /> '.$file.'</a>'; + $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0" /> '.$file.'</a>'; } } $lastsubonly.='<br />'; } if ($hide eq 'anon') { - $lastsubonly.='<br /><b>'.&mt('Anonymous Survey').'</b>'; + $lastsubonly.='<b>'.&mt('Anonymous Survey').'</b>'; } else { - $lastsubonly.='<br /><b>'.&mt('Submitted Answer:').' </b>'. + $lastsubonly.='<b>'.&mt('Submitted Answer:').' </b>'. &cleanRecord($subval,$responsetype,$symb,$partid, $respid,\%record,$order,undef,$uname,$udom,$type,$trial,$rndseed); } @@ -2357,11 +2330,10 @@ KEYWORDS $lastsubonly.='</div>'."\n"; # End: LC_grade_submissions_body } $request->print($lastsubonly); - if ($env{'form.lastSub'} eq 'datesub') { + } elsif ($env{'form.lastSub'} eq 'datesub') { my (undef,$responseType,undef,$parts) = &showResourceInfo($symb); $request->print(&displaySubByDates($symb,\%record,$parts,$responseType,$checkIcon,$uname,$udom)); - } - if ($env{'form.lastSub'} =~ /^(last|all)$/) { + } elsif ($env{'form.lastSub'} =~ /^(last|all)$/) { $request->print(&Apache::loncommon::get_previous_attempt($symb,$uname,$udom, $env{'request.course.id'}, $last,'.submission', @@ -2403,9 +2375,9 @@ KEYWORDS '<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n"; $result.=' <a href="javascript:msgCenter(document.SCORE,'.$counter. ',\''.$msgfor.'\');" target="_self">'. - &mt('Compose message to student'.(scalar(@$col_fullnames) >= 1 ? 's' : '')).'</a><label> ('. + &mt('Compose message to student').(scalar(@$col_fullnames) >= 1 ? 's' : '').'</a><label> ('. &mt('incl. grades').' <input type="checkbox" name="withgrades'.$counter.'" /></label>)'. - ' <img src="'.$request->dir_config('lonIconsURL'). + '<img src="'.$request->dir_config('lonIconsURL'). '/mailbkgrd.gif" width="14" height="10" name="mailicon'.$counter.'" />'."\n". '<br /> ('. &mt('Message will be sent when you click on Save & Next below.').")\n"; @@ -2627,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('<span class="LC_warning">Unable to view previous version for requested student.('. - $uname.':'.$udom.' in section '.$usec.' in course id '. - $env{'request.course.id'}.')</span>'); - 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". - '<div class="LC_grade_show_user">'. - '<h2>'.&nameUserString(undef,$env{'form.fullname'},$uname,$udom). - '</h2>'."\n"); - &Apache::lonxml::clear_problem_counter(); - $request->print(&show_problem($request,$symb,$uname,$udom,1,1,$mode, - {'previousversion' => $env{'form.previousversion'} })); - $request->print("\n</div>"); - } - } - 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 = '<div class="LC_left_float">'; - 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 .= '<option value="'.$i.'">'.&mt('Current').'</option>'."\n"; - $numversions ++; - } - } elsif (defined($record{'resource.'.$i.'.0.status'})) { - unless ($i == $env{'form.previousversion'}) { - $numversions ++; - } - $list .= '<option value="'.$i.'">'.$i.'</option>'."\n"; - } - } - if ($numversions) { - $symb = &HTML::Entities::encode($symb,'<>"&'); - $result .= - '<form name="getprev" method="post" action=""'. - ' onsubmit="return previousVersion('."'$uname','$udom','$symb','$displayed'".');">'. - &Apache::loncommon::start_data_table(). - &Apache::loncommon::start_data_table_row(). - '<th align="left">'.$rowtitle.'</th>'. - '<td><select name="version">'. - '<option>'.&mt('Select').'</option>'. - $list. - '</select></td>'. - &Apache::loncommon::end_data_table_row(); - unless ($nomenu) { - $result .= &Apache::loncommon::start_data_table_row(). - '<th align="left">'.&mt('Open in new window').'</th>'. - '<td><span class="LC_nobreak">'. - '<label><input type="radio" name="prevwin" value="1" />'. - &mt('Yes').'</label>'. - '<label><input type="radio" name="prevwin" value="0" checked="checked" />'.&mt('No').'</label>'. - '</span></td>'. - &Apache::loncommon::end_data_table_row(); - } - $result .= - &Apache::loncommon::start_data_table_row(). - '<th align="left"> </th>'. - '<td>'. - '<input type="submit" name="prevsub" value="'.&mt('Display').'" />'. - '</td>'. - &Apache::loncommon::end_data_table_row(). - &Apache::loncommon::end_data_table(). - '</form>'; - $js = &previous_display_javascript($nomenu,$current); - } elsif ($displayed && $nomenu) { - $result .= '<a href="javascript:window.close()">'.&mt('Close window').'</a>'; - } else { - $result .= &mt('No previous versions to show for this student'); - } - $result .= '</div>'; - } - return ($current,$displayed,$result,$js); -} - -sub previous_display_javascript { - my ($nomenu,$current) = @_; - my $js = <<"JSONE"; -<script type="text/javascript"> -// <![CDATA[ -function previousVersion(uname,udom,symb) { - var current = '$current'; - var version = document.getprev.version.options[document.getprev.version.selectedIndex].value; - var prevstr = new RegExp("^\\\\d+\$"); - if (!prevstr.test(version)) { - return false; - } - var url = ''; - if (version == current) { - url = '/adm/grades?student='+uname+'&userdom='+udom+'&symb='+symb+'&command=submission'; - } else { - url = '/adm/grades?student='+uname+'&userdom='+udom+'&symb='+symb+'&command=versionsub&previousversion='+version; - } -JSONE - if ($nomenu) { - $js .= <<"JSTWO"; - document.location.href = url; -JSTWO - } else { - $js .= <<"JSTHREE"; - var newwin = 0; - for (var i=0; i<document.getprev.prevwin.length; i++) { - if (document.getprev.prevwin[i].checked == true) { - newwin = document.getprev.prevwin[i].value; - } - } - if (newwin == 1) { - var options = 'height=600,width=800,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no'; - url = url+'&inhibitmenu=yes'; - if (typeof(previousWin) == 'undefined' || previousWin.closed) { - previousWin = window.open(url,'',options,1); - } else { - previousWin.location.href = url; - } - previousWin.focus(); - return false; - } else { - document.location.href = url; - return false; - } -JSTHREE - } - $js .= <<"ENDJS"; - return false; -} -// ]]> -</script> -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'}; @@ -3212,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, @@ -3236,7 +3029,7 @@ sub handback_files { $file_msg.='<span class="LC_filename"><a href="/uploaded/'."$domain/$stuname/".$save_file_name.'">'.$save_file_name."</a></span> <br />"; } - $request->print('<br />'.&mt('[_1] will be the uploaded filename [_2]','<span class="LC_info">'.$fname.'</span>','<span class="LC_filename">'.$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter}.'</span>')); + $request->print('<br />'.&mt('[_1] will be the uploaded file name [_2]','<span class="LC_info">'.$fname.'</span>','<span class="LC_filename">'.$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter}.'</span>')); } } } @@ -3375,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); @@ -3398,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); } @@ -3642,7 +3430,7 @@ sub viewgrades { &Apache::lonnet::clear_EXT_cache_status(); my $result='<h3><span class="LC_info">'.&mt('Manual Grading').'</span></h3>'; - $result.='<h4><b>'.&mt('Current Resource').':</b> '.$env{'form.probTitle'}.'</h4>'."\n"; + $result.='<h4>'.&mt('<b>Current Resource: </b>[_1]',$env{'form.probTitle'}).'</h4>'."\n"; #view individual student submission form - called using Javascript viewOneStudent $result.=&jscriptNform($symb); @@ -3705,9 +3493,8 @@ sub viewgrades { $partid.'" size="4" '.'onchange="javascript:writePoint(\''. $partid.'\','.$weight{$partid}.',\'textval\')" /> /'. $weight{$partid}.' '.&mt('(problem weight)').'</td>'."\n"; - $line.= '<td><b>'.&mt('Grade Status').':</b>'. - '<select name="SELVAL_'.$partid.'" '. - 'onchange="javascript:writeRadText(\''.$partid.'\','. + $line.= '<td><b>'.&mt('Grade Status').':</b><select name="SELVAL_'.$partid.'"'. + 'onchange="javascript:writeRadText(\''.$partid.'\','. $weight{$partid}.')"> '. '<option selected="selected"> </option>'. '<option value="excused">'.&mt('excused').'</option>'. @@ -3754,8 +3541,8 @@ sub viewgrades { my $display_part=&get_display_part($partid,$symb); if ($display =~ /^Partial Credit Factor/) { $result.='<th>'. - &mt('Score Part: [_1][_2](weight = [_3])', - $display_part,'<br />',$weight{$partid}).'</th>'."\n"; + &mt('Score Part: [_1]<br /> (weight = [_2])', + $display_part,$weight{$partid}).'</th>'."\n"; next; } else { @@ -3876,11 +3663,11 @@ 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='<h2>'.&mt('Current Grade Status').'</h2>'; - $title.='<h4><b>'.&mt('Current Resource').':</b> '.$env{'form.probTitle'}.'</h4>'."\n"; - $title.='<h4><b>'.&mt('Section:').'</b> '.$section_display.'</h4>'."\n"; + $title.='<h4>'.&mt('<b>Current Resource: </b>[_1]',$env{'form.probTitle'}).'</h4>'."\n"; + $title.='<h4>'.&mt('<b>Section: </b>[_1]',$section_display).'</h4>'."\n"; my $result= &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(). @@ -4265,12 +4052,11 @@ sub csvupload_fields { sub csvuploadmap_footer { my ($request,$i,$keyfields) =@_; - my $buttontext = &mt('Assign Grades'); $request->print(<<ENDPICK); </table> <input type="hidden" name="nfields" value="$i" /> <input type="hidden" name="keyfields" value="$keyfields" /> -<input type="button" onclick="javascript:verify(this.form)" value="$buttontext" /><br /> +<input type="button" onclick="javascript:verify(this.form)" value="Assign Grades" /><br /> </form> ENDPICK } @@ -4414,7 +4200,7 @@ ENDPICK } # FIXME do a check for any duplicated user ids... # FIXME do a check for any invalid user ids?... - $request->print('<input type="submit" value="'.&mt('Assign Grades').'" /><br /> + $request->print('<input type="submit" value="Assign Grades" /><br /> <hr /></form>'."\n"); $request->print(&show_grading_menu_form($symb)); return ''; @@ -4822,8 +4608,8 @@ sub displayPage { &Apache::loncommon::start_data_table_row(). '<td align="center" valign="top" >'.$prob. (scalar(@{$parts}) == 1 ? '' - : '<br />('.&mt('[_1]parts', - scalar(@{$parts}).' ').')' + : '<br />('.&mt('[_1]parts)', + scalar(@{$parts}).' ') ). '</td>'; $studentTable.='<td valign="top">'; @@ -4905,7 +4691,6 @@ sub displaySubByDates { &Apache::loncommon::start_data_table_header_row(). '<th>'.&mt('Date/Time').'</th>'. ($isCODE?'<th>'.&mt('CODE').'</th>':''). - ($isTask?'<th>'.&mt('Version').'</th>':''). '<th>'.&mt('Submission').'</th>'. '<th>'.&mt('Status').'</th>'. &Apache::loncommon::end_data_table_header_row(); @@ -4926,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(). @@ -4936,9 +4719,6 @@ sub displaySubByDates { if ($isCODE) { $studentTable.='<td>'.$record->{$version.':resource.CODE'}.'</td>'; } - if ($isTask) { - $studentTable.='<td>'.$interaction.'</td>'; - } my @versionKeys = split(/\:/,$$record{$version.':keys'}); my @displaySub = (); foreach my $partid (@{$parts}) { @@ -4958,7 +4738,7 @@ sub displaySubByDates { my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/) : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/)); - $displaySub[0].='<span class="LC_nobreak">'; + $displaySub[0].='<span class="LC_nobreak"'; $displaySub[0].='<b>'.&mt('Part: [_1]',$display_part).'</b>' .' <span class="LC_internal_info">' .'('.&mt('Response ID: [_1]',$responseId).')' @@ -5230,7 +5010,7 @@ like. Next each scanline is checked for any errors of either 'missing bubbles' (it's an error because it may have been mis-scanned because too light bubbling), 'double bubble' (each bubble line should -have no more than one letter picked), invalid or duplicated CODE, +have no more that one letter picked), invalid or duplicated CODE, invalid student/employee ID If the CODE option is used that determines the randomization of the @@ -5320,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. @@ -5338,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; @@ -5358,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 @@ -5376,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; } @@ -5693,7 +5477,7 @@ sub scantron_selectphase { &Apache::lonpickcode::code_list($r,2); - $r->print('<br /><form method="post" name="checkscantron" action="">'. + $r->print('<br /><form method="post" name="checkscantron">'. $default_form_data."\n". &Apache::loncommon::start_data_table('LC_scantron_action')."\n". &Apache::loncommon::start_data_table_header_row()."\n". @@ -5783,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 @@ -5815,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; @@ -6027,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 @@ -6092,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 || @@ -6133,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++; @@ -6164,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; @@ -6184,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 ++; } @@ -6199,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); } } } @@ -6213,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 @@ -6291,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); } @@ -6355,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 @@ -6398,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)) { @@ -6589,11 +6254,7 @@ sub scantron_process_corrections { } } if ($err) { - $r->print( - '<p class="LC_error">' - .&mt('Unable to accept last correction, an error occurred: [_1]', - $errmsg) - .'</p>'); + $r->print("<span class=\"LC_warning\">Unable to accept last correction, an error occurred :$errmsg:</span>"); } else { &scantron_put_line($scanlines,$scan_data,$which,$line,$skip); &scantron_putfile($scanlines,$scan_data); @@ -6720,25 +6381,19 @@ sub scantron_warning_screen { '<tr><td><b>'.&mt('List of CODES to validate against:').'</b></td><td><tt>'. $env{'form.scantron_CODElist'}.'</tt></td></tr>'; } - my $lastbubblepoints; - if ($env{'form.scantron_lastbubblepoints'} ne '') { - $lastbubblepoints = - '<tr><td><b>'.&mt('Hand-graded items: points from last bubble in row').'</b></td><td><tt>'. - $env{'form.scantron_lastbubblepoints'}.'</tt></td></tr>'; - } return (' <p> <span class="LC_warning"> -'.&mt("Please double check the information below before clicking on '[_1]'",&mt($button_text)).'</span> +'.&mt('Please double check the information below before clicking on \'[_1]\'',&mt($button_text)).'</span> </p> <table> <tr><td><b>'.&mt('Sequence to be Graded:').'</b></td><td>'.$title.'</td></tr> <tr><td><b>'.&mt('Data File that will be used:').'</b></td><td><tt>'.$env{'form.scantron_selectfile'}.'</tt></td></tr> -'.$CODElist.$lastbubblepoints.' +'.$CODElist.' </table> <br /> -<p> '.&mt("If this information is correct, please click on '[_1]'.",&mt($button_text)).'</p> -<p> '.&mt("If something is incorrect, please click the 'Grading Menu' button to start over.").'</p> +<p> '.&mt('If this information is correct, please click on \'[_1]\'.',&mt($button_text)).'</p> +<p> '.&mt('If something is incorrect, please click the \'Grading Menu\' button to start over.').'</p> <br /> '); @@ -6774,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.' <input type="submit" name="submit" value="'.&mt('Grading: Validate Records').'" /> <input type="hidden" name="command" value="scantron_validate" /> '); @@ -6818,11 +6472,9 @@ SCANTRONFORM '<input type="hidden" name="scantron.sub_bubblelines.'.$line.'" value="'.$env{"form.scantron.sub_bubblelines.$line"}.'" />'."\n"; $chunk .= '<input type="hidden" name="scantron.responsetype.'.$line.'" value="'.$env{"form.scantron.responsetype.$line"}.'" />'."\n"; - $chunk .= - '<input type="hidden" name="scantron.residpart.'.$line.'" value="'.$env{"form.scantron.residpart.$line"}.'" />'."\n"; $result .= $chunk; $line++; - } + } return $result; } @@ -6844,7 +6496,7 @@ sub scantron_validate_file { if (!$symb) {return '';} my $default_form_data=&defaultFormData($symb); - # do the detection of only doing skipped records first before we delete + # do the detection of only doing skipped records first befroe we delete # them when doing the corrections reset if ($env{'form.scantron_options_redo'} ne 'redo_skipped_ready') { &reset_skipping_status(); @@ -6868,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 .= '<input type="hidden" name="scantron_lastbubblepoints" value="'.$env{'form.scantron_lastbubblepoints'}.'" />'; - } $r->print($result); my @validate_phases=( 'sequence', @@ -6895,7 +6543,6 @@ sub scantron_validate_file { while (!$stop && $currentphase < scalar(@validate_phases)) { $r->print(&mt('Validating '.$validate_phases[$currentphase]).'<br />'); $r->rflush(); - my $which="scantron_validate_".$validate_phases[$currentphase]; { no strict 'refs'; @@ -7304,12 +6951,7 @@ sub scantron_validate_sequence { my @resources= $navmap->retrieveResources($map,\&scantron_filter_not_exam,1,0); if (@resources) { - $r->print('<p class="LC_warning">' - .&mt('Some resources in the sequence currently are not set to' - .' exam mode. Grading these resources currently may not' - .' work correctly.') - .'</p>' - ); + $r->print("<p>".&mt('Some resources in the sequence currently are not set to exam mode. Grading these resources currently may not work correctly.')."</p>"); return (1,$currentphase); } } @@ -7331,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); @@ -7390,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 @@ -7441,7 +7082,7 @@ sub scantron_get_correction { $r->print(&Apache::loncommon::selectstudent_link('scantronupload', 'scantron_username','scantron_domain')); $r->print(": <input type='text' name='scantron_username' value='' />"); - $r->print("\n:\n". + $r->print("\n@". &Apache::loncommon::select_dom_form($env{'request.role.domain'},'scantron_domain')); $r->print('</li>'); @@ -7527,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('<input type="hidden" name="scantron_questions" value="'. $line_list.'" />'); @@ -7536,9 +7176,7 @@ ENDSCRIPT $r->print("<p>".&mt("Please indicate which bubble should be used for grading")."</p>"); 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)); @@ -7552,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('<input type="hidden" name="scantron_questions" value="'. $line_list.'" />'); 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)); @@ -7614,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}) { @@ -7636,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]; @@ -7653,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)); @@ -7684,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. @@ -7716,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}; - } - $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]; @@ -7743,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.').'<br />'); - 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).'<br /><br />'.&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.').'<br />'.&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.').'<br />'.&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.").'<br /><br />'); + 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).'<br /><br />'.&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.').'<br />'.&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.').'<br />'.&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.").'<br /><br />'); } else { $r->print(&mt("Select at most one bubble in a single line and select 'No Bubble' in all the other lines. ")."<br />"); } } 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++; @@ -7803,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(). @@ -7970,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); @@ -8024,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); @@ -8070,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); @@ -8086,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(); @@ -8105,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(); @@ -8117,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; @@ -8153,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++) { @@ -8167,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; @@ -8189,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; @@ -8267,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); } @@ -8313,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.').'<p>'. - &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?','<br />'). - '<label><input type="radio" name="scantron_lastbubblepoints" value="'.$bubbles_per_row.'" checked="checked" />'.&mt('[quant,_1,point]',$bubbles_per_row).'</label> '.&mt('or').' '. - '<label><input type="radio" name="scantron_lastbubblepoints" value="0"/>0 points</label></p>'; - } - return; -} sub scantron_process_students { my ($r) = @_; @@ -8360,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); @@ -8368,28 +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); - 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= <<SCANTRONFORM; @@ -8404,7 +7839,9 @@ SCANTRONFORM my $lock=&Apache::lonnet::set_lock(&mt('Grading bubblesheet exam')); my $count=&get_todo_count($scanlines,$scan_data); - my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,$count); + my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Bubblesheet Status', + 'Bubblesheet Progress',$count, + 'inline',undef,'scantronupload'); &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state, 'Processing first student'); $r->print('<br />'); @@ -8412,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 ''; @@ -8431,7 +7869,6 @@ SCANTRONFORM my %lettdig = &letter_to_digits(); my $numletts = scalar(keys(%lettdig)); - my %orderedforcode; while ($i<$scanlines->{'count'}) { ($uname,$udom)=('',''); @@ -8443,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, @@ -8463,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(); @@ -8493,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}; @@ -8514,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("</form>"); &ssi_print_error($r); @@ -8527,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("</form>"); &ssi_print_error($r); @@ -8574,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) { @@ -8599,11 +7998,11 @@ SCANTRONFORM &Apache::loncommon::end_data_table_header_row()."\n". &Apache::loncommon::start_data_table_row(). '<td>'.&mt('Bubblesheet').'</td>'. - '<td><span class="LC_nobreak" style="white-space: pre;"><tt>'.$studentdata.'</tt></span></td>'. + '<td><span class="LC_nobreak">'.$studentdata.'</span></td>'. &Apache::loncommon::end_data_table_row(). &Apache::loncommon::start_data_table_row(). '<td>'.&mt('Stored submissions').'</td>'. - '<td><span class="LC_nobreak" style="white-space: pre;"><tt>'.$studentrecord.'</tt></span></td>'."\n". + '<td><span class="LC_nobreak">'.$studentrecord.'</span></td>'."\n". &Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table().'</p>'); } else { @@ -8630,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') { @@ -8652,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}) { @@ -8725,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++; } } @@ -8761,9 +8089,8 @@ sub scantron_upload_scantron_data { 'domainid', 'coursename',$dom); my $syllabuslink = '<a href="javascript:ToSyllabus();">'.&mt('Syllabus').'</a>'. - (' '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(' @@ -8844,30 +8171,23 @@ sub scantron_upload_scantron_data_save { } my %coursedata=&Apache::lonnet::coursedescription($env{'form.domainid'}.'_'.$env{'form.courseid'}); my $uploadedfile; - $r->print('<p>'.&mt("Uploading file to [_1]",$coursedata{'description'}).'</p>'); + $r->print('<h3>'.&mt("Uploading file to [_1]",$coursedata{'description'}).'</h3>'); if (length($env{'form.upfile'}) < 2) { - $r->print( - &Apache::lonhtmlcommon::confirm_success( - &mt('The file: [_1] you attempted to upload contained no information. Please check that you entered the correct filename.', - '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'),1)); + $r->print(&mt('[_1]Error:[_2] The file you attempted to upload, [_3] contained no information. Please check that you entered the correct filename.','<span class="LC_error">','</span>','<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>')); } else { my $result = &Apache::lonnet::userfileupload('upfile','','scantron','','','', $env{'form.courseid'},$env{'form.domainid'}); if ($result =~ m{^/uploaded/}) { - $r->print( - &Apache::lonhtmlcommon::confirm_success(&mt('Upload successful')).'<br />'. - &mt('Uploaded [_1] bytes of data into location: [_2]', - (length($env{'form.upfile'})-1), - '<span class="LC_filename">'.$result.'</span>')); + $r->print(&mt('[_1]Success:[_2] Successfully uploaded [_3] bytes of data into location: [_4]', + '<span class="LC_success">','</span>',(length($env{'form.upfile'})-1), + '<span class="LC_filename">'.$result.'</span>')); ($uploadedfile) = ($result =~ m{/([^/]+)$}); $r->print(&validate_uploaded_scantron_file($env{'form.domainid'}, $env{'form.courseid'},$uploadedfile)); } else { - $r->print( - &Apache::lonhtmlcommon::confirm_success(&mt('Upload failed'),1).'<br />'. - &mt('An error ([_1]) occurred when attempting to upload the file: [_2]', - $result, + $r->print(&mt('[_1]Error:[_2] An error ([_3]) occurred when attempting to upload the file, [_4]', + '<span class="LC_error">','</span>',$result, '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>')); } } @@ -8889,7 +8209,7 @@ sub validate_uploaded_scantron_file { my $output; if (@lines) { my (%counts,$max_match_format); - my ($found_match_count,$max_match_count,$max_match_pct) = (0,0,0); + my ($max_match_count,$max_match_pct) = (0,0); my $classlist = &Apache::loncoursedata::get_classlist($cdom,$cname); my %idmap = &username_to_idmap($classlist); foreach my $key (keys(%idmap)) { @@ -8932,7 +8252,6 @@ sub validate_uploaded_scantron_file { if (($max_match_format eq '') || ($percent_match > $max_match_pct)) { $max_match_pct = $percent_match; $max_match_format = $key; - $found_match_count = $counts{$key}{'found'}; $max_match_count = $counts{$key}{'total'}; } } @@ -8951,40 +8270,17 @@ sub validate_uploaded_scantron_file { } } my $showpct = sprintf("%.0f",$max_match_pct).'%'; - $output .= '<br />'; - if ($found_match_count == $max_match_count) { - # 100% matching entries - $output .= &Apache::lonhtmlcommon::confirm_success( - &mt('Comparison of student IDs: [_1] matching ([quant,_2,entry,entries])', - '<b>'.$showpct.'</b>',$found_match_count)).'<br />'. - &mt('Comparison of student IDs in the uploaded file with'. - ' the course roster found matches for [_1] of the [_2] entries'. - ' in the file (for the format defined for [_3]).', - '<b>'.$showpct.'</b>','<b>'.$max_match_count.'</b>',$format_descs); - } else { - # Not all entries matching? -> Show warning and additional info - $output .= - &Apache::lonhtmlcommon::confirm_success( - &mt('Comparison of student IDs: [_1] matching ([_2]/[quant,_3,entry,entries])', - '<b>'.$showpct.'</b>',$found_match_count,$max_match_count).'<br />'. - &mt('Not all entries could be matched!'),1).'<br />'. - &mt('Comparison of student IDs in the uploaded file with'. - ' the course roster found matches for [_1] of the [_2] entries'. - ' in the file (for the format defined for [_3]).', - '<b>'.$showpct.'</b>','<b>'.$max_match_count.'</b>',$format_descs). - '<p class="LC_info">'. - &mt('A low percentage of matches results from one of the following:'). - '</p><ul>'. - '<li>'.&mt('The file was uploaded to the wrong course.').'</li>'. - '<li>'.&mt('The data is not in the format expected for the domain: [_1]', - '<i>'.$cdom.'</i>').'</li>'. - '<li>'.&mt('Students did not bubble their IDs, or mis-bubbled them').'</li>'. - '<li>'.&mt('The course roster is not up to date.').'</li>'. - '</ul>'; - } + $output .= '<br />'.&mt('Comparison of student IDs in the uploaded file with the course roster found matches for [_1] of the [_2] entries in the file (for the format defined for [_3]).','<b>'.$showpct.'</b>','<b>'.$max_match_count.'</b>',$format_descs). + '<br />'.&mt('A low percentage of matches results from one of the following:').'<ul>'. + '<li>'.&mt('The file was uploaded to the wrong course').'</li>'. + '<li>'.&mt('The data are not in the format expected for the domain: [_1]', + '<i>'.$cdom.'</i>').'</li>'. + '<li>'.&mt('Students did not bubble their IDs, or mis-bubbled them').'</li>'. + '<li>'.&mt('The course roster is not up to date').'</li>'. + '</ul>'; } } else { - $output = '<p class="LC_warning">'.&mt('Uploaded file contained no data').'</p>'; + $output = '<span class="LC_warning">'.&mt('Uploaded file contained no data').'</span>'; } return $output; } @@ -8999,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(' <p> - '.&mt('The requested filename was invalid.').' + '.&mt('The requested file name was invalid.').' </p> '); - $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; @@ -9033,7 +8328,7 @@ sub scantron_download_scantron_data { '<a href="'.$skipped.'">','</a>').' </p> '); - $r->print(&show_grading_menu_form($symb)); + $r->print(&show_grading_menu_form(&get_symb($r,1))); return ''; } @@ -9051,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); @@ -9061,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(' @@ -9083,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 $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); - &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 ''; @@ -9110,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; @@ -9124,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; } } @@ -9220,11 +8476,7 @@ sub checkscantron_results { $env{'form.scantron_maxbubble'}). '</p>' ); - $r->print('<p>' - .&mt('Exact matches for [_1][quant,_2,student][_3].','<b>',$passed,'</b>') - .'<br />' - .&mt('Discrepancies detected for [_1][quant,_2,student][_3].','<b>',$failed,'</b>') - .'</p>'); + $r->print('<p>'.&mt('Exact matches for <b>[quant,_1,student]</b>.',$passed).'<br />'.&mt('Discrepancies detected for <b>[quant,_1,student]</b>.',$failed).'</p>'); if ($passed) { $r->print(&mt('Students with exact correspondence between bubblesheet data and submissions are as follows:').'<br /><br />'); $r->print(&Apache::loncommon::start_data_table()."\n". @@ -9250,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()); @@ -9260,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; @@ -9370,7 +8615,7 @@ sub verify_scantron_grading { return ($counter,$record); } -sub letter_to_digits { +sub letter_to_digits { my %lettdig = ( A => 1, B => 2, @@ -9417,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); @@ -9847,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.=<<ENDUPFORM; <script type="text/javascript"> @@ -9977,18 +9214,16 @@ sub process_clicker_file { $number++; } $result.="</p>\n"; - if ($number==0) { - $result .= - &Apache::lonhtmlcommon::confirm_success( - &mt('No IDs found to determine correct answer'),1); - return $result,.&show_grading_menu_form($symb); - } + if ($number==0) { + $result.='<span class="LC_error">'.&mt('No IDs found to determine correct answer').'</span>'; + return $result.&show_grading_menu_form($symb); + } } if (length($env{'form.upfile'}) < 2) { - $result .= - &Apache::lonhtmlcommon::confirm_success( - &mt('The file: [_1] you attempted to upload contained no information. Please check that you entered the correct filename.', - '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'),1); + $result.=&mt('[_1] Error: [_2] The file you attempted to upload, [_3] contained no information. Please check that you entered the correct filename.', + '<span class="LC_error">', + '</span>', + '<span class="LC_filename">'.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').'</span>'); return $result.&show_grading_menu_form($symb); } @@ -10023,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.='<br />'.&mt('Found [_1] question(s)',$number).'<br />'. '<input type="hidden" name="number" value="'.$number.'" />'. &mt('Awarding [_1] percent for correct and [_2] percent for incorrect responses', @@ -10080,7 +9312,7 @@ ENDHEADER &mt('Found [_1] registered and [_2] unregistered clickers.',$student_count,$unknown_count); if (($env{'form.gradingmechanism'} ne 'attendance') && ($env{'form.gradingmechanism'} ne 'given')) { if ($correct_count==0) { - $errormsg.="Found no correct answers for grading!"; + $errormsg.="Found no correct answers answers for grading!"; } elsif ($correct_count>1) { $result.='<br /><span class="LC_warning">'.&mt("Found [_1] entries for grading!",$correct_count).'</span>'; } @@ -10157,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); @@ -10255,7 +9462,7 @@ sub assign_clicker_grades { if ($user) { if ($users{$user}) { $result.='<br /><span class="LC_warning">'. - &mt('More than one entry found for [_1]!','<tt>'.$user.'</tt>'). + &mt("More than one entry found for <tt>[_1]</tt>!",$user). '</span><br />'; } $users{$user}=1; @@ -10323,19 +9530,6 @@ sub navmap_errormsg { '</div>'; } -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(); @@ -10357,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'); @@ -10390,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; @@ -10411,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('<br clear="all" />'); ($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('<br clear="all" />'); - $request->print(&show_previous_task_version($request,$symb)); } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) { &pickStudentPage($request); } elsif ($command eq 'displayPage' && $perm{'vgr'}) { @@ -10608,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: @@ -10627,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() @@ -10638,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.