--- loncom/homework/grades.pm 2003/03/28 18:15:24 1.79 +++ loncom/homework/grades.pm 2003/04/21 18:39:43 1.86 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.79 2003/03/28 18:15:24 bowersj2 Exp $ +# $Id: grades.pm,v 1.86 2003/04/21 18:39:43 ng Exp $ # # Copyright Michigan State University Board of Trustees # @@ -343,8 +343,8 @@ LISTJAVASCRIPT my $checklastsub = $ENV{'form.handgrade'} eq 'yes' ? '' : 'checked'; my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'."\n". - ' <b>View Problem: </b><input type="radio" name="vProb" value="no" /> no '."\n". - '<input type="radio" name="vProb" value="yes" checked /> one student '."\n". + ' <b>View Problem: </b><input type="radio" name="vProb" value="no" checked /> no '."\n". + '<input type="radio" name="vProb" value="yes" /> one student '."\n". '<input type="radio" name="vProb" value="all" /> all students <br />'."\n". ' <b>Submissions: </b>'."\n"; if ($ENV{'form.handgrade'} eq 'yes') { @@ -628,6 +628,7 @@ SUBJAVASCRIPT #--- javascript for essay type problem -- sub sub_page_kw_js { my $request = shift; + my $iconpath = $request->dir_config('lonIconsURL'); $request->print(<<SUBJAVASCRIPT); <script type="text/javascript" language="javascript"> @@ -675,6 +676,12 @@ sub sub_page_kw_js { } //====================== Script for composing message ============== + // preload images + img1 = new Image(); + img1.src = "$iconpath/mailbkgrd.gif"; + img2 = new Image(); + img2.src = "$iconpath/mailto.gif"; + function msgCenter(msgform,usrctr,fullname) { var Nmsg = msgform.savemsgN.value; savedMsgHeader(Nmsg,usrctr,fullname); @@ -710,7 +717,7 @@ sub sub_page_kw_js { height = 600; scrollbar = "yes"; } -// if (window.pWin) window.pWin.close(); +// if (window.pWin) {window.pWin.close(); window.pWin=null} pWin = window.open('', 'MessageCenter', 'toolbar=no,location=no,scrollbars='+scrollbar+',screenx=70,screeny=75,width=600,height='+height); pWin.focus(); pDoc = pWin.document; @@ -729,18 +736,23 @@ sub sub_page_kw_js { pDoc.write(" if (document.msgcenter.subchk.checked) {"); pDoc.write(" msgchk = \\"msgsub,\\";"); pDoc.write(" }"); - pDoc.write( "for (var i=1; i<=nmsg; i++) {"); + pDoc.write(" var includemsg = 0;"); + pDoc.write(" for (var i=1; i<=nmsg; i++) {"); pDoc.write(" var opnmsg = eval(\\"opener.document.SCORE.savemsg\\"+i);"); pDoc.write(" var frmmsg = eval(\\"document.msgcenter.msg\\"+i);"); pDoc.write(" opnmsg.value = frmmsg.value;"); pDoc.write(" var chkbox = eval(\\"document.msgcenter.msgn\\"+i);"); pDoc.write(" if (chkbox.checked) {"); pDoc.write(" msgchk += \\"savemsg\\"+i+\\",\\";"); + pDoc.write(" includemsg = 1;"); pDoc.write(" }"); pDoc.write(" }"); pDoc.write(" if (document.msgcenter.newmsgchk.checked) {"); pDoc.write(" msgchk += \\"newmsg\\"+usrctr;"); + pDoc.write(" includemsg = 1;"); pDoc.write(" }"); + pDoc.write(" imgformname = eval(\\"opener.document.SCORE.mailicon\\"+usrctr);"); + pDoc.write(" imgformname.src = \\"$iconpath/\\"+((includemsg) ? \\"mailto.gif\\" : \\"mailbkgrd.gif\\");"); pDoc.write(" var includemsg = eval(\\"opener.document.SCORE.includemsg\\"+usrctr);"); pDoc.write(" includemsg.value = msgchk;"); @@ -1030,7 +1042,7 @@ sub submission { $request->print('<form action="/adm/grades" method="post" name="SCORE">'."\n". '<input type="hidden" name="command" value="handgrade" />'."\n". - '<input type="hidden" name="saveState" value="'.$ENV{'form.saveState'}.'" />'."\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="refresh" value="off" />'."\n". '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". @@ -1054,7 +1066,9 @@ sub submission { my ($cts,$prnmsg) = (1,''); while ($cts <= $ENV{'form.savemsgN'}) { $prnmsg.='<input type="hidden" name="savemsg'.$cts.'" value="'. - ($keyhash{$symb.'_savemsg'.$cts} eq '' ? $ENV{'form.savemsg'.$cts} : $keyhash{$symb.'_savemsg'.$cts}). + ($keyhash{$symb.'_savemsg'.$cts} eq '' ? + &Apache::lonfeedback::clear_out_html($ENV{'form.savemsg'.$cts}) : + &Apache::lonfeedback::clear_out_html($keyhash{$symb.'_savemsg'.$cts})). '" />'."\n"; $cts++; } @@ -1094,8 +1108,7 @@ KEYWORDS my @col_fullnames; my ($classlist,$fullname); if ($ENV{'form.handgrade'} eq 'yes') { - my @col_list; - ($classlist,undef,$fullname) = &getclasslist('all',$ENV{'form.showgrading'} eq 'yes' ? '1' : '0'); + ($classlist,undef,$fullname) = &getclasslist('all','0'); for (keys (%$handgrade)) { my $ncol = &Apache::lonnet::EXT('resource.'.$_. '.maxcollaborators', @@ -1103,50 +1116,46 @@ KEYWORDS next if ($ncol <= 0); s/\_/\./g; next if ($record{'resource.'.$_.'.collaborators'} eq ''); - my (@collaborators) = split(/,?\s+/, - $record{'resource.'.$_.'.collaborators'}); - my (@badcollaborators); - if (scalar(@collaborators) != 0) { + my @goodcollaborators = (); + my @badcollaborators = (); + foreach (split(/,?\s+/,$record{'resource.'.$_.'.collaborators'})) { + $_ =~ s/[\$\^\(\)]//g; + next if ($_ eq ''); + my ($co_name,$co_dom) = split /\@|:/,$_; + $co_dom = $udom if (! defined($co_dom) || $co_dom =~ /^domain$/i); + next if ($co_name eq $uname && $co_dom eq $udom); + # Doing this grep allows 'fuzzy' specification + my @Matches = grep /^$co_name:$co_dom$/i,keys %$classlist; + if (! scalar(@Matches)) { + push @badcollaborators,$_; + } else { + push @goodcollaborators, @Matches; + } + } + if (scalar(@goodcollaborators) != 0) { $result.='<b>Collaborators: </b>'; - foreach my $collaborator (@collaborators) { - my ($co_name,$co_dom) = split /\@|:/,$collaborator; - $co_dom = $udom if (! defined($co_dom)); - next if ($co_name eq $uname && $co_dom eq $udom); - # Doing this grep allows 'fuzzy' specification - my @Matches = grep /^$co_name:$co_dom/i, - keys %$classlist; - if (! scalar(@Matches)) { - push @badcollaborators,$collaborator; - next; - } - push @col_list, @Matches; - foreach (@Matches) { - my ($lastname,$givenn) = split(/,/,$$fullname{$_}); - push @col_fullnames, $givenn.' '.$lastname; - $result.=$$fullname{$_}.' '; - } - } + foreach (@goodcollaborators) { + my ($lastname,$givenn) = split(/,/,$$fullname{$_}); + push @col_fullnames, $givenn.' '.$lastname; + $result.=$$fullname{$_}.' '; + } $result.='<br />'."\n"; - if (scalar(@badcollaborators) > 0) { - $result.='<table border="0"><tr bgcolor="#ffbbbb"><td>'; - $result.='This student has submitted '; - if (scalar(@badcollaborators) == 1) { - $result .= 'an invalid collaborator'; - } else { - $result .= 'invalid collaborators'; - } - $result .= ': '.join(', ',@badcollaborators); - $result .= '</td></tr></table>'; - } - if (scalar(@collaborators > $ncol)) { - $result .= '<table border="0"><tr bgcolor="#ffbbbb"><td>'; - $result .= 'This student has submitted too many '. - 'collaborators. Maximum is '.$ncol; - $result .= '</td></tr></table>'; - } - $result.='<input type="hidden" name="collaborator'.$counter. - '" value="'.(join ':',@col_list).'" />'."\n"; - } + $result.='<input type="hidden" name="collaborator'.$counter. + '" value="'.(join ':',@goodcollaborators).'" />'."\n"; + } + if (scalar(@badcollaborators) > 0) { + $result.='<table border="0"><tr bgcolor="#ffbbbb"><td>'; + $result.='This student has submitted '; + $result.=(scalar(@badcollaborators) == 1) ? 'an invalid collaborator' : 'invalid collaborators'; + $result .= ': '.join(', ',@badcollaborators); + $result .= '</td></tr></table>'; + } + if (scalar(@badcollaborators > $ncol)) { + $result .= '<table border="0"><tr bgcolor="#ffbbbb"><td>'; + $result .= 'This student has submitted too many '. + 'collaborators. Maximum is '.$ncol.'.'; + $result .= '</td></tr></table>'; + } } } $request->print($result."\n"); @@ -1226,10 +1235,13 @@ KEYWORDS my $lastone = pop @col_fullnames; $msgfor .= ', '.(join ', ',@col_fullnames).' and '.$lastone.'.'; } + $msgfor =~ s/\'/\\'/g; #\' $result.='<tr><td bgcolor="#ffffff">'."\n". ' <a href="javascript:msgCenter(document.SCORE,'.$counter. ',\''.$msgfor.'\')"; TARGET=_self>'. - 'Compose Message to student'.(scalar(@col_fullnames) >= 1 ? 's' : '').'</a>'. + 'Compose Message to student'.(scalar(@col_fullnames) >= 1 ? 's' : '').'</a> '. + '<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'); $request->print($result); @@ -1348,7 +1360,6 @@ sub processHandGrade { $ctr++; next; } - my $includemsg = $ENV{'form.includemsg'.$ctr}; my ($subject,$message,$msgstatus) = ('','',''); if ($includemsg =~ /savemsg|newmsg\Q$ctr\E/) { @@ -1357,9 +1368,11 @@ sub processHandGrade { foreach (@msgnum) { $message.=$ENV{'form.'.$_} if ($_ =~ /savemsg|newmsg/ && $_ ne ''); } - $message =~ s/<([^>]|\n)*>//g; # removes html codes Or should this be lonnet::escape ?? + $message =&Apache::lonfeedback::clear_out_html($message); $message.="\n\nPoint".($pts > 1 ? 's':'').' awarded = '.$pts.' out of '.$wgt; - $message.=" for <a href=\"$url?symb=$symb\">$ENV{'form.probTitle'}</a>"; + $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); } @@ -1420,12 +1433,20 @@ sub processHandGrade { $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); # Called by Save & Refresh from Highlight Attribute Window + my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'0'); if ($ENV{'form.refresh'} eq 'on') { - my $ctr = 0; - $ENV{'form.NTSTU'}=$ngrade; + my ($ctr,$total) = (0,0); while ($ctr < $ngrade) { - ($ENV{'form.student'},$ENV{'form.userdom'}) = split(/:/,$ENV{'form.unamedom'.$ctr}); - &submission($request,$ctr,$ngrade-1); + $total++ if $ENV{'form.unamedom'.$ctr} ne ''; + $ctr++; + } + $ENV{'form.NTSTU'}=$ngrade; + $ctr = 0; + while ($ctr < $total) { + my $processUser = $ENV{'form.unamedom'.$ctr}; + ($ENV{'form.student'},$ENV{'form.userdom'}) = split(/:/,$processUser); + $ENV{'form.fullname'} = $$fullname{$processUser}; + &submission($request,$ctr,$total-1); $ctr++; } return ''; @@ -1441,7 +1462,6 @@ sub processHandGrade { $laststu = $firststu if ($ctr > $ngrade); } - my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'0'); my (@parsedlist,@nextlist); my ($nextflg) = 0; foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) { @@ -2187,6 +2207,48 @@ sub csvuploadmap_footer { ENDPICK } +sub upcsvScores_form { + my ($request) = shift; + my ($symb,$url)=&get_symb_and_url($request); + if (!$symb) {return '';} + my $result =<<CSVFORMJS; +<script type="text/javascript" language="javascript"> + function checkUpload(formname) { + if (formname.upfile.value == "") { + alert("Please use the browse button to select a file from your local directory."); + return false; + } + formname.submit(); + } + </script> +CSVFORMJS + $ENV{'form.probTitle'} = &Apache::lonnet::gettitle($symb); + $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 problem - '.$ENV{'form.probTitle'}. + '.</b></td></tr>'."\n"; + $result.='<tr bgcolor=#ffffe6><td>'."\n"; + my $upfile_select=&Apache::loncommon::upfile_select_html(); + $result.=<<ENDUPFORM; +<form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload" target="LONcatInfo"> +<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" /> + +</form> +ENDUPFORM + $result.='</td></tr></table>'."\n"; + $result.='</td></tr></table><br /><br />'."\n"; + $result.=&show_grading_menu_form($symb,$url); + + return $result; +} + + sub csvuploadmap { my ($request)= @_; my ($symb,$url)=&get_symb_and_url($request); @@ -2343,7 +2405,7 @@ LISTJAVASCRIPT my $result='<h3><font color="#339933"> '. 'Manual Grading by Page or Sequence</font></h3>'; - $result.='<form action="/adm/grades" method="post" name="displayPage">'."<br>\n"; + $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+)___/); @@ -2377,10 +2439,10 @@ LISTJAVASCRIPT $result.='<input type="hidden" name="section" value="'.$getsec.'" />'."\n". '<input type="hidden" name="command" value="displayPage" />'."\n". '<input type="hidden" name="url" value="'.$url.'" />'."\n". - '<input type="hidden" name="symb" value="'.$symb.'" />'."<br><br>\n". - '<input type="hidden" name="saveState" value="'.$ENV{'form.saveState'}.'" />'."\n"; + '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". + '<input type="hidden" name="saveState" value="'.$ENV{'form.saveState'}.'" />'."<br />\n"; - $result.='<br /> <input type="button" '. + $result.=' <input type="button" '. 'onClick="javascript:checkPickOne(this.form);"value="Submit" /><br />'."\n"; $request->print($result); @@ -2540,8 +2602,8 @@ sub displayPage { } else { my $companswer = &Apache::loncommon::get_student_answers( $symbx,$uname,$udom,$ENV{'request.course.id'}); - $companswer=~s|<form(.*?)>||g; - $companswer=~s|</form>||g; + $companswer =~ s|<form(.*?)>||g; + $companswer =~ s|</form>||g; # while ($companswer =~ /(<a href\=\"javascript:newWindow.*?Script Vars<\/a>)/s) { #<a href="javascript:newWindow</a> # $request->print('match='.$1.'<br>'); @@ -2574,8 +2636,10 @@ sub displayPage { # next if ($record{"$version:resource.$partid.award"} eq 'APPROX_ANS' && # $record{"$version:resource.$partid.solved"} eq ''); $displaySub[0].=(exists $record{$version.':'.$matchKey[0]}) ? - '<b>Trial '.$version.' Part '.$partid.'</b> ' - .$record{$version.':'.$matchKey[0]}.'<br />' : ''; + '<b>Part '.$partid.' '. + ($record{"$version:resource.$partid.tries"} eq '' ? 'Trial not counted' : + 'Trial '.$record{"$version:resource.$partid.tries"}).'</b> '. + $record{$version.':'.$matchKey[0]}.'<br />' : ''; $displaySub[1].=(exists $record{"$version:resource.$partid.award"}) ? '<b>Part '.$partid.'</b> '. $record{"$version:resource.$partid.award"}.'/'. @@ -2750,6 +2814,15 @@ sub updateGradeByPage { # #------ start of section for handling grading by page/sequence --------- +sub defaultFormData { + my ($symb,$url)=@_; + 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"; +} + sub getSequenceDropDown { my ($request,$symb)=@_; my $result='<select name="selectpage">'."\n"; @@ -2767,17 +2840,47 @@ sub getSequenceDropDown { return $result; } +sub scantron_uploads { + if (!-e $Apache::lonnet::perlvar{'lonScansDir'}) { return ''}; + my $result= '<select name="scantron_selectfile">'; + opendir(DIR,$Apache::lonnet::perlvar{'lonScansDir'}); + my @files=sort(readdir(DIR)); + foreach my $filename (@files) { + if ($filename eq '.' or $filename eq '..') { next; } + $result.="<option>$filename</option>\n"; + } + closedir(DIR); + $result.="</select>"; + return $result; +} + +sub scantron_scantab { + my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab'); + my $result='<select name="scantron_format">'."\n"; + foreach my $line (<$fh>) { + my ($name,$descrip)=split(/:/,$line); + if ($name =~ /^\#/) { next; } + $result.='<option value="'.$name.'">'.$descrip.'</option>'."\n"; + } + $result.='</select>'."\n"; + + return $result; +} + sub scantron_selectphase { my ($r) = @_; my ($symb,$url)=&get_symb_and_url($r); if (!$symb) {return '';} my $sequence_selector=&getSequenceDropDown($r,$symb); + my $default_form_data=&defaultFormData($symb,$url); + my $grading_menu_button=&show_grading_menu_form($symb,$url); + my $file_selector=&scantron_uploads(); + my $format_selector=&scantron_scantab(); my $result; $result.= <<SCANTRONFORM; -<form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantronupload"> - <input type="hidden" name="symb" value="$symb" /> - <input type="hidden" name="url" value="$url" /> - <input type="hidden" name="command" value="scantron_configphase" /> +<form method="post" enctype="multipart/form-data" action="/adm/grades" name="scantro_process"> + <input type="hidden" name="command" value="scantron_process" /> + $default_form_data <table width="100%" border="0"> <tr> <td bgcolor="#777777"> @@ -2794,12 +2897,12 @@ sub scantron_selectphase { </tr> <tr bgcolor="#ffffe6"> <td> - <!-- FIXME I need to present a list of files from a specfic directory that has been configured, or any existing delay queues --> - Filename of scoring office file: - <select name="selectfile"> - <option value="filname1">filename1</option> - <option value="filname2">filename2</option> - </select> + Filename of scoring office file: $file_selector + </td> + </tr> + <tr bgcolor="#ffffe6"> + <td> + Format of data file: $format_selector </td> </tr> </table> @@ -2808,42 +2911,211 @@ sub scantron_selectphase { </table> <input type="submit" value="Submit" /> </form> +$grading_menu_button SCANTRONFORM return $result; } -sub scantron_configphase { - my ($r) = @_; - my $sequence=$ENV{'form.selectpage'}; - my $result; - $result.="got page $sequence"; - $Apache::lonxml::debug=1; - &Apache::lonhomework::showhash(%ENV); - $Apache::lonxml::debug=0; - #FIXME Needs to present some lines from the file and allow the instructor to specify which columns represent what data, possibly have some nice defaults setup, probably should do a pass through all problems for a student to get an idea of how many questions there are, and homw many lines we'll have, - return $result; +sub get_scantron_config { + my ($which) = @_; + my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab'); + my %config; + foreach my $line (<$fh>) { + my ($name,$descrip)=split(/:/,$line); + if ($name ne $which ) { next; } + chomp($line); + my @config=split(/:/,$line); + $config{'name'}=$config[0]; + $config{'description'}=$config[1]; + $config{'CODElocation'}=$config[2]; + $config{'CODEstart'}=$config[3]; + $config{'CODElength'}=$config[4]; + $config{'IDstart'}=$config[5]; + $config{'IDlength'}=$config[6]; + $config{'Qstart'}=$config[7]; + $config{'Qlength'}=$config[8]; + $config{'Qoff'}=$config[9]; + $config{'Qon'}=$config[10]; + last; + } + return %config; +} + +sub username_to_idmap { + my ($classlist)= @_; + my %idmap; + foreach my $student (keys(%$classlist)) { + $idmap{$classlist->{$student}->[&Apache::loncoursedata::CL_ID]}= + $student; + } + return %idmap; +} + +sub scantron_parse_scanline { + my ($line,$scantron_config)=@_; + 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) { + $record{'scantron.CODE'}=substr($data,$$scantron_config{'CODEstart'}-1, + $$scantron_config{'CODElength'}); + } else { + #FIXME interpret first N questions + } + } + $record{'scantron.ID'}=substr($data,$$scantron_config{'IDstart'}-1, + $$scantron_config{'IDlength'}); + my @alphabet=('A'..'Z'); + my $questnum=0; + while ($questions) { + $questnum++; + my $currentquest=substr($questions,0,$$scantron_config{'Qlength'}); + substr($questions,0,$$scantron_config{'Qlength'})=''; + if (length($currentquest) < $$scantron_config{'Qlength'}) { next; } + my (@array)=split(/$$scantron_config{'Qon'}/,$currentquest); + if (scalar(@array) gt 2) { + #FIXME do something intelligent with double bubbles + Apache->request->print("<br ><b>Wha!!!</b> <pre>".scalar(@array). + '-'.$currentquest.'-'.$questnum.'</pre><br />'); + } + if (length($array[0]) eq $$scantron_config{'Qlength'}) { + $record{"scantron.$questnum.answer"}=''; + } else { + $record{"scantron.$questnum.answer"}=$alphabet[length($array[0])]; + } + } + $record{'scantron.maxquest'}=$questnum; + return \%record; +} + +sub scantron_add_delay { +} + +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}; } + } + return undef; +} + +sub scantron_filter { + my ($curres)=@_; + if (ref($curres) && $curres->is_problem() && !$curres->randomout) { + return 1; + } + return 0; } sub scantron_process_students { + my ($r) = @_; + my (undef,undef,$sequence)=split(/___/,$ENV{'form.selectpage'}); + my ($symb,$url)=&get_symb_and_url($r); + if (!$symb) {return '';} + my $default_form_data=&defaultFormData($symb,$url); + + my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'}); + my $scanlines=Apache::File->new($Apache::lonnet::perlvar{'lonScansDir'}."/$ENV{'form.scantron_selectfile'}"); + 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 $map=$navmap->getResourceByUrl($sequence); + my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); + $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" /> + $default_form_data +SCANTRONFORM + $r->print($result); + + my @delayqueue; + my $totalcorrect; + my $totalincorrect; + + my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r, + 'Scantron Status','Scantron Progress',scalar(@scanlines)); + foreach my $line (@scanlines) { + my $studentcorrect; + my $studentincorrect; + + chomp($line); + my $scan_record=&scantron_parse_scanline($line,\%scantron_config); + my ($uname,$udom); + if ($uname=&scantron_find_student($scan_record,\%idmap)) { + &scantron_add_delay(\@delayqueue,$line, + 'Unable to find a student that matches'); + } + $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; + foreach my $resource (@resources) { + $i++; + my $result=&Apache::lonnet::ssi($resource->src(), + ('submitted' =>'scantron', + 'grade_target' =>'grade', + 'grade_username'=>$uname, + '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;} + } + &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; + #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::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 - # loop through students, { - # Check if studnet info valid, if not add line to delay queue - # foreach question 'submit' the students answer to the server - # through grade target { - # generate data to pass back that includes grade recevied - # } - # } - # loop through delay queue { - # 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 - # } # 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(); } #-------- end of section for handling grading scantron forms ------- # @@ -2890,10 +3162,7 @@ sub gradingmenu { var cmd = formname.command; formname.saveState.value = "saveCmd="+radioSelection(cmd)+":saveSec="+pullDownSelection(formname.section)+ ":saveSub="+radioSelection(formname.submitonly)+":saveStatus="+pullDownSelection(formname.status); - if (cmd[0].checked || cmd[1].checked || cmd[2].checked || cmd[4].checked) formname.submit(); - - if (cmd[3].checked) browseAndUpload(); - + if (cmd[0].checked || cmd[1].checked || cmd[2].checked || cmd[3].checked || cmd[4].checked) formname.submit(); if (cmd[5].checked) { if (!checkReceiptNo(formname,'notOK')) { return false;} formname.submit(); @@ -2942,57 +3211,6 @@ sub gradingmenu { } } - function browseAndUpload() { - bNLoad = window.open('', 'BrowseAndUpload', 'toolbar=no,location=no,scrollbars=no,width=550,height=200,screenx=100,screeny=75'); - bNLoad.focus(); - var lDoc = bNLoad.document; - lDoc.write("<html><head>"); - lDoc.write("<title>Browse And Upload</title>"); - - lDoc.write("<script language=javascript>"); - lDoc.write("function checkUpload(formname) {"); - - lDoc.write(" if (formname.upfile.value == \\"\\") {"); - lDoc.write(" alert(\\"Please use the browse button to select a file from your local directory.\\");"); - lDoc.write(" return false;"); - lDoc.write(" }"); - lDoc.write(" var openformname = opener.document.gradingMenu;"); - lDoc.write(" formname.saveState.value = \\"saveCmd=\\"+opener.radioSelection(openformname.command)+\\":saveSec=\\"+opener.pullDownSelection(openformname.section)+\\":saveSub=\\"+opener.radioSelection(openformname.submitonly)+\\":saveStatus=\\"+opener.pullDownSelection(openformname.status);"); - lDoc.write(" document.gradesupload.submit();"); - lDoc.write(" if (navigator.appName !=\\"Netscape\\") {self.close()};"); - lDoc.write(" setTimeout('self.close()',750)"); - lDoc.write("}"); - - lDoc.write("<"); - lDoc.write("/script>"); - - lDoc.write("</head><body bgcolor=white>"); - lDoc.write("<form method=\\"post\\" enctype=\\"multipart/form-data\\" action=\\"/adm/grades\\" name=\\"gradesupload\\" target=\\"LONcatInfo\\">"); - lDoc.write("<input type=\\"hidden\\" name=\\"symb\\" value=\\"$symb\\">"); - lDoc.write("<input type=\\"hidden\\" name=\\"url\\" value=\\"$url\\">"); - lDoc.write("<input type=\\"hidden\\" name=\\"probTitle\\" value=\\"$probTitle\\">"); - lDoc.write("<input type=\\"hidden\\" name=\\"saveState\\" value=\\"\\">"); - lDoc.write("<input type=\\"hidden\\" name=\\"command\\" value=\\"csvuploadmap\\">"); - - lDoc.write("<font color=\\"green\\" size=+1> <b>Specify a file containing the class scores for problem - $probTitle</b></font><br><br>"); - - lDoc.write("<table border=0 width=100%><tr><td bgcolor=\\"#777777\\">"); - lDoc.write("<table border=0 width=100%><tr bgcolor=\\"#ddffff\\">"); - lDoc.write("<td>"); - lDoc.write("<input type=\\"file\\" name=\\"upfile\\" size=\\"50\\" />"); - lDoc.write("<br />Type: <select name=\\"upfiletype\\">"); - lDoc.write("<option value=\\"csv\\">CSV (comma separated values, spreadsheet)</option>"); - lDoc.write("<option value=\\"space\\">Space separated</option>"); - lDoc.write("<option value=\\"tab\\">Tabulator separated</option>"); - lDoc.write("<option value=\\"xml\\">HTML/XML</option>"); - lDoc.write("</select>"); - lDoc.write("</td></tr></table>"); - lDoc.write("</td></tr></table> "); - lDoc.write("<input type=\\"button\\" value=\\"Upload Scores\\" onClick=\\"javascript:checkUpload(this.form)\\"> "); - lDoc.write("<input type=\\"button\\" value=\\"Cancel\\" onClick=\\"self.close()\\"><br><br>"); - lDoc.write("</form>"); - lDoc.write("</body></html>"); - } </script> GRADINGMENUJS @@ -3054,12 +3272,13 @@ GRADINGMENUJS ($saveSub eq 'all' ? 'checked' : '').' /> everybody</td></tr>'."\n". '<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'. - '<input type="radio" name="command" value="csvupload" '. - ($saveCmd eq 'csvupload' ? 'checked' : '').'> '. + '<input type="radio" name="command" value="csvform" '. + ($saveCmd eq 'csvform' ? 'checked' : '').'> '. 'Upload scores from file</td></tr>'."\n"; $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'. - '<input type="radio" name="command" value="scantron_selectphase" /> '. + '<input type="radio" name="command" value="scantron_selectphase" '. + ($saveCmd eq 'scantron_selectphase' ? 'checked="on"' : '').' /> '. 'Grade scantron forms</td></tr>'."\n"; if ((&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'})) && ($symb)) { @@ -3192,8 +3411,8 @@ sub handler { } } elsif ($command eq 'scantron_selectphase') { $request->print(&scantron_selectphase($request)); - } elsif ($command eq 'scantron_configphase') { - $request->print(&scantron_configphase($request)); + } elsif ($command eq 'scantron_process') { + $request->print(&scantron_process_students($request)); } else { $request->print("Unknown action: $command:"); }