--- loncom/homework/grades.pm 2003/07/28 18:04:39 1.126 +++ loncom/homework/grades.pm 2003/09/22 20:48:21 1.142 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.126 2003/07/28 18:04:39 ng Exp $ +# $Id: grades.pm,v 1.142 2003/09/22 20:48:21 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -96,6 +96,18 @@ sub get_fullname { return $fullname; } +#--- Format fullname, username:domain if different for display +#--- Use anywhere where the student names are listed +sub nameUserString { + my ($type,$fullname,$uname,$udom) = @_; + if ($type eq 'header') { + return '<b> Fullname </b><font color="#999999">(Username)</font> '; + } else { + return ' '.$fullname.'<font color="#999999"> ('.$uname. + ($ENV{'user.domain'} eq $udom ? '' : ' ('.$udom.')').')</font>'; + } +} + #--- Get the partlist and the response type for a given problem. --- #--- Indicate if a response type is coded handgraded or not. --- sub response_type { @@ -109,9 +121,8 @@ sub response_type { my ($responsetype,$part) = split(/_/,$_,2); my ($partid,$respid) = split(/_/,$part); $responsetype =~ s/response$//; # make it compatible w/ navmaps - should move to that!! -# my ($value) = &Apache::lonnet::EXT('resource.'.$part.'.handgrade',$symb); -# $handgrade{$part} = $responsetype.':'.($value eq 'yes' ? 'yes' : 'no'); #a bug $value is 'yes' regardless - $handgrade{$part} = $responsetype.':'.(($allkeys =~ /parameter_$part\_handgrade/) ? 'yes' : 'no'); + my ($value) = &Apache::lonnet::EXT('resource.'.$part.'.handgrade',$symb); + $handgrade{$part} = $responsetype.':'.($value eq 'yes' ? 'yes' : 'no'); next if ($seen{$partid} > 0); $seen{$partid}++; push @partlist,$partid; @@ -207,7 +218,8 @@ sub commonJSfunctions { } } } else { - if (selectOne.selected) return selectOne.value; + // only one value it must be the selected one + return selectOne.value; } } </script> @@ -299,7 +311,7 @@ sub student_gradeStatus { my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname); my %partstatus = (); foreach (@$partlist) { - my ($status,$foo) = split(/_/,$record{"resource.$_.solved"},2); + my ($status,undef) = split(/_/,$record{"resource.$_.solved"},2); $status = 'nothing' if ($status eq ''); $partstatus{$_} = $status; my $subkey = "resource.$_.submitted_by"; @@ -506,8 +518,8 @@ LISTJAVASCRIPT my $saveStatus = $ENV{'form.Status'} eq '' ? 'Active' : $ENV{'form.Status'}; $ENV{'form.Status'} = $saveStatus; - $gradeTable.='<input type="radio" name="lastSub" value="lastonly" '.$checklastsub.' /> last sub only'."\n". - '<input type="radio" name="lastSub" value="last" /> last sub & parts info'."\n". + $gradeTable.='<input type="radio" name="lastSub" value="lastonly" '.$checklastsub.' /> last submission only'."\n". + '<input type="radio" name="lastSub" value="last" /> last submission & parts info'."\n". '<input type="radio" name="lastSub" value="datesub" /> by dates and submissions'."\n". '<input type="radio" name="lastSub" value="all" /> all details'."\n". '<input type="hidden" name="section" value="'.$getsec.'" />'."\n". @@ -533,15 +545,14 @@ LISTJAVASCRIPT $gradeTable.='<input type="button" '."\n". 'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n". 'value="Next->" />'."\n"; - + $gradeTable.='<input type="checkbox" name="checkPlag" checked="on">Check For Plagiarism</input>'; my (undef, undef, $fullname) = &getclasslist($getsec,'1'); $gradeTable.='<table border="0"><tr><td bgcolor="#777777">'. '<table border="0"><tr bgcolor="#e6ffff">'; my $loop = 0; while ($loop < 2) { $gradeTable.='<td><b> No.</b> </td><td><b> Select </b></td>'. - '<td><b> Fullname </b>'. - '<font color="#999999">(Username)</font> </td>'; + '<td>'.&nameUserString('header').'</td>'; if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { foreach (sort(@$partlist)) { $gradeTable.='<td><b> Part '.(split(/_/))[0].' Status </b></td>'; @@ -578,8 +589,7 @@ LISTJAVASCRIPT $gradeTable.='<td align="right">'.$ctr.' </td>'. '<td align="center"><input type=checkbox name="stuinfo" value="'. $student.':'.$$fullname{$student}.' "></td>'."\n". - '<td> '.$$fullname{$student}.' '."\n". - '<font color="#999999">('.$uname.')</font></td>'."\n"; + '<td>'.&nameUserString(undef,$$fullname{$student},$uname,$udom).'</td>'."\n"; if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { foreach (sort keys(%status)) { @@ -755,12 +765,13 @@ sub sub_page_js { for (i=0;i<=total;i++) { for (j=0;j<parttot;j++) { var partid = formname["partid"+i+"_"+j].value; - var selopt = formname["GD_SEL"+i+"_"+partid]; - if (selopt[0].selected) { + if (formname["GD_SEL"+i+"_"+partid][0].selected) { var points = formname["GD_BOX"+i+"_"+partid].value; if (points == "") { var name = formname["name"+i].value; - var resp = confirm("You did not assign a score for "+name+", part "+partid+". Continue?"); + var studentID = (name != '' ? name : formname["unamedom"+i].value); + var resp = confirm("You did not assign a score for "+studentID+ + ", part "+partid+". Continue?"); if (resp == false) { formname["GD_BOX"+i+"_"+partid].focus(); return false; @@ -788,8 +799,7 @@ sub sub_page_js { var ptr = 0; for (i=1;i<total;i++) { var partid = formname["q_"+i].value; - var selopt = formname["GD_SEL"+i+"_"+partid]; - if (selopt[0].selected) { + if (formname["GD_SEL"+i+"_"+partid][0].selected) { var points = formname["GD_BOX"+i+"_"+partid].value; var status = formname["solved"+i+"_"+partid].value; if (points == "" && status != "correct_by_student") { @@ -837,8 +847,8 @@ sub sub_page_kw_js { if (nret==null) return; formname.keywords.value = nret; - formname.refresh.value = "on"; if (formname.keywords.value != "") { + formname.refresh.value = "on"; formname.submit(); } return; @@ -865,10 +875,9 @@ sub sub_page_kw_js { } var nret = prompt("Add selection to keyword list? Edit if desired.",cleantxt); if (nret==null) return; - var curlist = document.SCORE.keywords.value; - document.SCORE.keywords.value = curlist+" "+nret; - document.SCORE.refresh.value = "on"; + document.SCORE.keywords.value = document.SCORE.keywords.value+" "+nret; if (document.SCORE.keywords.value != "") { + document.SCORE.refresh.value = "on"; document.SCORE.submit(); } return; @@ -885,8 +894,7 @@ sub sub_page_kw_js { var Nmsg = msgform.savemsgN.value; savedMsgHeader(Nmsg,usrctr,fullname); var subject = msgform.msgsub.value; - var rtrchk = document.SCORE["includemsg"+usrctr]; - var msgchk = rtrchk.value; + var msgchk = document.SCORE["includemsg"+usrctr].value; re = /msgsub/; var shwsel = ""; if (re.test(msgchk)) { shwsel = "checked" } @@ -934,7 +942,6 @@ sub sub_page_kw_js { height = 600; scrollbar = "yes"; } -// if (window.pWin) {window.pWin.close(); window.pWin=null} var xpos = (screen.width-600)/2; xpos = (xpos < 0) ? '0' : xpos; var ypos = (screen.height-height)/2-30; @@ -943,6 +950,7 @@ sub sub_page_kw_js { pWin = window.open('', 'MessageCenter', 'toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=600,height='+height); pWin.focus(); pDoc = pWin.document; + pDoc.open('text/html','replace'); pDoc.write("<html><head>"); pDoc.write("<title>Message Central</title>"); @@ -1029,6 +1037,7 @@ sub sub_page_kw_js { pDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>"); pDoc.write("</form>"); pDoc.write("</body></html>"); + pDoc.close(); } //====================== Script for keyword highlight options ============== @@ -1072,6 +1081,7 @@ sub sub_page_kw_js { hwdWin = window.open('', 'KeywordHighlightCentral', 'toolbar=no,location=no,scrollbars=no,width=400,height=300,screenx='+xpos+',screeny='+ypos); hwdWin.focus(); var hDoc = hwdWin.document; + hDoc.open('text/html','replace'); hDoc.write("<html><head>"); hDoc.write("<title>Highlight Central</title>"); @@ -1120,6 +1130,7 @@ sub sub_page_kw_js { hDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>"); hDoc.write("</form>"); hDoc.write("</body></html>"); + hDoc.close(); } </script> @@ -1353,9 +1364,7 @@ KEYWORDS 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>'.$ENV{'form.fullname'}. - '<font color="#999999"> Username: '.$uname. - ($ENV{'user.domain'} eq $udom ? '' : ' ('.$udom.')').'</font><br />'."\n"; + $result.='<b>Fullname: </b>'.&nameUserString(undef,$ENV{'form.fullname'},$uname,$udom).'<br />'."\n"; $result.='<input type="hidden" name="name'.$counter. '" value="'.$ENV{'form.fullname'}.'" />'."\n"; @@ -1453,13 +1462,20 @@ KEYWORDS my ($ressub,$subval) = split(/:/,$_,2); # Similarity check my $similar=''; - my ($oname,$odom,$ocrsid,$oessay,$osim)=&most_similar($uname,$udom,$subval); - if ($osim) { - $osim=int($osim*100.0); - $similar='<hr /><h3><font color="#FF0000">Essay is '.$osim. - '% similar to an essay by '.&Apache::loncommon::plainname($oname,$odom). - '</font></h3><blockquote><i>'. - &keywords_highlight($oessay).'</i></blockquote><hr />'; + my $oname; + my $odom; + my $ocrsid; + my $oessay; + my $osim; + if($ENV{'form.checkPlag'}){ + ($oname,$odom,$ocrsid,$oessay,$osim)=&most_similar($uname,$udom,$subval); + if ($osim) { + $osim=int($osim*100.0); + $similar='<hr /><h3><font color="#FF0000">Essay is '.$osim. + '% similar to an essay by '.&Apache::loncommon::plainname($oname,$odom). + '</font></h3><blockquote><i>'. + &keywords_highlight($oessay).'</i></blockquote><hr />'; + } } $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '. $partid.'</b> <font color="#999999">( ID '.$respid. @@ -1472,7 +1488,7 @@ KEYWORDS 'this file may contain virusses</font><br />':''). '<b>Submitted Answer: </b>'. &cleanRecord($subval,$responsetype,$symb). - '<br /><br />'.$similar."\n" + '<br /><br />'.$similar."\n" if ($ENV{'form.lastSub'} eq 'lastonly' || ($ENV{'form.lastSub'} eq 'hdgrade' && $$handgrade{$part} =~ /:yes$/)); @@ -1533,17 +1549,21 @@ KEYWORDS my %seen = (); my @partlist; + my @gradePartRespid; for (sort keys(%$handgrade)) { my ($partid,$respid) = split(/_/); next if ($seen{$partid} > 0); $seen{$partid}++; next if ($$handgrade{$_} =~ /: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. '" value="'.(join ":",@partlist).'" />'."\n"; + $result.='<input type="hidden" name="gradePartRespid'. + '" value="'.(join ":",@gradePartRespid).'" />'."\n" if ($counter == 0); my $ctr = 0; while ($ctr < scalar(@partlist)) { $result.='<input type="hidden" name="partid'.$counter.'_'.$ctr.'" value="'. @@ -1769,21 +1789,19 @@ sub processHandGrade { } } $ctr = 0; - my ($partlist,$handgrade) = &response_type($ENV{'form.url'},$symb); @parsedlist = reverse @parsedlist if ($button eq 'Previous'); foreach my $student (@parsedlist) { my ($uname,$udom) = split(/:/,$student); if ($ENV{'form.submitonly'} eq 'yes') { - my (%status) = &student_gradeStatus($ENV{'form.url'},$symb,$udom,$uname,$partlist) ; + my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname); my $statusflg = ''; - foreach (keys(%status)) { - $statusflg = 1 if ($status{$_} ne 'nothing'); - my ($foo,$partid,$foo1) = split(/\./); - $statusflg = '' if ($status{'resource.'.$partid.'.submitted_by'} ne ''); + foreach (split(/:/,$ENV{'form.gradePartRespid'})){ + $statusflg = 1 if (exists ($record{'resource.'.$_.'.submission'})); } next if ($statusflg eq ''); } push @nextlist,$student if ($ctr < $ntstu); + last if ($ctr == $ntstu); $ctr++; } @@ -2121,7 +2139,7 @@ sub viewgrades { $result.= '<h3>Assign Grade to Specific Students in '.$sectionClass; $result.= '<table border=0><tr><td bgcolor="#777777">'."\n". '<table border=0><tr bgcolor="#deffff"><td> <b>No.</b> </td>'. - '<td> <b>Fullname</b> <font color="#999999">(Username)</font></td>'."\n"; + '<td>'.&nameUserString('header')."</td>\n"; my (@parts) = sort(&getpartlist($url)); foreach my $part (@parts) { my $display=&Apache::lonnet::metadata($url,$part.'.display'); @@ -2165,7 +2183,7 @@ sub viewgrades { #--- call by previous routine to display each student sub viewstudentgrade { - my ($$url,$symb,$courseid,$student,$fullname,$parts,$weight,$ctr) = @_; + my ($url,$symb,$courseid,$student,$fullname,$parts,$weight,$ctr) = @_; my ($uname,$udom) = split(/:/,$student); $student=~s/:/_/; my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname); @@ -2221,8 +2239,9 @@ sub editgrades { $title.='<font size=+1><b>Section: </b>'.$ENV{'form.section'}.'</font>'."\n"; my $result= '<table border="0"><tr><td bgcolor="#777777">'."\n"; - $result.= '<table border="0"><tr bgcolor="#deffff"><td rowspan=2> <b>No.</b> </td>'. - '<td rowspan=2> <b>Fullname</b> <font color="#999999">(username)</font></td>'."\n"; + $result.= '<table border="0"><tr bgcolor="#deffff">'. + '<td rowspan=2 valign="center"> <b>No.</b> </td>'. + '<td rowspan=2 valign="center">'.&nameUserString('header')."</td>\n"; my %scoreptr = ( 'correct' =>'correct_by_override', @@ -2281,8 +2300,7 @@ sub editgrades { my ($uname,$udom)=split(/_/,$user); my %newrecord; my $updateflag = 0; - $line .= '<td> '.$$fullname{$usercolon}. - ' <font color="#999999">('.$uname.($udom eq $ENV{'user.domain'} ? '' : '$udom').')</font></td>'; + $line .= '<td>'.&nameUserString(undef,$$fullname{$usercolon},$uname,$udom).'</td>'; my $usec=$classlist->{"$uname:$udom"}[5]; if (!&canmodify($usec)) { my $numcols=scalar(@partid)*4+2; @@ -2317,18 +2335,17 @@ sub editgrades { $newrecord{'resource.'.$_.'.awarded'} = 0; $newrecord{'resource.'.$_.'.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}"; $updateflag = 1; + } elsif (!($old_part eq $partial && $old_score eq $score)) { + $updateflag = 1; + $newrecord{'resource.'.$_.'.awarded'} = $partial if $partial ne ''; + $newrecord{'resource.'.$_.'.solved'} = $score; + $rec_update++; } $line .= '<td align="center">'.$old_aw.' </td>'. '<td align="center">'.$awarded. ($score eq 'excused' ? $score : '').' </td>'; - if (!($old_part eq $partial && $old_score eq $score)) { - $updateflag = 1; - $newrecord{'resource.'.$_.'.awarded'} = $partial if $partial ne ''; - $newrecord{'resource.'.$_.'.solved'} = $score; - $rec_update++; - } my $partid=$_; foreach my $stores (@parts) { @@ -2500,7 +2517,6 @@ to this page if the data selected is ins $javascript </script> ENDPICK - $request->print(&show_grading_menu_form($symb,$url)); return ''; } @@ -2717,7 +2733,9 @@ LISTJAVASCRIPT $result.='<form action="/adm/grades" method="post" name="displayPage">'."\n"; $result.=' <b>Problems from:</b> <select name="selectpage">'."\n"; my ($titles,$symbx) = &getSymbMap($request); - my ($curpage,$type,$mapId) = ($symb =~ /(.*?\.(page|sequence))___(\d+)___/); + my ($curpage) =&Apache::lonnet::decode_symb($symb); +# my ($curpage,$mapId) =&Apache::lonnet::decode_symb($symb); +# my $type=($curpage =~ /\.(page|sequence)/); my $ctr=0; foreach (@$titles) { my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/); @@ -2761,9 +2779,9 @@ LISTJAVASCRIPT '<table border="0"><tr><td bgcolor="#777777">'. '<table border="0"><tr bgcolor="#e6ffff">'. '<td align="right"> <b>No.</b></td>'. - '<td><b> Fullname <font color="#999999">(username)</font></b></td>'. + '<td>'.&nameUserString('header').'</td>'. '<td align="right"> <b>No.</b></td>'. - '<td><b> Fullname <font color="#999999">(username)</font></b></td></tr>'; + '<td>'.&nameUserString('header').'</td></tr>'; my (undef,undef,$fullname) = &getclasslist($getsec,'1'); my $ptr = 1; @@ -2771,8 +2789,8 @@ LISTJAVASCRIPT 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.'" /> '.$$fullname{$student}. - '<font color="#999999"> ('.$uname.($udom eq $cdom ? '':':'.$udom).')</font>'."\n"; + $studentTable.='<td> <input type="radio" name="student" value="'.$student.'" /> ' + .&nameUserString(undef,$$fullname{$student},$uname,$udom)."\n"; $studentTable.=($ptr%2 == 0 ? '</td></tr>' : ''); $ptr++; } @@ -2789,9 +2807,7 @@ LISTJAVASCRIPT sub getSymbMap { my ($request) = @_; - my $navmap = Apache::lonnavmaps::navmap-> new($ENV{'request.course.fn'}.'.db', - $ENV{'request.course.fn'}.'_parms.db'); - $navmap->init(); + my $navmap = Apache::lonnavmaps::navmap->new(); my %symbx = (); my @titles = (); @@ -2831,15 +2847,13 @@ sub displayPage { return; } my $result='<h3><font color="#339933"> '.$ENV{'form.title'}.'</font></h3>'; - $result.='<h3> Student: '.$$fullname{$ENV{'form.student'}}. - '<font color="#999999"> ('.$uname.($udom eq $cdom ? '':':'.$udom).')</font></h3>'."\n"; - + $result.='<h3> Student: '.&nameUserString(undef,$$fullname{$ENV{'form.student'}},$uname,$udom). + '</h3>'."\n"; &sub_page_js($request); $request->print($result); - my $navmap = Apache::lonnavmaps::navmap-> new($ENV{'request.course.fn'}.'.db', - $ENV{'request.course.fn'}.'_parms.db',1, 1); - my ($mapUrl, $id, $resUrl) = split(/___/, $ENV{'form.page'}); + 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 my $iterator = $navmap->getIterator($map->map_start(), @@ -2995,14 +3009,13 @@ sub updateGradeByPage { return; } my $result='<h3><font color="#339933"> '.$ENV{'form.title'}.'</font></h3>'; - $result.='<h3> Student: '.$ENV{'form.fullname'}. - '<font color="#999999"> ('.$uname.($udom eq $cdom ? '':':'.$udom).')</font></h3>'."\n"; + $result.='<h3> Student: '.&nameUserString(undef,$ENV{'form.fullname'},$uname,$udom). + '</h3>'."\n"; $request->print($result); - my $navmap = Apache::lonnavmaps::navmap-> new($ENV{'request.course.fn'}.'.db', - $ENV{'request.course.fn'}.'_parms.db',1, 1); - my ($mapUrl, $id, $resUrl) = split(/___/, $ENV{'form.page'}); + 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 my $iterator = $navmap->getIterator($map->map_start(), @@ -3124,7 +3137,7 @@ sub getSequenceDropDown { my ($request,$symb)=@_; my $result='<select name="selectpage">'."\n"; my ($titles,$symbx) = &getSymbMap($request); - my ($curpage,$type,$mapId) = ($symb =~ /(.*?\.(page|sequence))___(\d+)___/); + my ($curpage)=&Apache::lonnet::decode_symb($symb); my $ctr=0; foreach (@$titles) { my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/); @@ -3176,7 +3189,7 @@ sub scantron_selectphase { my $result; $result.= <<SCANTRONFORM; <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantro_process"> - <input type="hidden" name="command" value="scantron_process" /> + <input type="hidden" name="command" value="scantron_validate" /> $default_form_data <table width="100%" border="0"> <tr> @@ -3206,7 +3219,7 @@ sub scantron_selectphase { </td> </tr> </table> - <input type="submit" value="Submit" /> + <input type="submit" value="Validate Scantron Records" /> </form> $grading_menu_button SCANTRONFORM @@ -3288,14 +3301,23 @@ sub scantron_parse_scanline { } sub scantron_add_delay { + my ($delayqueue,$scanline,$errormessage,$errorcode)=@_; + Apache->request->print('add_delay_error '.$_[2] ); + push(@$delayqueue, + {'line' => $scanline, 'emsg' => $errormessage, + 'ecode' => $errorcode } + ); } sub scantron_find_student { my ($scantron_record,$idmap)=@_; my $scanID=$$scantron_record{'scantron.ID'}; foreach my $id (keys(%$idmap)) { - Apache->request->print('<pre>checking studnet -'.$id.'- againt -'.$scanID.'- </pre>'); - if (lc($id) eq lc($scanID)) { Apache->request->print('success');return $$idmap{$id}; } + #Apache->request->print('<pre>checking studnet -'.$id.'- againt -'.$scanID.'- </pre>'); + if (lc($id) eq lc($scanID)) { + #Apache->request->print('success'); + return $$idmap{$id}; + } } return undef; } @@ -3308,9 +3330,21 @@ 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_students { my ($r) = @_; - my (undef,undef,$sequence)=split(/___/,$ENV{'form.selectpage'}); + my (undef,undef,$sequence)=&Apache::lonnet::decode_symb($ENV{'form.selectpage'}); my ($symb,$url)=&get_symb_and_url($r); if (!$symb) {return '';} my $default_form_data=&defaultFormData($symb,$url); @@ -3320,10 +3354,10 @@ sub scantron_process_students { my @scanlines=<$scanlines>; my $classlist=&Apache::loncoursedata::get_classlist(); my %idmap=&username_to_idmap($classlist); - my $navmap=Apache::lonnavmaps::navmap->new($ENV{'request.course.fn'}.'.db',$ENV{'request.course.fn'}.'_parms.db',1, 1); + my $navmap=Apache::lonnavmaps::navmap->new(); my $map=$navmap->getResourceByUrl($sequence); my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); - $r->print("geto ".scalar(@resources)."<br />"); +# $r->print("geto ".scalar(@resources)."<br />"); my $result= <<SCANTRONFORM; <form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantronupload"> <input type="hidden" name="command" value="scantron_configphase" /> @@ -3332,29 +3366,36 @@ SCANTRONFORM $r->print($result); my @delayqueue; - my $totalcorrect; - my $totalincorrect; - + my %completedstudents; + my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r, 'Scantron Status','Scantron Progress',scalar(@scanlines)); + &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state, + 'Processing first student'); + my $start=&Time::HiRes::time(); foreach my $line (@scanlines) { - my $studentcorrect; - my $studentincorrect; + $r->print('<pre>line is'.$line.'</pre>'); chomp($line); my $scan_record=&scantron_parse_scanline($line,\%scantron_config); my ($uname,$udom); - if ($uname=&scantron_find_student($scan_record,\%idmap)) { + unless ($uname=&scantron_find_student($scan_record,\%idmap)) { + &scantron_add_delay(\@delayqueue,$line, + 'Unable to find a student that matches',1); + next; + } + if (exists $completedstudents{$uname}) { &scantron_add_delay(\@delayqueue,$line, - 'Unable to find a student that matches'); + '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"); +# $Apache::lonxml::debug=1; +# &Apache::lonxml::debug("line is $line"); my $i=0; foreach my $resource (@resources) { @@ -3366,31 +3407,31 @@ 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); +# 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 { &Apache::lonnet::delenv('form.counter'); &Apache::lonnet::delenv('scantron\.'); &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state, - 'last student Who got a '.$studentcorrect.' correct and '. - $studentincorrect.' incorrect. The class has gotten '. - $totalcorrect.' correct and '.$totalincorrect.' incorrect'); - last; + 'last student'); + #last; #FIXME #get iterator for $sequence #foreach question 'submit' the students answer to the server @@ -3398,7 +3439,11 @@ SCANTRONFORM # generate data to pass back that includes grade recevied #} } - $Apache::lonxml::debug=0; + &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 @@ -3584,9 +3629,9 @@ sub handler { undef(%perm); if ($ENV{'browser.mathml'}) { - $request->content_type('text/xml'); + &Apache::loncommon::content_type($request,'text/xml'); } else { - $request->content_type('text/html'); + &Apache::loncommon::content_type($request,'text/html'); } $request->send_http_header; return '' if $request->header_only; @@ -3596,7 +3641,7 @@ sub handler { my $command=$ENV{'form.command'}; if (!$url) { my ($temp1,$temp2); - ($temp1,$temp2,$ENV{'form.url'})=split(/___/,$symb); + ($temp1,$temp2,$ENV{'form.url'})=&Apache::lonnet::decode_symb($symb); $url = $ENV{'form.url'}; } &send_header($request); @@ -3609,7 +3654,7 @@ sub handler { my ($tsymb,$tuname,$tudom,$tcrsid)= &Apache::lonnet::checkin($token); if ($tsymb) { - my ($map,$id,$url)=split(/\_\_\_/,$tsymb); + my ($map,$id,$url)=&Apache::lonnet::decode_symb($tsymb); if (&Apache::lonnet::allowed('mgr',$tcrsid)) { $request->print(&Apache::lonnet::ssi_body('/res/'.$url, ('grade_username' => $tuname, @@ -3681,6 +3726,8 @@ sub handler { } } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) { $request->print(&scantron_selectphase($request)); + } elsif ($command eq 'scantron_validate' && $perm{'mgr'}) { + $request->print(&scantron_validate_file($request)); } elsif ($command eq 'scantron_process' && $perm{'mgr'}) { $request->print(&scantron_process_students($request)); } elsif ($command) {