--- loncom/homework/grades.pm 2007/10/09 19:33:56 1.449 +++ loncom/homework/grades.pm 2007/10/17 10:48:20 1.461 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.449 2007/10/09 19:33:56 banghart Exp $ +# $Id: grades.pm,v 1.461 2007/10/17 10:48:20 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -35,6 +35,7 @@ use Apache::loncommon; use Apache::lonhtmlcommon; use Apache::lonnavmaps; use Apache::lonhomework; +use Apache::lonpickcode; use Apache::loncoursedata; use Apache::lonmsg(); use Apache::Constants qw(:common); @@ -56,9 +57,7 @@ my %first_bubble_line = (); # First bubb sub save_bubble_lines { - &Apache::lonnet::logthis("Saving bubble_lines..."); foreach my $line (keys(%bubble_lines_per_response)) { - &Apache::lonnet::logthis("Saving form.scantron.bubblelines.$line value: $bubble_lines_per_response{$line}"); $env{"form.scantron.bubblelines.$line"} = $bubble_lines_per_response{$line}; $env{"form.scantron.first_bubble_line.$line"} = $first_bubble_line{$line}; @@ -71,7 +70,6 @@ sub restore_bubble_lines { %bubble_lines_per_response = (); while ($env{"form.scantron.bubblelines.$line"}) { my $value = $env{"form.scantron.bubblelines.$line"}; - &Apache::lonnet::logthis("Restoring form.scantron.bubblelines.$line value: $value"); $bubble_lines_per_response{$line} = $value; $first_bubble_line{$line} = $env{"form.scantron.first_bubble_line.$line"}; @@ -86,12 +84,14 @@ sub restore_bubble_lines { sub get_response_bubbles { my ($parsed_line, $response) = @_; - my $bubble_line = $first_bubble_line{$response}; - my $bubble_lines= $bubble_lines_per_response{$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"}; + $selected .= $$parsed_line{"scantron.$bubble_line.answer"}.":"; $bubble_line++; } return $selected; @@ -477,6 +477,7 @@ COMMONJSFUNCTIONS sub getclasslist { my ($getsec,$filterlist,$getgroup) = @_; my @getsec; + my @getgroup; my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status')); if (!ref($getsec)) { if ($getsec ne '' && $getsec ne 'all') { @@ -486,6 +487,14 @@ sub getclasslist { @getsec=@{$getsec}; } if (grep(/^all$/,@getsec)) { undef(@getsec); } + if (!ref($getgroup)) { + if ($getgroup ne '' && $getgroup ne 'all') { + @getgroup=($getgroup); + } + } else { + @getgroup=@{$getgroup}; + } + if (grep(/^all$/,@getgroup)) { undef(@getgroup); } my ($classlist,$keylist)=&Apache::loncoursedata::get_classlist(); # Bail out if we were unable to get the classlist @@ -512,15 +521,35 @@ sub getclasslist { # filter students according to status selected if ($filterlist && (!($stu_status =~ /Any/))) { if (!($stu_status =~ $status)) { - delete ($classlist->{$student}); + delete($classlist->{$student}); next; } } + # filter students according to groups selected + my @stu_groups = split(/,/,$group); + if (@getgroup) { + my $exclude = 1; + foreach my $grp (@getgroup) { + foreach my $stu_group (@stu_groups) { + if ($stu_group eq $grp) { + $exclude = 0; + } + } + if (($grp eq 'none') && !$group) { + $exclude = 0; + } + } + if ($exclude) { + delete($classlist->{$student}); + } + } $section = ($section ne '' ? $section : 'none'); if (&canview($section)) { if (!@getsec || grep(/^\Q$section\E$/,@getsec)) { $sections{$section}++; - $fullnames{$student}=$fullname; + if ($classlist->{$student}) { + $fullnames{$student}=$fullname; + } } else { delete($classlist->{$student}); } @@ -872,7 +901,7 @@ LISTJAVASCRIPT 'value="Next->" /> <br />'."\n"; $gradeTable.=&check_buttons(); $gradeTable.='<label><input type="checkbox" name="checkPlag" checked="checked" />Check For Plagiarism</label>'; - my ($classlist, undef, $fullname) = &getclasslist($getsec,'1'); + my ($classlist, undef, $fullname) = &getclasslist($getsec,'1',$getgroup); $gradeTable.='<table border="0"><tr><td bgcolor="#777777">'. '<table border="0"><tr bgcolor="#e6ffff">'; my $loop = 0; @@ -947,7 +976,7 @@ LISTJAVASCRIPT $ctr++; my $section = $classlist->{$student}->[&Apache::loncoursedata::CL_SECTION()]; - + my $group = $classlist->{$student}->[&Apache::loncoursedata::CL_GROUP()]; if ( $perm{'vgr'} eq 'F' ) { $gradeTable.='<tr bgcolor="#ffffe6">' if ($ctr%2 ==1); $gradeTable.='<td align="right">'.$ctr.' </td>'. @@ -955,7 +984,7 @@ LISTJAVASCRIPT $student.':'.$$fullname{$student}.':::SECTION'.$section. ') " /> </label></td>'."\n".'<td>'. &nameUserString(undef,$$fullname{$student},$uname,$udom). - ' '.$section.'</td>'."\n"; + ' '.$section.'/'.$group.'</td>'."\n"; if ($env{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { foreach (sort keys(%status)) { @@ -4864,11 +4893,10 @@ SCANTRONFORM </tr> SCANTRONFORM - $r->print(<<SCANTRONFORM); - </table> -$grading_menu_button -SCANTRONFORM - + $r->print('<tr><td bgcolor="#777777">'); + &Apache::lonpickcode::code_list($r,2); + $r->print('</td></tr></table>'); + $r->print($grading_menu_button); return } @@ -5240,7 +5268,12 @@ sub scantron_parse_scanline { || (&occurence_count($currentquest, "[A-Z]") > 1)) { push(@{$record{'scantron.doubleerror'}},$questnum); for (my $ans = 0; $ans < $answers_needed; $ans++) { - $record{"scantron.$ansnum.answer"}=''; + my $bubble = substr($currentquest, $ans, 1); + if ($bubble =~ /[A-Z]/ ) { + $record{"scantron.$ansnum.answer"} = $bubble; + } else { + $record{"scantron.$ansnum.answer"}=''; + } $ansnum++; } @@ -5275,7 +5308,12 @@ sub scantron_parse_scanline { || (&occurence_count($currentquest, '\d') > 1)) { push(@{$record{'scantron.doubleerror'}},$questnum); for (my $ans = 0; $ans < $answers_needed; $ans++) { - $record{"scantron.$ansnum.answer"}=''; + my $bubble = substr($currentquest, $ans, 1); + if ($bubble =~ /\d/) { + $record{"scantron.$ansnum.answer"} = $alphabet[$bubble]; + } else { + $record{"scantron.$ansnum.answer"}=' '; + } $ansnum++; } @@ -5322,7 +5360,7 @@ sub scantron_parse_scanline { } } elsif (scalar(@array) lt 2) { - my $location = [length($array[0])]; + my $location = length($array[0]); my $line_num = $location / $$scantron_config{'Qlength'}; my $bubble = $alphabet[$location % $$scantron_config{'Qlength'}]; @@ -5718,7 +5756,6 @@ SCANTRONFORM my $line = 0; while (defined($env{"form.scantron.bubblelines.$line"})) { - &Apache::lonnet::logthis("Saving chunk for $line"); my $chunk = '<input type="hidden" name="scantron.bubblelines.'.$line.'" value="'.$env{"form.scantron.bubblelines.$line"}.'" />'."\n"; $chunk .= @@ -5784,7 +5821,6 @@ sub scantron_validate_file { } my $currentphase=$env{'form.validatepass'}; - &Apache::lonnet::logthis("Phase: $currentphase"); my $stop=0; while (!$stop && $currentphase < scalar(@validate_phases)) { @@ -6296,7 +6332,7 @@ sub scantron_validate_ID { sub scantron_get_correction { my ($r,$i,$scan_record,$scan_config,$line,$error,$arg)=@_; -#FIXME in the case of a duplicated ID the previous line, probaly need +#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 @@ -6395,10 +6431,10 @@ ENDSCRIPT $r->print($message); $r->print("<p>Please indicate which bubble should be used for grading</p>"); foreach my $question (@{$arg}) { - my $selected = &get_response_bubbles($scan_record, $question); + my @select_array = split(/:/,$selected); &scantron_bubble_selector($r,$scan_config,$question, - split('',$selected)); + @select_array); } } elsif ($error eq 'missingbubble') { $r->print("<p>There have been <b>no</b> bubbles scanned for some question(s)</p>\n"); @@ -6429,22 +6465,24 @@ ENDSCRIPT $r - Apache request object $scan_config - hash from &get_scantron_config() $quest - number of the bubble line to make a corrector for - $selected - array of letters of previously selected bubbles + $lines - array of answer lines. =cut sub scantron_bubble_selector { - my ($r,$scan_config,$quest,@selected)=@_; + my ($r,$scan_config,$quest,@lines)=@_; my $max=$$scan_config{'Qlength'}; + my $scmode=$$scan_config{'Qon'}; + my $bubble_length = scalar(@lines); + if ($scmode eq 'number' || $scmode eq 'letter') { $max=10; } my $response = $quest-1; my $lines = $bubble_lines_per_response{$response}; - &Apache::lonnet::logthis("Question $quest, lines: $lines"); my $total_lines = $lines*2; my @alphabet=('A'..'Z'); @@ -6454,12 +6492,8 @@ sub scantron_bubble_selector { if ($l != 0) { $r->print('<tr>'); } - - # FIXME: This loop probably has to be considerably more clever for - # multiline bubbles: User can multibubble by having bubbles in - # several lines. User can skip lines legitimately etc. etc. - for (my $i=0;$i<$max;$i++) { + my @selected = split(//,$lines[$l]); $r->print("\n".'<td align="center">'); if ($selected[0] eq $alphabet[$i]) { $r->print('X'); @@ -6708,14 +6742,11 @@ sub scantron_validate_doublebubble { =cut sub scantron_get_maxbubble { - &Apache::lonnet::logthis("get_max_bubble"); if (defined($env{'form.scantron_maxbubble'}) && $env{'form.scantron_maxbubble'}) { - &Apache::lonnet::logthis("cached"); &restore_bubble_lines(); return $env{'form.scantron_maxbubble'}; } - &Apache::lonnet::logthis("computing"); my (undef, undef, $sequence) = &Apache::lonnet::decode_symb($env{'form.selectpage'}); @@ -6753,9 +6784,9 @@ sub scantron_get_maxbubble { foreach my $part_id (@{$analysis{'parts'}}) { - my ($trash, $part) = split(/\./, $part_id); - my $lines = $analysis{"$part_id.bubble_lines"}[0]; + + my $lines = $analysis{"$part_id.bubble_lines"};; # TODO - make this a persistent hash not an array. @@ -7194,29 +7225,15 @@ sub grading_menu { $fields{'command'} = 'scantron_selectphase'; $url = &Apache::lonhtmlcommon::build_url('grades/',\%fields); push (@menu, { url => $url, - name => &mt('Grade Scantron Forms'), + name => &mt('Grade/Manage Scantron Forms'), short_description => &mt('')}); $fields{'command'} = 'verify'; $url = &Apache::lonhtmlcommon::build_url('grades/',\%fields); push (@menu, { url => "", - jscript => ' onClick="javascript:checkChoice2(document.forms.gradingMenu,\'5\',\'verify\')" ', name => &mt('Verify Receipt'), short_description => &mt('')}); - $fields{'command'} = 'manage'; - $url = &Apache::lonhtmlcommon::build_url('/adm/helper/resettimes.helper',\%fields); - push (@menu, { url => $url, - name => &mt('Manage Access Times'), - short_description => - &mt('')}); - $fields{'command'} = 'view'; - $url = &Apache::lonhtmlcommon::build_url('/adm/pickcode',\%fields); - push (@menu, { url => $url, - name => &mt('View Saved CODEs'), - short_description => - &mt('')}); - # # Create the menu my $Str; @@ -7238,10 +7255,10 @@ sub grading_menu { $menudata->{'url'}.'" >'. $menudata->{'name'}."</a></h3>\n"; } else { - $Str .=' <h3><a '. + $Str .=' <h3><input type="button" value="Verify Receipt" '. $menudata->{'jscript'}. - ' href="javascript:checkChoice2(document.forms.gradingMenu,\'5\',\'verify\')" >'. - $menudata->{'name'}."</a></h3>\n"; + ' onClick="javascript:checkChoice(document.forms.gradingMenu,\'5\',\'verify\')" '. + ' /></h3>'; $Str .= (' 'x8). ' receipt: '.&Apache::lonnet::recprefix($env{'request.course.id'}). '-<input type="text" name="receipt" size="4" onChange="javascript:checkReceiptNo(this.form,\'OK\')" />'; @@ -7262,30 +7279,14 @@ sub grading_menu { cmdsave = 'submission'; } formname.command.value = cmd; - formname.saveState.value = "saveCmd="+cmdsave+":saveSec="+pullDownSelection(formname.section)+ - ":saveSub="+pullDownSelection(formname.submitonly)+":saveStatus="+pullDownSelection(formname.Status); if (val < 5) formname.submit(); if (val == 5) { - if (!checkReceiptNo(formname,'notOK')) { return false;} - formname.submit(); - } - if (val < 7) formname.submit(); - } - function checkChoice2(formname,val,cmdx) { - if (val <= 2) { - var cmd = radioSelection(formname.radioChoice); - var cmdsave = cmd; - } else { - cmd = cmdx; - cmdsave = 'submission'; - } - formname.command.value = cmd; - if (val < 5) formname.submit(); - if (val == 5) { - if (!checkReceiptNo(formname,'notOK')) { return false;} - formname.submit(); + if (!checkReceiptNo(formname,'notOK')) { + return false; + } else { + formname.submit(); + } } - if (val < 7) formname.submit(); } function checkReceiptNo(formname,nospace) { @@ -7304,43 +7305,6 @@ sub grading_menu { </script> GRADINGMENUJS &commonJSfunctions($request); - my $result='<h3> <span class="LC_info">Manual Grading/View Submission</span></h3>'; - $result.=$table; - my (undef,$sections) = &getclasslist('all','0'); - my $savedState = &savedState(); - my $saveCmd = ($$savedState{'saveCmd'} eq '' ? 'submission' : $$savedState{'saveCmd'}); - my $saveSec = ($$savedState{'saveSec'} eq '' ? 'all' : $$savedState{'saveSec'}); - my $saveSub = ($$savedState{'saveSub'} eq '' ? 'all' : $$savedState{'saveSub'}); - my $saveStatus = ($$savedState{'saveStatus'} eq '' ? 'Active' : $$savedState{'saveStatus'}); - - $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n". - '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n". - '<input type="hidden" name="handgrade" value="'.$hdgrade.'" />'."\n". - '<input type="hidden" name="probTitle" value="'.$probTitle.'" ue="" />'."\n". - '<input type="hidden" name="saveState" value="" />'."\n". - '<input type="hidden" name="gradingMenu" value="1" />'."\n". - '<input type="hidden" name="showgrading" value="yes" />'."\n"; - - $result.='<table width="100%" border="0"><tr><td bgcolor=#777777>'."\n". - '<table width="100%" border="0"><tr bgcolor="#e6ffff"><td colspan="2">'."\n". - ' <b>Select a Grading/Viewing Option</b></td></tr>'."\n". - '<tr bgcolor="#ffffe6" valign="top"><td>'."\n"; - - $result.='<table width="100%" border="0">'; - $result.='<tr bgcolor="#ffffe6" valign="top">'."\n"; - $result.='<td><b>'.&mt('Sections').'</b></td>'; -# $result.='<td>Groups</td>'; - $result.='<td><b>'.&mt('Access Status').'</td>'."\n"; - $result.='</tr>'; - $result.='<tr bgcolor="#ffffe6" valign="top"><td>'."\n". - ' <select name="section" multiple="multiple" size="3">'."\n"; - if (ref($sections)) { - foreach (sort (@$sections)) { - $result.='<option value="'.$_.'" '. - ($saveSec eq $_ ? 'selected="selected"':'').'>'.$_.'</option>'."\n"; - } - } - $result.= '<option value="all" '.($saveSec eq 'all' ? 'selected="selected"' : ''). '>all</option></select> '; return $Str; } @@ -7418,6 +7382,7 @@ GRADINGMENUJS $result.='<td><b>'.&mt('Sections').'</b></td>'; $result.='<td><b>'.&mt('Groups').'</b></td>'; $result.='<td><b>'.&mt('Access Status').'</td>'."\n"; + $result.='<td><b>'.&mt('Submission Status').'</td>'."\n"; $result.='</tr>'; $result.='<tr bgcolor="#ffffe6" valign="top"><td>'."\n". ' <select name="section" multiple="multiple" size="3">'."\n"; @@ -7433,12 +7398,8 @@ GRADINGMENUJS $result.='</td><td>'."\n"; $result.=&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,3,undef,'mult'); - $result.='</td></tr>'; - - $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="3"><label>'. - '<input type="radio" name="radioChoice" value="submission" '. - ($saveCmd eq 'submission' ? 'checked="checked"' : '').' /> '.'<b>'.&mt('Current Resource').':</b> '.&mt('For one or more students'). - '</label> <select name="submitonly">'. + $result.='</td>'; + $result.='<td><select name="submitonly" size="3">'. '<option value="yes" '. ($saveSub eq 'yes' ? 'selected="selected"' : '').'>'.&mt('with submissions').'</option>'. '<option value="queued" '. @@ -7448,19 +7409,29 @@ GRADINGMENUJS '<option value="incorrect" '. ($saveSub eq 'incorrect' ? 'selected="selected"' : '').'>'.&mt('with incorrect submissions').'</option>'. '<option value="all" '. - ($saveSub eq 'all' ? 'selected="selected"' : '').'>'.&mt('with any status').'</option></select></td></tr>'."\n"; + ($saveSub eq 'all' ? 'selected="selected"' : '').'>'.&mt('with any status').'</option></select></td></tr>'; - $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'. + $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="3"><label>'. + '<input type="radio" name="radioChoice" value="submission" '. + ($saveCmd eq 'submission' ? 'checked="checked"' : '').' /> '.'<b>'.&mt('Current Resource').':</b> '.&mt('For one or more students'). + '</label> </td></tr>'."\n"; + + $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="3">'. '<label><input type="radio" name="radioChoice" value="viewgrades" '. ($saveCmd eq 'viewgrades' ? 'checked="checked"' : '').' /> '. '<b>Current Resource:</b> For all students in selected section or course</label></td></tr>'."\n"; - $result.='<tr bgcolor="#ffffe6" valign="top"><td colspan="2">'. - '<label><input type="radio" name="radioChoice" value="pickStudentPage" '. + $result.='<tr bgcolor="#ffffe6"><td colspan="3"><br />'. + '<input type="button" onClick="javascript:checkChoice(this.form,\'2\');" value="Next->" />'. + '</td></tr>'."\n"; + + + $result.='<tr bgcolor="#ffffe6" valign="top"><td colspan="3">'. + '<br /><label><input type="radio" name="radioChoice" value="pickStudentPage" '. ($saveCmd eq 'pickStudentPage' ? 'checked="checked"' : '').' /> '. - 'The <b>complete</b> set/page/sequence: For one student</label></td></tr>'."\n"; + 'The <b>complete</b> set/page/sequence/folder: For one student</label></td></tr>'."\n"; - $result.='<tr bgcolor="#ffffe6"><td colspan="2"><br />'. + $result.='<tr bgcolor="#ffffe6"><td colspan="3"><br />'. '<input type="button" onClick="javascript:checkChoice(this.form,\'2\');" value="Next->" />'. '</td></tr></table>'."\n"; @@ -7670,9 +7641,9 @@ function sanitycheck() { <input type="hidden" name="saveState" value="$env{'form.saveState'}" /> <input type="file" name="upfile" size="50" /> <br /><label>$type: $selectform</label> -<br /><label>$attendance: <input type="radio" name="gradingmechanism" value="attendance" $checked{'attendance'} onClick="sanitycheck()" /></label> -<br /><label>$personnel: <input type="radio" name="gradingmechanism" value="personnel" $checked{'personnel'} onClick="sanitycheck()" /></label> -<br /><label>$specific: <input type="radio" name="gradingmechanism" value="specific" $checked{'specific'} onClick="sanitycheck()" /></label> +<br /><label><input type="radio" name="gradingmechanism" value="attendance" $checked{'attendance'} onClick="sanitycheck()" />$attendance </label> +<br /><label><input type="radio" name="gradingmechanism" value="personnel" $checked{'personnel'} onClick="sanitycheck()" />$personnel</label> +<br /><label><input type="radio" name="gradingmechanism" value="specific" $checked{'specific'} onClick="sanitycheck()" />$specific </label> <input type="text" name="specificid" value="$env{'form.specificid'}" size="20" /> <input type="hidden" name="waschecked" value="$env{'form.gradingmechanism'}" /> <br /><label>$pcorrect: <input type="text" name="pcorrect" size="4" value="$env{'form.pcorrect'}" onChange="sanitycheck()" /></label> @@ -8007,7 +7978,6 @@ ENDHEADER sub handler { my $request=$_[0]; - &reset_caches(); if ($env{'browser.mathml'}) { &Apache::loncommon::content_type($request,'text/xml'); @@ -8103,7 +8073,6 @@ sub handler { } elsif ($command eq 'csvuploadassign' && $perm{'mgr'} ) { $request->print(&csvuploadassign($request)); } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) { - &Apache::lonnet::logthis("Selecting pyhase"); $request->print(&scantron_selectphase($request)); } elsif ($command eq 'scantron_warning' && $perm{'mgr'}) { $request->print(&scantron_do_warning($request));