--- loncom/homework/grades.pm 2003/11/12 21:18:10 1.157 +++ loncom/homework/grades.pm 2003/12/05 19:40:56 1.168 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.157 2003/11/12 21:18:10 albertel Exp $ +# $Id: grades.pm,v 1.168 2003/12/05 19:40:56 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -48,7 +48,8 @@ use Apache::lonhomework; use Apache::loncoursedata; use Apache::lonmsg qw(:user_normal_msg); use Apache::Constants qw(:common); -use String::Similarity; +use Apache::lonlocal; +#use String::Similarity; my %oldessays=(); my %perm=(); @@ -168,7 +169,7 @@ sub showResourceInfo { my $col=3; if ($checkboxes) { $col=4; } my $result ='<table border="0">'. - '<tr><td colspan="'.$col.'"><font size="+1"><b>Current Resource: </b>'. + '<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 %resptype = (); @@ -290,7 +291,8 @@ sub cleanRecord { $ENV{'form.kwstyle'} = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : ''; $ENV{'form.'.$symb} = 1; # so that we don't have to read it from disk for multiple sub of the same prob. } - return '<br /><br /><blockquote><pre>'.&keywords_highlight($answer).'</pre></blockquote>'; + $answer =~ s-\n-<br />-g; + return '<br /><br /><blockquote><tt>'.&keywords_highlight($answer).'</tt></blockquote>'; } return $answer; } @@ -678,10 +680,11 @@ LISTJAVASCRIPT if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist); my $submitted = 0; - my $graded = 1; + my $graded = 0; foreach (keys(%status)) { $submitted = 1 if ($status{$_} ne 'nothing'); - $graded = 0 if ($status{$_} =~ /^correct/); + $graded = 1 if ($status{$_} !~ /^correct/); + my ($foo,$partid,$foo1) = split(/\./,$_); if ($status{'resource.'.$partid.'.submitted_by'} ne '') { $submitted = 0; @@ -1375,7 +1378,9 @@ sub submission { return; } - $ENV{'form.lastSub'} = ($ENV{'form.lastSub'} eq '' ? 'datesub' : $ENV{'form.lastSub'}); + if (!$ENV{'form.lastSub'}) { $ENV{'form.lastSub'} = 'datesub'; } + if (!$ENV{'form.vProb'}) { $ENV{'form.vProb'} = 'yes'; } + if (!$ENV{'form.vAns'}) { $ENV{'form.vAns'} = 'yes'; } my $last = ($ENV{'form.lastSub'} eq 'last' ? 'last' : ''); my $checkIcon = '<img src="'.$request->dir_config('lonIconsURL'). '/check.gif" height="16" border="0" />'; @@ -1644,7 +1649,7 @@ KEYWORDS $partid.'</b> <font color="#999999">( ID '.$respid. ' )</font> '; if ($record{"resource.$partid.$respid.uploadedurl"}) { - $lastsubonly.='<a href="'.&Apache::lonnet::tokenwrapper($record{"resource.$partid.$respid.uploadedurl"}).'"><img src="/adm/lonIcons/unknown.gif" border=0"> File uploaded by student</a> <font color="red" size="1">Like all files provided by users, this file may contain virusses</font><br />'; + $lastsubonly.='<a href="'.&Apache::lonnet::tokenwrapper($record{"resource.$partid.$respid.uploadedurl"}).'" target="lonGRDs"><img src="/adm/lonIcons/unknown.gif" border=0"> File uploaded by student</a> <font color="red" size="1">Like all files provided by users, this file may contain virusses</font><br />'; } $lastsubonly.='<b>Submitted Answer: </b>'. &cleanRecord($subval,$responsetype,$symb,$partid, @@ -2243,8 +2248,14 @@ sub viewgrades { &viewgrades_js($request); my ($symb,$url) = ($ENV{'form.symb'},$ENV{'form.url'}); - my $result='<h3><font color="#339933">Manual Grading</font></h3>'; + #need to make sure we have the correct data for later EXT calls, + #thus invalidate the cache + &Apache::lonnet::devalidatecourseresdata( + $ENV{'course.'.$ENV{'request.course.id'}.'.num'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}); + &Apache::lonnet::clear_EXT_cache_status(); + my $result='<h3><font color="#339933">'.&mt('Manual Grading').'</font></h3>'; $result.='<font size=+1><b>Current Resource: </b>'.$ENV{'form.probTitle'}.'</font>'."\n"; #view individual student submission form - called using Javascript viewOneStudent @@ -2840,7 +2851,9 @@ sub csvuploadassign { foreach my $grade (@gradedata) { my %entries=&Apache::loncommon::record_sep($grade); my $username=$entries{$fields{'username'}}; + $username=~s/\s//g; my $domain=$entries{$fields{'domain'}}; + $domain=~s/\s//g; if (!exists($$classlist{"$username:$domain"})) { push(@skipped,"$username:$domain"); next; @@ -3025,6 +3038,14 @@ sub displayPage { my ($classlist,undef,$fullname) = &getclasslist($getsec,'1'); my ($uname,$udom) = split(/:/,$ENV{'form.student'}); my $usec=$classlist->{$ENV{'form.student'}}[5]; + + #need to make sure we have the correct data for later EXT calls, + #thus invalidate the cache + &Apache::lonnet::devalidatecourseresdata( + $ENV{'course.'.$ENV{'request.course.id'}.'.num'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}); + &Apache::lonnet::clear_EXT_cache_status(); + 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)); @@ -3196,7 +3217,7 @@ sub displaySubByDates { } if (exists $$record{"$version:resource.$partid.regrader"}) { $displaySub[2].=$$record{"$version:resource.$partid.regrader"}. - ' (<b>Part:</b> '.$partid.')'; + ' (<b>'.&mt('Part').':</b> '.$partid.')'; } } # needed because old essay regrader has not parts info @@ -3371,24 +3392,13 @@ sub getSequenceDropDown { return $result; } -#FIXME, I am in loncreatecourse, use that one instead -sub propath { - my ($udom,$uname)=@_; - $udom=~s/\W//g; - $uname=~s/\W//g; - my $subdir=$uname.'__'; - $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/; - my $proname="$Apache::lonnet::perlvar{'lonUsersDir'}/$udom/$subdir/$uname"; - return $proname; -} - sub scantron_uploads { if (!-e $Apache::lonnet::perlvar{'lonScansDir'}) { return ''}; my $result= '<select name="scantron_selectfile">'; my $cdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'}; my @files=&Apache::lonnet::dirlist('userfiles',$cdom,$cname, - &propath($cdom,$cname)); + &Apache::loncommon::propath($cdom,$cname)); foreach my $filename (@files) { ($filename)=split(/&/,$filename); if ($filename!~/^scantron_orig_/) { next ; } @@ -3425,12 +3435,12 @@ sub scantron_selectphase { #FIXME allow instructor to be able to download the scantron file # and to upload it, $result.= <<SCANTRONFORM; -<form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantro_process"> - <input type="hidden" name="command" value="scantron_validate" /> - $default_form_data - <table width="100%" border="0"> + <table width="100%" border="0"> <tr> <td bgcolor="#777777"> + <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantro_process"> + <input type="hidden" name="command" value="scantron_validate" /> + $default_form_data <table width="100%" border="0"> <tr bgcolor="#e6ffff"> <td> @@ -3459,16 +3469,52 @@ sub scantron_selectphase { <input type="text" name="scantron_maxbubble" /> </td> </tr> + <tr bgcolor="#ffffe6"> + <td> + <input type="submit" value="Validate Scantron Records" /> + </td> + </tr> </table> + </form> </td> </tr> +SCANTRONFORM + + $r->print($result); + + if (&Apache::lonnet::allowed('usc',$ENV{'request.role.domain'}) || + &Apache::lonnet::allowed('usc',$ENV{'request.course.id'})) { + + $r->print(<<SCANTRONFORM); + <tr> + <td bgcolor="#777777"> + <table width="100%" border="0"> + <tr bgcolor="#e6ffff"> + <td> + Specify a Scantron data file to upload. + </td> + </tr> + <tr bgcolor="#ffffe6"> + <td> +SCANTRONFORM + &scantron_upload_scantron_data($r); + + $r->print(<<SCANTRONFORM); + </td> + </tr> + </table> + </td> + </tr> +SCANTRONFORM + } + + $r->print(<<SCANTRONFORM); </table> - <input type="submit" value="Validate Scantron Records" /> </form> $grading_menu_button SCANTRONFORM - return $result; + return } sub get_scantron_config { @@ -3643,18 +3689,6 @@ sub scantron_filter { return 0; } -#FIXME I think I am doing this in the wrong order, I think it would be -#better to make a several passes analyzing all of the lines in the -#file for common errors wrong/invalid PID/username duplicated -#PID/username, missing bubbles, double bubbles, missing/invalid CODE -#and then get the instructor to fix all of these errors, then grade -#the corrected one, I'll still need to catch error conditions, but -#maybe most will taken care even before we start - -sub scantron_validate_file { - my ($r) = @_; -} - sub scantron_process_corrections { my ($r) = @_; my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'}); @@ -3764,10 +3798,6 @@ sub scantron_getfile { my $lines; $lines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'. 'scantron_orig_'.$ENV{'form.scantron_selectfile'}); - if ($lines eq '-1') { - #FIXME need to actually replicate file to course space - #FIXME when replicating strip CRLF to LF or CR to LF - } my %scanlines; $scanlines{'orig'}=[(split("\n",$lines,-1))]; my $temp=$scanlines{'orig'}; @@ -3876,8 +3906,7 @@ sub scantron_validate_ID { $found{'usernames'}{$username}++; } else { if ($id =~ /^\s*$/) { - my $username=&scan_data($scan_dat -a,"$i.user"); + my $username=&scan_data($scan_data,"$i.user"); if (defined($username) && $found{'usernames'}{$username}) { &scantron_get_correction($r,$i,$scan_record, \%scantron_config, @@ -3908,7 +3937,7 @@ sub scantron_get_correction { #to show both the current line and the previous one and allow skipping #the previous one or the current one - $r->print("<p>An error was detected ($error) "); + $r->print("<p><b>An error was detected ($error)</b>"); if ( defined($$scan_record{'scantron.PaperID'}) ) { $r->print(" for PaperID <tt>". $$scan_record{'scantron.PaperID'}."</tt> \n"); @@ -4079,12 +4108,12 @@ SCANTRONFORM &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state, 'Processing first student'); my $start=&Time::HiRes::time(); - + my $i=-1; + my ($uname,$udom); while ($i<$scanlines->{'count'}) { ($uname,$udom)=('',''); $i++; my $line=&scantron_get_line($scanlines,$i); -# $r->print('<pre>line is'.$line.'</pre>'); if ($line=~/^[\s\cz]*$/) { next; } my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config, $scan_data); @@ -4099,15 +4128,11 @@ SCANTRONFORM 'Student '.$uname.' has multiple sheets',2); next; } -# $r->print('<pre>doing studnet'.$uname.'</pre>'); ($uname,$udom)=split(/:/,$uname); &Apache::lonnet::delenv('form.counter'); &Apache::lonnet::appenv(%$scan_record); -# &Apache::lonhomework::showhash(%ENV); -# $Apache::lonxml::debug=1; -# &Apache::lonxml::debug("line is $line"); - - my $i=0; + + my $i=0; foreach my $resource (@resources) { $i++; my $result=&Apache::lonnet::ssi($resource->src(), @@ -4117,23 +4142,6 @@ SCANTRONFORM 'grade_domain' =>$udom, 'grade_courseid'=>$ENV{'request.course.id'}, 'grade_symb' =>$resource->symb())); -# my %score=&Apache::lonnet::restore($resource->symb(), -# $ENV{'request.course.id'}, -# $udom,$uname); -# foreach my $part ($resource->{PARTS}) { -# if ($score{'resource.'.$part.'.solved'} =~ /^correct/) { -# $studentcorrect++; -# $totalcorrect++; -# } else { -# $studentincorrect++; -# $totalincorrect++; -# } -# } -# $r->print('<pre>'. -# $resource->symb().'-'. -# $resource->src().'-'.'</pre>result is'.$result); -# &Apache::lonhomework::showhash(%score); - # if ($i eq 3) {last;} } $completedstudents{$uname}={'line'=>$line}; } continue { @@ -4141,32 +4149,11 @@ SCANTRONFORM &Apache::lonnet::delenv('scantron\.'); &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state, 'last student'); - #last; - #FIXME - #get iterator for $sequence - #foreach question 'submit' the students answer to the server - # through grade target { - # generate data to pass back that includes grade recevied - #} } &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); my $lasttime = &Time::HiRes::time()-$start; $r->print("<p>took $lasttime</p>"); - #$Apache::lonxml::debug=0; - foreach my $delay (@delayqueue) { - #FIXME - #print out each delayed student with interface to select how - # to repair student provided info - #Expected errors include - # 1 bad/no stuid/username - # 2 invalid bubblings - - } - #FIXME - # if delay queue exists 2 submits one to process delayed students one - # to ignore delayed students, possibly saving the delay queue for later - $navmap->untieHashes(); $r->print("<p>Done</p>"); $r->print(&show_grading_menu_form($symb,$url)); @@ -4180,6 +4167,7 @@ sub scantron_upload_scantron_data { 'domainid'); my $domsel=&Apache::loncommon::select_dom_form($ENV{'request.role.domain'}, 'domainid'); + my $default_form_data=&defaultFormData(&get_symb_and_url($r)); $r->print(<<UPLOAD); <script type="text/javascript" language="javascript"> function checkUpload(formname) { @@ -4192,6 +4180,7 @@ sub scantron_upload_scantron_data { </script> <form enctype='multipart/form-data' action='/adm/grades' name='rules' method='post'> +$default_form_data Course: <input name='courseid' type='text' /> Domain: $domsel $select_link <br /> @@ -4206,7 +4195,14 @@ UPLOAD sub scantron_upload_scantron_data_save { my($r)=@_; - $r->print("Doing upload to ".$ENV{'form.courseid'}); + if (!&Apache::lonnet::allowed('usc',$ENV{'form.domainid'}) && + !&Apache::lonnet::allowed('usc', + $ENV{'form.domainid'}.'_'.$ENV{'form.courseid'})) { + $r->print("You are not allowed to upload Scantron data to the requested course.<br />"); + $r->print(&show_grading_menu_form(&get_symb_and_url($r))); + return ''; + } + $r->print("Doing upload to ".$ENV{'form.courseid'}." <br />"); my $home=&Apache::lonnet::homeserver($ENV{'form.courseid'}, $ENV{'form.domainid'}); my $fname=$ENV{'form.upfile.filename'}; @@ -4224,10 +4220,10 @@ sub scantron_upload_scantron_data_save { # See if there is anything left unless ($fname) { return 'error: no uploaded file'; } $fname='scantron_orig_'.$fname; - &Apache::lonnet::logthis("fname is $fname"); $r->print(&Apache::lonnet::finishuserfileupload($ENV{'form.courseid'}, $ENV{'form.domainid'}, $home,'upfile',$fname)); + $r->print(&show_grading_menu_form(&get_symb_and_url($r))); return ''; } @@ -4334,7 +4330,7 @@ GRADINGMENUJS $result.='<table width="100%" border=0>'; $result.='<tr bgcolor="#ffffe6" valign="top"><td>'."\n". - ' Select Section: <select name="section">'."\n"; + ' '.&mt('Select Section').': <select name="section">'."\n"; if (ref($sections)) { foreach (sort (@$sections)) { $result.='<option value="'.$_.'" '. @@ -4343,7 +4339,7 @@ GRADINGMENUJS } $result.= '<option value="all" '.($saveSec eq 'all' ? 'selected="on"' : ''). '>all</select> '; - $result.='Student Status:</b>'.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,undef); + $result.=&mt('Student Status').':</b>'.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,undef); if (ref($sections) && (grep /no/,@$sections)) { $result.=' (Section "no" implies the students were not assigned a section.)<br />'; @@ -4352,8 +4348,8 @@ GRADINGMENUJS $result.='<tr bgcolor="#ffffe6"valign="top"><td>'. '<input type="radio" name="radioChoice" value="submission" '. - ($saveCmd eq 'submission' ? 'checked' : '').'> '.'<b>Current Resource:</b> For one or more students '. - '<select name="submitonly">'. + ($saveCmd eq 'submission' ? 'checked' : '').'> '.'<b>'.&mt('Current Resource').':</b> '.&mt('For one or more students'). + ' <select name="submitonly">'. '<option value="yes" '. ($saveSub eq 'yes' ? 'selected="on"' : '').'>with submissions</option>'. '<option value="graded" '. @@ -4416,7 +4412,11 @@ sub handler { &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}); my $url=$ENV{'form.url'}; my $symb=$ENV{'form.symb'}; - my $command=$ENV{'form.command'}; + 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); @@ -4510,12 +4510,16 @@ sub handler { } elsif ($command eq 'scantron_process' && $perm{'mgr'}) { $request->print(&scantron_process_students($request)); } elsif ($command eq 'scantronupload' && - &Apache::lonnet::allowed('usc',$ENV{'request.role.domain'})) { - $request->print(&scantron_upload_scantron_data($request)); - + (&Apache::lonnet::allowed('usc',$ENV{'request.role.domain'})|| + &Apache::lonnet::allowed('usc',$ENV{'request.course.id'}))) { + $request->print(&scantron_upload_scantron_data($request)); } elsif ($command eq 'scantronupload_save' && - &Apache::lonnet::allowed('usc',$ENV{'request.role.domain'})) { + (&Apache::lonnet::allowed('usc',$ENV{'request.role.domain'})|| + &Apache::lonnet::allowed('usc',$ENV{'request.course.id'}))) { $request->print(&scantron_upload_scantron_data_save($request)); + } elsif ($command eq 'scantrondownload' && + &Apache::lonnet::allowed('usc',$ENV{'request.course.id'})) { + $request->print(&scantron_download_scantron_data($request)); } elsif ($command) { $request->print("Access Denied ($command)"); }