--- loncom/homework/grades.pm 2007/11/01 20:56:51 1.475 +++ loncom/homework/grades.pm 2007/11/06 19:19:54 1.484 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.475 2007/11/01 20:56:51 albertel Exp $ +# $Id: grades.pm,v 1.484 2007/11/06 19:19:54 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -3362,15 +3362,14 @@ sub editgrades { my $symb=&get_symb($request); my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section')); - my $title='<h3><span class="LC_info">'.&mt('Current Grade Status').'</span></h3>'; - $title.='<h4>'.&mt('<b>Current Resource: </b>[_1]',$env{'form.probTitle'}).'</h4><br />'."\n"; + my $title='<h2>'.&mt('Current Grade Status').'</h2>'; + $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= '<table border="0"><tr><td bgcolor="#777777">'."\n"; - $result.= '<table border="0"><tr bgcolor="#deffff">'. - '<td rowspan=2 valign="center"> <b>No.</b> </td>'. - '<td rowspan=2 valign="center">'.&nameUserString('header')."</td>\n"; - + my $result= &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + '<th rowspan="2" valign="middle">'.&mt('No.').'</th>'. + '<th rowspan="2" valign="middle">'.&nameUserString('header')."</th>\n"; my %scoreptr = ( 'correct' =>'correct_by_override', 'incorrect'=>'incorrect_by_override', @@ -3395,8 +3394,8 @@ sub editgrades { } my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb); foreach my $partid (@partid) { - $header .= '<td align="center"> <b>Old Score</b> </td>'. - '<td align="center"> <b>New Score</b> </td>'; + $header .= '<th align="center">'.&mt('Old Score').'</th>'. + '<th align="center">'.&mt('New Score').'</th>'; $columns{$partid}=2; foreach my $stores (@parts) { my ($part,$type) = &split_part_type($stores); @@ -3405,22 +3404,23 @@ sub editgrades { my $display=&Apache::lonnet::metadata($url,$stores.'.display'); $display =~ s/\[Part: (\w)+\]//; $display =~ s/Number of Attempts/Tries/; - $header .= '<td align="center"> <b>Old '.$display.'</b> </td>'. - '<td align="center"> <b>New '.$display.'</b> </td>'; + $header .= '<th align="center">'.&mt('Old '.$display).'</th>'. + '<th align="center">'.&mt('New '.$display).'</th>'; $columns{$partid}+=2; } } foreach my $partid (@partid) { my $display_part=&get_display_part($partid,$symb); - $result .= '<td colspan="'.$columns{$partid}. - '" align="center"><b>Part:</b> '.$display_part. - ' (Weight = '.$weight{$partid}.')</td>'; + $result .= '<th colspan="'.$columns{$partid}.'" align="center">'. + &mt('Part: [_1] (Weight = [_2])',$display_part,$weight{$partid}). + '</th>'; } - $result .= '</tr><tr bgcolor="#deffff">'; - $result .= $header; - $result .= '</tr>'."\n"; - my $noupdate; + $result .= &Apache::loncommon::end_data_table_header_row(). + &Apache::loncommon::start_data_table_header_row(). + $header. + &Apache::loncommon::end_data_table_header_row(); + my @noupdate; my ($updateCtr,$noupdateCtr) = (1,1); for ($i=0; $i<$env{'form.total'}; $i++) { my $line; @@ -3432,7 +3432,9 @@ sub editgrades { my $usec=$classlist->{"$uname:$udom"}[5]; if (!&canmodify($usec)) { my $numcols=scalar(@partid)*4+2; - $noupdate.=$line."<td colspan=\"$numcols\"><span class=\"LC_warning\">Not allowed to modify student</span></td></tr>"; + push(@noupdate, + $line."<td colspan=\"$numcols\"><span class=\"LC_warning\">". + &mt('Not allowed to modify student')."</span></td></tr>"); next; } my %aggregate = (); @@ -3501,7 +3503,7 @@ sub editgrades { '<td align="center">'.$awarded.' </td>'; } } - $line.='</tr>'."\n"; + $line.="\n"; my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; @@ -3534,10 +3536,13 @@ sub editgrades { } } - $result.='<tr bgcolor="#ffffde"><td align="right"> '.$updateCtr.' </td>'.$line; + $result.=&Apache::loncommon::start_data_table_row(). + '<td align="right"> '.$updateCtr.' </td>'.$line. + &Apache::loncommon::end_data_table_row(); $updateCtr++; } else { - $noupdate.='<tr bgcolor="#ffffde"><td align="right"> '.$noupdateCtr.' </td>'.$line; + push(@noupdate, + '<td align="right"> '.$noupdateCtr.' </td>'.$line); $noupdateCtr++; } if ($aggregateflag) { @@ -3545,16 +3550,28 @@ sub editgrades { $cdom,$cnum); } } - if ($noupdate) { + if (@noupdate) { # my $numcols=(scalar(@partid)*(scalar(@parts)-1)*2)+3; my $numcols=scalar(@partid)*4+2; - $result .= '<tr bgcolor="#ffffff"><td align="center" colspan="'.$numcols.'">No Changes Occurred For the Students Below</td></tr><tr bgcolor="#ffffde">'.$noupdate; + $result .= &Apache::loncommon::start_data_table_row('LC_empty_row'). + '<td align="center" colspan="'.$numcols.'">'. + &mt('No Changes Occurred For the Students Below'). + '</td>'. + &Apache::loncommon::end_data_table_row(); + foreach my $line (@noupdate) { + $result.= + &Apache::loncommon::start_data_table_row(). + $line. + &Apache::loncommon::end_data_table_row(); + } } - $result .= '</table></td></tr></table>'."\n". - &show_grading_menu_form ($symb); - my $msg = '<br /><b>Number of records updated = '.$rec_update. - ' for '.$count.' student'.($count <= 1 ? '' : 's').'.</b><br />'. - '<b>Total number of students = '.$env{'form.total'}.'</b><br />'; + $result .= &Apache::loncommon::end_data_table(). + &show_grading_menu_form($symb); + my $msg = '<p><b>'. + &mt('Number of records updated = [_1] for [quant,_2,student].', + $rec_update,$count).'</b><br />'. + '<b>'.&mt('Total number of students = [_1]',$env{'form.total'}). + '</b></p>'; return $title.$msg.$result; } @@ -4082,12 +4099,13 @@ LISTJAVASCRIPT $request->print($result); my $studentTable.=' <b>Select a student you wish to grade and then click on the Next button.</b><br />'. - '<table border="0"><tr><td bgcolor="#777777">'. - '<table border="0"><tr bgcolor="#e6ffff">'. - '<td align="right"> <b>No.</b></td>'. - '<td>'.&nameUserString('header').'</td>'. - '<td align="right"> <b>No.</b></td>'. - '<td>'.&nameUserString('header').'</td></tr>'; + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + '<th align="right"> No.</th>'. + '<th>'.&nameUserString('header').'</th>'. + '<th align="right"> No.</th>'. + '<th>'.&nameUserString('header').'</th>'. + &Apache::loncommon::end_data_table_header_row(); my (undef,undef,$fullname) = &getclasslist($getsec,'1'); my $ptr = 1; @@ -4099,15 +4117,21 @@ LISTJAVASCRIPT return $a cmp $b; } (keys(%$fullname))) { my ($uname,$udom) = split(/:/,$student); - $studentTable.=($ptr%2 == 1 ? '<tr bgcolor="#ffffe6">' : '</td>'); + $studentTable.=($ptr%2==1 ? &Apache::loncommon::start_data_table_row() + : '</td>'); $studentTable.='<td align="right">'.$ptr.' </td>'; $studentTable.='<td> <label><input type="radio" name="student" value="'.$student.'" /> ' .&nameUserString(undef,$$fullname{$student},$uname,$udom)."</label>\n"; - $studentTable.=($ptr%2 == 0 ? '</td></tr>' : ''); + $studentTable.= + ($ptr%2 == 0 ? '</td>'.&Apache::loncommon::end_data_table_row() + : ''); $ptr++; } - $studentTable.='</td><td> </td><td> </td></tr>' if ($ptr%2 == 0); - $studentTable.='</table></td></tr></table>'."\n"; + if ($ptr%2 == 0) { + $studentTable.='</td><td> </td><td> </td>'. + &Apache::loncommon::end_data_table_row(); + } + $studentTable.=&Apache::loncommon::end_data_table()."\n"; $studentTable.='<input type="button" '. 'onClick="javascript:checkPickOne(this.form);"value="Next->" /></form>'."\n"; @@ -4207,10 +4231,11 @@ sub displayPage { $studentTable.=' <b>Note:</b> Problems graded correct by the computer are marked with a '.$checkIcon. ' symbol.'."\n". - '<table border="0"><tr><td bgcolor="#777777">'. - '<table border="0"><tr bgcolor="#e6ffff">'. - '<td align="center"><b> Prob. </b></td>'. - '<td><b> '.($env{'form.vProb'} eq 'no' ? 'Title' : 'Problem Text').'/Grade</b></td></tr>'; + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + '<th align="center"> Prob. </th>'. + '<th> '.($env{'form.vProb'} eq 'no' ? 'Title' : 'Problem Text').'/Grade</th>'. + &Apache::loncommon::end_data_table_header_row(); &Apache::lonxml::clear_problem_counter(); my ($depth,$question,$prob) = (1,1,1); @@ -4224,7 +4249,9 @@ sub displayPage { my $parts = $curRes->parts(); my $title = $curRes->compTitle(); my $symbx = $curRes->symb(); - $studentTable.='<tr bgcolor="#ffffe6"><td align="center" valign="top" >'.$prob. + $studentTable.= + &Apache::loncommon::start_data_table_row(). + '<td align="center" valign="top" >'.$prob. (scalar(@{$parts}) == 1 ? '' : '<br />('.scalar(@{$parts}).' parts)').'</td>'; $studentTable.='<td valign="top">'; my %form = ('CODE' => $env{'form.CODE'},); @@ -4432,12 +4459,14 @@ sub updateGradeByPage { my $iterator = $navmap->getIterator($map->map_start(), $map->map_finish()); - my $studentTable='<table border="0"><tr><td bgcolor="#777777">'. - '<table border="0"><tr bgcolor="#e6ffff">'. - '<td align="center"><b> Prob. </b></td>'. - '<td><b> Title </b></td>'. - '<td><b> Previous Score </b></td>'. - '<td><b> New Score </b></td></tr>'; + my $studentTable= + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + '<th align="center"> Prob. </th>'. + '<th> Title </th>'. + '<th> Previous Score </th>'. + '<th> New Score </th>'. + &Apache::loncommon::end_data_table_header_row(); $iterator->next(); # skip the first BEGIN_MAP my $curRes = $iterator->next(); # for "current resource" @@ -4450,7 +4479,9 @@ sub updateGradeByPage { my $parts = $curRes->parts(); my $title = $curRes->compTitle(); my $symbx = $curRes->symb(); - $studentTable.='<tr bgcolor="#ffffe6"><td align="center" valign="top" >'.$prob. + $studentTable.= + &Apache::loncommon::start_data_table_row(). + '<td align="center" valign="top" >'.$prob. (scalar(@{$parts}) == 1 ? '' : '<br />('.scalar(@{$parts}).' parts)').'</td>'; $studentTable.='<td valign="top"> <b>'.$title.'</b> </td>'; @@ -4538,14 +4569,14 @@ sub updateGradeByPage { $studentTable.='<td valign="top">'.$displayPts[0].'</td>'. '<td valign="top">'.$displayPts[1].'</td>'. - '</tr>'; + &Apache::loncommon::end_data_table_row(); $prob++; } $curRes = $iterator->next(); } - $studentTable.='</td></tr></table></td></tr></table>'; + $studentTable.=&Apache::loncommon::end_data_table(); $studentTable.=&show_grading_menu_form($env{'form.symb'}); my $grademsg=($changeflag == 0 ? 'No score was changed or updated.' : 'The scores were changed for '. @@ -5099,7 +5130,8 @@ sub username_to_idmap { sub scantron_fixup_scanline { my ($scantron_config,$scan_data,$line,$whichline,$field,$args)=@_; - + + if ($field eq 'ID') { if (length($args->{'newid'}) > $$scantron_config{'IDlength'}) { return ($line,1,'New value too large'); @@ -5130,28 +5162,58 @@ sub scantron_fixup_scanline { $$scantron_config{'CODElength'})=$args->{'CODE'}; } } elsif ($field eq 'answer') { - my $length=$scantron_config->{'Qlength'}; + &scantron_get_maxbubble(); # Need the bubble counter info. + my $length =$scantron_config->{'Qlength'}; my $off=$scantron_config->{'Qoff'}; my $on=$scantron_config->{'Qon'}; - my $answer=${off}x$length; - if ($args->{'response'} eq 'none') { - &scan_data($scan_data, - "$whichline.no_bubble.".$args->{'question'},'1'); - } else { - if ($on eq 'letter') { - my @alphabet=('A'..'Z'); - $answer=$alphabet[$args->{'response'}]; - } elsif ($on eq 'number') { - $answer=$args->{'response'}+1; - if ($answer == 10) { $answer = '0'; } + my $question_number = $args->{'question'} -1; + my $first_position = $first_bubble_line{$question_number}; + my $bubble_count = $bubble_lines_per_response{$question_number}; + my $bubbles_per_line= $$scantron_config{'Qlength'}; + my $answer=${off}x($bubbles_per_line*$bubble_count); + my $final_answer; + if ($$scantron_config{'Qon'} eq 'letter' || + $$scantron_config{'Qon'} eq 'number') { + $bubbles_per_line = 10; + } + if (defined $args->{'response'}) { + + if ($args->{'response'} eq 'none') { + &scan_data($scan_data, + "$whichline.no_bubble.".$args->{'question'},'1'); } else { - substr($answer,$args->{'response'},1)=$on; + my ($bubble_line, $bubble_number) = split(/:/,$args->{'response'}); + if ($on eq 'letter') { + my @alphabet=('A'..'Z'); + $answer=$alphabet[$bubble_number]; + } elsif ($on eq 'number') { + $answer= $bubble_number+1; + if ($answer == 10) { $answer = '0'; } + } else { + substr($answer,$bubble_number+$bubble_line*$bubbles_per_line,1)=$on; + $final_answer = $answer; + } + &scan_data($scan_data, + "$whichline.no_bubble.".$args->{'question'},undef,'1'); + + # Positional notation already has the right final answer length.. + + if (($on eq 'letter') || ($on eq 'number')) { + for (my $l = 0; $l < $bubble_count; $l++) { + if ($l eq $bubble_line) { + $final_answer .= $answer; + } else { + $final_answer .= ' '; + } + } + } } - &scan_data($scan_data, - "$whichline.no_bubble.".$args->{'question'},undef,'1'); + # $where=$length*($args->{'question'}-1)+$scantron_config->{'Qstart'}; + #substr($line,$where-1,$length)=$answer; + substr($line, + $scantron_config->{'Qstart'}+$first_position-1, + $bubbles_per_line*$length) = $final_answer; } - my $where=$length*($args->{'question'}-1)+$scantron_config->{'Qstart'}; - substr($line,$where-1,$length)=$answer; } return $line; } @@ -5398,11 +5460,16 @@ sub scantron_parse_scanline { if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) { push(@{$record{"scantron.missingerror"}},$questnum); } - } elsif (scalar(@array) lt 2) { + + # If the bubble is not the last position, there will be + # 2 elements. If it is the last position, there will be 1 element. + + } elsif (scalar(@array) le 2) { my $location = length($array[0]); - my $line_num = $location / $$scantron_config{'Qlength'}; + my $line_num = int($location / $$scantron_config{'Qlength'}); my $bubble = $alphabet[$location % $$scantron_config{'Qlength'}]; + for (my $ans = 0; $ans < $answers_needed; $ans++) { if ($ans eq $line_num) { @@ -6529,6 +6596,7 @@ sub scantron_bubble_selector { my $total_lines = $lines*2; my @alphabet=('A'..'Z'); + $r->print("<table border='1'><tr><td rowspan='".$total_lines."'>$quest</td>"); for (my $l = 0; $l < $lines; $l++) { @@ -6562,9 +6630,10 @@ sub scantron_bubble_selector { # multiline questions (different values e.g..). for (my $i=0;$i<$max;$i++) { + my $value = "$l:$i"; # Relative bubble line #: Bubble in line. $r->print("\n". '<td><label><input type="radio" name="scantron_correct_Q_'. - $quest.'" value="'.$i.'" />'.$alphabet[$i]."</label></td>"); + $quest.'" value="'.$value.'" />'.$alphabet[$i]."</label></td>"); } $r->print('</tr>'); @@ -7214,7 +7283,7 @@ sub show_grading_menu_form { '<input type="hidden" name="symb" value="'.&Apache::lonenc::check_encrypt($symb).'" />'."\n". '<input type="hidden" name="saveState" value="'.$env{'form.saveState'}.'" />'."\n". '<input type="hidden" name="command" value="gradingmenu" />'."\n". - '<input type="submit" name="submit" value="Grading Menu" />'."\n". + '<input type="submit" name="submit" value="'.&mt('Grading Menu').'" />'."\n". '</form>'."\n"; return $result; } @@ -7284,7 +7353,7 @@ sub grading_menu { $Str .= '<input type="hidden" name="command" value="" />'. '<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="probTitle" value="'.$probTitle.'" />'."\n". '<input type="hidden" name="saveState" value="" />'."\n". '<input type="hidden" name="gradingMenu" value="1" />'."\n". '<input type="hidden" name="showgrading" value="yes" />'."\n"; @@ -7308,7 +7377,6 @@ sub grading_menu { $Str .= ' '.(' 'x8).$menudata->{'short_description'}. "\n"; } - $Str .="</dl>\n"; $Str .="</form>\n"; $request->print(<<GRADINGMENUJS); <script type="text/javascript" language="javascript">