--- loncom/homework/grades.pm 2003/06/20 21:45:20 1.105 +++ loncom/homework/grades.pm 2003/07/17 22:08:25 1.118 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.105 2003/06/20 21:45:20 albertel Exp $ +# $Id: grades.pm,v 1.118 2003/07/17 22:08:25 ng Exp $ # # Copyright Michigan State University Board of Trustees # @@ -41,6 +41,7 @@ use Apache::style; use Apache::lonxml; use Apache::lonnet; use Apache::loncommon; +use Apache::lonhtmlcommon; use Apache::lonnavmaps; use Apache::lonhomework; use Apache::loncoursedata; @@ -105,6 +106,7 @@ sub response_type { if (/^\w+response_\w+.*/) { my ($responsetype,$part) = split(/_/,$_,2); my ($partid,$respid) = split(/_/,$part); + $responsetype =~ s/response$//; # make it compatible w/ navmaps - should move to that!! $handgrade{$part} = $responsetype.':'.($allkeys =~ /parameter_$part\_handgrade/ ? 'yes' : 'no'); next if ($seen{$partid} > 0); $seen{$partid}++; @@ -114,6 +116,84 @@ sub response_type { return \@partlist,\%handgrade; } +#--- Show resource title +#--- and parts and response type +sub showResourceInfo { + my ($url,$probTitle) = @_; + my $result ='<table border="0">'. + '<tr><td colspan=3><font size=+1><b>Current Resource: </b>'.$probTitle.'</font></td></tr>'."\n"; + my ($partlist,$handgrade) = &response_type($url); + my ($resptype,$hdgrade)=('','no'); + for (sort keys(%$handgrade)) { + my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_}); + $resptype = $responsetype; + $hdgrade = $handgrade if ($handgrade eq 'yes'); + $result.='<tr><td><b>Part </b>'.(split(/_/))[0].'</td>'. + '<td><b>Type: </b>'.$responsetype.'</td></tr>'; +# '<td><b>Handgrade: </b>'.$handgrade.'</td></tr>'; + } + $result.='</table>'."\n"; + return $result,$resptype,$hdgrade,$partlist,$handgrade; +} + +#--- Clean response type for display +#--- Currently filters option response type only. +sub cleanRecord { + my ($answer,$response) = @_; + $answer =~ s|^<br />||; + if ($response eq 'option') { + my (@IDs,@ans); + foreach (split(/\&/,&Apache::lonnet::unescape($answer))) { + my ($optionID,$ans) = split(/=/); + push @IDs,$optionID.'</font>'; + push @ans,$ans; + } + my $grayFont = '<font color="#999999">'; + return '<table border="1">'. + '<tr valign="top"><td>Answer</td><td>'. + (join '</td><td>',@ans).'</td></tr>'. + '<tr valign="top"><td>'.$grayFont.'Option ID</font></td><td>'.$grayFont. + (join '</td><td>'.$grayFont,@IDs).'</font></td></tr>'. + '</table>'; + } + return $answer; +} + +#-- A couple of common js functions +sub commonJSfunctions { + my $request = shift; + $request->print(<<COMMONJSFUNCTIONS); +<script type="text/javascript" language="javascript"> + function radioSelection(radioButton) { + var selection=null; + if (radioButton.length > 1) { + for (var i=0; i<radioButton.length; i++) { + if (radioButton[i].checked) { + return radioButton[i].value; + } + } + } else { + if (radioButton.checked) return radioButton.value; + } + return selection; + } + + function pullDownSelection(selectOne) { + var selection=""; + if (selectOne.length > 1) { + for (var i=0; i<selectOne.length; i++) { + if (selectOne[i].selected) { + return selectOne[i].value; + } + } + } else { + if (selectOne.selected) return selectOne.value; + } + } +</script> +COMMONJSFUNCTIONS +} + #--- Dumps the class list with usernames,list of sections, #--- section, ids and fullnames for each user. sub getclasslist { @@ -129,14 +209,14 @@ sub getclasslist { my (undef,undef,$end,$start,$id,$section,$fullname,$status)= @{$classlist->{$_}}; # filter students according to status selected - if ($filterlist && $ENV{'form.status'} ne 'Any') { - if ($ENV{'form.status'} ne $status) { + if ($filterlist && $ENV{'form.Status'} ne 'Any') { + if ($ENV{'form.Status'} ne $status) { delete ($classlist->{$_}); next; } } $section = ($section ne '' ? $section : 'no'); - if (1 || &canview($section)) { + if (&canview($section)) { if ($getsec eq 'all' || $getsec eq $section) { $sections{$section}++; $fullnames{$_}=$fullname; @@ -296,7 +376,7 @@ sub verifyreceipt { my $title.='<h3><font color="#339933">Verifying Submission Receipt '. $receipt.'</h3></font>'."\n". - '<font size=+1><b>Problem: </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'); @@ -344,67 +424,67 @@ sub listStudents { my $getsec = $ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'}; my $submitonly= $ENV{'form.submitonly'} eq '' ? 'all' : $ENV{'form.submitonly'}; - my $result; - my ($partlist,$handgrade) = &response_type($url); - for (sort keys(%$handgrade)) { - my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_}); - $ENV{'form.handgrade'} = 'yes' if ($handgrade eq 'yes'); - $result.='<tr><td><b>Part </b>'.(split(/_/))[0].'</td>'. - '<td><b>Type: </b>'.$responsetype.'</td>'. - '<td><b>Handgrade: </b>'.$handgrade.'</font></td></tr>'; - } - $result.='</table>'."\n"; - - my $viewgrade = $ENV{'form.handgrade'} eq 'yes' ? 'View/Grade' : 'View'; + my $viewgrade = $ENV{'form.showgrading'} eq 'yes' ? 'View/Grade/Regrade' : 'View'; $ENV{'form.probTitle'} = $ENV{'form.probTitle'} eq '' ? &Apache::lonnet::gettitle($symb) : $ENV{'form.probTitle'}; - $result='<h3><font color="#339933"> '. - $viewgrade. - ' Submissions for a Student or a Group of Students</font></h3>'. - '<table border="0"><tr><td colspan=3><font size=+1>'. - '<b>Problem: </b>'.$ENV{'form.probTitle'}.'</font></td></tr>'.$result; + my $result='<h3><font color="#339933"> '.$viewgrade. + ' Submissions for a Student or a Group of Students</font></h3>'; + + my ($table,$resptype,$hdgrade,$partlist,$handgrade) = &showResourceInfo($url,$ENV{'form.probTitle'}); + $result.=$table; $request->print(<<LISTJAVASCRIPT); <script type="text/javascript" language="javascript"> - function checkSelect(checkBox) { - var ctr=0; - var sense=""; - if (checkBox.length > 1) { - for (var i=0; i<checkBox.length; i++) { - if (checkBox[i].checked) { - ctr++; - } - } - sense = "a student or group of students"; - } else { - if (checkBox.checked) { - ctr = 1; - } - sense = "the student"; - } - if (ctr == 0) { - alert("Please select "+sense+" before clicking on the $viewgrade button."); - return false; + function checkSelect(checkBox) { + var ctr=0; + var sense=""; + if (checkBox.length > 1) { + for (var i=0; i<checkBox.length; i++) { + if (checkBox[i].checked) { + ctr++; + } + } + sense = "a student or group of students"; + } else { + if (checkBox.checked) { + ctr = 1; + } + sense = "the student"; + } + if (ctr == 0) { + alert("Please select "+sense+" before clicking on the $viewgrade button."); + return false; + } + document.gradesub.submit(); + } + + function reLoadList(formname) { + if (formname.saveStatusOld.value == pullDownSelection(formname.Status)) {return;} + formname.command.value = 'submission'; + formname.submit(); } - document.gradesub.submit(); - } </script> LISTJAVASCRIPT + &commonJSfunctions($request); $request->print($result); - my $checkhdgrade = $ENV{'form.handgrade'} eq 'yes' ? 'checked' : ''; - my $checklastsub = $ENV{'form.handgrade'} eq 'yes' ? '' : 'checked'; - + my $checkhdgrade = ($ENV{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1 ) ? 'checked' : ''; + my $checklastsub = ($ENV{'form.handgrade'} eq 'no') ? 'checked' : ''; + $checklastsub = 'checked' if ($checkhdgrade eq '' && $checklastsub eq ''); my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'."\n". - ' <b>View Problem: </b><input type="radio" name="vProb" value="no" checked /> no '."\n". + ' <b>View Problem Text: </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') { - $gradeTable.='<input type="radio" name="lastSub" value="hdgrade" '.$checkhdgrade.' /> handgrade only'."\n"; + if ($ENV{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1) { + $gradeTable.='<input type="radio" name="lastSub" value="hdgrade" '.$checkhdgrade.' /> essay part only'."\n"; } + + 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". '<input type="radio" name="lastSub" value="all" /> all details'."\n". @@ -417,58 +497,82 @@ LISTJAVASCRIPT '<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". - 'To '.lc($viewgrade).' a submission, click on the check box next to the student\'s name. Then '."\n". + '<input type="hidden" name="saveStatusOld" value="'.$saveStatus.'" />'."\n"; + + $gradeTable.='<b>Student Status:</b> '. + &Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,'javascript:reLoadList(this.form);').'<br />'; + + $gradeTable.='To '.lc($viewgrade).' a submission, click on the check box next to the student\'s name. Then '."\n". 'click on the '.$viewgrade.' button. To view the submissions for a group of students, click'."\n". ' on the check boxes for the group of students.<br />'."\n". - '<input type="hidden" name="command" value="processGroup" />'."\n". - '<input type="button" '."\n". + '<input type="hidden" name="command" value="processGroup" />'."\n"; + $gradeTable.='<input type="button" '."\n". 'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n". 'value="'.$viewgrade.'" />'."\n"; - - my (undef,undef,$fullname) = &getclasslist($getsec,$ENV{'form.showgrading'} eq 'yes' ? '1' : '0'); - + + my (undef, undef, $fullname) = &getclasslist($getsec,'1'); $gradeTable.='<table border="0"><tr><td bgcolor="#777777">'. - '<table border="0"><tr bgcolor="#e6ffff">'. - '<td><b> Select </b></td><td><b> Fullname </b></td>'. - '<td><b> Username </b></td><td><b> Domain </b></td>'; - foreach (sort(@$partlist)) { - $gradeTable.='<td><b> Part '.(split(/_/))[0].' Status </b></td>'; + '<table border="0"><tr bgcolor="#e6ffff">'; + my $loop = 0; + while ($loop < 2) { + $gradeTable.='<td><b> Select </b></td><td><b> Fullname </b>'. + '<font color="#999999">(Username)</font> </td>'; + if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { + foreach (sort(@$partlist)) { + $gradeTable.='<td><b> Part '.(split(/_/))[0].' Status </b></td>'; + } + } + $loop++; } $gradeTable.='</tr>'."\n"; my $ctr = 0; foreach my $student (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) { my ($uname,$udom) = split(/:/,$student); - my (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist); - my $statusflg = ''; - foreach (keys(%status)) { - $statusflg = 1 if ($status{$_} ne 'nothing'); - my ($foo,$partid,$foo1) = split(/\./,$_); - if ($status{'resource.'.$partid.'.submitted_by'} ne '') { - $statusflg = ''; - $gradeTable.='<input type="hidden" name="'. - $student.':submitted_by" value="'. - $status{'resource.'.$partid.'.submitted_by'}.'" />'; + my %status = (); + if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { + (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist); + my $statusflg = ''; + foreach (keys(%status)) { + $statusflg = 1 if ($status{$_} ne 'nothing'); + my ($foo,$partid,$foo1) = split(/\./,$_); + if ($status{'resource.'.$partid.'.submitted_by'} ne '') { + $statusflg = ''; + $gradeTable.='<input type="hidden" name="'. + $student.':submitted_by" value="'. + $status{'resource.'.$partid.'.submitted_by'}.'" />'; + } } + next if ($statusflg eq '' && $submitonly eq 'yes'); } - next if ($statusflg eq '' && $submitonly eq 'yes'); $ctr++; if ( $perm{'vgr'} eq 'F' ) { - $gradeTable.='<tr bgcolor="#ffffe6">'. - '<td align="center"><input type=checkbox name="stuinfo" value="'. - $student.':'.$$fullname{$student}.'"></td>'."\n". - '<td> '.$$fullname{$student}.' </td>'."\n". - '<td> '.$uname.' </td>'."\n". - '<td align="middle"> '.$udom.' </td>'."\n"; - - foreach (sort keys(%status)) { - next if (/^resource.*?submitted_by$/); - $gradeTable.='<td align="middle"> '.$status{$_}.' </td>'."\n"; + $gradeTable.='<tr bgcolor="#ffffe6">' if ($ctr%2 ==1); + $gradeTable.='<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"; + + 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.='</tr>'."\n"; + $gradeTable.='</tr>'."\n" if ($ctr%2 ==0); } } + if ($ctr%2 ==1) { + $gradeTable.='<td> </td><td> </td>'; + if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { + foreach (@$partlist) { + $gradeTable.='<td> </td>'; + } + } + $gradeTable.='</tr>'; + } + $gradeTable.='</table></td></tr></table>'. '<input type="button" '. 'onClick="javascript:checkSelect(this.form.stuinfo);" '. @@ -479,7 +583,8 @@ LISTJAVASCRIPT $gradeTable='<br /> <font color="red">There are no students currently enrolled.</font>'; } else { $gradeTable='<br /> <font color="red">'. - 'No submissions found for this resource for any students. ('.$num_students.' checked for submissions</font><br />'; + 'No submissions found for this resource for any students. ('.$num_students. + ' checked for submissions</font><br />'; } } elsif ($ctr == 1) { $gradeTable =~ s/type=checkbox/type=checkbox checked/; @@ -605,8 +710,8 @@ sub sub_page_js { function checkSolved(formname,id) { if (eval("formname.solved"+id+".value") == "correct_by_student") { - alert("This problem has been graded correct by the computer. The score cannot be changed."); - return "noupdate"; + var reply = confirm("This problem has been graded correct by the computer. Do you want to change the score?"); + if (!reply) {return "noupdate";} } return "update"; } @@ -689,6 +794,7 @@ SUBJAVASCRIPT sub sub_page_kw_js { my $request = shift; my $iconpath = $request->dir_config('lonIconsURL'); + &commonJSfunctions($request); $request->print(<<SUBJAVASCRIPT); <script type="text/javascript" language="javascript"> @@ -769,7 +875,6 @@ sub sub_page_kw_js { return; } -// var pWin = null; function savedMsgHeader(Nmsg,usrctr,fullname) { var height = 70*Nmsg+250; var scrollbar = "no"; @@ -778,7 +883,12 @@ sub sub_page_kw_js { scrollbar = "yes"; } // 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); + var xpos = (screen.width-600)/2; + xpos = (xpos < 0) ? '0' : xpos; + var ypos = (screen.height-height)/2-30; + ypos = (ypos < 0) ? '0' : ypos; + + pWin = window.open('', 'MessageCenter', 'toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=600,height='+height); pWin.focus(); pDoc = pWin.document; pDoc.write("<html><head>"); @@ -898,10 +1008,14 @@ sub sub_page_kw_js { return; } -// var hwdWin = null; function highlightCentral() { // if (window.hwdWin) window.hwdWin.close(); - hwdWin = window.open('', 'KeywordHighlightCentral', 'toolbar=no,location=no,scrollbars=no,width=400,height=300,screenx=100,screeny=75'); + var xpos = (screen.width-400)/2; + xpos = (xpos < 0) ? '0' : xpos; + var ypos = (screen.height-330)/2-30; + ypos = (ypos < 0) ? '0' : ypos; + + hwdWin = window.open('', 'KeywordHighlightCentral', 'toolbar=no,location=no,scrollbars=no,width=400,height=300,screenx='+xpos+',screeny='+ypos); hwdWin.focus(); var hDoc = hwdWin.document; hDoc.write("<html><head>"); @@ -909,9 +1023,9 @@ sub sub_page_kw_js { hDoc.write("<script language=javascript>"); hDoc.write("function updateChoice(flag) {"); - hDoc.write(" opener.document.SCORE.kwclr.value = radioSelection(document.hlCenter.kwdclr);"); - hDoc.write(" opener.document.SCORE.kwsize.value = radioSelection(document.hlCenter.kwdsize);"); - hDoc.write(" opener.document.SCORE.kwstyle.value = radioSelection(document.hlCenter.kwdstyle);"); + hDoc.write(" opener.document.SCORE.kwclr.value = opener.radioSelection(document.hlCenter.kwdclr);"); + hDoc.write(" opener.document.SCORE.kwsize.value = opener.radioSelection(document.hlCenter.kwdsize);"); + hDoc.write(" opener.document.SCORE.kwstyle.value = opener.radioSelection(document.hlCenter.kwdstyle);"); hDoc.write(" opener.document.SCORE.refresh.value = \\"on\\";"); hDoc.write(" if (opener.document.SCORE.keywords.value!=\\"\\"){"); hDoc.write(" opener.document.SCORE.submit();"); @@ -919,7 +1033,7 @@ sub sub_page_kw_js { hDoc.write(" self.close()"); hDoc.write("}"); - hDoc.write("function radioSelection(radioButton) {"); +/* hDoc.write("function radioSelection(radioButton) {"); hDoc.write(" var selection=null;"); hDoc.write(" for (var i=0; i<radioButton.length; i++) {"); hDoc.write(" if (radioButton[i].checked) {"); @@ -927,7 +1041,7 @@ sub sub_page_kw_js { hDoc.write(" return selection;"); hDoc.write(" }"); hDoc.write(" }"); - hDoc.write("}"); + hDoc.write("}"); */ hDoc.write("<"); hDoc.write("/script>"); @@ -1065,7 +1179,8 @@ sub submission { if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; } if (!&canview($usec)) { - $request->print('<font color="red">Unable to view requested student.('.$uname.$udom.$usec.$ENV{'request.course.id'}.')</font>'); + $request->print('<font color="red">Unable to view requested student.('. + $uname.$udom.$usec.$ENV{'request.course.id'}.')</font>'); $request->print(&show_grading_menu_form($symb,$url)); return; } @@ -1075,12 +1190,20 @@ sub submission { # header info if ($counter == 0) { &sub_page_js($request); - &sub_page_kw_js($request); + &sub_page_kw_js($request) if ($ENV{'form.handgrade'} eq 'yes'); $ENV{'form.probTitle'} = $ENV{'form.probTitle'} eq '' ? &Apache::lonnet::gettitle($symb) : $ENV{'form.probTitle'}; $request->print('<h3> <font color="#339933">Submission Record</font></h3>'."\n". - '<font size=+1> <b>Problem: </b>'.$ENV{'form.probTitle'}.'</font>'."\n"); + '<font size=+1> <b>Resource: </b>'.$ENV{'form.probTitle'}.'</font>'."\n"); + + if ($ENV{'form.handgrade'} eq 'no') { + my $checkIcon = '<img src="'.$request->dir_config('lonIconsURL'). + '/check.gif" height="16" border="0" />'; + my $checkMark='<br /><br /> <b>Note:</b> Part(s) graded correct by the computer is marked with a '. + $checkIcon.' symbol.'."\n"; + $request->print($checkMark); + } # option to display problem, only once else it cause problems # with the form later since the problem has a form. @@ -1091,7 +1214,7 @@ sub submission { # kwclr is the only variable that is guaranteed to be non blank # if this subroutine has been called once. my %keyhash = (); - if ($ENV{'form.kwclr'} eq '') { + if ($ENV{'form.kwclr'} eq '' && $ENV{'form.handgrade'} eq 'yes') { %keyhash = &Apache::lonnet::dump('nohist_handgrade', $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); @@ -1177,12 +1300,12 @@ KEYWORDS '<table border="0" width=100%><tr bgcolor="#edffff"><td>'."\n"; $result.='<b>Fullname: </b>'.$ENV{'form.fullname'}. - '<font color="#999999"> Username: '.$uname.'</font>'. - '<font color="#999999"> Domain: '.$udom.'</font><br />'."\n"; + '<font color="#999999"> Username: '.$uname. + ($ENV{'user.domain'} eq $udom ? '' : ' ('.$udom.')').'</font><br />'."\n"; $result.='<input type="hidden" name="name'.$counter. '" value="'.$ENV{'form.fullname'}.'" />'."\n"; - # If this is handgraded, then check for collaborators + # If any part of the problem is an essay-response (handgraded), then check for collaborators my @col_fullnames; my ($classlist,$fullname); if ($ENV{'form.handgrade'} eq 'yes') { @@ -1258,41 +1381,53 @@ KEYWORDS &get_last_submission (%record); my $lastsubonly=''. ($$timestamp eq '' ? '' : '<b>Date Submitted:</b> '. - $$timestamp).''; + $$timestamp)."</td></tr>\n"; if ($$timestamp eq '') { - $lastsubonly.='<tr><td bgcolor="#ffffe6">'.$$string[0].'</td></tr>'."\n"; + $lastsubonly.='<tr><td bgcolor="#ffffe6">'.$$string[0]; } else { for my $part (sort keys(%$handgrade)) { - foreach (@$string) { - my ($partid,$respid) = /^resource\.(\d+)\.(\d+)\.submission/; - if ($part eq ($partid.'_'.$respid)) { - 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 />'; - } - $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '. - $partid.'</b> <font color="#999999">( ID '.$respid. - ' )</font> '. - ($record{"resource.$partid.$respid.uploadedurl"}? - '<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 />':''). - '<b>Answer: </b><blockquote>'. - &keywords_highlight($subval).'</blockquote><br /> '.$similar.'</td></tr>'."\n" - if ($ENV{'form.lastSub'} eq 'lastonly' || - ($ENV{'form.lastSub'} eq 'hdgrade' && - $$handgrade{$part} =~ /:yes$/)); + my ($responsetype,$foo) = split(/:/,$$handgrade{$part}); + my ($partid,$respid) = split(/_/,$part); + if (!exists($record{'resource.'.$partid.'.'.$respid.'.submission'})) { + $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '. + $partid.'</b> <font color="#999999">( ID '.$respid. + ' )</font> Nothing submitted<br /><br />'; + } else { + foreach (@$string) { + my ($partid,$respid) = /^resource\.(\w+)\.(\w+)\.submission/; + if ($part eq ($partid.'_'.$respid)) { + 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 />'; + } + $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '. + $partid.'</b> <font color="#999999">( ID '.$respid. + ' )</font> '. + ($record{"resource.$partid.$respid.uploadedurl"}? + '<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 />':''). + '<b>Submitted Answer: </b>'.($responsetype eq 'essay' ? '<blockquote>' : ''). + &cleanRecord(&keywords_highlight($subval),$responsetype). + ($responsetype eq 'essay' ? '</blockquote><br />' : '<br /><br />').$similar."\n" + if ($ENV{'form.lastSub'} eq 'lastonly' || + ($ENV{'form.lastSub'} eq 'hdgrade' && + $$handgrade{$part} =~ /:yes$/)); + } } } } } - $lastsubonly.='</td></tr>'."\n"; + $lastsubonly.='</td></tr><tr bgcolor="#ffffff"><td>'."\n"; $request->print($lastsubonly); } } else { @@ -1304,6 +1439,7 @@ KEYWORDS # return if view submission with no grading option if ($ENV{'form.showgrading'} eq '' || (!&canmodify($usec))) { +# if (!&canmodify($usec)) { $request->print('</td></tr></table></td></tr></table></form>'."\n"); $request->print(&show_grading_menu_form($symb,$url)) if (($ENV{'form.command'} eq 'submission') || @@ -1311,27 +1447,29 @@ KEYWORDS return; } - # Grading options - $result='<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n". - '<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n". - '<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':' - .$udom.'" />'."\n"; - my ($lastname,$givenn) = split(/,/,$ENV{'form.fullname'}); - my $msgfor = $givenn.' '.$lastname; - if (scalar(@col_fullnames) > 0) { - my $lastone = pop @col_fullnames; - $msgfor .= ', '.(join ', ',@col_fullnames).' and '.$lastone.'.'; - } - $msgfor =~ s/\'/\\'/g; #' stupid emacs - $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> '. - '<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); + # essay grading options + if ($ENV{'form.handgrade'} eq 'yes') { + $result='<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n". + '<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n". + '<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':' + .$udom.'" />'."\n"; + my ($lastname,$givenn) = split(/,/,$ENV{'form.fullname'}); + my $msgfor = $givenn.' '.$lastname; + if (scalar(@col_fullnames) > 0) { + my $lastone = pop @col_fullnames; + $msgfor .= ', '.(join ', ',@col_fullnames).' and '.$lastone.'.'; + } + $msgfor =~ s/\'/\\'/g; #' stupid emacs - no! javascript +# $result.='<tr><td bgcolor="#ffffff">'."\n". + $result.=' <a href="javascript:msgCenter(document.SCORE,'.$counter. + ',\''.$msgfor.'\')"; TARGET=_self>'. + '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); + } my %seen = (); my @partlist; @@ -1339,7 +1477,7 @@ KEYWORDS my ($partid,$respid) = split(/_/); next if ($seen{$partid} > 0); $seen{$partid}++; - next if ($$handgrade{$_} =~ /:no$/); + next if ($$handgrade{$_} =~ /:no$/ && $ENV{'form.lastSub'} =~ /^(hdgrade)$/); push @partlist,$partid; $request->print(&gradeBox($request,$symb,$uname,$udom,$counter,$partid,\%record)); @@ -1358,7 +1496,7 @@ KEYWORDS if ($counter == $total) { my $endform='<table border="0"><tr><td>'. '<input type="hidden" name="gradeOpt" value="" />'."\n"; - if ($ENV{'form.handgrade'} eq 'yes') { +# if ($ENV{'form.handgrade'} eq 'yes') { $endform.='<input type="button" value="Save & Next" '. 'onClick="javascript:checksubmit(this.form,\'Save & Next\','. $total.','.scalar(@partlist).');" TARGET=_self> '."\n"; @@ -1369,15 +1507,15 @@ KEYWORDS my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1'); $ntstu =~ s/<option>$nsel</<option selected="on">$nsel</; $endform.=$ntstu.'student(s) '; - } else { - $endform.='<input type="hidden" name="NTSTU" value="1" />'."\n"; - } +# } else { +# $endform.='<input type="hidden" name="NTSTU" value="1" />'."\n"; +# } $endform.='<input type="button" value="Next" '. 'onClick="javascript:checksubmit(this.form,\'Next\');" TARGET=_self> '."\n". '<input type="button" value="Previous" '. 'onClick="javascript:checksubmit(this.form,\'Previous\');" TARGET=_self> '; - $endform.='(Next and Previous do not save the scores.)'."\n" - if ($ENV{'form.handgrade'} eq 'yes'); + $endform.='(Next and Previous do not save the scores.)'."\n" ; +# if ($ENV{'form.handgrade'} eq 'yes'); $endform.='</td><tr></table></form>'; $endform.=&show_grading_menu_form($symb,$url); $request->print($endform); @@ -1673,8 +1811,8 @@ sub viewgrades_js { var textbox = eval("document.classgrade.TEXTVAL_"+partid); if (point == "textval") { var point = eval("document.classgrade.TEXTVAL_"+partid+".value"); - if (isNaN(point) || point < 0) { - alert("A number equal or greater than 0 is expected. Entered value = "+point); + if (isNaN(point) || parseFloat(point) < 0) { + alert("A number equal or greater than 0 is expected. Entered value = "+parseFloat(point)); var resetbox = false; for (var i=0; i<radioButton.length; i++) { if (radioButton[i].checked) { @@ -1687,8 +1825,8 @@ sub viewgrades_js { } return; } - if (point > weight) { - var resp = confirm("You entered a value ("+point+ + if (parseFloat(point) > parseFloat(weight)) { + var resp = confirm("You entered a value ("+parseFloat(point)+ ") greater than the weight for the part. Accept?"); if (resp == false) { textbox.value = ""; @@ -1697,7 +1835,7 @@ sub viewgrades_js { } for (var i=0; i<radioButton.length; i++) { radioButton[i].checked=false; - if (point == i) { + if (parseFloat(point) == i) { radioButton[i].checked=true; } } @@ -1771,13 +1909,13 @@ sub viewgrades_js { var point = textbox.value; var weight = eval("document.classgrade.weight_"+partid+".value"); - if (isNaN(point) || point < 0) { - alert("A number equal or greater than 0 is expected. Entered value = "+point); + if (isNaN(point) || parseFloat(point) < 0) { + alert("A number equal or greater than 0 is expected. Entered value = "+parseFloat(point)); textbox.value = ""; return; } - if (point > weight) { - var resp = confirm("You entered a value ("+point+ + if (parseFloat(point) > parseFloat(weight)) { + var resp = confirm("You entered a value ("+parseFloat(point)+ ") greater than the weight of the part. Accept?"); if (resp == false) { textbox.value = ""; @@ -1840,14 +1978,14 @@ sub viewgrades { my ($symb,$url) = ($ENV{'form.symb'},$ENV{'form.url'}); my $result='<h3><font color="#339933">Manual Grading</font></h3>'; - $result.='<font size=+1><b>Problem: </b>'.$ENV{'form.probTitle'}.'</font>'."\n"; + $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); #beginning of class grading form $result.= '<form action="/adm/grades" method="post" name="classgrade">'."\n". - '<input type="hidden" name="symb" value="'.$symb.'" /resu\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". @@ -1908,9 +2046,9 @@ sub viewgrades { $result.='</table>'.'</td></tr></table>'.'</td></tr></table>'."\n". '<input type="hidden" name="totalparts" value="'.$ctsparts.'" />'; $result.='<input type="button" value="Reset" '. - 'onClick="javascript:resetEntry('.$ctsparts.');" TARGET=_self> '; - $result.='<input type="button" value="Submit Changes" '. - 'onClick="javascript:submit();" TARGET=_self />'."\n"; + 'onClick="javascript:resetEntry('.$ctsparts.');" TARGET=_self>'; +# $result.=' <input type="button" value="Submit Changes" name="subButton1'. +# 'onClick="javascript:submit();" TARGET=_self />'."\n"; #table listing all the students in a section/class #header of table @@ -1924,10 +2062,11 @@ sub viewgrades { } $result.= '<table border=0><tr><td bgcolor="#777777">'."\n". '<table border=0><tr bgcolor="#deffff">'. - '<td><b>Fullname</b></td><td><b>Username</b></td><td><b>Domain</b></td>'."\n"; + '<td><b>Fullname</b> <font color="#999999">(Username)</font></td>'."\n"; my (@parts) = sort(&getpartlist($url)); foreach my $part (@parts) { my $display=&Apache::lonnet::metadata($url,$part.'.display'); + next if ($display =~ /Number of Attempts/); if (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); } if ($display =~ /^Partial Credit Factor/) { my ($partid) = &split_part_type($part); @@ -1958,7 +2097,8 @@ sub viewgrades { 'onClick="javascript:submit();" TARGET=_self /></form>'."\n"; if (scalar(%$fullname) eq 0) { my $colspan=3+scalar(@parts); - $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='<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); return $result; @@ -1972,8 +2112,8 @@ sub viewstudentgrade { my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname); my $result='<tr bgcolor="#ffffdd"><td>'. '<a href="javascript:viewOneStudent(\''.$uname.'\',\''.$udom. - '\')"; TARGET=_self>'.$fullname.'</a>'. - '</td><td>'.$uname.'</td><td align="middle">'.$udom.'</td>'."\n"; + '\')"; TARGET=_self>'.$fullname.'</a> '. + '<font color="#999999">('.$uname.($ENV{'user.domain'} eq $udom ? '' : ':'.$udom).')</font></td>'."\n"; foreach my $apart (@$parts) { my ($part,$type) = &split_part_type($apart); my $score=$record{"resource.$part.$type"}; @@ -1998,13 +2138,13 @@ sub viewstudentgrade { if ($status eq 'excused'); $result.=$optsel; $result.="</select></td>\n"; - } else { - $result.='<input type="hidden" name="'. - 'GD_'.$student.'_'.$part.'_'.$type.'_s" value="'.$score.'" />'. - "\n"; - $result.='<td align="middle"><input type="text" name="'. - 'GD_'.$student.'_'.$part.'_'.$type.'" '. - 'value="'.$score.'" size="4" /></td>'."\n"; +# } else { +# $result.='<input type="hidden" name="'. +# 'GD_'.$student.'_'.$part.'_'.$type.'_s" value="'.$score.'" />'. +# "\n"; +# $result.='<td align="middle"><input type="text" name="'. +# 'GD_'.$student.'_'.$part.'_'.$type.'" '. +# 'value="'.$score.'" size="4" /></td>'."\n"; } } $result.='</tr>'; @@ -2019,7 +2159,7 @@ sub editgrades { my $symb=$ENV{'form.symb'}; my $url =$ENV{'form.url'}; my $title='<h3><font color="#339933">Current Grade Status</font></h3>'; - $title.='<font size=+1><b>Problem: </b>'.$ENV{'form.probTitle'}.'</font><br />'."\n"; + $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"; my $result= '<table border="0"><tr><td bgcolor="#777777">'."\n"; $result.= '<table border="0"><tr bgcolor="#deffff">'. @@ -2083,7 +2223,7 @@ sub editgrades { $line .= '<tr bgcolor="#ffffde"><td>'.$uname.' </td><td>'. $udom.' </td><td>'. $$fullname{$usercolon}.' </td>'; - my $usec=%$classlist->{"$uname:$udom"}[5]; + my $usec=$classlist->{"$uname:$udom"}[5]; if (!&canmodify($usec)) { my $numcols=scalar(@partid)*(scalar(@parts)-1)*2; $noupdate.=$line."<td colspan=\"$numcols\"><font color=\"red\">Not allowed to modify student</font></td></tr>"; @@ -2257,19 +2397,8 @@ sub csvuploadmap_header { $javascript=&csvupload_javascript_forward_associate(); } - my $result='<table border="0">'; - $result.='<tr><td colspan=3><font size=+1><b>Problem: </b>'.$ENV{'form.probTitle'}.'</font></td></tr>'; - my ($partlist,$handgrade) = &response_type($url); - my ($resptype,$hdgrade)=('','no'); - for (sort keys(%$handgrade)) { - my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_}); - $resptype = $responsetype; - $hdgrade = $handgrade if ($handgrade eq 'yes'); - $result.='<tr><td><b>Part </b>'.(split(/_/))[0].'</td>'. - '<td><b>Type: </b>'.$responsetype.'</td>'. - '<td><b>Handgrade: </b>'.$handgrade.'</font></td></tr>'; - } - $result.='</table>'; + my ($result,$resptype,$hdgrade,$partlist,$handgrade) = &showResourceInfo($url,$ENV{'form.probTitle'}); + $request->print(<<ENDPICK); <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload"> <h3><font color="#339933">Uploading Class Grades</font></h3> @@ -2297,7 +2426,8 @@ to this page if the data selected is ins $javascript </script> ENDPICK -return ''; + $request->print(&show_grading_menu_form($symb,$url)); + return ''; } @@ -2343,14 +2473,16 @@ sub upcsvScores_form { </script> CSVFORMJS $ENV{'form.probTitle'} = &Apache::lonnet::gettitle($symb); + my ($table) = &showResourceInfo($url,$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.=' <b>Specify a file containing the class scores for problem - '.$ENV{'form.probTitle'}. + $result.=' <b>Specify a file containing the class scores for current resource'. '.</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"> +<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" /> @@ -2364,7 +2496,6 @@ ENDUPFORM $result.='</td></tr></table>'."\n"; $result.='</td></tr></table><br /><br />'."\n"; $result.=&show_grading_menu_form($symb,$url); - return $result; } @@ -2429,6 +2560,7 @@ sub csvuploadassign { $request->print('<h3>Assigning Grades</h3>'); my $courseid=$ENV{'request.course.id'}; my ($classlist) = &getclasslist('all',0); + my @notallowed; my @skipped; my $countdone=0; foreach my $grade (@gradedata) { @@ -2439,6 +2571,11 @@ sub csvuploadassign { push(@skipped,"$username:$domain"); next; } + my $usec=$classlist->{"$username:$domain"}[5]; + if (!&canmodify($usec)) { + push(@notallowed,"$username:$domain"); + next; + } my %grades; foreach my $dest (keys(%fields)) { if ($dest eq 'username' || $dest eq 'domain') { next; } @@ -2457,9 +2594,14 @@ sub csvuploadassign { } $request->print("<br />Stored $countdone students\n"); if (@skipped) { - $request->print('<br /><font size="+1"><b>Skipped Students</b></font><br />'); - foreach my $student (@skipped) { $request->print("<br />$student"); } + $request->print('<p<font size="+1"><b>Skipped Students</b></font></p>'); + foreach my $student (@skipped) { $request->print("$student<br />\n"); } + } + if (@notallowed) { + $request->print('<p><font size="+1" color="red"><b>Students Not Allowed to Modify</b></font></p>'); + foreach my $student (@notallowed) { $request->print("$student<br />\n"); } } + $request->print("<br />\n"); $request->print(&show_grading_menu_form($symb,$url)); return ''; } @@ -2487,35 +2629,9 @@ function checkPickOne(formname) { formname.submit(); } -function radioSelection(radioButton) { - var selection=null; - if (radioButton.length > 1) { - for (var i=0; i<radioButton.length; i++) { - if (radioButton[i].checked) { - return radioButton[i].value; - } - } - } else { - if (radioButton.checked) return radioButton.value; - } - return selection; -} - -function pullDownSelection(selectOne) { - var selection=""; - if (selectOne.length > 1) { - for (var i=0; i<selectOne.length; i++) { - if (selectOne[i].selected) { - return selectOne[i].value; - } - } - } else { - if (selectOne.selected) return selectOne.value; - } -} </script> LISTJAVASCRIPT - + &commonJSfunctions($request); my ($symb,$url) = &get_symb_and_url($request); my $cdom = $ENV{"course.$ENV{'request.course.id'}.domain"}; my $cnum = $ENV{"course.$ENV{'request.course.id'}.num"}; @@ -2547,7 +2663,7 @@ LISTJAVASCRIPT $result.='<input type="hidden" name="page" />'."\n". '<input type="hidden" name="title" />'."\n"; - $result.=' <b>View Problems: </b><input type="radio" name="vProb" value="no" checked /> no '."\n". + $result.=' <b>View Problems Text: </b><input type="radio" name="vProb" value="no" checked /> no '."\n". '<input type="radio" name="vProb" value="yes" /> yes '."<br>\n"; $result.=' <b>Submission Details: </b>'. @@ -2556,7 +2672,7 @@ LISTJAVASCRIPT '<input type="radio" name="lastSub" value="all" /> all details'."\n"; $result.='<input type="hidden" name="section" value="'.$getsec.'" />'."\n". - '<input type="hidden" name="status" value="'.$ENV{'form.status'}.'" />'."\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". @@ -2601,53 +2717,22 @@ LISTJAVASCRIPT sub getSymbMap { my ($request) = @_; my $navmap = Apache::lonnavmaps::navmap-> new($ENV{'request.course.fn'}.'.db', - $ENV{'request.course.fn'}.'_parms.db',1, 1); - - my $res = $navmap->firstResource(); # temp resource to access constants + $ENV{'request.course.fn'}.'_parms.db'); $navmap->init(); - # End navmap using boilerplate - - my $iterator = $navmap->getIterator(undef, undef, undef, 1); - my $depth = 1; - $iterator->next(); # ignore first BEGIN_MAP - my $curRes = $iterator->next(); - my %symbx = (); my @titles = (); - my $minder=0; - while ($depth > 0) { - if ($curRes == $iterator->BEGIN_MAP()) {$depth++;} - if ($curRes == $iterator->END_MAP()) { $depth--; } + my $minder = 0; - if (ref($curRes) && $curRes->is_map()) { - my ($mapUrl, $id, $resUrl) = split(/___/, $curRes->symb()); # check map contains at least one problem - my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps - - my $mapiterator = $navmap->getIterator($map->map_start(), - $map->map_finish()); - - my $mapdepth = 1; - my $countProblems = 0; - $mapiterator->next(); # skip the first BEGIN_MAP - my $mapcurRes = $mapiterator->next(); # for "current resource" - while ($mapdepth > 0) { - if($mapcurRes == $mapiterator->BEGIN_MAP) { $mapdepth++; } - if($mapcurRes == $mapiterator->END_MAP) { $mapdepth--; } - - if (ref($mapcurRes) && $mapcurRes->is_problem() && !$mapcurRes->randomout) { - $countProblems++; - } - $mapcurRes = $mapiterator->next(); - } - if ($countProblems > 0) { - my $title = $curRes->compTitle(); - push @titles,$minder.'.'.$title; # minder, just in case two titles are identical - $symbx{$minder.'.'.$title} = $curRes->symb(); - $minder++; - } - } - $curRes = $iterator->next(); + # Gather every sequence that has problems. + my @sequences = $navmap->retrieveResources(undef, sub { shift->is_map(); }, 1); + for my $sequence ($navmap->getById('0.0'), @sequences) { + if ($navmap->hasResource($sequence, sub { shift->is_problem(); }, 0) ) { + my $title = $minder.'.'.$sequence->compTitle(); + push @titles, $title; # minder in case two titles are identical + $symbx{$title} = $sequence->symb(); + $minder++; + } } $navmap->untieHashes(); @@ -2699,12 +2784,12 @@ sub displayPage { my $checkIcon = '<img src="'.$request->dir_config('lonIconsURL'). '/check.gif" height="16" border="0" />'; - $studentTable.=' <b>Note:</b> A problem graded correct ('.$checkIcon. - ') by the computer cannot be changed.'."\n". + $studentTable.=' <b>Note:</b> Problems graded correct by the computer are marked with a '.$checkIcon. + ' symbol.'."\n". '<table border="0"><tr><td bgcolor="#777777">'. '<table border="0"><tr bgcolor="#e6ffff">'. - '<td align="center"><b> No </b></td>'. - '<td><b> '.($ENV{'form.vProb'} eq 'no' ? 'Title' : 'Problem View').'/Grade</b></td></tr>'; + '<td align="center"><b> Prob. </b></td>'. + '<td><b> '.($ENV{'form.vProb'} eq 'no' ? 'Title' : 'Problem Text').'/Grade</b></td></tr>'; my ($depth,$question) = (1,1); $iterator->next(); # skip the first BEGIN_MAP @@ -2723,21 +2808,18 @@ sub displayPage { if ($ENV{'form.vProb'} eq 'yes') { $studentTable.=&show_problem($request,$symbx,$uname,$udom,1); } else { - my $companswer = &Apache::loncommon::get_student_answers( - $symbx,$uname,$udom,$ENV{'request.course.id'}); + my $companswer = &Apache::loncommon::get_student_answers($symbx,$uname,$udom,$ENV{'request.course.id'}); $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>'); -# $companswer =~ s/$1/ /s; +# $companswer =~ s/$1/ /ms; +# $request->print('match='.$1."<br>\n"); # } -# $companswer =~ s/<table border=\"1\">/<table border=\"0\">/g; +# $companswer =~ s|<table border=\"1\">|<table border=\"0\">|g; $studentTable.=' <b>'.$title.'</b> <br> <b>Correct answer:</b><br>'.$companswer; } my %record = &Apache::lonnet::restore($symbx,$ENV{'request.course.id'},$udom,$uname); - if ($ENV{'form.lastSub'} eq 'datesub') { if ($record{'version'} eq '') { $studentTable.='<br /> <font color="red">No recorded submission for this problem</font><br />'; @@ -2747,7 +2829,13 @@ sub displayPage { '<td><b>Date/Time</b></td>'. '<td><b>Submission</b></td>'. '<td><b>Status </b></td></tr>'; + my %responseType = (); + foreach my $partid (@{$parts}) { + $responseType{$partid} = $curRes->responseType($partid); + } my ($version); + my %mark; + $mark{'correct_by_student'} = $checkIcon; for ($version=1;$version<=$record{'version'};$version++) { my $timestamp = scalar(localtime($record{$version.':timestamp'})); $studentTable.='<tr bgcolor="#ffffff" valign="top"><td>'.$timestamp.'</td>'; @@ -2756,17 +2844,16 @@ sub displayPage { foreach my $partid (@{$parts}) { my @matchKey = grep /^resource\.$partid\..*?\.submission$/,@versionKeys; next if ($record{"$version:resource.$partid.solved"} eq ''); -# next if ($record{"$version:resource.$partid.award"} eq 'APPROX_ANS' && -# $record{"$version:resource.$partid.solved"} eq ''); $displaySub[0].=(exists $record{$version.':'.$matchKey[0]}) ? '<b>Part '.$partid.' '. ($record{"$version:resource.$partid.tries"} eq '' ? 'Trial not counted' : 'Trial '.$record{"$version:resource.$partid.tries"}).'</b> '. - $record{$version.':'.$matchKey[0]}.'<br />' : ''; + &cleanRecord($record{$version.':'.$matchKey[0]},$responseType{$partid}).'<br />' : ''; $displaySub[1].=(exists $record{"$version:resource.$partid.award"}) ? '<b>Part '.$partid.'</b> '. - $record{"$version:resource.$partid.award"}.'/'. - $record{"$version:resource.$partid.solved"}.'<br />' : ''; + lc($record{"$version:resource.$partid.award"}).' '. + $mark{$record{"$version:resource.$partid.solved"}}.'<br />' : ''; +# $record{"$version:resource.$partid.solved"}.'<br />' : ''; $displaySub[2].=(exists $record{"$version:resource.$partid.regrader"}) ? $record{"$version:resource.$partid.regrader"}.' (<b>Part:</b> '.$partid.')' : ''; } @@ -3276,12 +3363,19 @@ sub gradingmenu { $request->print(<<GRADINGMENUJS); <script type="text/javascript" language="javascript"> - function checkChoice(formname) { - 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[3].checked || cmd[4].checked) formname.submit(); - if (cmd[5].checked) { + function checkChoice(formname,val,cmdx) { + if (val <= 2) { + var cmd = radioSelection(formname.radioChoice); + var cmdsave = cmd; + } else { + cmd = cmdx; + cmdsave = 'submission'; + } + formname.command.value = cmd; + formname.saveState.value = "saveCmd="+cmdsave+":saveSec="+pullDownSelection(formname.section)+ + ":saveSub="+radioSelection(formname.submitonly)+":saveStatus="+pullDownSelection(formname.Status); + if (val < 5) formname.submit(); + if (val == 5) { if (!checkReceiptNo(formname,'notOK')) { return false;} formname.submit(); } @@ -3298,60 +3392,19 @@ sub gradingmenu { formname.receipt.focus(); return false; } - formname.command[5].checked = true; return true; } - - function radioSelection(radioButton) { - var selection=null; - if (radioButton.length > 1) { - for (var i=0; i<radioButton.length; i++) { - if (radioButton[i].checked) { - return radioButton[i].value; - } - } - } else { - if (radioButton.checked) return radioButton.value; - } - return selection; - } - - function pullDownSelection(selectOne) { - var selection=""; - if (selectOne.length > 1) { - for (var i=0; i<selectOne.length; i++) { - if (selectOne[i].selected) { - return selectOne[i].value; - } - } - } else { - if (selectOne.selected) return selectOne.value; - } - } - </script> GRADINGMENUJS - - my $result='<h3> <font color="#339933">Manual Grading/View Submission</font></h3>'. - '<table border="0">'. - '<tr><td colspan=3><font size=+1><b>Problem: </b>'.$probTitle.'</font></td></tr>'."\n"; - my ($partlist,$handgrade) = &response_type($url); - my ($resptype,$hdgrade)=('','no'); - for (sort keys(%$handgrade)) { - my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_}); - $resptype = $responsetype; - $hdgrade = $handgrade if ($handgrade eq 'yes'); - $result.='<tr><td><b>Part </b>'.(split(/_/))[0].'</td>'. - '<td><b>Type: </b>'.$responsetype.'</td>'. - '<td><b>Handgrade: </b>'.$handgrade.'</font></td></tr>'; - } - $result.='</table>'."\n"; - + &commonJSfunctions($request); + my $result='<h3> <font color="#339933">Manual Grading/View Submission</font></h3>'; + my ($table,$resptype,$hdgrade) = &showResourceInfo($url,$probTitle); + $result.=$table; my (undef,$sections) = &getclasslist('all','0'); my $savedState = &savedState(); - my $saveCmd = ($$savedState{'saveCmd'} eq '' ? 'pickStudentPage' : $$savedState{'saveCmd'}); + my $saveCmd = ($$savedState{'saveCmd'} eq '' ? 'submission' : $$savedState{'saveCmd'}); my $saveSec = ($$savedState{'saveSec'} eq '' ? 'all' : $$savedState{'saveSec'}); - my $saveSub = ($$savedState{'saveSub'} eq '' ? 'yes' : $$savedState{'saveSub'}); + my $saveSub = ($$savedState{'saveSub'} eq '' ? 'all' : $$savedState{'saveSub'}); my $saveStatus = ($$savedState{'saveStatus'} eq '' ? 'Active' : $$savedState{'saveStatus'}); $result.='<form action="/adm/grades" method="post" name="gradingMenu">'."\n". @@ -3360,80 +3413,75 @@ GRADINGMENUJS '<input type="hidden" name="response" value="'.$resptype.'" />'."\n". '<input type="hidden" name="handgrade" value="'.$hdgrade.'" />'."\n". '<input type="hidden" name="probTitle" value="'.$probTitle.'" />'."\n". + '<input type="hidden" name="command" value="" />'."\n". '<input type="hidden" name="saveState" value="" />'."\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>'."\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><td>'."\n"; + '<tr bgcolor="#ffffe6" valign="top"><td>'."\n"; - $result.='<table width=100% border=0>'. - '<tr bgcolor="#ffffe6" valign="top"><td colspan="2">'. - '<input type="radio" name="command" value="pickStudentPage" '. - ($saveCmd eq 'pickStudentPage' ? 'checked' : '').'> '. - 'Handgrade/View Submission for a student by page/sequence</td></tr>'."\n". + $result.='<table width="100%" border=0>'; + $result.='<tr bgcolor="#ffffe6" valign="top"><td>'."\n". + ' Select Section: <select name="section">'."\n"; + if (ref($sections)) { + foreach (sort (@$sections)) {$result.='<option value="'.$_.'" '. + ($saveSec eq $_ ? 'selected="on"' : '').'>'.$_.'</option>'."\n";} + } + $result.= '<option value="all" '.($saveSec eq 'all' ? 'selected="on"' : ''). '>all</select> '; - '<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'. - '<input type="radio" name="command" value="viewgrades" '. - ($saveCmd eq 'viewgrades' ? 'checked' : '').'> '. - 'Grade by section or class</td></tr>'."\n". + $result.='Student Status:</b>'.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,undef); - '<tr bgcolor="#ffffe6"valign="top"><td><input type="radio" name="command" value="submission" '. - ($saveCmd eq 'submission' ? 'checked' : '').'> '. - ($hdgrade eq 'yes' ? 'View/Grade essay response of' : 'View'). - ' an individual student </td>'."\n". - '<td>--> For students who has: '. + if (ref($sections)) { + $result.=' (Section "no" implies the students were not assigned a section.)<br />' + if (grep /no/,@$sections); + } + $result.='</td></tr>'; + + $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'. + '<br /> -->For students with '. '<input type="radio" name="submitonly" value="yes" '. - ($saveSub eq 'yes' ? 'checked' : '').' /> submitted'. + ($saveSub eq 'yes' ? 'checked' : '').' /> submissions or '. '<input type="radio" name="submitonly" value="all" '. - ($saveSub eq 'all' ? 'checked' : '').' /> everybody</td></tr>'."\n". + ($saveSub eq 'all' ? 'checked' : '').' /> for all</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"; + + $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"; - '<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'. - '<input type="radio" name="command" value="csvform" '. - ($saveCmd eq 'csvform' ? 'checked' : '').'> '. - 'Upload scores from file</td></tr>'."\n"; + $result.='<tr bgcolor="#ffffe6"><td><br />'. + '<input type="button" onClick="javascript:checkChoice(this.form,\'2\');" value="View/Grade/Regrade" />'. + '</td></tr></table>'."\n"; + + $result.='</td><td valign="top">'; + + $result.='<table width="100%" border=0>'; + $result.='<tr bgcolor="#ffffe6"><td>'. + '<input type="button" onClick="javascript:checkChoice(this.form,\'3\',\'csvform\');" value="Upload" />'. + ' scores from file </td></tr>'."\n"; $result.='<tr bgcolor="#ffffe6"valign="top"><td colspan="2">'. - '<input type="radio" name="command" value="scantron_selectphase" '. - ($saveCmd eq 'scantron_selectphase' ? 'checked="on"' : '').' /> '. - 'Grade scantron forms</td></tr>'."\n"; + '<input type="button" onClick="javascript:checkChoice(this.form,\'4\',\'scantron_selectphase\');'. + '" value="Grade" /> scantron forms</td></tr>'."\n"; if ((&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'})) && ($symb)) { $result.='<tr bgcolor="#ffffe6"valign="top"><td>'. - '<input type="radio" name="command" value="verify" onChecked="javascript:this.form.receipt.focus()" '. - ($saveCmd eq 'verify' ? 'checked' : '').'> '. - 'Verify a submission receipt issued by this server</td>'. - '<td>--> Receipt no: '.unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}). + '<input type="button" onClick="javascript:checkChoice(this.form,\'5\',\'verify\');" value="Verify" />'. + ' submission Receipt no: '.unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}). '-<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"><br />'."\n". - ' Select section: <select name="section">'."\n"; - if (ref($sections)) { - foreach (sort (@$sections)) {$result.='<option value="'.$_.'" '. - ($saveSec eq $_ ? 'selected="on"' : '').'>'.$_.'</option>'."\n";} - } - $result.= '<option value="all" '.($saveSec eq 'all' ? 'selected="on"' : ''). '>all</select> '; - - $result.='Student Status:</b><select name="status">'. - '<option value="Active" '.($saveStatus eq 'Active' ? 'selected' : '').'>Active</option>'. - '<option value="Expired" '.($saveStatus eq 'Expired' ? 'selected' : '').'>Expired</option>'. - '<option value="Any" '.($saveStatus eq 'Any' ? 'selected' : '').'>Any</option>'. - '</select>'; - - $result.=' <font color="red">(Applies to the first three options only.)</font>'."\n"; - - if (ref($sections)) { - $result.=' (Section "no" implies the students were not assigned a section.)<br />' - if (grep /no/,@$sections); - } - $result.='</td></tr>'; - - $result.='<tr bgcolor="#ffffe6"><td colspan="2"><br />'. - '<input type="button" onClick="javascript:checkChoice(this.form);" value="View/Grade" />'."\n". - '</form></td></tr></table>'."\n". + $result.='</form></td></tr></table>'."\n". '</td></tr></table>'."\n". '</td></tr></table>'."\n"; return $result; @@ -3501,9 +3549,6 @@ sub handler { delete($perm{'mgr'}); } } - #delete($perm{'mgr'}); - #$Apache::lonxml::debug=1; - #&Apache::lonxml::debug("command is $command"); if ($command eq 'submission' && $perm{'vgr'}) { ($ENV{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0)); @@ -3521,19 +3566,17 @@ sub handler { $request->print(&viewgrades($request)); } elsif ($command eq 'handgrade' && $perm{'mgr'}) { $request->print(&processHandGrade($request)); - } elsif ($command eq 'editgrades' && $perm{'mgr'} ) { + } elsif ($command eq 'editgrades' && $perm{'mgr'}) { $request->print(&editgrades($request)); - } elsif ($command eq 'verify') { + } elsif ($command eq 'verify' && $perm{'vgr'}) { $request->print(&verifyreceipt($request)); - } elsif ($command eq 'csvform') { + } elsif ($command eq 'csvform' && $perm{'mgr'}) { $request->print(&upcsvScores_form($request)); - } elsif ($command eq 'csvupload') { + } elsif ($command eq 'csvupload' && $perm{'mgr'}) { $request->print(&csvupload($request)); - } elsif ($command eq 'viewclasslist') { - $request->print(&viewclasslist($request)); - } elsif ($command eq 'csvuploadmap') { + } elsif ($command eq 'csvuploadmap' && $perm{'mgr'} ) { $request->print(&csvuploadmap($request)); - } elsif ($command eq 'csvuploadassign') { + } elsif ($command eq 'csvuploadassign' && $perm{'mgr'}) { if ($ENV{'form.associate'} ne 'Reverse Association') { $request->print(&csvuploadassign($request)); } else { @@ -3544,12 +3587,12 @@ sub handler { } $request->print(&csvuploadmap($request)); } - } elsif ($command eq 'scantron_selectphase') { + } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) { $request->print(&scantron_selectphase($request)); - } elsif ($command eq 'scantron_process') { + } elsif ($command eq 'scantron_process' && $perm{'mgr'}) { $request->print(&scantron_process_students($request)); - } else { - $request->print("Unknown action: $command:"); + } elsif ($command) { + $request->print("Access Denied"); } } &send_footer($request);