--- loncom/homework/grades.pm 2004/05/25 05:27:09 1.203 +++ loncom/homework/grades.pm 2004/12/03 22:44:36 1.233 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.203 2004/05/25 05:27:09 albertel Exp $ +# $Id: grades.pm,v 1.233 2004/12/03 22:44:36 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,16 +25,6 @@ # # http://www.lon-capa.org/ # -# 2/9,2/13 Guy Albertelli -# 6/8 Gerd Kortemeyer -# 7/26 H.K. Ng -# 8/20 Gerd Kortemeyer -# Year 2002 -# June-August H.K. Ng -# Year 2003 -# February, March H.K. Ng -# July, H. K. Ng -# package Apache::grades; use strict; @@ -101,25 +91,6 @@ sub get_symb_and_url { return ($symb,$url); } -# --- Retrieve the fullname for a user. Return lastname, first middle --- -# --- Generation is attached next to the lastname if it exists. --- -sub get_fullname { - my ($uname,$udom) = @_; - my %name=&Apache::lonnet::get('environment', ['lastname','generation', - 'firstname','middlename'], - $udom,$uname); - my $fullname; - my ($tmp) = keys(%name); - if ($tmp !~ /^(con_lost|error|no_such_host)/i) { - $fullname = &Apache::loncoursedata::ProcessFullName - (@name{qw/lastname generation firstname middlename/}); - } else { - &Apache::lonnet::logthis('grades.pm: no name data for '.$uname. - '@'.$udom.':'.$tmp); - } - return $fullname; -} - #--- Format fullname, username:domain if different for display #--- Use anywhere where the student names are listed sub nameUserString { @@ -167,6 +138,20 @@ sub response_type { return \@partlist,\%handgrade,\%responseType; } +sub get_display_part { + my ($partID,$url,$symb)=@_; + if (!defined($symb) || $symb eq '') { + $symb=$ENV{'form.symb'}; + if ($symb eq '') { $symb=&Apache::lonnet::symbread($url) } + } + my $display=&Apache::lonnet::EXT('resource.'.$partID.'.display',$symb); + if (defined($display) and $display ne '') { + $display.= " (<font color=\"#999900\">id $partID</font>)"; + } else { + $display=$partID; + } + return $display; +} #--- Show resource title #--- and parts and response type sub showResourceInfo { @@ -194,7 +179,8 @@ sub showResourceInfo { } $partsseen{$partID}=1; } - $result.='<td><b>Part </b>'.$partID.' <font color="#999999">'. + my $display_part=&get_display_part($partID,$url); + $result.='<td><b>Part: </b>'.$display_part.' <font color="#999999">'. $resID.'</font></td>'. '<td><b>Type: </b>'.$responsetype.'</td></tr>'; # '<td><b>Handgrade: </b>'.$handgrade.'</td></tr>'; @@ -349,27 +335,36 @@ sub getclasslist { # my %sections; my %fullnames; - foreach (keys(%$classlist)) { - # the following undefs are for 'domain', and 'username' respectively. - my (undef,undef,$end,$start,$id,$section,$fullname,$status)= - @{$classlist->{$_}}; + foreach my $student (keys(%$classlist)) { + my $end = + $classlist->{$student}->[&Apache::loncoursedata::CL_END()]; + my $start = + $classlist->{$student}->[&Apache::loncoursedata::CL_START()]; + my $id = + $classlist->{$student}->[&Apache::loncoursedata::CL_ID()]; + my $section = + $classlist->{$student}->[&Apache::loncoursedata::CL_SECTION()]; + my $fullname = + $classlist->{$student}->[&Apache::loncoursedata::CL_FULLNAME()]; + my $status = + $classlist->{$student}->[&Apache::loncoursedata::CL_STATUS()]; # filter students according to status selected if ($filterlist && $ENV{'form.Status'} ne 'Any') { if ($ENV{'form.Status'} ne $status) { - delete ($classlist->{$_}); + delete ($classlist->{$student}); next; } } - $section = ($section ne '' ? $section : 'no'); + $section = ($section ne '' ? $section : 'none'); if (&canview($section)) { if ($getsec eq 'all' || $getsec eq $section) { $sections{$section}++; - $fullnames{$_}=$fullname; + $fullnames{$student}=$fullname; } else { - delete($classlist->{$_}); + delete($classlist->{$student}); } } else { - delete($classlist->{$_}); + delete($classlist->{$student}); } } my %seen = (); @@ -682,7 +677,9 @@ LISTJAVASCRIPT '<td>'.&nameUserString('header').'</td>'; if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { foreach (sort(@$partlist)) { - $gradeTable.='<td><b> Part '.(split(/_/))[0].' Status </b></td>'; + my $display_part=&get_display_part((split(/_/))[0],$url,$symb); + $gradeTable.='<td><b> Part: '.$display_part. + ' Status </b></td>'; } } $loop++; @@ -975,6 +972,7 @@ sub sub_page_kw_js { my $request = shift; my $iconpath = $request->dir_config('lonIconsURL'); &commonJSfunctions($request); + my $docopen=&Apache::lonhtmlcommon::javascript_docopen(); $request->print(<<SUBJAVASCRIPT); <script type="text/javascript" language="javascript"> @@ -1084,10 +1082,10 @@ sub sub_page_kw_js { var ypos = (screen.height-height)/2-30; ypos = (ypos < 0) ? '0' : ypos; - pWin = window.open('', 'MessageCenter', 'toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=600,height='+height); + pWin = window.open('', 'MessageCenter', 'resizable=yes,toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=600,height='+height); pWin.focus(); pDoc = pWin.document; - pDoc.open('text/html','replace'); + pDoc.$docopen; pDoc.write("<html><head>"); pDoc.write("<title>Message Central</title>"); @@ -1215,10 +1213,10 @@ sub sub_page_kw_js { var ypos = (screen.height-330)/2-30; ypos = (ypos < 0) ? '0' : ypos; - hwdWin = window.open('', 'KeywordHighlightCentral', 'toolbar=no,location=no,scrollbars=no,width=400,height=300,screenx='+xpos+',screeny='+ypos); + hwdWin = window.open('', 'KeywordHighlightCentral', 'resizeable=yes,toolbar=no,location=no,scrollbars=no,width=400,height=300,screenx='+xpos+',screeny='+ypos); hwdWin.focus(); var hDoc = hwdWin.document; - hDoc.open('text/html','replace'); + hDoc.$docopen; hDoc.write("<html><head>"); hDoc.write("<title>Highlight Central</title>"); @@ -1289,8 +1287,9 @@ sub gradeBox { '' : $$record{'resource.'.$partid.'.awarded'}*$wgt); my $result='<input type="hidden" name="WGT'.$counter.'_'.$partid.'" value="'.$wgt.'" />'."\n"; + my $display_part=&get_display_part($partid,undef,$symb); $result.='<table border="0"><tr><td>'. - '<b>Part </b>'.$partid.' <b>Points: </b></td><td>'."\n"; + '<b>Part: </b>'.$display_part.' <b>Points: </b></td><td>'."\n"; my $ctr = 0; $result.='<table border="0"><tr>'."\n"; # display radio buttons in a nice table 10 across @@ -1386,14 +1385,15 @@ sub submission { my ($uname,$udom) = ($ENV{'form.student'},$ENV{'form.userdom'}); $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'} = &get_fullname ($uname,$udom) if $ENV{'form.fullname'} eq ''; + $ENV{'form.fullname'} = &Apache::loncommon::plainname($uname,$udom,'lastname') if $ENV{'form.fullname'} eq ''; my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url))); if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; } if (!&canview($usec)) { $request->print('<font color="red">Unable to view requested student.('. - $uname.$udom.$usec.$ENV{'request.course.id'}.')</font>'); + $uname.'@'.$udom.' in section '.$usec.' in course id '. + $ENV{'request.course.id'}.')</font>'); $request->print(&show_grading_menu_form($symb,$url)); return; } @@ -1622,11 +1622,12 @@ KEYWORDS my %seenparts; for my $part (sort keys(%$handgrade)) { my ($partid,$respid) = split(/_/,$part); + my $display_part=&get_display_part($partid,$url,$symb); if ($ENV{"form.$uname:$udom:$partid:submitted_by"}) { if (exists($seenparts{$partid})) { next; } $seenparts{$partid}=1; - my $submitby='<b>Part '.$partid. - ' Collaborative submission by: </b>'. + 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>'. @@ -1636,8 +1637,8 @@ KEYWORDS } my $responsetype = $responseType->{$partid}->{$respid}; if (!exists($record{"resource.$partid.$respid.submission"})) { - $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '. - $partid.'</b> <font color="#999999">( ID '.$respid. + $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part:</b> '. + $display_part.' <font color="#999999">( ID '.$respid. ' )</font> '. '<font color="red">Nothing submitted - no attempts</font><br /><br />'; next; @@ -1665,13 +1666,29 @@ KEYWORDS if ($ENV{'form.lastSub'} eq 'lastonly' || ($ENV{'form.lastSub'} eq 'hdgrade' && $$handgrade{$part} eq 'yes')) { - $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '. - $partid.'</b> <font color="#999999">( ID '.$respid. + my $display_part=&get_display_part($partid,$url,$symb); + $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part:</b> '. + $display_part.' <font color="#999999">( ID '.$respid. ' )</font> '; + my @files; + if ($record{"resource.$partid.$respid.portfiles"}) { + my $file_url = '/uploaded/'.$udom.'/'.$uname.'/portfolio'; + foreach my $file (split(',',$record{"resource.$partid.$respid.portfiles"})) { + push(@files,$file_url.$file); + + &Apache::lonnet::logthis("found a portfolio file".$record{"resource.$partid.$respid.portfiles"}); + &Apache::lonnet::logthis("uploaded URL file".$record{"resource.$partid.$respid.uploadedurl"}); + } + } if ($record{"resource.$partid.$respid.uploadedurl"}) { - &Apache::lonnet::allowuploaded('/adm/grades', - $record{"resource.$partid.$respid.uploadedurl"}); - $lastsubonly.='<a href="'.$record{"resource.$partid.$respid.uploadedurl"}.'" target="lonGRDs"><img src="/adm/lonIcons/unknown.gif" border=0"> File uploaded by student</a> <font color="red" size="1">Like all files provided by users, this file may contain virusses</font><br />'; + push(@files,$record{"resource.$partid.$respid.uploadedurl"}); + } + if (@files) { + $lastsubonly.='<br /><font color="red" size="1">Like all files provided by users, this file may contain virusses</font><br />'; + foreach my $file (@files) { + &Apache::lonnet::allowuploaded('/adm/grades',$file); + $lastsubonly.='<br /><a href="'.$file.'" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border=0"> '.$file.'</a>'; + } } $lastsubonly.='<b>Submitted Answer: </b>'. &cleanRecord($subval,$responsetype,$symb,$partid, @@ -2299,7 +2316,7 @@ sub viewgrades { my $sectionClass; if ($ENV{'form.section'} eq 'all') { $sectionClass='Class </h3>'; - } elsif ($ENV{'form.section'} eq 'no') { + } elsif ($ENV{'form.section'} eq 'none') { $sectionClass='Students in no Section </h3>'; } else { $sectionClass='Students in Section '.$ENV{'form.section'}.'</h3>'; @@ -2326,7 +2343,8 @@ sub viewgrades { $ctsparts.'" value="'.$partid.'" />'."\n"; $result.='<input type="hidden" name="weight_'. $partid.'" value="'.$weight{$partid}.'" />'."\n"; - $result.='<tr><td><b>Part '.$partid.' Point:</b> </td><td>'; + my $display_part=&get_display_part($partid,$url,$symb); + $result.='<tr><td><b>Part:</b> '.$display_part.' <b>Point:</b> </td><td>'; $result.='<table border="0"><tr>'; my $ctr = 0; while ($ctr<=$weight{$partid}) { # display radio buttons in a nice table 10 across @@ -2365,14 +2383,17 @@ sub viewgrades { my $display=&Apache::lonnet::metadata($url,$part.'.display'); $display =~ s|^Number of Attempts|Tries<br />|; # makes the column narrower if (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); } + my ($partid) = &split_part_type($part); + my $display_part=&get_display_part($partid,$url,$symb); if ($display =~ /^Partial Credit Factor/) { - my ($partid) = &split_part_type($part); - $result.='<td><b>Score Part '.$partid.'<br />(weight = '. - $weight{$partid}.')</b></td>'."\n"; + $result.='<td><b>Score Part:</b> '.$display_part. + ' <br /><b>(weight = '.$weight{$partid}.')</b></td>'."\n"; next; + } else { + $display =~s/\[Part: \Q$partid\E\]/Part:<\/b> $display_part/; } $display =~ s|Problem Status|Grade Status<br />|; - $result.='<td><b>'.$display.'</b></td>'."\n"; + $result.='<td><b>'.$display.'</td>'."\n"; } $result.='</tr>'; @@ -2381,9 +2402,6 @@ sub viewgrades { my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'1'); my $ctr = 0; foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) { - my $uname = $_; - $uname=~s/:/_/; - $result.='<input type="hidden" name="ctr'.$ctr.'" value="'.$uname.'" />'."\n"; $ctr++; $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'}, $_,$$fullname{$_},\@parts,\%weight,$ctr); @@ -2407,18 +2425,21 @@ sub viewstudentgrade { my ($uname,$udom) = split(/:/,$student); $student=~s/:/_/; my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname); - my $result='<tr bgcolor="#ffffdd"><td align="right">'.$ctr.' </td><td> '. + my $result='<tr bgcolor="#ffffdd"><td align="right">'. + '<input type="hidden" name="ctr'.($ctr-1).'" value="'.$student.'" />'. + "\n".$ctr.' </td><td> '. '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom. '\')"; TARGET=_self>'.$fullname.'</a> '. '<font color="#999999">('.$uname.($ENV{'user.domain'} eq $udom ? '' : ':'.$udom).')</font></td>'."\n"; foreach my $apart (@$parts) { my ($part,$type) = &split_part_type($apart); my $score=$record{"resource.$part.$type"}; + $result.='<td align="middle">'; if ($type eq 'awarded') { my $pts = $score eq '' ? '' : $score*$$weight{$part}; $result.='<input type="hidden" name="'. 'GD_'.$student.'_'.$part.'_awarded_s" value="'.$pts.'" />'."\n"; - $result.='<td align="middle"><input type="text" name="'. + $result.='<input type="text" name="'. 'GD_'.$student.'_'.$part.'_awarded" '. 'onChange="javascript:changeSelect(\''.$part.'\',\''.$student. '\')" value="'.$pts.'" size="4" /></td>'."\n"; @@ -2427,7 +2448,7 @@ sub viewstudentgrade { $status = 'nothing' if ($status eq ''); $result.='<input type="hidden" name="'.'GD_'.$student.'_'. $part.'_solved_s" value="'.$status.'" />'."\n"; - $result.='<td align="middle"> <select name="'. + $result.=' <select name="'. 'GD_'.$student.'_'.$part.'_solved" '. 'onChange="javascript:changeOneScore(\''.$part.'\',\''.$student.'\')" >'."\n"; $result.= (($status eq 'excused') ? '<option> </option><option selected="on">excused</option>' @@ -2438,7 +2459,7 @@ sub viewstudentgrade { $result.='<input type="hidden" name="'. 'GD_'.$student.'_'.$part.'_'.$type.'_s" value="'.$score.'" />'. "\n"; - $result.='<td align="middle"><input type="text" name="'. + $result.='<input type="text" name="'. 'GD_'.$student.'_'.$part.'_'.$type.'" '. 'value="'.$score.'" size="4" /></td>'."\n"; } @@ -2502,9 +2523,10 @@ sub editgrades { } } foreach my $partid (@partid) { + my $display_part=&get_display_part($partid,$url,$symb); $result .= '<td colspan="'.$columns{$partid}. - '" align="center"><b>Part '.$partid. - '</b> (Weight = '.$weight{$partid}.')</td>'; + '" align="center"><b>Part:</b> '.$display_part. + ' (Weight = '.$weight{$partid}.')</td>'; } $result .= '</tr><tr bgcolor="#deffff">'; @@ -2598,7 +2620,7 @@ sub editgrades { 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>'.$noupdate; + $result .= '<tr bgcolor="#ffffff"><td align="center" colspan="'.$numcols.'">No Changes Occurred For the Students Below</td></tr><tr bgcolor="#ffffde">'.$noupdate; } $result .= '</table></td></tr></table>'."\n". &show_grading_menu_form ($symb,$url); @@ -3045,8 +3067,6 @@ sub getSymbMap { $minder++; } } - - $navmap->untieHashes(); return \@titles,\%symbx; } @@ -3179,8 +3199,6 @@ sub displayPage { $curRes = $iterator->next(); } - $navmap->untieHashes(); - $studentTable.='</td></tr></table></td></tr></table>'."\n". '<input type="button" value="Save" '. 'onClick="javascript:checkSubmitPage(this.form,'.$question.');" TARGET=_self />'. @@ -3193,9 +3211,12 @@ sub displayPage { sub displaySubByDates { my ($symb,$record,$parts,$responseType,$checkIcon,$uname,$udom) = @_; + my $isCODE=0; + if (exists($record->{'resource.CODE'})) { $isCODE=1; } my $studentTable='<table border="0" width="100%"><tr><td bgcolor="#777777">'. '<table border="0" width="100%"><tr bgcolor="#e6ffff">'. '<td><b>Date/Time</b></td>'. + ($isCODE?'<td><b>CODE</b></td>':''). '<td><b>Submission</b></td>'. '<td><b>Status </b></td></tr>'; my ($version); @@ -3208,18 +3229,22 @@ sub displaySubByDates { for ($version=1;$version<=$$record{'version'};$version++) { my $timestamp = scalar(localtime($$record{$version.':timestamp'})); $studentTable.='<tr bgcolor="#ffffff" valign="top"><td>'.$timestamp.'</td>'; + if ($isCODE) { + $studentTable.='<td>'.$record->{$version.':resource.CODE'}.'</td>'; + } my @versionKeys = split(/\:/,$$record{$version.':keys'}); my @displaySub = (); foreach my $partid (@{$parts}) { my @matchKey = sort(grep /^resource\.\Q$partid\E\..*?\.submission$/,@versionKeys); # next if ($$record{"$version:resource.$partid.solved"} eq ''); + my $display_part=&get_display_part($partid,undef,$symb); foreach my $matchKey (@matchKey) { if (exists($$record{$version.':'.$matchKey}) && $$record{$version.':'.$matchKey} ne '') { my ($responseId)=($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/); - $displaySub[0].='<b>Part '.$partid.' '; + $displaySub[0].='<b>Part:</b> '.$display_part.' '; $displaySub[0].='<font color="#999999">(ID '. - $responseId.')</font> '; + $responseId.')</font> <b>'; if ($$record{"$version:resource.$partid.tries"} eq '') { $displaySub[0].='Trial not counted'; } else { @@ -3237,14 +3262,14 @@ sub displaySubByDates { } } if (exists $$record{"$version:resource.$partid.award"}) { - $displaySub[1].='<b>Part '.$partid.'</b> '. + $displaySub[1].='<b>Part:</b> '.$display_part.' '. lc($$record{"$version:resource.$partid.award"}).' '. $mark{$$record{"$version:resource.$partid.solved"}}. '<br />'; } if (exists $$record{"$version:resource.$partid.regrader"}) { $displaySub[2].=$$record{"$version:resource.$partid.regrader"}. - ' (<b>'.&mt('Part').':</b> '.$partid.')'; + ' (<b>'.&mt('Part').':</b> '.$display_part.')'; } } # needed because old essay regrader has not parts info @@ -3341,12 +3366,13 @@ sub updateGradeByPage { $changeflag++; $newpts = ''; } - + my $display_part=&get_display_part($partid,undef, + $curRes->symb()); my $oldstatus = $ENV{'form.solved'.$question.'_'.$partid}; - $displayPts[0].=' <b>Part</b> '.$partid.' = '. + $displayPts[0].=' <b>Part:</b> '.$display_part.' = '. (($oldstatus eq 'excused') ? 'excused' : $oldpts). ' <br>'; - $displayPts[1].=' <b>Part</b> '.$partid.' = '. + $displayPts[1].=' <b>Part:</b> '.$display_part.' = '. (($score eq 'excused') ? 'excused' : $newpts). ' <br>'; @@ -3374,8 +3400,6 @@ sub updateGradeByPage { $curRes = $iterator->next(); } - $navmap->untieHashes(); - $studentTable.='</td></tr></table></td></tr></table>'; $studentTable.=&show_grading_menu_form($ENV{'form.symb'},$ENV{'form.url'}); my $grademsg=($changeflag == 0 ? 'No score was changed or updated.' : @@ -3436,10 +3460,11 @@ sub scantron_filenames { } sub scantron_uploads { + my ($file2grade) = @_; my $result= '<select name="scantron_selectfile">'; $result.="<option></option>"; foreach my $filename (sort(&scantron_filenames())) { - $result.="<option>$filename</option>\n"; + $result.="<option".($filename eq $file2grade ? ' selected="on"':'').">$filename</option>\n"; } $result.="</select>"; return $result; @@ -3464,7 +3489,7 @@ sub scantron_CODElist { my $cnum = $ENV{'course.'.$ENV{'request.course.id'}.'.num'}; my @names=&Apache::lonnet::getkeys('CODEs',$cdom,$cnum); my $namechoice='<option></option>'; - foreach my $name (sort(@names)) { + foreach my $name (sort {uc($a) cmp uc($b)} @names) { if ($name =~ /^error: 2 /) { next; } $namechoice.='<option value="'.$name.'">'.$name.'</option>'; } @@ -3485,13 +3510,13 @@ sub scantron_CODEunique { } sub scantron_selectphase { - my ($r) = @_; + my ($r,$file2grade) = @_; my ($symb,$url)=&get_symb_and_url($r); if (!$symb) {return '';} my $sequence_selector=&getSequenceDropDown($r,$symb); my $default_form_data=&defaultFormData($symb,$url); my $grading_menu_button=&show_grading_menu_form($symb,$url); - my $file_selector=&scantron_uploads(); + my $file_selector=&scantron_uploads($file2grade); my $format_selector=&scantron_scantab(); my $CODE_selector=&scantron_CODElist(); my $CODE_unique=&scantron_CODEunique(); @@ -3501,8 +3526,8 @@ sub scantron_selectphase { $result.= <<SCANTRONFORM; <table width="100%" border="0"> <tr> + <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantron_process"> <td bgcolor="#777777"> - <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantron_process"> <input type="hidden" name="command" value="scantron_warning" /> $default_form_data <table width="100%" border="0"> @@ -3539,8 +3564,8 @@ sub scantron_selectphase { </td> </tr> </table> - </form> - </td> + </td> + </form> </tr> SCANTRONFORM @@ -3596,8 +3621,8 @@ SCANTRONFORM } $r->print(<<SCANTRONFORM); <tr> - <td bgcolor="#777777"> - <form action='/adm/grades' name='scantron_download'> + <form action='/adm/grades' name='scantron_download'> + <td bgcolor="#777777"> <input type="hidden" name="command" value="scantron_download" /> <table width="100%" border="0"> <tr bgcolor="#e6ffff"> @@ -3614,14 +3639,13 @@ SCANTRONFORM </td> </tr> </table> - </form> - </td> + </td> + </form> </tr> SCANTRONFORM $r->print(<<SCANTRONFORM); </table> -</form> $grading_menu_button SCANTRONFORM @@ -3818,7 +3842,8 @@ sub scantron_find_student { sub scantron_filter { my ($curres)=@_; - if (ref($curres) && $curres->is_problem() && !$curres->randomout) { + # randomout is dysfunctional at best for this purpose + if (ref($curres) && $curres->is_problem()) { #&& !$curres->randomout) { return 1; } return 0; @@ -3970,7 +3995,7 @@ sub scantron_form_start { <input type="hidden" name="selectpage" value="$ENV{'form.selectpage'}" /> <input type="hidden" name="scantron_format" value="$ENV{'form.scantron_format'}" /> <input type="hidden" name="scantron_selectfile" value="$ENV{'form.scantron_selectfile'}" /> - <input type="hidden" name="scantron_maxbubble" value="$max_bubble'" /> + <input type="hidden" name="scantron_maxbubble" value="$max_bubble" /> <input type="hidden" name="scantron_CODElist" value="$ENV{'form.scantron_CODElist'}" /> <input type="hidden" name="scantron_CODEunique" value="$ENV{'form.scantron_CODEunique'}" /> <input type="hidden" name="scantron_options_redo" value="$ENV{'form.scantron_options_redo'}" /> @@ -4290,8 +4315,8 @@ sub scantron_get_correction { } elsif ($error eq 'duplicateCODE') { $r->print("</p><p>The encoded CODE has also been used by a previous paper ".join(', ',@{$arg}).", and CODEs are supposed to be unique</p>\n"); } - $r->print("<p>The CODE on the form is <tt>". - $$scan_record{'scantron.CODE'}."</tt><br />\n"); + $r->print("<p>The CODE on the form is <tt>'". + $$scan_record{'scantron.CODE'}."'</tt><br />\n"); $r->print("<p>The ID on the form is <tt>". $$scan_record{'scantron.ID'}."</tt><br />\n"); $r->print("The name on the paper is ". @@ -4437,13 +4462,21 @@ sub scantron_validate_CODE { $scan_data); my $CODE=$$scan_record{'scantron.CODE'}; my $error=0; - if (!exists($allcodes{$CODE}) && !$$scan_record{'scantron.useCODE'}) { + if (!&Apache::lonnet::validCODE($CODE)) { &scantron_get_correction($r,$i,$scan_record, \%scantron_config, $line,'incorrectCODE',\%allcodes); return(1,$currentphase); } - if (exists($usedCODEs{$CODE}) && $ENV{'form.scantron_CODEunique'} + if (%allcodes && !exists($allcodes{$CODE}) + && !$$scan_record{'scantron.useCODE'}) { + &scantron_get_correction($r,$i,$scan_record, + \%scantron_config, + $line,'incorrectCODE',\%allcodes); + return(1,$currentphase); + } + if (exists($usedCODEs{$CODE}) + && $ENV{'form.scantron_CODEunique'} eq 'yes' && !$$scan_record{'scantron.CODE_ignore_dup'}) { &scantron_get_correction($r,$i,$scan_record, \%scantron_config, @@ -4608,11 +4641,18 @@ SCANTRONFORM if (exists($scan_record->{'scantron.CODE'}) && $scan_record->{'scantron.CODE'}) { $form{'CODE'}=$scan_record->{'scantron.CODE'}; + } else { + $form{'CODE'}=''; } my $result=&Apache::lonnet::ssi($resource->src(),%form); - + if ($result ne '') { + &Apache::lonnet::logthis("scantron grading error -> $result"); + &Apache::lonnet::logthis("scantron grading error info name $uname domain $udom course $ENV{'request.course.id'} url ".$resource->src()); + } + if (&Apache::loncommon::connection_aborted($r)) { last; } } $completedstudents{$uname}={'line'=>$line}; + if (&Apache::loncommon::connection_aborted($r)) { last; } } continue { &Apache::lonnet::delenv('form.counter'); &Apache::lonnet::delenv('scantron\.'); @@ -4621,7 +4661,6 @@ SCANTRONFORM # my $lasttime = &Time::HiRes::time()-$start; # $r->print("<p>took $lasttime</p>"); - $navmap->untieHashes(); $r->print("</form>"); $r->print(&show_grading_menu_form($symb,$url)); return ''; @@ -4682,7 +4721,8 @@ sub scantron_upload_scantron_data_save { } return ''; } - $r->print("Doing upload to ".$ENV{'form.courseid'}." <br />"); + my %coursedata=&Apache::lonnet::coursedescription($ENV{'form.domainid'}.'_'.$ENV{'form.courseid'}); + $r->print("Doing upload to ".$coursedata{'description'}." <br />"); my $home=&Apache::lonnet::homeserver($ENV{'form.courseid'}, $ENV{'form.domainid'}); my $fname=$ENV{'form.upfile.filename'}; @@ -4699,6 +4739,7 @@ sub scantron_upload_scantron_data_save { $fname=~s/[^\w\.\-]//g; # See if there is anything left unless ($fname) { return 'error: no uploaded file'; } + my $uploadedfile=$fname; $fname='scantron_orig_'.$fname; if (length($ENV{'form.upfile'}) < 2) { $r->print("<font color='red'>Error:</font> The file you attempted to upload, <tt>".&HTML::Entities::encode($ENV{'form.upfile.filename'},'<>&"')."</tt>, contained no information. Please check that you entered the correct filename."); @@ -4707,11 +4748,11 @@ sub scantron_upload_scantron_data_save { if ($result =~ m|^/uploaded/|) { $r->print("<font color='green'>Success:</font> Successfully uploaded ".(length($ENV{'form.upfile'})-1)." bytes of data into location <tt>".$result."</tt>"); } else { - $r->print("<font color='red'>Error:</font> An error (".$result.") occured when attempting to upload the file, <tt>".&HTML::Entities::encode($ENV{'form.upfile.filename'},'<>&"')."</tt>"); + $r->print("<font color='red'>Error:</font> An error (".$result.") occurred when attempting to upload the file, <tt>".&HTML::Entities::encode($ENV{'form.upfile.filename'},'<>&"')."</tt>"); } } if ($symb) { - $r->print(&show_grading_menu_form($symb,$url)); + $r->print(&scantron_selectphase($r,$uploadedfile)); } else { $r->print($doanotherupload); } @@ -4876,9 +4917,6 @@ GRADINGMENUJS $result.=&mt('Student Status').':</b>'.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,undef); - if (ref($sections) && (grep /no/,@$sections)) { - $result.=' (Section "no" implies the students were not assigned a section.)<br />'; - } $result.='</td></tr>'; $result.='<tr bgcolor="#ffffe6"valign="top"><td>'. @@ -5078,8 +5116,7 @@ sub send_header { sub send_footer { my ($request)= @_; - $request->print('</body>'); - $request->print(&Apache::lontexconvert::footer()); + $request->print('</body></html>'); } 1;