--- loncom/homework/grades.pm 2005/06/04 02:56:44 1.270 +++ loncom/homework/grades.pm 2006/03/13 20:26:51 1.333 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.270 2005/06/04 02:56:44 albertel Exp $ +# $Id: grades.pm,v 1.333 2006/03/13 20:26:51 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -40,6 +40,7 @@ use Apache::lonmsg qw(:user_normal_msg); use Apache::Constants qw(:common); use Apache::lonlocal; use String::Similarity; +use POSIX qw(floor); my %oldessays=(); my %perm=(); @@ -48,7 +49,8 @@ my %perm=(); # # --- Retrieve the parts from the metadata file.--- sub getpartlist { - my ($url,$symb) = @_; + my ($symb) = @_; + my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb); my $partorder = &Apache::lonnet::metadata($url, 'partorder'); my @parts; if ($partorder) { @@ -78,7 +80,7 @@ sub getpartlist { } # --- Get the symbolic name of a problem and the url -sub get_symb_and_url { +sub get_symb { my ($request,$silent) = @_; (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))); @@ -88,7 +90,7 @@ sub get_symb_and_url { return (); } } - return ($symb,$url); + return ($symb); } #--- Format fullname, username:domain if different for display @@ -106,8 +108,8 @@ sub nameUserString { #--- Get the partlist and the response type for a given problem. --- #--- Indicate if a response type is coded handgraded or not. --- sub response_type { - my ($url,$symb) = shift; - $symb=($env{'form.symb'} ne '' ? $env{'form.symb'} : (&Apache::lonnet::symbread($url))) if ($symb eq ''); + my ($symb) = shift; + my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb); my $allkeys = &Apache::lonnet::metadata($url,'keys'); my %vPart; foreach my $partid (&Apache::loncommon::get_env_multiple('form.vPart')) { @@ -135,15 +137,11 @@ sub response_type { push @partlist,$partid; } } - return \@partlist,\%handgrade,\%responseType; + 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 ($partID,$symb)=@_; my $display=&Apache::lonnet::EXT('resource.'.$partID.'.display',$symb); if (defined($display) and $display ne '') { $display.= " (<font color=\"#999900\">id $partID</font>)"; @@ -156,13 +154,13 @@ sub get_display_part { #--- Show resource title #--- and parts and response type sub showResourceInfo { - my ($url,$probTitle,$checkboxes) = @_; + my ($symb,$probTitle,$checkboxes) = @_; my $col=3; if ($checkboxes) { $col=4; } my $result ='<table border="0">'. '<tr><td colspan="'.$col.'"><font size="+1"><b>'.&mt('Current Resource').': </b>'. $probTitle.'</font></td></tr>'."\n"; - my ($partlist,$handgrade,$responseType) = &response_type($url); + my ($partlist,$handgrade,$responseType) = &response_type($symb); my %resptype = (); my $hdgrade='no'; my %partsseen; @@ -180,7 +178,7 @@ sub showResourceInfo { } $partsseen{$partID}=1; } - my $display_part=&get_display_part($partID,$url); + my $display_part=&get_display_part($partID,$symb); $result.='<td><b>Part: </b>'.$display_part.' <font color="#999999">'. $resID.'</font></td>'. '<td><b>Type: </b>'.$responsetype.'</td></tr>'; @@ -334,7 +332,16 @@ COMMONJSFUNCTIONS #--- section, ids and fullnames for each user. sub getclasslist { my ($getsec,$filterlist) = @_; - $getsec = $getsec eq '' ? 'all' : $getsec; + my @getsec; + if (!ref($getsec)) { + if ($getsec ne '' && $getsec ne 'all') { + @getsec=($getsec); + } + } else { + @getsec=@{$getsec}; + } + if (grep(/^all$/,@getsec)) { undef(@getsec); } + my $classlist=&Apache::loncoursedata::get_classlist(); # Bail out if we were unable to get the classlist return if (! defined($classlist)); @@ -363,7 +370,7 @@ sub getclasslist { } $section = ($section ne '' ? $section : 'none'); if (&canview($section)) { - if ($getsec eq 'all' || $getsec eq $section) { + if (!@getsec || grep(/^\Q$section\E$/,@getsec)) { $sections{$section}++; $fullnames{$student}=$fullname; } else { @@ -420,7 +427,7 @@ sub canview { #--- Retrieve the grade status of a student for all the parts sub student_gradeStatus { - my ($url,$symb,$udom,$uname,$partlist) = @_; + my ($symb,$udom,$uname,$partlist) = @_; my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname); my %partstatus = (); foreach (@$partlist) { @@ -437,7 +444,7 @@ sub student_gradeStatus { # Use by verifyscript and viewgrades # Shows a student's view of problem and submission sub jscriptNform { - my ($url,$symb) = @_; + my ($symb) = @_; my $jscript='<script type="text/javascript" language="javascript">'."\n". ' function viewOneStudent(user,domain) {'."\n". ' document.onestudent.student.value = user;'."\n". @@ -447,7 +454,6 @@ sub jscriptNform { '</script>'."\n"; $jscript.= '<form action="/adm/grades" method="post" name="onestudent">'."\n". '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". - '<input type="hidden" name="url" value="'.$url.'" />'."\n". '<input type="hidden" name="saveState" value="'.$env{'form.saveState'}.'" />'."\n". '<input type="hidden" name="probTitle" value="'.$env{'form.probTitle'}.'" />'."\n". '<input type="hidden" name="Status" value="'.$env{'form.Status'}.'" />'."\n". @@ -458,6 +464,33 @@ sub jscriptNform { return $jscript; } +# Given the score (as a number [0-1] and the weight) what is the final +# point value? This function will round to the nearest tenth, third, +# or quarter if one of those is within the tolerance of .00001. +sub compute_points { + my ($score, $weight) = @_; + + my $tolerance = .00001; + my $points = $score * $weight; + + # Check for nearness to 1/x. + my $check_for_nearness = sub { + my ($factor) = @_; + my $num = ($points * $factor) + $tolerance; + my $floored_num = floor($num); + if ($num - $floored_num < 2 * $tolerance * $factor) { + return $floored_num / $factor; + } + return $points; + }; + + $points = $check_for_nearness->(10); + $points = $check_for_nearness->(3); + $points = $check_for_nearness->(4); + + return $points; +} + #------------------ End of general use routines -------------------- # @@ -471,6 +504,10 @@ sub most_similar { $uessay=~s/\W+/ /gs; +# ignore empty submissions (occuring when only files are sent) + + unless ($uessay=~/\w+/) { return ''; } + # these will be returned. Do not care if not at least 50 percent similar my $limit=0.6; my $sname=''; @@ -515,15 +552,11 @@ sub verifyreceipt { my $receipt = &Apache::lonnet::recprefix($courseid).'-'. $env{'form.receipt'}; $receipt =~ s/[^\-\d]//g; - my $url = $env{'form.url'}; - my $symb = $env{'form.symb'}; - unless ($symb) { - $symb = &Apache::lonnet::symbread($url); - } + my $symb = &Apache::lonnet::symbread(); my $title.='<h3><font color="#339933">Verifying Submission Receipt '. $receipt.'</h3></font>'."\n". - '<font size=+1><b>Resource: </b>'.$env{'form.probTitle'}.'</font><br><br>'."\n"; + '<font size=+1><b>Resource: </b>'.$env{'form.probTitle'}.'</font><br /><br />'."\n"; my ($string,$contents,$matches) = ('','',0); my (undef,undef,$fullname) = &getclasslist('all','0'); @@ -531,8 +564,14 @@ sub verifyreceipt { my $receiptparts=0; if ($env{"course.$courseid.receiptalg"} eq 'receipt2') { $receiptparts=1; } my $parts=['0']; - if ($receiptparts) { ($parts)=&response_type($url,$symb); } - foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) { + if ($receiptparts) { ($parts)=&response_type($symb); } + foreach (sort + { + if (lc($$fullname{$a}) ne lc($$fullname{$b})) { + return (lc($$fullname{$a}) cmp lc($$fullname{$b})); + } + return $a cmp $b; + } (keys(%$fullname))) { my ($uname,$udom)=split(/\:/); foreach my $part (@$parts) { if ($receipt eq &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb,$part)) { @@ -553,7 +592,7 @@ sub verifyreceipt { if ($matches == 0) { $string = $title.'No match found for the above receipt.'; } else { - $string = &jscriptNform($url,$symb).$title. + $string = &jscriptNform($symb).$title. 'The above receipt matches the following student'. ($matches <= 1 ? '.' : 's.')."\n". '<table border="0"><tr><td bgcolor="#777777">'."\n". @@ -567,7 +606,7 @@ sub verifyreceipt { $string.='</tr>'."\n".$contents. '</table></td></tr></table>'."\n"; } - return $string.&show_grading_menu_form($symb,$url); + return $string.&show_grading_menu_form($symb); } #--- This is called by a number of programs. @@ -577,7 +616,7 @@ sub verifyreceipt { sub listStudents { my ($request) = shift; - my ($symb,$url) = &get_symb_and_url($request); + my ($symb) = &get_symb($request); my $cdom = $env{"course.$env{'request.course.id'}.domain"}; my $cnum = $env{"course.$env{'request.course.id'}.num"}; my $getsec = $env{'form.section'} eq '' ? 'all' : $env{'form.section'}; @@ -590,7 +629,7 @@ sub listStudents { my $result='<h3><font color="#339933"> '.$viewgrade. ' Submissions for a Student or a Group of Students</font></h3>'; - my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($url,$env{'form.probTitle'},($env{'form.showgrading'} eq 'yes')); + my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($symb,$env{'form.probTitle'},($env{'form.showgrading'} eq 'yes')); $request->print(<<LISTJAVASCRIPT); <script type="text/javascript" language="javascript"> @@ -656,7 +695,6 @@ LISTJAVASCRIPT '<input type="hidden" name="showgrading" value="'.$env{'form.showgrading'}.'" /><br />'."\n". '<input type="hidden" name="saveState" value="'.$env{'form.saveState'}.'" />'."\n". '<input type="hidden" name="probTitle" value="'.$env{'form.probTitle'}.'" />'."\n". - '<input type="hidden" name="url" value="'.$url.'" />'."\n". '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". '<input type="hidden" name="saveStatusOld" value="'.$saveStatus.'" />'."\n"; @@ -685,12 +723,16 @@ LISTJAVASCRIPT while ($loop < 2) { $gradeTable.='<td><b> No.</b> </td><td><b> Select </b></td>'. '<td>'.&nameUserString('header').' Section/Group</td>'; - if ($env{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { + if ($env{'form.showgrading'} eq 'yes' + && $submitonly ne 'queued' + && $submitonly ne 'all') { foreach (sort(@$partlist)) { - my $display_part=&get_display_part((split(/_/))[0],$url,$symb); + my $display_part=&get_display_part((split(/_/))[0],$symb); $gradeTable.='<td><b> Part: '.$display_part. ' Status </b></td>'; } + } elsif ($submitonly eq 'queued') { + $gradeTable.='<td><b> '.&mt('Queue Status').' </b></td>'; } $loop++; # $gradeTable.='<td></td>' if ($loop%2 ==1); @@ -698,11 +740,30 @@ LISTJAVASCRIPT $gradeTable.='</tr>'."\n"; my $ctr = 0; - foreach my $student (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) { + foreach my $student (sort + { + if (lc($$fullname{$a}) ne lc($$fullname{$b})) { + return (lc($$fullname{$a}) cmp lc($$fullname{$b})); + } + return $a cmp $b; + } + (keys(%$fullname))) { my ($uname,$udom) = split(/:/,$student); + my %status = (); - if ($env{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { - (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist); + + if ($submitonly eq 'queued') { + my %queue_status = + &Apache::bridgetask::get_student_status($symb,$cdom,$cnum, + $udom,$uname); + next if (!defined($queue_status{'gradingqueue'})); + $status{'gradingqueue'} = $queue_status{'gradingqueue'}; + } + + if ($env{'form.showgrading'} eq 'yes' + && $submitonly ne 'queued' + && $submitonly ne 'all') { + (%status) =&student_gradeStatus($symb,$udom,$uname,$partlist); my $submitted = 0; my $graded = 0; my $incorrect = 0; @@ -743,7 +804,7 @@ LISTJAVASCRIPT if ($env{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { foreach (sort keys(%status)) { next if (/^resource.*?submitted_by$/); - $gradeTable.='<td align="middle"> '.$status{$_}.' </td>'."\n"; + $gradeTable.='<td align="center"> '.$status{$_}.' </td>'."\n"; } } # $gradeTable.='<td></td>' if ($ctr%2 ==1); @@ -752,10 +813,14 @@ LISTJAVASCRIPT } if ($ctr%2 ==1) { $gradeTable.='<td> </td><td> </td><td> </td>'; - if ($env{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { + if ($env{'form.showgrading'} eq 'yes' + && $submitonly ne 'queued' + && $submitonly ne 'all') { foreach (@$partlist) { $gradeTable.='<td> </td>'; } + } elsif ($submitonly eq 'queued') { + $gradeTable.='<td> </td>'; } $gradeTable.='</tr>'; } @@ -772,6 +837,7 @@ LISTJAVASCRIPT my $submissions='submissions'; if ($submitonly eq 'incorrect') { $submissions = 'incorrect submissions'; } if ($submitonly eq 'graded' ) { $submissions = 'ungraded submissions'; } + if ($submitonly eq 'queued' ) { $submissions = 'queued submissions'; } $gradeTable='<br /> <font color="red">'. 'No '.$submissions.' found for this resource for any students. ('.$num_students. ' students checked for '.$submissions.')</font><br />'; @@ -779,7 +845,7 @@ LISTJAVASCRIPT } elsif ($ctr == 1) { $gradeTable =~ s/type=checkbox/type=checkbox checked/; } - $gradeTable.=&show_grading_menu_form($symb,$url); + $gradeTable.=&show_grading_menu_form($symb); $request->print($gradeTable); return ''; } @@ -1198,7 +1264,7 @@ sub sub_page_kw_js { pDoc.write("<form action=\\"inactive\\" name=\\"msgcenter\\">"); pDoc.write("<input value=\\""+usrctr+"\\" name=\\"usrctr\\" type=\\"hidden\\">"); - pDoc.write("<font color=\\"green\\" size=+1> Compose Message for \"+fullname+\"</font><br><br>"); + pDoc.write("<font color=\\"green\\" size=+1> Compose Message for \"+fullname+\"</font><br /><br />"); pDoc.write("<table border=0 width=100%><tr><td bgcolor=\\"#777777\\">"); pDoc.write("<table border=0 width=100%><tr bgcolor=\\"#ddffff\\">"); @@ -1233,7 +1299,7 @@ sub sub_page_kw_js { pDoc.write("</table>"); pDoc.write("</td></tr></table> "); pDoc.write("<input type=\\"button\\" value=\\"Save\\" onClick=\\"javascript:checkInput()\\"> "); - pDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>"); + pDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br /><br />"); pDoc.write("</form>"); pDoc.write("</body></html>"); pDoc.close(); @@ -1302,7 +1368,7 @@ sub sub_page_kw_js { hDoc.write("</head><body bgcolor=white>"); hDoc.write("<form action=\\"inactive\\" name=\\"hlCenter\\">"); - hDoc.write("<font color=\\"green\\" size=+1> Keyword Highlight Options</font><br><br>"); + hDoc.write("<font color=\\"green\\" size=+1> Keyword Highlight Options</font><br /><br />"); hDoc.write("<table border=0 width=100%><tr><td bgcolor=\\"#777777\\">"); hDoc.write("<table border=0 width=100%><tr bgcolor=\\"#ddffff\\">"); @@ -1326,7 +1392,7 @@ sub sub_page_kw_js { hDoc.write("</table>"); hDoc.write("</td></tr></table> "); hDoc.write("<input type=\\"button\\" value=\\"Save\\" onClick=\\"javascript:updateChoice(1)\\"> "); - hDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>"); + hDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br /><br />"); hDoc.write("</form>"); hDoc.write("</body></html>"); hDoc.close(); @@ -1339,42 +1405,35 @@ SUBJAVASCRIPT #--- displays the grading box, used in essay type problem and grading by page/sequence sub gradeBox { my ($request,$symb,$uname,$udom,$counter,$partid,$record) = @_; - my $checkIcon = '<img src="'.$request->dir_config('lonIconsURL'). '/check.gif" height="16" border="0" />'; - my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb,$udom,$uname); my $wgtmsg = ($wgt > 0 ? '(problem weight)' : '<font color="red">problem weight assigned by computer</font>'); $wgt = ($wgt > 0 ? $wgt : '1'); my $score = ($$record{'resource.'.$partid.'.awarded'} eq '' ? - '' : $$record{'resource.'.$partid.'.awarded'}*$wgt); + '' : &compute_points($$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); - + my $display_part=&get_display_part($partid,$symb); my %last_resets = &get_last_resets($symb,$env{'request.course.id'}, [$partid]); my $aggtries = $$record{'resource.'.$partid.'.tries'}; if ($last_resets{$partid}) { $aggtries = &get_num_tries($record,$last_resets{$partid},$partid); } - $result.='<table border="0"><tr><td>'. '<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 while ($ctr<=$wgt) { - $result.= '<td><nobr><input type="radio" name="RADVAL'.$counter.'_'.$partid.'" '. + $result.= '<td><nobr><label><input type="radio" name="RADVAL'.$counter.'_'.$partid.'" '. 'onclick="javascript:writeBox(this.form,\''.$counter.'_'.$partid.'\','. $ctr.')" value="'.$ctr.'" '. - ($score eq $ctr ? 'checked':'').' /> '.$ctr."</nobr></td>\n"; + ($score eq $ctr ? 'checked':'').' /> '.$ctr."</label></nobr></td>\n"; $result.=(($ctr+1)%10 == 0 ? '</tr><tr>' : ''); $ctr++; } $result.='</tr></table>'; - $result.='</td><td> <b>or</b> </td>'."\n"; $result.='<td><input type="text" name="GD_BOX'.$counter.'_'.$partid.'"'. ($score ne ''? ' value = "'.$score.'"':'').' size="4" '. @@ -1383,7 +1442,6 @@ sub gradeBox { $result.='<td>/'.$wgt.' '.$wgtmsg. ($$record{'resource.'.$partid.'.solved'} eq 'correct_by_student' ? ' '.$checkIcon : ''). ' </td><td>'."\n"; - $result.='<select name="GD_SEL'.$counter.'_'.$partid.'" '. 'onChange="javascript:clearRadBox(this.form,\''.$counter.'_'.$partid.'\')" >'."\n"; if ($$record{'resource.'.$partid.'.solved'} eq 'excused') { @@ -1404,12 +1462,42 @@ sub gradeBox { '<input type="hidden" name="aggtries'.$counter.'_'.$partid.'" value="'. $aggtries.'" />'."\n"; $result.='</td></tr></table>'."\n"; + $result.=&handback_box($symb,$uname,$udom,$counter,$partid,$record); return $result; } +sub handback_box { + my ($symb,$uname,$udom,$counter,$partid,$record) = @_; + my ($partlist,$handgrade,$responseType) = &response_type($symb); + my (@respids); + foreach my $part_resp (sort(keys(%$handgrade))) { + my ($part,$resp) = split(/_/,$part_resp); + if ($part eq $partid) { + push @respids,$resp; + } + } + my $result; + foreach my $respid (@respids) { + my $prefix = $counter.'_'.$partid.'_'.$respid.'_'; + my $files=&get_submitted_files($udom,$uname,$partid,$respid,$record); + next if (!@$files); + my $file_counter = 1; + foreach my $file (@$files) { + my ($file_disp) = ($file =~ m|.+/(.+)$|); + $result.=&mt('Return commented version of [_1] to student.', + '<span class="filename">'.$file_disp.'</span>'); + $result.='<input type="file" name="'.$prefix.'returndoc'.$file_counter.'" />'."\n"; + $result.='<input type="hidden" name="'.$prefix.'origdoc'.$file_counter.'" value="'.$file.'" /><br />'; + $file_counter++; + } + } + return $result; +} + sub show_problem { my ($request,$symb,$uname,$udom,$removeform,$viewon,$mode) = @_; my $rendered; + &Apache::lonxml::remember_problem_counter(); if ($mode eq 'both' or $mode eq 'text') { $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom, $env{'request.course.id'}); @@ -1421,6 +1509,7 @@ sub show_problem { } my $companswer; if ($mode eq 'both' or $mode eq 'answer') { + &Apache::lonxml::restore_problem_counter(); $companswer=&Apache::loncommon::get_student_answers($symb,$uname,$udom, $env{'request.course.id'}); } @@ -1457,20 +1546,19 @@ sub show_problem { sub submission { my ($request,$counter,$total) = @_; - (my $url=$env{'form.url'})=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--; 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'} = &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 ''; } + my $symb = &get_symb($request); + if ($symb eq '') { $request->print("Unable to handle ambiguous references:."); return ''; } if (!&canview($usec)) { $request->print('<font color="red">Unable to view requested student.('. $uname.'@'.$udom.' in section '.$usec.' in course id '. $env{'request.course.id'}.')</font>'); - $request->print(&show_grading_menu_form($symb,$url)); + $request->print(&show_grading_menu_form($symb)); return; } @@ -1508,6 +1596,7 @@ sub submission { } elsif ($env{'form.vAns'} eq 'yes') { $mode='answer'; } + &Apache::lonxml::clear_problem_counter(); $request->print(&show_problem($request,$symb,$uname,$udom,0,1,$mode)); } @@ -1530,7 +1619,7 @@ sub submission { } my $overRideScore = $env{'form.overRideScore'} eq '' ? 'no' : $env{'form.overRideScore'}; - $request->print('<form action="/adm/grades" method="post" name="SCORE">'."\n". + $request->print('<form action="/adm/grades" method="post" name="SCORE" enctype="multipart/form-data">'."\n". '<input type="hidden" name="command" value="handgrade" />'."\n". '<input type="hidden" name="saveState" value="'.$env{'form.saveState'}.'" />'."\n". '<input type="hidden" name="Status" value="'.$env{'form.Status'}.'" />'."\n". @@ -1540,14 +1629,13 @@ sub submission { '<input type="hidden" name="studentNo" value="" />'."\n". '<input type="hidden" name="gradeOpt" value="" />'."\n". '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". - '<input type="hidden" name="url" value="'.$url.'" />'."\n". '<input type="hidden" name="showgrading" value="'.$env{'form.showgrading'}.'" />'."\n". '<input type="hidden" name="vProb" value="'.$env{'form.vProb'}.'" />'."\n". '<input type="hidden" name="vAns" value="'.$env{'form.vAns'}.'" />'."\n". '<input type="hidden" name="lastSub" value="'.$env{'form.lastSub'}.'" />'."\n". - '<input type="hidden" name="section" value="'.$env{'form.section'}.'">'."\n". - '<input type="hidden" name="submitonly" value="'.$env{'form.submitonly'}.'">'."\n". - '<input type="hidden" name="handgrade" value="'.$env{'form.handgrade'}.'">'."\n". + '<input type="hidden" name="section" value="'.$env{'form.section'}.'" />'."\n". + '<input type="hidden" name="submitonly" value="'.$env{'form.submitonly'}.'" />'."\n". + '<input type="hidden" name="handgrade" value="'.$env{'form.handgrade'}.'" />'."\n". '<input type="hidden" name="NCT"'. ' value="'.($env{'form.NTSTU'} ne '' ? $env{'form.NTSTU'} : $total+1).'" />'."\n"); if ($env{'form.handgrade'} eq 'yes') { @@ -1589,7 +1677,7 @@ KEYWORDS # # Load the other essays for similarity check # - my $essayurl=&Apache::lonnet::declutter($url); + my (undef,undef,$essayurl) = &Apache::lonnet::decode_symb($symb); my ($adom,$aname,$apath)=($essayurl=~/^(\w+)\/(\w+)\/(.*)$/); $apath=&Apache::lonnet::escape($apath); $apath=~s/\W/\_/gs; @@ -1607,16 +1695,17 @@ KEYWORDS } elsif ($env{'form.vAns'} eq 'all') { $mode='answer'; } + &Apache::lonxml::clear_problem_counter(); $request->print(&show_problem($request,$symb,$uname,$udom,1,1,$mode)); } my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname); - my ($partlist,$handgrade,$responseType) = &response_type($url,$symb); + my ($partlist,$handgrade,$responseType) = &response_type($symb); # Display student info $request->print(($counter == 0 ? '' : '<br />')); - my $result='<table border="0" width=100%><tr><td bgcolor="#777777">'."\n". - '<table border="0" width=100%><tr bgcolor="#edffff"><td>'."\n"; + my $result='<table border="0" width="100%"><tr><td bgcolor="#777777">'."\n". + '<table border="0" width="100%"><tr bgcolor="#edffff"><td>'."\n"; $result.='<b>Fullname: </b>'.&nameUserString(undef,$env{'form.fullname'},$uname,$udom).'<br />'."\n"; $result.='<input type="hidden" name="name'.$counter. @@ -1697,7 +1786,7 @@ KEYWORDS my %seenparts; for my $part (sort keys(%$handgrade)) { my ($partid,$respid) = split(/_/,$part); - my $display_part=&get_display_part($partid,$url,$symb); + my $display_part=&get_display_part($partid,$symb); if ($env{"form.$uname:$udom:$partid:submitted_by"}) { if (exists($seenparts{$partid})) { next; } $seenparts{$partid}=1; @@ -1741,28 +1830,18 @@ KEYWORDS if ($env{'form.lastSub'} eq 'lastonly' || ($env{'form.lastSub'} eq 'hdgrade' && $$handgrade{$part} eq 'yes')) { - my $display_part=&get_display_part($partid,$url,$symb); + my $display_part=&get_display_part($partid,$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"}) { - push(@files,$record{"resource.$partid.$respid.uploadedurl"}); - } - if (@files) { + my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record); + 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) { + my $file_counter = 0; + foreach my $file (@$files) { + $file_counter ++; &Apache::lonnet::allowuploaded('/adm/grades',$file); - $lastsubonly.='<br /><a href="'.$file.'" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border=0"> '.$file.'</a>'; + $lastsubonly.='<br /><a href="'.$file.'" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0"> '.$file.'</a>'; } $lastsubonly.='<br />'; } @@ -1777,7 +1856,7 @@ KEYWORDS $lastsubonly.='</td></tr><tr bgcolor="#ffffff"><td>'."\n"; $request->print($lastsubonly); } elsif ($env{'form.lastSub'} eq 'datesub') { - my (undef,$responseType,undef,$parts) = &showResourceInfo($url); + my (undef,$responseType,undef,$parts) = &showResourceInfo($symb); $request->print(&displaySubByDates($symb,\%record,$parts,$responseType,$checkIcon,$uname,$udom)); } elsif ($env{'form.lastSub'} =~ /^(last|all)$/) { $request->print(&Apache::loncommon::get_previous_attempt($symb,$uname,$udom, @@ -1797,7 +1876,7 @@ KEYWORDS $toGrade.='</td></tr></table></td></tr></table>'."\n"; if (($env{'form.command'} eq 'submission') || ($env{'form.command'} eq 'processGroup' && $counter == $total)) { - $toGrade.='</form>'.&show_grading_menu_form($symb,$url) + $toGrade.='</form>'.&show_grading_menu_form($symb); } $request->print($toGrade); return; @@ -1818,25 +1897,35 @@ KEYWORDS '<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n"; $result.=' <a href="javascript:msgCenter(document.SCORE,'.$counter. ',\''.$msgfor.'\')"; TARGET=_self>'. - 'Compose Message to student'.(scalar(@col_fullnames) >= 1 ? 's' : '').'</a> '. + &mt('Compose message to student').(scalar(@col_fullnames) >= 1 ? 's' : '').'</a> ('. + &mt('incl. grades').' <input type="checkbox" name="withgrades'.$counter.'" />)'. '<img src="'.$request->dir_config('lonIconsURL'). '/mailbkgrd.gif" width="14" height="10" name="mailicon'.$counter.'" />'."\n". - '<br /> (Message will be sent when you click on Save & Next below.)'."\n" - if ($env{'form.handgrade'} eq 'yes'); + '<br /> ('. + &mt('Message will be sent when you click on Save & Next below.').")\n"; $request->print($result); } + if ($perm{'vgr'}) { + $request->print('<br />'. + &Apache::loncommon::track_student_link(&mt('View recent activity'), + $uname,$udom,'check')); + } + if ($perm{'opa'}) { + $request->print('<br />'. + &Apache::loncommon::pprmlink(&mt('Set/Change parameters'), + $uname,$udom,$symb,'check')); + } my %seen = (); my @partlist; my @gradePartRespid; - for (sort keys(%$handgrade)) { - my ($partid,$respid) = split(/_/); + for my $part_resp (sort(keys(%$handgrade))) { + my ($partid,$respid) = split(/_/, $part_resp); next if ($seen{$partid} > 0); $seen{$partid}++; - next if ($$handgrade{$_} =~ /:no$/ && $env{'form.lastSub'} =~ /^(hdgrade)$/); + next if ($$handgrade{$part_resp} =~ /:no$/ && $env{'form.lastSub'} =~ /^(hdgrade)$/); push @partlist,$partid; push @gradePartRespid,$partid.'.'.$respid; - $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record)); } $result='<input type="hidden" name="partlist'.$counter. @@ -1870,7 +1959,7 @@ KEYWORDS 'onClick="javascript:checksubmit(this.form,\'Next\');" TARGET=_self> '; $endform.='(Next and Previous (student) do not save the scores.)'."\n" ; $endform.='</td><tr></table></form>'; - $endform.=&show_grading_menu_form($symb,$url); + $endform.=&show_grading_menu_form($symb); $request->print($endform); } return ''; @@ -1918,16 +2007,19 @@ sub keywords_highlight { #--- Called from submission routine sub processHandGrade { my ($request) = shift; - my $url = $env{'form.url'}; - my $symb = $env{'form.symb'}; + my $symb = &get_symb($request); + my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb); my $button = $env{'form.gradeOpt'}; my $ngrade = $env{'form.NCT'}; my $ntstu = $env{'form.NTSTU'}; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + if ($button eq 'Save & Next') { my $ctr = 0; while ($ctr < $ngrade) { my ($uname,$udom) = split(/:/,$env{'form.unamedom'.$ctr}); - my ($errorflag,$pts,$wgt) = &saveHandGrade($request,$url,$symb,$uname,$udom,$ctr); + my ($errorflag,$pts,$wgt) = &saveHandGrade($request,$symb,$uname,$udom,$ctr); if ($errorflag eq 'no_score') { $ctr++; next; @@ -1940,35 +2032,40 @@ sub processHandGrade { my $includemsg = $env{'form.includemsg'.$ctr}; my ($subject,$message,$msgstatus) = ('','',''); if ($includemsg =~ /savemsg|newmsg\Q$ctr\E/) { - $subject = $env{'form.msgsub'} if ($includemsg =~ /^msgsub/); + $subject = $env{'form.msgsub'} if ($includemsg =~ /msgsub/); + unless ($subject=~/\w/) { $subject=&mt('Grading Feedback'); } my (@msgnum) = split(/,/,$includemsg); foreach (@msgnum) { $message.=$env{'form.'.$_} if ($_ =~ /savemsg|newmsg/ && $_ ne ''); } $message =&Apache::lonfeedback::clear_out_html($message); - $message.="\n\nPoint".($pts > 1 ? 's':'').' awarded = '.$pts.' out of '.$wgt; - $message.=" for <a href=\"". + if ($env{'form.withgrades'.$ctr}) { + $message.="\n\nPoint".($pts > 1 ? 's':'').' awarded = '.$pts.' out of '.$wgt; + $message.=" for <a href=\"". &Apache::lonnet::clutter($url). "?symb=$symb\">$env{'form.probTitle'}</a>"; - $msgstatus = &Apache::lonmsg::user_normal_msg ($uname,$udom, - $env{'form.msgsub'},$message); + } + $msgstatus = &Apache::lonmsg::user_normal_msg($uname,$udom, + $subject.' ['. + &Apache::lonnet::declutter($url).']',$message); + $request->print('<br />'.&mt('Sending message to [_1]@[_2]',$uname,$udom).': '. + $msgstatus); } if ($env{'form.collaborator'.$ctr}) { my @collabstrs=&Apache::loncommon::get_env_multiple("form.collaborator$ctr"); foreach my $collabstr (@collabstrs) { my ($part,@collaborators) = split(/:/,$collabstr); - foreach (@collaborators) { + foreach my $collaborator (@collaborators) { my ($errorflag,$pts,$wgt) = - &saveHandGrade($request,$url,$symb,$_,$udom,$ctr, + &saveHandGrade($request,$symb,$collaborator,$udom,$ctr, $env{'form.unamedom'.$ctr},$part); if ($errorflag eq 'not_allowed') { - $request->print("<font color=\"red\">Not allowed to modify grades for $_:$udom</font>"); + $request->print("<font color=\"red\">Not allowed to modify grades for $collaborator:$udom</font>"); next; } else { if ($message ne '') { - $msgstatus = &Apache::lonmsg::user_normal_msg($_,$udom,$env{'form.msgsub'},$message); + $msgstatus = &Apache::lonmsg::user_normal_msg($collaborator,$udom,$env{'form.msgsub'},$message); } - } } } @@ -2014,9 +2111,7 @@ sub processHandGrade { $env{'form.savemsgN'} = --$idx; $keyhash{$symb.'_savemsgN'} = $env{'form.savemsgN'}; my $putresult = &Apache::lonnet::put - ('nohist_handgrade',\%keyhash, - $env{'course.'.$env{'request.course.id'}.'.domain'}, - $env{'course.'.$env{'request.course.id'}.'.num'}); + ('nohist_handgrade',\%keyhash,$cdom,$cnum); } # Called by Save & Refresh from Highlight Attribute Window my (undef,undef,$fullname) = &getclasslist($env{'form.section'},'1'); @@ -2040,7 +2135,7 @@ sub processHandGrade { # Go directly to grade student - from submission or link from chart page if ($button eq 'Grade Student') { - (undef,undef,$env{'form.handgrade'},undef,undef) = &showResourceInfo($url); + (undef,undef,$env{'form.handgrade'},undef,undef) = &showResourceInfo($symb); my $processUser = $env{'form.unamedom'.$env{'form.studentNo'}}; ($env{'form.student'},$env{'form.userdom'}) = split(/:/,$processUser); $env{'form.fullname'} = $$fullname{$processUser}; @@ -2060,7 +2155,13 @@ sub processHandGrade { my (@parsedlist,@nextlist); my ($nextflg) = 0; - foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) { + foreach (sort + { + if (lc($$fullname{$a}) ne lc($$fullname{$b})) { + return (lc($$fullname{$a}) cmp lc($$fullname{$b})); + } + return $a cmp $b; + } (keys(%$fullname))) { if ($nextflg == 1 && $button =~ /Next$/) { push @parsedlist,$_; } @@ -2072,13 +2173,21 @@ sub processHandGrade { } $ctr = 0; @parsedlist = reverse @parsedlist if ($button eq 'Previous'); - my ($partlist) = &response_type($url); + my ($partlist) = &response_type($symb); foreach my $student (@parsedlist) { my $submitonly=$env{'form.submitonly'}; my ($uname,$udom) = split(/:/,$student); + + if ($submitonly eq 'queued') { + my %queue_status = + &Apache::bridgetask::get_student_status($symb,$cdom,$cnum, + $udom,$uname); + next if (!defined($queue_status{'gradingqueue'})); + } + if ($submitonly =~ /^(yes|graded|incorrect)$/) { # my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname); - my %status=&student_gradeStatus($url,$symb,$udom,$uname,$partlist); + my %status=&student_gradeStatus($symb,$udom,$uname,$partlist); my $submitted = 0; my $ungraded = 0; my $incorrect = 0; @@ -2117,7 +2226,7 @@ sub processHandGrade { my $the_end = '<h3><font color="red">LON-CAPA User Message</font></h3><br />'."\n"; $the_end.='<b>Message: </b> No more students for this section or class.<br /><br />'."\n"; $the_end.='Click on the button below to return to the grading menu.<br /><br />'."\n"; - $the_end.=&show_grading_menu_form ($symb,$url); + $the_end.=&show_grading_menu_form($symb); $request->print($the_end); } return ''; @@ -2125,7 +2234,7 @@ sub processHandGrade { #---- Save the score and award for each student, if changed sub saveHandGrade { - my ($request,$url,$symb,$stuname,$domain,$newflg,$submitter,$part) = @_; + my ($request,$symb,$stuname,$domain,$newflg,$submitter,$part) = @_; my @v_flag; my $usec = &Apache::lonnet::getsection($domain,$stuname, $env{'request.course.id'}); @@ -2136,7 +2245,9 @@ sub saveHandGrade { my ($pts,$wgt) = ('',''); my %aggregate = (); my $aggregateflag = 0; - foreach my $new_part (split(/:/,$env{'form.partlist'.$newflg})) { + + my @parts = split(/:/,$env{'form.partlist'.$newflg}); + foreach my $new_part (@parts) { #collaborator may vary for different parts if ($submitter && $new_part ne $part) { next; } my $dropMenu = $env{'form.GD_SEL'.$newflg.'_'.$new_part}; @@ -2167,7 +2278,7 @@ sub saveHandGrade { my $solvedstatus = $record{'resource.'.$new_part.'.solved'}; if ($aggtries > 0) { - &decrement($symb,$new_part,\%aggregate,$aggtries,$totaltries,$solvedstatus); + &decrement_aggs($symb,$new_part,\%aggregate,$aggtries,$totaltries,$solvedstatus); $aggregateflag = 1; } } elsif ($dropMenu eq '') { @@ -2206,24 +2317,81 @@ sub saveHandGrade { $newrecord{'resource.'.$new_part.'.regrader'}= "$env{'user.name'}:$env{'user.domain'}"; } + my ($partlist,$handgrade,$responseType) = &response_type($symb); + foreach my $part_resp (sort(keys(%$handgrade))) { + my ($part_id, $resp_id) = split(/_/,$part_resp); + if (($env{'form.'.$newflg.'_'.$part_resp.'_returndoc1'}) && ($new_part == $part_id)) { + # if multiple files are uploaded names will be 'returndoc2','returndoc3' + my $file_counter = 1; + while ($env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$file_counter}) { + my $fname=$env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$file_counter.'.filename'}; + $newrecord{"resource.$new_part.$resp_id.handback"} = $env{'form.returndocorig'.$file_counter}; + # set the filename to match the submitted file name + $env{'form.'.$newflg.'_'.$part_resp.'_returndoc1.filename'} = $env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$file_counter}; + my $result=&Apache::lonnet::userfileupload($newflg.'_'.$part_resp.'_returndoc'.$file_counter,'', + 'portfolio',undef,undef,undef,$stuname,$domain); + if ($result !~ m|^/uploaded/|) { + $request->print('<font color="red"> An errror occured ('.$result. + ') while trying to upload '.&display_file().'</font><br />'); + # $request->print(&done('Back')); + } + $request->print("<br />".$fname." will be the uploaded file name"); + $request->print("<font color=\"red\">Will upload document</font>".$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$file_counter}); + $file_counter++; + } + } + } + # unless problem has been graded, set flag to version the submitted files - unless ($record{'resource.'.$new_part.'.solved'} =~ /^correct_/ || $record{'resource.'.$new_part.'.solved'} eq 'incorrect_by_override') { + unless ($record{'resource.'.$new_part.'.solved'} =~ /^correct_/ || + $record{'resource.'.$new_part.'.solved'} eq 'incorrect_by_override' || + $dropMenu eq 'reset status') + { push (@v_flag,$new_part); } } + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + if (scalar(keys(%newrecord)) > 0) { if (scalar(@v_flag)) { &version_portfiles(\%record, \@parts_graded, $env{'request.course.id'}, $symb, $domain, $stuname, \@v_flag); } &Apache::lonnet::cstore(\%newrecord,$symb, $env{'request.course.id'},$domain,$stuname); + + my @ungraded_parts; + foreach my $part (@parts) { + if ( !defined($record{'resource.'.$part.'.awarded'}) + && !defined($newrecord{'resource.'.$part.'.awarded'}) ) { + push(@ungraded_parts, $part); + } + } + if ( !@ungraded_parts ) { + &Apache::bridgetask::remove_from_queue('gradingqueue',$symb,$cdom, + $cnum,$domain,$stuname); + } } if ($aggregateflag) { &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, - $env{'course.'.$env{'request.course.id'}.'.domain'}, - $env{'course.'.$env{'request.course.id'}.'.num'}); + $cdom,$cnum); } - return '',$pts,$wgt; + return ('',$pts,$wgt); +} + +sub get_submitted_files { + my ($udom,$uname,$partid,$respid,$record) = @_; + 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); + } + } + if ($$record{"resource.$partid.$respid.uploadedurl"}) { + push(@files,$$record{"resource.$partid.$respid.uploadedurl"}); + } + return (\@files); } # ----------- Provides number of tries since last reset. @@ -2273,76 +2441,108 @@ sub get_last_resets { my %last_resets; my $cdom = $env{'course.'.$courseid.'.domain'}; my $cname = $env{'course.'.$courseid.'.num'}; - my %resethash = &Apache::lonnet::restore($symb,'nohist_resourcetracker', - $cdom,$cname); - if ($resethash{'version'}) { - foreach my $part (@{$partids}) { - $last_resets{$part} = ''; - for (my $version=$resethash{'version'};$version>=1;$version--) { - if (exists($resethash{$version.':'.$part."\0".'prev_attempts'})) { - $last_resets{$part} = $resethash{$version.':timestamp'}; - last; - } - } - } + my @keys; + foreach my $part (@{$partids}) { + push(@keys,"$symb\0$part\0resettime"); + } + my %results=&Apache::lonnet::get('nohist_resourcetracker',\@keys, + $cdom,$cname); + foreach my $part (@{$partids}) { + $last_resets{$part}=$results{"$symb\0$part\0resettime"}; } return %last_resets; } # ----------- Handles creating versions for portfolio files as answers sub version_portfiles { - my ($record, $parts_graded, $courseid, $symb, $domain, $stuname, $v_flag) = @_; + my ($record, $parts_graded, $courseid, $symb, $domain, $stu_name, $v_flag) = @_; my $version_parts = join('|',@$v_flag); my $parts = join('|', @$parts_graded); my $portfolio_root = &Apache::loncommon::propath($domain, - $stuname). + $stu_name). '/userfiles/portfolio'; - foreach my $key(keys %$record) { + foreach my $key (keys(%$record)) { my $new_portfiles; if ($key =~ /^resource\.($version_parts)\./ && $key =~ /\.portfiles$/ ) { my @v_portfiles; my @portfiles = split(/,/,$$record{$key}); - # &Apache::lonnet::logthis("should be unmarking and remarking"); foreach my $file (@portfiles) { - &Apache::lonnet::unmark_as_readonly($domain,$stuname,[$symb,$env{'request.course.id'}],$file); - my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*$)/); + &Apache::lonnet::unmark_as_readonly($domain,$stu_name,[$symb,$env{'request.course.id'}],$file); + my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*)$/); my $version = 0; - my @answer_file_parts = split(/\./, $answer_file); - my @dir_list = &Apache::lonnet::dirlist($directory,$domain,$stuname,$portfolio_root); - my @file_names; - my @file_name_parts; - foreach my $row (@dir_list) { - @file_names = split(/\&/,$row,2); - @file_name_parts = split(/\./, $file_names[0]); - # ($file_name_parts[scalar @file_name_parts] eq $answer_file_parts[scalar @answer_file_parts]) - if (($file_name_parts[0] eq $answer_file_parts[0]) && - ($file_name_parts[-1] eq $answer_file_parts[-1])) { - # gets here if filename and extension match, regardless of version - if (scalar @file_name_parts == 3) { # a versioned file is found - # so save it for later - if ($file_name_parts[1] > $version) {$version = $file_name_parts[1]}; - } - } - } - $version++; - my $home_server = &Apache::lonnet::homeserver($stuname,$domain,undef); - $env{'form.copy'} = &Apache::lonnet::getfile("/uploaded/$domain/$stuname/portfolio$directory$answer_file"); - if($env{'form.copy'} eq '-1') { - &Apache::lonnet::logthis('problem getting file '.$directory.$answer_file); - } else { - my $copy_result = &Apache::lonnet::finishuserfileupload($stuname,$domain,$home_server,'copy', - '/portfolio'.$directory.$answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]); - push(@v_portfiles, $answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]); - &Apache::lonnet::mark_as_readonly($domain,$stuname, - ['/portfolio'.$directory.$answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]], - [$symb,$env{'request.course.id'},'graded']); + my ($answer_name,$answer_ver,$answer_ext) = + &file_name_version_ext($answer_file); + my @dir_list = &Apache::lonnet::dirlist($directory,$domain,$stu_name,$portfolio_root); + $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(@v_portfiles, $directory.$new_answer); + &Apache::lonnet::mark_as_readonly($domain,$stu_name, + ['/portfolio'.$directory.$new_answer], + [$symb,$env{'request.course.id'},'graded']); } + } $$record{$key} = join(',',@v_portfiles); } } return 'ok'; - +} + +sub get_next_version { + my ($answer_name, $answer_ext, $dir_list); + my $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; + } + } + } + } + $version ++; + return($version); +} + +sub version_selected_portfile { + my ($domain,$stu_name,$directory,$file_name,$version) = @_; + my ($answer_name,$answer_ver,$answer_ext) = + &file_name_version_ext($file_name); + my $new_answer; + $env{'form.copy'} = &Apache::lonnet::getfile("/uploaded/$domain/$stu_name/portfolio$directory$file_name"); + if($env{'form.copy'} eq '-1') { + &Apache::lonnet::logthis('problem getting file '.$file_name); + $new_answer = 'problem getting file'; + } else { + $new_answer = $answer_name.'.'.$version.'.'.$answer_ext; + my $copy_result = &Apache::lonnet::finishuserfileupload( + $stu_name,$domain,'copy', + '/portfolio'.$directory.$new_answer); + } + return ($new_answer); +} + +sub file_name_version_ext { + my ($file)=@_; + my @file_parts = split(/\./, $file); + my ($name,$version,$ext); + if (@file_parts > 1) { + $ext=pop(@file_parts); + if (@file_parts > 1 && $file_parts[-1] =~ /^\d+$/) { + $version=pop(@file_parts); + } + $name=join('.',@file_parts); + } else { + $name=join('.',@file_parts); + } + return($name,$version,$ext); } #-------------------------------------------------------------------------------------- @@ -2394,6 +2594,7 @@ sub viewgrades_js { } for (i=0;i<document.classgrade.total.value;i++) { var user = document.classgrade["ctr"+i].value; + user = user.replace(new RegExp(':', 'g'),"_"); var scorename = document.classgrade["GD_"+user+"_"+partid+"_awarded"]; var saveval = document.classgrade["GD_"+user+"_"+partid+"_solved_s"].value; var selname = document.classgrade["GD_"+user+"_"+partid+"_solved"]; @@ -2421,6 +2622,7 @@ sub viewgrades_js { for (i=0;i<document.classgrade.total.value;i++) { var user = document.classgrade["ctr"+i].value; + user = user.replace(new RegExp(':', 'g'),"_"); var scorename = document.classgrade["GD_"+user+"_"+partid+"_awarded"]; var saveval = document.classgrade["GD_"+user+"_"+partid+"_solved_s"].value; var selname = document.classgrade["GD_"+user+"_"+partid+"_solved"]; @@ -2438,6 +2640,7 @@ sub viewgrades_js { } else { for (i=0;i<document.classgrade.total.value;i++) { var user = document.classgrade["ctr"+i].value; + user = user.replace(new RegExp(':', 'g'),"_"); var scorename = document.classgrade["GD_"+user+"_"+partid+"_awarded"]; var saveval = document.classgrade["GD_"+user+"_"+partid+"_solved_s"].value; var selname = document.classgrade["GD_"+user+"_"+partid+"_solved"]; @@ -2496,6 +2699,7 @@ sub viewgrades_js { for (i=0;i<document.classgrade.total.value;i++) { var user = document.classgrade["ctr"+i].value; + user = user.replace(new RegExp(':', 'g'),"_"); var resetscore = document.classgrade["GD_"+user+"_"+partid+"_awarded"]; resetscore.value = document.classgrade["GD_"+user+"_"+partid+"_awarded_s"].value; var resettries = document.classgrade["GD_"+user+"_"+partid+"_tries"]; @@ -2520,7 +2724,7 @@ sub viewgrades { my ($request) = shift; &viewgrades_js($request); - my ($symb,$url) = ($env{'form.symb'},$env{'form.url'}); + my ($symb) = &get_symb($request); #need to make sure we have the correct data for later EXT calls, #thus invalidate the cache &Apache::lonnet::devalidatecourseresdata( @@ -2532,12 +2736,11 @@ sub viewgrades { $result.='<font size=+1><b>Current Resource: </b>'.$env{'form.probTitle'}.'</font>'."\n"; #view individual student submission form - called using Javascript viewOneStudent - $result.=&jscriptNform($url,$symb); + $result.=&jscriptNform($symb); #beginning of class grading form $result.= '<form action="/adm/grades" method="post" name="classgrade">'."\n". '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". - '<input type="hidden" name="url" value="'.$url.'" />'."\n". '<input type="hidden" name="command" value="editgrades" />'."\n". '<input type="hidden" name="section" value="'.$env{'form.section'}.'" />'."\n". '<input type="hidden" name="saveState" value="'.$env{'form.saveState'}.'" />'."\n". @@ -2557,7 +2760,7 @@ sub viewgrades { '<table border=0><tr bgcolor="#ffffdd"><td>'; #radio buttons/text box for assigning points for a section or class. #handles different parts of a problem - my ($partlist,$handgrade) = &response_type($url,$symb); + my ($partlist,$handgrade) = &response_type($symb); my %weight = (); my $ctsparts = 0; $result.='<table border="0">'; @@ -2574,14 +2777,14 @@ sub viewgrades { $ctsparts.'" value="'.$partid.'" />'."\n"; $result.='<input type="hidden" name="weight_'. $partid.'" value="'.$weight{$partid}.'" />'."\n"; - my $display_part=&get_display_part($partid,$url,$symb); + my $display_part=&get_display_part($partid,$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 - $result.= '<td><input type="radio" name="RADVAL_'.$partid.'" '. + $result.= '<td><label><input type="radio" name="RADVAL_'.$partid.'" '. 'onclick="javascript:writePoint(\''.$partid.'\','.$weight{$partid}. - ','.$ctr.')" />'.$ctr."</td>\n"; + ','.$ctr.')" />'.$ctr."</label></td>\n"; $result.=(($ctr+1)%10 == 0 ? '</tr><tr>' : ''); $ctr++; } @@ -2610,7 +2813,8 @@ sub viewgrades { $result.= '<table border=0><tr><td bgcolor="#777777">'."\n". '<table border=0><tr bgcolor="#deffff"><td> <b>No.</b> </td>'. '<td>'.&nameUserString('header')."</td>\n"; - my (@parts) = sort(&getpartlist($url,$symb)); + my (@parts) = sort(&getpartlist($symb)); + my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb); my @partids = (); foreach my $part (@parts) { my $display=&Apache::lonnet::metadata($url,$part.'.display'); @@ -2618,7 +2822,7 @@ sub viewgrades { if (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); } my ($partid) = &split_part_type($part); push(@partids, $partid); - my $display_part=&get_display_part($partid,$url,$symb); + my $display_part=&get_display_part($partid,$symb); if ($display =~ /^Partial Credit Factor/) { $result.='<td><b>Score Part:</b> '.$display_part. ' <br /><b>(weight = '.$weight{$partid}.')</b></td>'."\n"; @@ -2638,9 +2842,15 @@ sub viewgrades { #list all the students - with points and grade status my (undef,undef,$fullname) = &getclasslist($env{'form.section'},'1'); my $ctr = 0; - foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) { + foreach (sort + { + if (lc($$fullname{$a}) ne lc($$fullname{$b})) { + return (lc($$fullname{$a}) cmp lc($$fullname{$b})); + } + return $a cmp $b; + } (keys(%$fullname))) { $ctr++; - $result.=&viewstudentgrade($url,$symb,$env{'request.course.id'}, + $result.=&viewstudentgrade($symb,$env{'request.course.id'}, $_,$$fullname{$_},\@parts,\%weight,$ctr,\%last_resets); } $result.='</table></td></tr></table>'; @@ -2652,15 +2862,14 @@ sub viewgrades { $result='<font color="red">There are no students in section "'.$env{'form.section'}. '" with enrollment status "'.$env{'form.Status'}.'" to modify or grade.</font>'; } - $result.=&show_grading_menu_form($symb,$url); + $result.=&show_grading_menu_form($symb); return $result; } #--- call by previous routine to display each student sub viewstudentgrade { - my ($url,$symb,$courseid,$student,$fullname,$parts,$weight,$ctr,$last_resets) = @_; + my ($symb,$courseid,$student,$fullname,$parts,$weight,$ctr,$last_resets) = @_; my ($uname,$udom) = split(/:/,$student); - $student=~s/:/_/; my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname); my %aggregates = (); my $result='<tr bgcolor="#ffffdd"><td align="right">'. @@ -2669,10 +2878,11 @@ sub viewstudentgrade { '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom. '\')"; TARGET=_self>'.$fullname.'</a> '. '<font color="#999999">('.$uname.($env{'user.domain'} eq $udom ? '' : ':'.$udom).')</font></td>'."\n"; + $student=~s/:/_/; # colon doen't work in javascript for names foreach my $apart (@$parts) { my ($part,$type) = &split_part_type($apart); my $score=$record{"resource.$part.$type"}; - $result.='<td align="middle">'; + $result.='<td align="center">'; my ($aggtries,$totaltries); unless (exists($aggregates{$part})) { $totaltries = $record{'resource.'.$part.'.tries'}; @@ -2689,7 +2899,7 @@ sub viewstudentgrade { $aggregates{$part} = 1; } if ($type eq 'awarded') { - my $pts = $score eq '' ? '' : $score*$$weight{$part}; + my $pts = $score eq '' ? '' : &compute_points($score,$$weight{$part}); $result.='<input type="hidden" name="'. 'GD_'.$student.'_'.$part.'_awarded_s" value="'.$pts.'" />'."\n"; $result.='<input type="text" name="'. @@ -2726,8 +2936,7 @@ sub viewstudentgrade { sub editgrades { my ($request) = @_; - my $symb=$env{'form.symb'}; - my $url =$env{'form.url'}; + my $symb=&get_symb($request); my $title='<h3><font color="#339933">Current Grade Status</font></h3>'; $title.='<font size=+1><b>Current Resource: </b>'.$env{'form.probTitle'}.'</font><br />'."\n"; $title.='<font size=+1><b>Section: </b>'.$env{'form.section'}.'</font>'."\n"; @@ -2751,7 +2960,7 @@ sub editgrades { my %columns = (); my ($i,$ctr,$count,$rec_update) = (0,0,0,0); - my (@parts) = sort(&getpartlist($url,$symb)); + my (@parts) = sort(&getpartlist($symb)); my $header; while ($ctr < $env{'form.totalparts'}) { my $partid = $env{'form.partid_'.$ctr}; @@ -2759,6 +2968,7 @@ sub editgrades { $weight{$partid} = $env{'form.weight_'.$partid}; $ctr++; } + 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>'; @@ -2776,7 +2986,7 @@ sub editgrades { } } foreach my $partid (@partid) { - my $display_part=&get_display_part($partid,$url,$symb); + my $display_part=&get_display_part($partid,$symb); $result .= '<td colspan="'.$columns{$partid}. '" align="center"><b>Part:</b> '.$display_part. ' (Weight = '.$weight{$partid}.')</td>'; @@ -2790,12 +3000,10 @@ sub editgrades { for ($i=0; $i<$env{'form.total'}; $i++) { my $line; my $user = $env{'form.ctr'.$i}; - my $usercolon = $user; - $usercolon =~s/_/:/; - my ($uname,$udom)=split(/_/,$user); + my ($uname,$udom)=split(/:/,$user); my %newrecord; my $updateflag = 0; - $line .= '<td>'.&nameUserString(undef,$$fullname{$usercolon},$uname,$udom).'</td>'; + $line .= '<td>'.&nameUserString(undef,$$fullname{$user},$uname,$udom).'</td>'; my $usec=$classlist->{"$uname:$udom"}[5]; if (!&canmodify($usec)) { my $numcols=scalar(@partid)*4+2; @@ -2804,6 +3012,7 @@ sub editgrades { } my %aggregate = (); my $aggregateflag = 0; + $user=~s/:/_/; # colon doen't work in javascript for names foreach (@partid) { my $old_aw = $env{'form.GD_'.$user.'_'.$_.'_awarded_s'}; my $old_part_pcr = $old_aw/($weight{$_} ne '0' ? $weight{$_}:1); @@ -2823,13 +3032,14 @@ sub editgrades { my $dropMenu = $env{'form.GD_'.$user.'_'.$_.'_solved'}; $score = 'excused' if (($dropMenu eq 'excused') && ($score ne 'excused')); + $newrecord{'resource.'.$_.'.regrader'}= + "$env{'user.name'}:$env{'user.domain'}"; if ($dropMenu eq 'reset status' && $old_score ne '') { # ignore if no previous attempts => nothing to reset - $newrecord{'resource.'.$_.'.tries'} = 0; + $newrecord{'resource.'.$_.'.tries'} = ''; $newrecord{'resource.'.$_.'.solved'} = ''; $newrecord{'resource.'.$_.'.award'} = ''; - $newrecord{'resource.'.$_.'.awarded'} = 0; - $newrecord{'resource.'.$_.'.regrader'}="$env{'user.name'}:$env{'user.domain'}"; + $newrecord{'resource.'.$_.'.awarded'} = ''; $updateflag = 1; if ($env{'form.GD_'.$user.'_'.$_.'_aggtries'} > 0) { my $aggtries = $env{'form.GD_'.$user.'_'.$_.'_aggtries'}; @@ -2867,10 +3077,38 @@ sub editgrades { } } $line.='</tr>'."\n"; + + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + if ($updateflag) { $count++; &Apache::lonnet::cstore(\%newrecord,$symb,$env{'request.course.id'}, $udom,$uname); + + if (&Apache::bridgetask::in_queue('gradingqueue',$symb,$cdom, + $cnum,$udom,$uname)) { + # need to figure out if should be in queue. + my %record = + &Apache::lonnet::restore($symb,$env{'request.course.id'}, + $udom,$uname); + my $all_graded = 1; + my $none_graded = 1; + foreach my $part (@parts) { + if ( $record{'resource.'.$part.'.awarded'} eq '' ) { + $all_graded = 0; + } else { + $none_graded = 0; + } + } + + if ($all_graded || $none_graded) { + &Apache::bridgetask::remove_from_queue('gradingqueue', + $symb,$cdom,$cnum, + $udom,$uname); + } + } + $result.='<tr bgcolor="#ffffde"><td align="right"> '.$updateCtr.' </td>'.$line; $updateCtr++; } else { @@ -2879,8 +3117,7 @@ sub editgrades { } if ($aggregateflag) { &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, - $env{'course.'.$env{'request.course.id'}.'.domain'}, - $env{'course.'.$env{'request.course.id'}.'.num'}); + $cdom,$cnum); } } if ($noupdate) { @@ -2889,7 +3126,7 @@ sub editgrades { $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); + &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 />'; @@ -2992,7 +3229,7 @@ ENDPICK } sub csvuploadmap_header { - my ($request,$symb,$url,$datatoken,$distotal)= @_; + my ($request,$symb,$datatoken,$distotal)= @_; my $javascript; if ($env{'form.upfile_associate'} eq 'reverse') { $javascript=&csvupload_javascript_reverse_associate(); @@ -3000,14 +3237,14 @@ sub csvuploadmap_header { $javascript=&csvupload_javascript_forward_associate(); } - my ($result) = &showResourceInfo($url,$env{'form.probTitle'}); + my ($result) = &showResourceInfo($symb,$env{'form.probTitle'}); my $checked=(($env{'form.noFirstLine'})?' checked="checked"':''); my $ignore=&mt('Ignore First Line'); $request->print(<<ENDPICK); <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload"> <h3><font color="#339933">Uploading Class Grades</font></h3> $result -<hr> +<hr /> <h3>Identify fields</h3> Total number of records found in file: $distotal <hr /> Enter as many fields as you can. The system will inform you and bring you back @@ -3022,7 +3259,6 @@ to this page if the data selected is ins <input type="hidden" name="upfile_associate" value="$env{'form.upfile_associate'}" /> <input type="hidden" name="symb" value="$symb" /> -<input type="hidden" name="url" value="$url" /> <input type="hidden" name="saveState" value="$env{'form.saveState'}" /> <input type="hidden" name="probTitle" value="$env{'form.probTitle'}" /> <input type="hidden" name="command" value="csvuploadoptions" /> @@ -3036,11 +3272,12 @@ ENDPICK } sub csvupload_fields { - my ($url,$symb) = @_; - my (@parts) = &getpartlist($url,$symb); + my ($symb) = @_; + my (@parts) = &getpartlist($symb); my @fields=(['ID','Student ID'], ['username','Student Username'], ['domain','Student Domain']); + my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb); foreach my $part (sort(@parts)) { my @datum; my $display=&Apache::lonnet::metadata($url,$part.'.display'); @@ -3066,10 +3303,7 @@ sub csvuploadmap_footer { ENDPICK } -sub upcsvScores_form { - my ($request) = shift; - my ($symb,$url)=&get_symb_and_url($request); - if (!$symb) {return '';} +sub checkforfile_js { my $result =<<CSVFORMJS; <script type="text/javascript" language="javascript"> function checkUpload(formname) { @@ -3081,11 +3315,19 @@ sub upcsvScores_form { } </script> CSVFORMJS + return $result; +} + +sub upcsvScores_form { + my ($request) = shift; + my ($symb)=&get_symb($request); + if (!$symb) {return '';} + my $result=&checkforfile_js(); $env{'form.probTitle'} = &Apache::lonnet::gettitle($symb); - my ($table) = &showResourceInfo($url,$env{'form.probTitle'}); + my ($table) = &showResourceInfo($symb,$env{'form.probTitle'}); $result.=$table; - $result.='<br /><table width=100% border=0><tr><td bgcolor="#777777">'."\n"; - $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n"; + $result.='<br /><table width="100%" border="0"><tr><td bgcolor="#777777">'."\n"; + $result.='<table width="100%" border="0"><tr bgcolor="#e6ffff"><td>'."\n"; $result.=' <b>Specify a file containing the class scores for current resource'. '.</b></td></tr>'."\n"; $result.='<tr bgcolor=#ffffe6><td>'."\n"; @@ -3094,25 +3336,24 @@ CSVFORMJS $result.=<<ENDUPFORM; <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload"> <input type="hidden" name="symb" value="$symb" /> -<input type="hidden" name="url" value="$url" /> <input type="hidden" name="command" value="csvuploadmap" /> <input type="hidden" name="probTitle" value="$env{'form.probTitle'}" /> <input type="hidden" name="saveState" value="$env{'form.saveState'}" /> $upfile_select <br /><input type="button" onClick="javascript:checkUpload(this.form);" value="Upload Scores" /> -<label><input type="checkbox" name="noFirstLine" />$ignore</lable> +<label><input type="checkbox" name="noFirstLine" />$ignore</label> </form> ENDUPFORM $result.='</td></tr></table>'."\n"; $result.='</td></tr></table><br /><br />'."\n"; - $result.=&show_grading_menu_form($symb,$url); + $result.=&show_grading_menu_form($symb); return $result; } sub csvuploadmap { my ($request)= @_; - my ($symb,$url)=&get_symb_and_url($request); + my ($symb)=&get_symb($request); if (!$symb) {return '';} my $datatoken; @@ -3124,10 +3365,10 @@ sub csvuploadmap { } my @records=&Apache::loncommon::upfile_record_sep(); if ($env{'form.noFirstLine'}) { shift(@records); } - &csvuploadmap_header($request,$symb,$url,$datatoken,$#records+1); + &csvuploadmap_header($request,$symb,$datatoken,$#records+1); my ($i,$keyfields); if (@records) { - my @fields=&csvupload_fields($url,$symb); + my @fields=&csvupload_fields($symb); if ($env{'form.upfile_associate'} eq 'reverse') { &Apache::loncommon::csv_print_samples($request,\@records); @@ -3139,32 +3380,38 @@ sub csvuploadmap { unshift(@fields,['none','']); $i=&Apache::loncommon::csv_samples_select_table($request,\@records, \@fields); - my %sone=&Apache::loncommon::record_sep($records[0]); - $keyfields=join(',',sort(keys(%sone))); + foreach my $rec (@records) { + my %temp = &Apache::loncommon::record_sep($rec); + if (%temp) { + $keyfields=join(',',sort(keys(%temp))); + last; + } + } } } &csvuploadmap_footer($request,$i,$keyfields); - $request->print(&show_grading_menu_form($symb,$url)); + $request->print(&show_grading_menu_form($symb)); return ''; } sub csvuploadoptions { my ($request)= @_; - my ($symb,$url)=&get_symb_and_url($request); + my ($symb)=&get_symb($request); my $checked=(($env{'form.noFirstLine'})?'1':'0'); my $ignore=&mt('Ignore First Line'); $request->print(<<ENDPICK); <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload"> <h3><font color="#339933">Uploading Class Grade Options</font></h3> <input type="hidden" name="command" value="csvuploadassign" /> -<input type="submit" value="Assign Grades" /><br /> +<!-- <p> <label> <input type="checkbox" name="show_full_results" /> Show a table of all changes </label> </p> +--> <p> <label> <input type="checkbox" name="overwite_scores" checked="checked" /> @@ -3186,8 +3433,9 @@ ENDPICK } # FIXME do a check for any duplicated user ids... # FIXME do a check for any invalid user ids?... - $request->print("<hr /></form>\n"); - $request->print(&show_grading_menu_form($symb,$url)); + $request->print('<input type="submit" value="Assign Grades" /><br /> +<hr /></form>'."\n"); + $request->print(&show_grading_menu_form($symb)); return ''; } @@ -3210,7 +3458,7 @@ sub get_fields { sub csvuploadassign { my ($request)= @_; - my ($symb,$url)=&get_symb_and_url($request); + my ($symb)=&get_symb($request); if (!$symb) {return '';} &Apache::loncommon::load_tmp_file($request); my @gradedata = &Apache::loncommon::upfile_record_sep(); @@ -3282,15 +3530,25 @@ sub csvuploadassign { if (! %grades) { push(@skipped,"$username:$domain no data to store"); } $grades{"resource.regrader"}="$env{'user.name'}:$env{'user.domain'}"; # &Apache::lonnet::logthis(" storing ".(join('-',%grades))); - &Apache::lonnet::cstore(\%grades,$symb,$env{'request.course.id'}, - $domain,$username); - $request->print('.'); + my $result=&Apache::lonnet::cstore(\%grades,$symb, + $env{'request.course.id'}, + $domain,$username); + if ($result eq 'ok') { + $request->print('.'); + } else { + $request->print("<p> + <font color='red'> + Failed to store student $username\@$domain. + Message when trying to store was ($result) + </font> + </p>" ); + } $request->rflush(); $countdone++; } $request->print("<br />Stored $countdone students\n"); if (@skipped) { - $request->print('<p<font size="+1"><b>Skipped Students</b></font></p>'); + $request->print('<p><font size="+1"><b>Skipped Students</b></font></p>'); foreach my $student (@skipped) { $request->print("$student<br />\n"); } } if (@notallowed) { @@ -3298,7 +3556,7 @@ sub csvuploadassign { foreach my $student (@notallowed) { $request->print("$student<br />\n"); } } $request->print("<br />\n"); - $request->print(&show_grading_menu_form($symb,$url)); + $request->print(&show_grading_menu_form($symb)); return ''; } #------------- end of section for handling csv file upload --------- @@ -3328,7 +3586,7 @@ function checkPickOne(formname) { </script> LISTJAVASCRIPT &commonJSfunctions($request); - my ($symb,$url) = &get_symb_and_url($request); + my ($symb) = &get_symb($request); my $cdom = $env{"course.$env{'request.course.id'}.domain"}; my $cnum = $env{"course.$env{'request.course.id'}.num"}; my $getsec = $env{'form.section'} eq '' ? 'all' : $env{'form.section'}; @@ -3350,7 +3608,7 @@ LISTJAVASCRIPT '>'.$showtitle.'</option>'."\n"; $ctr++; } - $result.= '</select>'."<br>\n"; + $result.= '</select>'."<br />\n"; $ctr=0; foreach (@$titles) { my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/); @@ -3361,18 +3619,17 @@ LISTJAVASCRIPT $result.='<input type="hidden" name="page" />'."\n". '<input type="hidden" name="title" />'."\n"; - $result.=' <b>View Problems Text: </b><input type="radio" name="vProb" value="no" checked="on" /> no '."\n". - '<input type="radio" name="vProb" value="yes" /> yes '."<br>\n"; + $result.=' <b>View Problems Text: </b><label><input type="radio" name="vProb" value="no" checked="on" /> no </label>'."\n". + '<label><input type="radio" name="vProb" value="yes" /> yes </label>'."<br />\n"; $result.=' <b>Submission Details: </b>'. - '<input type="radio" name="lastSub" value="none" /> none'."\n". - '<input type="radio" name="lastSub" value="datesub" checked /> by dates and submissions'."\n". - '<input type="radio" name="lastSub" value="all" /> all details'."\n"; + '<label><input type="radio" name="lastSub" value="none" /> none</label>'."\n". + '<label><input type="radio" name="lastSub" value="datesub" checked /> by dates and submissions</label>'."\n". + '<label><input type="radio" name="lastSub" value="all" /> all details</label>'."\n"; $result.='<input type="hidden" name="section" value="'.$getsec.'" />'."\n". '<input type="hidden" name="Status" value="'.$env{'form.Status'}.'" />'."\n". '<input type="hidden" name="command" value="displayPage" />'."\n". - '<input type="hidden" name="url" value="'.$url.'" />'."\n". '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". '<input type="hidden" name="saveState" value="'.$env{'form.saveState'}.'" />'."<br />\n"; @@ -3381,7 +3638,7 @@ LISTJAVASCRIPT $request->print($result); - my $studentTable.=' <b>Select a student you wish to grade and then click on the Next button.</b><br>'. + 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>'. @@ -3391,12 +3648,18 @@ LISTJAVASCRIPT my (undef,undef,$fullname) = &getclasslist($getsec,'1'); my $ptr = 1; - foreach my $student (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) { + foreach my $student (sort + { + if (lc($$fullname{$a}) ne lc($$fullname{$b})) { + return (lc($$fullname{$a}) cmp lc($$fullname{$b})); + } + return $a cmp $b; + } (keys(%$fullname))) { my ($uname,$udom) = split(/:/,$student); $studentTable.=($ptr%2 == 1 ? '<tr bgcolor="#ffffe6">' : '</td>'); $studentTable.='<td align="right">'.$ptr.' </td>'; - $studentTable.='<td> <input type="radio" name="student" value="'.$student.'" /> ' - .&nameUserString(undef,$$fullname{$student},$uname,$udom)."\n"; + $studentTable.='<td> <label><input type="radio" name="student" value="'.$student.'" /> ' + .&nameUserString(undef,$$fullname{$student},$uname,$udom)."</label>\n"; $studentTable.=($ptr%2 == 0 ? '</td></tr>' : ''); $ptr++; } @@ -3405,7 +3668,7 @@ LISTJAVASCRIPT $studentTable.='<input type="button" '. 'onClick="javascript:checkPickOne(this.form);"value="Next->" /></form>'."\n"; - $studentTable.=&show_grading_menu_form($symb,$url); + $studentTable.=&show_grading_menu_form($symb); $request->print($studentTable); return ''; @@ -3438,7 +3701,7 @@ sub getSymbMap { sub displayPage { my ($request) = shift; - my ($symb,$url) = &get_symb_and_url($request); + my ($symb) = &get_symb($request); my $cdom = $env{"course.$env{'request.course.id'}.domain"}; my $cnum = $env{"course.$env{'request.course.id'}.num"}; my $getsec = $env{'form.section'} eq '' ? 'all' : $env{'form.section'}; @@ -3456,7 +3719,7 @@ sub displayPage { if (!&canview($usec)) { $request->print('<font color="red">Unable to view requested student.('.$env{'form.student'}.')</font>'); - $request->print(&show_grading_menu_form($symb,$url)); + $request->print(&show_grading_menu_form($symb)); return; } my $result='<h3><font color="#339933"> '.$env{'form.title'}.'</font></h3>'; @@ -3468,7 +3731,11 @@ sub displayPage { my $navmap = Apache::lonnavmaps::navmap->new(); my ($mapUrl, $id, $resUrl)=&Apache::lonnet::decode_symb($env{'form.page'}); my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps - + if (!$map) { + $request->print('<font color="red">Unable to view requested sequence. ('.$resUrl.')</font>'); + $request->print(&show_grading_menu_form($symb)); + return; + } my $iterator = $navmap->getIterator($map->map_start(), $map->map_finish()); @@ -3478,7 +3745,6 @@ sub displayPage { '<input type="hidden" name="student" value="'.$env{'form.student'}.'" />'."\n". '<input type="hidden" name="page" value="'.$pageTitle.'" />'."\n". '<input type="hidden" name="title" value="'.$env{'form.title'}.'" />'."\n". - '<input type="hidden" name="url" value="'.$url.'" />'."\n". '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". '<input type="hidden" name="overRideScore" value="no" />'."\n". '<input type="hidden" name="saveState" value="'.$env{'form.saveState'}.'" />'."\n"; @@ -3493,6 +3759,7 @@ sub displayPage { '<td align="center"><b> Prob. </b></td>'. '<td><b> '.($env{'form.vProb'} eq 'no' ? 'Title' : 'Problem Text').'/Grade</b></td></tr>'; + &Apache::lonxml::clear_problem_counter(); my ($depth,$question,$prob) = (1,1,1); $iterator->next(); # skip the first BEGIN_MAP my $curRes = $iterator->next(); # for "current resource" @@ -3505,7 +3772,7 @@ sub displayPage { my $title = $curRes->compTitle(); my $symbx = $curRes->symb(); $studentTable.='<tr bgcolor="#ffffe6"><td align="center" valign="top" >'.$prob. - (scalar(@{$parts}) == 1 ? '' : '<br>('.scalar(@{$parts}).' parts)').'</td>'; + (scalar(@{$parts}) == 1 ? '' : '<br />('.scalar(@{$parts}).' parts)').'</td>'; $studentTable.='<td valign="top">'; if ($env{'form.vProb'} eq 'yes' ) { $studentTable.=&show_problem($request,$symbx,$uname,$udom,1, @@ -3516,10 +3783,10 @@ sub displayPage { $companswer =~ s|</form>||g; # while ($companswer =~ /(<a href\=\"javascript:newWindow.*?Script Vars<\/a>)/s) { #<a href="javascript:newWindow</a> # $companswer =~ s/$1/ /ms; -# $request->print('match='.$1."<br>\n"); +# $request->print('match='.$1."<br />\n"); # } # $companswer =~ s|<table border=\"1\">|<table border=\"0\">|g; - $studentTable.=' <b>'.$title.'</b> <br> <b>Correct answer:</b><br>'.$companswer; + $studentTable.=' <b>'.$title.'</b> <br /> <b>Correct answer:</b><br />'.$companswer; } my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname); @@ -3566,7 +3833,7 @@ sub displayPage { '<input type="button" value="Save" '. 'onClick="javascript:checkSubmitPage(this.form,'.$question.');" TARGET=_self />'. '</form>'."\n"; - $studentTable.=&show_grading_menu_form($symb,$url); + $studentTable.=&show_grading_menu_form($symb); $request->print($studentTable); return ''; @@ -3600,7 +3867,7 @@ sub displaySubByDates { 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); + my $display_part=&get_display_part($partid,$symb); foreach my $matchKey (@matchKey) { if (exists($$record{$version.':'.$matchKey}) && $$record{$version.':'.$matchKey} ne '') { @@ -3662,7 +3929,7 @@ sub updateGradeByPage { my $usec=$classlist->{$env{'form.student'}}[5]; if (!&canmodify($usec)) { $request->print('<font color="red">Unable to modify requested student.('.$env{'form.student'}.'</font>'); - $request->print(&show_grading_menu_form($env{'form.symb'},$env{'form.url'})); + $request->print(&show_grading_menu_form($env{'form.symb'})); return; } my $result='<h3><font color="#339933"> '.$env{'form.title'}.'</font></h3>'; @@ -3674,7 +3941,12 @@ sub updateGradeByPage { my $navmap = Apache::lonnavmaps::navmap->new(); my ($mapUrl, $id, $resUrl) = &Apache::lonnet::decode_symb( $env{'form.page'}); my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps - + if (!$map) { + $request->print('<font color="red">Unable to grade requested sequence. ('.$resUrl.')</font>'); + my ($symb)=&get_symb($request); + $request->print(&show_grading_menu_form($symb)); + return; + } my $iterator = $navmap->getIterator($map->map_start(), $map->map_finish()); @@ -3697,7 +3969,7 @@ sub updateGradeByPage { my $title = $curRes->compTitle(); my $symbx = $curRes->symb(); $studentTable.='<tr bgcolor="#ffffe6"><td align="center" valign="top" >'.$prob. - (scalar(@{$parts}) == 1 ? '' : '<br>('.scalar(@{$parts}).' parts)').'</td>'; + (scalar(@{$parts}) == 1 ? '' : '<br />('.scalar(@{$parts}).' parts)').'</td>'; $studentTable.='<td valign="top"> <b>'.$title.'</b> </td>'; my %newrecord=(); @@ -3739,15 +4011,14 @@ sub updateGradeByPage { $aggregateflag = 1; } } - my $display_part=&get_display_part($partid,undef, - $curRes->symb()); + my $display_part=&get_display_part($partid,$curRes->symb()); my $oldstatus = $env{'form.solved'.$question.'_'.$partid}; $displayPts[0].=' <b>Part:</b> '.$display_part.' = '. (($oldstatus eq 'excused') ? 'excused' : $oldpts). - ' <br>'; + ' <br />'; $displayPts[1].=' <b>Part:</b> '.$display_part.' = '. (($score eq 'excused') ? 'excused' : $newpts). - ' <br>'; + ' <br />'; $question++; next if ($dropMenu eq 'reset status' || ($newpts == $oldpts && $score ne 'excused')); @@ -3779,7 +4050,7 @@ sub updateGradeByPage { } $studentTable.='</td></tr></table></td></tr></table>'; - $studentTable.=&show_grading_menu_form($env{'form.symb'},$env{'form.url'}); + $studentTable.=&show_grading_menu_form($env{'form.symb'}); my $grademsg=($changeflag == 0 ? 'No score was changed or updated.' : 'The scores were changed for '. $changeflag.' problem'.($changeflag == 1 ? '.' : 's.')); @@ -3797,10 +4068,9 @@ sub updateGradeByPage { #------ start of section for handling grading by page/sequence --------- sub defaultFormData { - my ($symb,$url)=@_; + my ($symb)=@_; return ' <input type="hidden" name="symb" value="'.$symb.'" />'."\n". - '<input type="hidden" name="url" value="'.$url.'" />'."\n". '<input type="hidden" name="saveState" value="'.$env{'form.saveState'}.'" />'."\n". '<input type="hidden" name="probTitle" value="'.$env{'form.probTitle'}.'" />'."\n"; } @@ -3869,6 +4139,7 @@ sub scantron_CODElist { my $namechoice='<option></option>'; foreach my $name (sort {uc($a) cmp uc($b)} @names) { if ($name =~ /^error: 2 /) { next; } + if ($name =~ /^type\0/) { next; } $namechoice.='<option value="'.$name.'">'.$name.'</option>'; } $namechoice='<select name="scantron_CODElist">'.$namechoice.'</select>'; @@ -3877,23 +4148,23 @@ sub scantron_CODElist { sub scantron_CODEunique { my $result='<nobr> - <input type="radio" name="scantron_CODEunique" - value="Yes" checked="on" /> Yes + <label><input type="radio" name="scantron_CODEunique" + value="yes" checked="checked" /> Yes </label> </nobr> <nobr> - <input type="radio" name="scantron_CODEunique" - value="No" /> No + <label><input type="radio" name="scantron_CODEunique" + value="no" /> No </label> </nobr>'; return $result; } sub scantron_selectphase { my ($r,$file2grade) = @_; - my ($symb,$url)=&get_symb_and_url($r); + my ($symb)=&get_symb($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 $default_form_data=&defaultFormData($symb); + my $grading_menu_button=&show_grading_menu_form($symb); my $file_selector=&scantron_uploads($file2grade); my $format_selector=&scantron_scantab(); my $CODE_selector=&scantron_CODElist(); @@ -3932,8 +4203,9 @@ sub scantron_selectphase { <tr bgcolor="#ffffe6"> <td> Options: </td> <td> - <input type="checkbox" name="scantron_options_redo" value="redo_skipped"/> Do only previously skipped records <br /> - <input type="checkbox" name="scantron_options_ignore" value="ignore_corrections"/> Remove all exisiting corrections + <label><input type="checkbox" name="scantron_options_redo" value="redo_skipped"/> Do only previously skipped records</label> <br /> + <label><input type="checkbox" name="scantron_options_ignore" value="ignore_corrections"/> Remove all exisiting corrections</label> <br /> + <label><input type="checkbox" name="scantron_options_hidden" value="ignore_hidden"/> Skip hidden resources when grading</label> </td> </tr> <tr bgcolor="#ffffe6"> @@ -3964,7 +4236,7 @@ SCANTRONFORM <tr bgcolor="#ffffe6"> <td> SCANTRONFORM - my $default_form_data=&defaultFormData(&get_symb_and_url($r,1)); + my $default_form_data=&defaultFormData(&get_symb($r,1)); my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'}; my $cnum= $env{'course.'.$env{'request.course.id'}.'.num'}; $r->print(<<UPLOAD); @@ -4013,7 +4285,7 @@ SCANTRONFORM </tr> <tr bgcolor="#ffffe6"> <td colspan="2"> - <input type="submit" value="Show List of Files" /> + <input type="submit" value="Download: Show List of Associated Files" /> </td> </tr> </table> @@ -4112,7 +4384,14 @@ sub scantron_fixup_scanline { &scan_data($scan_data, "$whichline.no_bubble.".$args->{'question'},'1'); } else { - substr($answer,$args->{'response'},1)=$on; + if ($on eq 'letter') { + my @alphabet=('A'..'Z'); + $answer=$alphabet[$args->{'response'}]; + } elsif ($on eq 'number') { + $answer=$args->{'response'}+1; + } else { + substr($answer,$args->{'response'},1)=$on; + } &scan_data($scan_data, "$whichline.no_bubble.".$args->{'question'},undef,'1'); } @@ -4137,8 +4416,11 @@ sub scantron_parse_scanline { my %record; my $questions=substr($line,$$scantron_config{'Qstart'}-1); my $data=substr($line,0,$$scantron_config{'Qstart'}-1); - if ($$scantron_config{'CODElocation'} ne 0) { - if ($$scantron_config{'CODElocation'} < 0) { + if (!($$scantron_config{'CODElocation'} eq 0 || + $$scantron_config{'CODElocation'} eq 'none')) { + if ($$scantron_config{'CODElocation'} < 0 || + $$scantron_config{'CODElocation'} eq 'letter' || + $$scantron_config{'CODElocation'} eq 'number') { $record{'scantron.CODE'}=substr($data, $$scantron_config{'CODEstart'}-1, $$scantron_config{'CODElength'}); @@ -4173,8 +4455,12 @@ sub scantron_parse_scanline { substr($questions,0,$$scantron_config{'Qlength'})=''; if (length($currentquest) < $$scantron_config{'Qlength'}) { next; } if ($$scantron_config{'Qon'} eq 'letter') { - if (!$currentquest || $currentquest eq $$scantron_config{'Qoff'} || - $currentquest !~ /^[A-Z]$/) { + if ($currentquest eq '?') { + push(@{$record{'scantron.doubleerror'}},$questnum); + $record{"scantron.$questnum.answer"}=''; + } elsif (!$currentquest + || $currentquest eq $$scantron_config{'Qoff'} + || $currentquest !~ /^[A-Z]$/) { $record{"scantron.$questnum.answer"}=''; if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) { push(@{$record{"scantron.missingerror"}},$questnum); @@ -4183,8 +4469,12 @@ sub scantron_parse_scanline { $record{"scantron.$questnum.answer"}=$currentquest; } } elsif ($$scantron_config{'Qon'} eq 'number') { - if (!$currentquest || $currentquest eq $$scantron_config{'Qoff'} || - $currentquest !~ /^\d$/) { + if ($currentquest eq '?') { + push(@{$record{'scantron.doubleerror'}},$questnum); + $record{"scantron.$questnum.answer"}=''; + } elsif (!$currentquest + || $currentquest eq $$scantron_config{'Qoff'} + || $currentquest !~ /^\d$/) { $record{"scantron.$questnum.answer"}=''; if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) { push(@{$record{"scantron.missingerror"}},$questnum); @@ -4244,8 +4534,15 @@ sub scantron_find_student { sub scantron_filter { my ($curres)=@_; - # randomout is dysfunctional at best for this purpose - if (ref($curres) && $curres->is_problem()) { #&& !$curres->randomout) { + + if (ref($curres) && $curres->is_problem()) { + # if the user has asked to not have either hidden + # or 'randomout' controlled resources to be graded + # don't include them + if ($env{'form.scantron_options_hidden'} eq 'ignore_hidden' + && $curres->randomout) { + return 0; + } return 1; } return 0; @@ -4301,7 +4598,7 @@ sub scantron_process_corrections { } } if ($err) { - $r->print("Unable to accept last correction, an error occurred :$errmsg:"); + $r->print("<font color='red'>Unable to accept last correction, an error occurred :$errmsg:</font>"); } else { &scantron_put_line($scanlines,$scan_data,$which,$line,$skip); &scantron_putfile($scanlines,$scan_data); @@ -4355,14 +4652,26 @@ sub check_for_error { sub scantron_warning_screen { my ($button_text)=@_; my $title=&Apache::lonnet::gettitle($env{'form.selectpage'}); + my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); + my $CODElist="a"; + if ($scantron_config{'CODElocation'} && + $scantron_config{'CODEstart'} && + $scantron_config{'CODElength'}) { + $CODElist=$env{'form.scantron_CODElist'}; + if ($CODElist eq '') { $CODElist='<font color="red">None</font>'; } + $CODElist= + '<tr><td><b>List of CODES to validate against:</b></td><td><tt>'. + $CODElist.'</tt></td></tr>'; + } return (<<STUFF); <p> <font color="red">Please double check the information below before clicking on '$button_text'</font> </p> <table> -<tr><td><b>Sequence To be Graded:</b></td><td>$title</td></tr> +<tr><td><b>Sequence to be Graded:</b></td><td>$title</td></tr> <tr><td><b>Data File that will be used:</b></td><td><tt>$env{'form.scantron_selectfile'}</tt></td></tr> +$CODElist </table> </font> <br /> @@ -4375,9 +4684,9 @@ STUFF sub scantron_do_warning { my ($r)=@_; - my ($symb,$url)=&get_symb_and_url($r); + my ($symb)=&get_symb($r); if (!$symb) {return '';} - my $default_form_data=&defaultFormData($symb,$url); + my $default_form_data=&defaultFormData($symb); $r->print(&scantron_form_start().$default_form_data); if ( $env{'form.selectpage'} eq '' || $env{'form.scantron_selectfile'} eq '' || @@ -4400,7 +4709,7 @@ $warning <input type="hidden" name="command" value="scantron_validate" /> STUFF } - $r->print("</form><br />".&show_grading_menu_form($symb,$url)."</body></html>"); + $r->print("</form><br />".&show_grading_menu_form($symb)."</body></html>"); return ''; } @@ -4416,15 +4725,16 @@ sub scantron_form_start { <input type="hidden" name="scantron_CODEunique" value="$env{'form.scantron_CODEunique'}" /> <input type="hidden" name="scantron_options_redo" value="$env{'form.scantron_options_redo'}" /> <input type="hidden" name="scantron_options_ignore" value="$env{'form.scantron_options_ignore'}" /> + <input type="hidden" name="scantron_options_hidden" value="$env{'form.scantron_options_hidden'}" /> SCANTRONFORM return $result; } sub scantron_validate_file { my ($r) = @_; - my ($symb,$url)=&get_symb_and_url($r); + my ($symb)=&get_symb($r); if (!$symb) {return '';} - my $default_form_data=&defaultFormData($symb,$url); + my $default_form_data=&defaultFormData($symb); # do the detection of only doing skipped records first befroe we delete # them when doing the corrections reset @@ -4450,7 +4760,7 @@ sub scantron_validate_file { $r->print("<p>Gathering neccessary info.</p>");$r->rflush(); #get the student pick code ready $r->print(&Apache::loncommon::studentbrowser_javascript()); - my $max_bubble=&scantron_get_maxbubble($r); + my $max_bubble=&scantron_get_maxbubble(); my $result=&scantron_form_start($max_bubble).$default_form_data; $r->print($result); @@ -4492,7 +4802,7 @@ STUFF $r->print("<input type='submit' value='Skip' name='scantron_skip_record' />"); $r->print(" this scanline saving it for later."); } - $r->print(" </form><br />".&show_grading_menu_form($symb,$url). + $r->print(" </form><br />".&show_grading_menu_form($symb). "</body></html>"); return ''; } @@ -4569,9 +4879,8 @@ sub lonnet_putfile { my ($contents,$filename)=@_; my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'}; my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'}; - my $docuhome=$env{'course.'.$env{'request.course.id'}.'.home'}; $env{'form.sillywaytopassafilearound'}=$contents; - &Apache::lonnet::finishuserfileupload($docuname,$docudom,$docuhome,'sillywaytopassafilearound',$filename); + &Apache::lonnet::finishuserfileupload($docuname,$docudom,'sillywaytopassafilearound',$filename); } @@ -4694,7 +5003,7 @@ sub scantron_get_correction { #the previous one or the current one $r->print("<p><b>An error was detected ($error)</b>"); - if ( defined($$scan_record{'scantron.PaperID'}) ) { + if ( $$scan_record{'scantron.PaperID'} =~ /\S/) { $r->print(" for PaperID <tt>". $$scan_record{'scantron.PaperID'}."</tt> \n"); } else { @@ -4739,19 +5048,24 @@ sub scantron_get_correction { $r->print("<p>How should I handle this? <br /> \n"); $r->print("\n<br /> "); my $i=0; - if ($error eq 'incorrectCODE') { + if ($error eq 'incorrectCODE' + && $$scan_record{'scantron.CODE'}=~/\S/ ) { my ($max,$closest)=&scantron_get_closely_matching_CODEs($arg,$$scan_record{'scantron.CODE'}); - foreach my $testcode (@{$closest}) { - my $checked=''; - if (!$i) { $checked=' checked="on" '; } - $r->print("<input type='radio' name='scantron_CODE_resolution' value='use_closest_$i' $checked /> Use the similar CODE <b><tt>".$testcode."</tt></b> instead.<input type='hidden' name='scantron_CODE_closest_$i' value='$testcode' />"); - $r->print("\n<br />"); - $i++; + if ($closest > 0) { + foreach my $testcode (@{$closest}) { + my $checked=''; + if (!$i) { $checked=' checked="on" '; } + $r->print("<label><input type='radio' name='scantron_CODE_resolution' value='use_closest_$i' $checked /> Use the similar CODE <b><tt>".$testcode."</tt></b> instead.</label><input type='hidden' name='scantron_CODE_closest_$i' value='$testcode' />"); + $r->print("\n<br />"); + $i++; + } } } - my $checked; if (!$i) { $checked=' checked="on" '; } - $r->print("<input type='radio' name='scantron_CODE_resolution' value='use_unfound' $checked /> Use the CODE <b><tt>".$$scan_record{'scantron.CODE'}."</tt></b> that is was on the paper, ignoring the error."); - $r->print("\n<br />"); + if ($$scan_record{'scantron.CODE'}=~/\S/ ) { + my $checked; if (!$i) { $checked=' checked="on" '; } + $r->print("<label><input type='radio' name='scantron_CODE_resolution' value='use_unfound' $checked /> Use the CODE <b><tt>".$$scan_record{'scantron.CODE'}."</tt></b> that is was on the paper, ignoring the error.</label>"); + $r->print("\n<br />"); + } $r->print(<<ENDSCRIPT); <script type="text/javascript"> @@ -4770,9 +5084,11 @@ ENDSCRIPT "&scantron_CODElist=".&Apache::lonnet::escape($env{'form.scantron_CODElist'}). "&curCODE=".&Apache::lonnet::escape($$scan_record{'scantron.CODE'}). "&scantron_selectfile=".&Apache::lonnet::escape($env{'form.scantron_selectfile'}); - $r->print("<input type='radio' name='scantron_CODE_resolution' value='use_found' /> <a target='_blank' href='$href'>Select</a> a CODE from the list of all CODEs and use it. Selected CODE is <input readonly='true' type='text' size='8' name='scantron_CODE_selectedvalue' onfocus=\"javascript:change_radio('use_found')\" onchange=\"javascript:change_radio('use_found')\" />"); - $r->print("\n<br />"); - $r->print("<input type='radio' name='scantron_CODE_resolution' value='use_typed' /> Use <input type='text' size='8' name='scantron_CODE_newvalue' onfocus=\"javascript:change_radio('use_typed')\" onkeypress=\"javascript:change_radio('use_typed')\" /> as the CODE."); + if ($env{'form.scantron_CODElist'} =~ /\S/) { + $r->print("<label><input type='radio' name='scantron_CODE_resolution' value='use_found' /> <a target='_blank' href='$href'>Select</a> a CODE from the list of all CODEs and use it.</label> Selected CODE is <input readonly='true' type='text' size='8' name='scantron_CODE_selectedvalue' onfocus=\"javascript:change_radio('use_found')\" onchange=\"javascript:change_radio('use_found')\" />"); + $r->print("\n<br />"); + } + $r->print("<label><input type='radio' name='scantron_CODE_resolution' value='use_typed' /> Use </label><input type='text' size='8' name='scantron_CODE_newvalue' onfocus=\"javascript:change_radio('use_typed')\" onkeypress=\"javascript:change_radio('use_typed')\" /> as the CODE."); $r->print("\n<br /><br />"); } elsif ($error eq 'doublebubble') { $r->print("<p>There have been multiple bubbles scanned for a some question(s)</p>\n"); @@ -4805,21 +5121,26 @@ ENDSCRIPT sub scantron_bubble_selector { my ($r,$scan_config,$quest,@selected)=@_; my $max=$$scan_config{'Qlength'}; + + my $scmode=$$scan_config{'Qon'}; + if ($scmode eq 'number' || $scmode eq 'letter') { $max=10; } + my @alphabet=('A'..'Z'); $r->print("<table border='1'><tr><td rowspan='2'>$quest</td>"); for (my $i=0;$i<$max+1;$i++) { - $r->print('<td align="center">'); + $r->print("\n".'<td align="center">'); if ($selected[0] eq $alphabet[$i]) { $r->print('X'); shift(@selected) } else { $r->print(' '); } $r->print('</td>'); } - $r->print('<td></td></tr><tr>'); + $r->print('</tr><tr>'); for (my $i=0;$i<$max;$i++) { - $r->print('<td><input type="radio" name="scantron_correct_Q_'.$quest. - '" value="'.$i.'" />'.$alphabet[$i]."</td>"); + $r->print("\n". + '<td><label><input type="radio" name="scantron_correct_Q_'. + $quest.'" value="'.$i.'" />'.$alphabet[$i]."</label></td>"); } - $r->print('<td><input type="radio" name="scantron_correct_Q_'.$quest. - '" value="none" /> No bubble </td>'); + $r->print('<td><label><input type="radio" name="scantron_correct_Q_'. + $quest.'" value="none" /> No bubble </label></td>'); $r->print('</tr></table>'); } @@ -4845,11 +5166,24 @@ sub scantron_get_closely_matching_CODEs } sub get_codes { - my $old_name=$env{'form.scantron_CODElist'}; - my $cdom =$env{'course.'.$env{'request.course.id'}.'.domain'}; - my $cnum =$env{'course.'.$env{'request.course.id'}.'.num'}; - my %result=&Apache::lonnet::get('CODEs',[$old_name],$cdom,$cnum); - my %allcodes=map {(&Apache::lonprintout::num_to_letters($_),1)} split(',',$result{$old_name}); + my ($old_name, $cdom, $cnum) = @_; + if (!$old_name) { + $old_name=$env{'form.scantron_CODElist'}; + } + if (!$cdom) { + $cdom =$env{'course.'.$env{'request.course.id'}.'.domain'}; + } + if (!$cnum) { + $cnum =$env{'course.'.$env{'request.course.id'}.'.num'}; + } + my %result=&Apache::lonnet::get('CODEs',[$old_name,"type\0$old_name"], + $cdom,$cnum); + my %allcodes; + if ($result{"type\0$old_name"} eq 'number') { + %allcodes=map {($_,1)} split(',',$result{$old_name}); + } else { + %allcodes=map {(&Apache::lonprintout::num_to_letters($_),1)} split(',',$result{$old_name}); + } return %allcodes; } @@ -4927,28 +5261,29 @@ sub scantron_validate_doublebubble { return (0,$currentphase+1); } -sub scantron_get_maxbubble { - my ($r)=@_; +sub scantron_get_maxbubble { if (defined($env{'form.scantron_maxbubble'}) && $env{'form.scantron_maxbubble'}) { return $env{'form.scantron_maxbubble'}; } + my $navmap=Apache::lonnavmaps::navmap->new(); my (undef,undef,$sequence)= &Apache::lonnet::decode_symb($env{'form.selectpage'}); + my $map=$navmap->getResourceByUrl($sequence); my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); - &Apache::lonnet::delenv('form.counter'); + + &Apache::lonxml::clear_problem_counter(); + foreach my $resource (@resources) { - my $result=&Apache::lonnet::ssi($resource->src().'?symb='.&Apache::lonnet::escape($resource->symb())); + my $result=&Apache::lonnet::ssi($resource->src(), + ('symb' => $resource->symb())); } &Apache::lonnet::delenv('scantron\.'); - my $envfile=$env{'user.environment'}; - $envfile=~/\/([^\/]+)\.id$/; - $envfile=$1; - &Apache::lonnet::transfer_profile_to_env($r->dir_config('lonIDsDir'), - $envfile); - $env{'form.scantron_maxbubble'}=$env{'form.counter'}-1; + $env{'form.scantron_maxbubble'} = + &Apache::lonxml::get_problem_counter()-1; + return $env{'form.scantron_maxbubble'}; } @@ -4987,9 +5322,9 @@ sub scantron_validate_missingbubbles { sub scantron_process_students { my ($r) = @_; my (undef,undef,$sequence)=&Apache::lonnet::decode_symb($env{'form.selectpage'}); - my ($symb,$url)=&get_symb_and_url($r); + my ($symb)=&get_symb($r); if (!$symb) {return '';} - my $default_form_data=&defaultFormData($symb,$url); + my $default_form_data=&defaultFormData($symb); my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); my ($scanlines,$scan_data)=&scantron_getfile(); @@ -5042,7 +5377,8 @@ SCANTRONFORM next; } ($uname,$udom)=split(/:/,$uname); - &Apache::lonnet::delenv('form.counter'); + + &Apache::lonxml::clear_problem_counter(); &Apache::lonnet::appenv(%$scan_record); my $i=0; @@ -5070,7 +5406,7 @@ SCANTRONFORM $completedstudents{$uname}={'line'=>$line}; if (&Apache::loncommon::connection_aborted($r)) { last; } } continue { - &Apache::lonnet::delenv('form.counter'); + &Apache::lonxml::clear_problem_counter(); &Apache::lonnet::delenv('scantron\.'); } &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); @@ -5078,7 +5414,7 @@ SCANTRONFORM # $r->print("<p>took $lasttime</p>"); $r->print("</form>"); - $r->print(&show_grading_menu_form($symb,$url)); + $r->print(&show_grading_menu_form($symb)); return ''; } @@ -5090,7 +5426,7 @@ sub scantron_upload_scantron_data { 'coursename'); my $domsel=&Apache::loncommon::select_dom_form($env{'request.role.domain'}, 'domainid'); - my $default_form_data=&defaultFormData(&get_symb_and_url($r,1)); + my $default_form_data=&defaultFormData(&get_symb($r,1)); $r->print(<<UPLOAD); <script type="text/javascript" language="javascript"> function checkUpload(formname) { @@ -5120,7 +5456,7 @@ UPLOAD sub scantron_upload_scantron_data_save { my($r)=@_; - my ($symb,$url)=&get_symb_and_url($r,1); + my ($symb)=&get_symb($r,1); my $doanotherupload= '<br /><form action="/adm/grades" method="post">'."\n". '<input type="hidden" name="command" value="scantronupload" />'."\n". @@ -5131,7 +5467,7 @@ sub scantron_upload_scantron_data_save { $env{'form.domainid'}.'_'.$env{'form.courseid'})) { $r->print("You are not allowed to upload Scantron data to the requested course.<br />"); if ($symb) { - $r->print(&show_grading_menu_form($symb,$url)); + $r->print(&show_grading_menu_form($symb)); } else { $r->print($doanotherupload); } @@ -5139,8 +5475,6 @@ sub scantron_upload_scantron_data_save { } 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'}; #FIXME #copied from lonnet::userfileupload() @@ -5160,7 +5494,7 @@ sub scantron_upload_scantron_data_save { 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."); } else { - my $result=&Apache::lonnet::finishuserfileupload($env{'form.courseid'},$env{'form.domainid'},$home,'upfile',$fname); + my $result=&Apache::lonnet::finishuserfileupload($env{'form.courseid'},$env{'form.domainid'},'upfile',$fname); 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 { @@ -5186,7 +5520,7 @@ sub valid_file { sub scantron_download_scantron_data { my ($r)=@_; - my $default_form_data=&defaultFormData(&get_symb_and_url($r,1)); + 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'}; @@ -5196,7 +5530,7 @@ sub scantron_download_scantron_data { The requested file name was invalid. </p> ERROR - $r->print(&show_grading_menu_form(&get_symb_and_url($r,1))); + $r->print(&show_grading_menu_form(&get_symb($r,1))); return; } my $orig='/uploaded/'.$cdom.'/'.$cname.'/scantron_orig_'.$file; @@ -5216,7 +5550,7 @@ ERROR <a href="$skipped">Skipped</a>, a file of records that were skipped. </p> DOWNLOAD - $r->print(&show_grading_menu_form(&get_symb_and_url($r,1))); + $r->print(&show_grading_menu_form(&get_symb($r,1))); return ''; } @@ -5228,10 +5562,9 @@ DOWNLOAD # #--- Show a Grading Menu button - Calls the next routine --- sub show_grading_menu_form { - my ($symb,$url)=@_; + my ($symb)=@_; my $result.='<br /><form action="/adm/grades" method="post">'."\n". '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". - '<input type="hidden" name="url" value="'.$url.'" />'."\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". @@ -5254,7 +5587,7 @@ sub savedState { #--- Displays the main menu page ------- sub gradingmenu { my ($request) = @_; - my ($symb,$url)=&get_symb_and_url($request); + my ($symb)=&get_symb($request); if (!$symb) {return '';} my $probTitle = &Apache::lonnet::gettitle($symb); @@ -5296,7 +5629,7 @@ sub gradingmenu { GRADINGMENUJS &commonJSfunctions($request); my $result='<h3> <font color="#339933">Manual Grading/View Submission</font></h3>'; - my ($table,undef,$hdgrade) = &showResourceInfo($url,$probTitle); + my ($table,undef,$hdgrade) = &showResourceInfo($symb,$probTitle); $result.=$table; my (undef,$sections) = &getclasslist('all','0'); my $savedState = &savedState(); @@ -5307,7 +5640,6 @@ GRADINGMENUJS $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n". '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". - '<input type="hidden" name="url" value="'.$url.'" />'."\n". '<input type="hidden" name="handgrade" value="'.$hdgrade.'" />'."\n". '<input type="hidden" name="probTitle" value="'.$probTitle.'" />'."\n". '<input type="hidden" name="command" value="" />'."\n". @@ -5315,12 +5647,12 @@ GRADINGMENUJS '<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". + $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.='<table width="100%" border="0">'; $result.='<tr bgcolor="#ffffe6" valign="top"><td>'."\n". ' '.&mt('Select Section').': <select name="section">'."\n"; if (ref($sections)) { @@ -5335,28 +5667,30 @@ GRADINGMENUJS $result.='</td></tr>'; - $result.='<tr bgcolor="#ffffe6"valign="top"><td>'. + $result.='<tr bgcolor="#ffffe6"valign="top"><td><label>'. '<input type="radio" name="radioChoice" value="submission" '. - ($saveCmd eq 'submission' ? 'checked' : '').'> '.'<b>'.&mt('Current Resource').':</b> '.&mt('For one or more students'). - ' <select name="submitonly">'. + ($saveCmd eq 'submission' ? 'checked' : '').' /> '.'<b>'.&mt('Current Resource').':</b> '.&mt('For one or more students'). + '</label> <select name="submitonly">'. '<option value="yes" '. - ($saveSub eq 'yes' ? 'selected="on"' : '').'>with submissions</option>'. + ($saveSub eq 'yes' ? 'selected="on"' : '').' />'.&mt('with submissions').'</option>'. + '<option value="queued" '. + ($saveSub eq 'queued' ? 'selected="on"' : '').' />'.&mt('in grading queue').'</option>'. '<option value="graded" '. - ($saveSub eq 'graded' ? 'selected="on"' : '').'>with ungraded submissions</option>'. + ($saveSub eq 'graded' ? 'selected="on"' : '').' />'.&mt('with ungraded submissions').'</option>'. '<option value="incorrect" '. - ($saveSub eq 'incorrect' ? 'selected="on"' : '').'>with incorrect submissions</option>'. + ($saveSub eq 'incorrect' ? 'selected="on"' : '').' />'.&mt('with incorrect submissions').'</option>'. '<option value="all" '. - ($saveSub eq 'all' ? 'selected="on"' : '').'>with any status</option></select></td></tr>'."\n"; + ($saveSub eq 'all' ? 'selected="on"' : '').' />'.&mt('with any status').'</option></select></td></tr>'."\n"; $result.='<tr bgcolor="#ffffe6"valign="top"><td>'. - '<input type="radio" name="radioChoice" value="viewgrades" '. - ($saveCmd eq 'viewgrades' ? 'checked' : '').'> '. - '<b>Current Resource:</b> For all students in selected section or course</td></tr>'."\n"; + '<label><input type="radio" name="radioChoice" value="viewgrades" '. + ($saveCmd eq 'viewgrades' ? 'checked' : '').' /> '. + '<b>Current Resource:</b> For all students in selected section or course</label></td></tr>'."\n"; $result.='<tr bgcolor="#ffffe6" valign="top"><td>'. - '<input type="radio" name="radioChoice" value="pickStudentPage" '. - ($saveCmd eq 'pickStudentPage' ? 'checked' : '').'> '. - 'The <b>complete</b> set/page/sequence: For one student</td></tr>'."\n"; + '<label><input type="radio" name="radioChoice" value="pickStudentPage" '. + ($saveCmd eq 'pickStudentPage' ? 'checked' : '').' /> '. + 'The <b>complete</b> set/page/sequence: For one student</label></td></tr>'."\n"; $result.='<tr bgcolor="#ffffe6"><td><br />'. '<input type="button" onClick="javascript:checkChoice(this.form,\'2\');" value="Next->" />'. @@ -5364,7 +5698,7 @@ GRADINGMENUJS $result.='</td><td valign="top">'; - $result.='<table width="100%" border=0>'; + $result.='<table width="100%" border="0">'; $result.='<tr bgcolor="#ffffe6"><td>'. '<input type="button" onClick="javascript:checkChoice(this.form,\'3\',\'csvform\');" value="'.&mt('Upload').'" />'. ' '.&mt('scores from file').' </td></tr>'."\n"; @@ -5378,12 +5712,15 @@ GRADINGMENUJS '<input type="button" onClick="javascript:checkChoice(this.form,\'5\',\'verify\');" value="'.&mt('Verify').'" />'. ' '.&mt('receipt').': '. &Apache::lonnet::recprefix($env{'request.course.id'}). - '-<input type="text" name="receipt" size="4" onChange="javascript:checkReceiptNo(this.form,\'OK\')">'. + '-<input type="text" name="receipt" size="4" onChange="javascript:checkReceiptNo(this.form,\'OK\')" />'. '</td></tr>'."\n"; } $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'. '<input type="button" onClick="javascript:this.form.action=\'/adm/helper/resettimes.helper\';this.form.submit();'. '" value="'.&mt('Manage').'" /> access times.</td></tr>'."\n"; + $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'. + '<input type="button" onClick="javascript:this.form.command.value=\'codelist\';this.form.action=\'/adm/pickcode\';this.form.submit();'. + '" value="'.&mt('View').'" /> saved CODEs.</td></tr>'."\n"; $result.='</form></td></tr></table>'."\n". '</td></tr></table>'."\n". @@ -5391,10 +5728,32 @@ GRADINGMENUJS return $result; } +sub reset_perm { + undef(%perm); +} + +sub init_perm { + &reset_perm(); + foreach my $test_perm ('vgr','mgr','opa') { + + my $scope = $env{'request.course.id'}; + if (!($perm{$test_perm}=&Apache::lonnet::allowed($test_perm,$scope))) { + + $scope .= '/'.$env{'request.course.sec'}; + if ( $perm{$test_perm}= + &Apache::lonnet::allowed($test_perm,$scope)) { + $perm{$test_perm.'_section'}=$env{'request.course.sec'}; + } else { + delete($perm{$test_perm}); + } + } + } +} + sub handler { my $request=$_[0]; - undef(%perm); + &reset_perm(); if ($env{'browser.mathml'}) { &Apache::loncommon::content_type($request,'text/xml'); } else { @@ -5403,20 +5762,14 @@ sub handler { $request->send_http_header; return '' if $request->header_only; &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}); - my $url=$env{'form.url'}; - my $symb=$env{'form.symb'}; + my $symb=&get_symb($request,1); my @commands=&Apache::loncommon::get_env_multiple('form.command'); my $command=$commands[0]; if ($#commands > 0) { &Apache::lonnet::logthis("grades got multiple commands ".join(':',@commands)); } - if (!$url) { - my ($temp1,$temp2); - ($temp1,$temp2,$env{'form.url'})=&Apache::lonnet::decode_symb($symb); - $url = $env{'form.url'}; - } &send_header($request); - if ($url eq '' && $symb eq '' && $command eq '') { + if ($symb eq '' && $command eq '') { if ($env{'user.adv'}) { if (($env{'form.codeone'}) && ($env{'form.codetwo'}) && ($env{'form.codethree'})) { @@ -5443,20 +5796,7 @@ sub handler { } } } else { - if (!($perm{'vgr'}=&Apache::lonnet::allowed('vgr',$env{'request.course.id'}))) { - if ($perm{'vgr'}=&Apache::lonnet::allowed('vgr',$env{'request.course.id'}.'/'.$env{'request.course.sec'})) { - $perm{'vgr_section'}=$env{'request.course.sec'}; - } else { - delete($perm{'vgr'}); - } - } - if (!($perm{'mgr'}=&Apache::lonnet::allowed('mgr',$env{'request.course.id'}))) { - if ($perm{'mgr'}=&Apache::lonnet::allowed('mgr',$env{'request.course.id'}.'/'.$env{'request.course.sec'})) { - $perm{'mgr_section'}=$env{'request.course.sec'}; - } else { - delete($perm{'mgr'}); - } - } + &init_perm(); if ($command eq 'submission' && $perm{'vgr'}) { ($env{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0)); } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {