--- loncom/homework/grades.pm 2005/02/12 03:14:44 1.244 +++ loncom/homework/grades.pm 2005/03/03 05:57:26 1.250 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.244 2005/02/12 03:14:44 albertel Exp $ +# $Id: grades.pm,v 1.250 2005/03/03 05:57:26 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -96,7 +96,7 @@ sub get_symb_and_url { sub nameUserString { my ($type,$fullname,$uname,$udom) = @_; if ($type eq 'header') { - return '<b> Fullname </b><font color="#999999">(Username)</font> '; + return '<b> Fullname </b><font color="#999999">(Username)</font>'; } else { return ' '.$fullname.'<font color="#999999"> ('.$uname. ($ENV{'user.domain'} eq $udom ? '' : ' ('.$udom.')').')</font>'; @@ -664,17 +664,21 @@ LISTJAVASCRIPT $gradeTable.='To '.lc($viewgrade).' a submission or a group of submissions, click on the check box(es) '. 'next to the student\'s name(s). Then click on the Next button.<br />'."\n". '<input type="hidden" name="command" value="processGroup" />'."\n"; + +# checkall buttons + $gradeTable.=&check_script('gradesub', 'stuinfo'); $gradeTable.='<input type="button" '."\n". 'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n". - 'value="Next->" />'."\n"; + 'value="Next->" /> <br />'."\n"; + $gradeTable.=&check_buttons(); $gradeTable.='<input type="checkbox" name="checkPlag" checked="on">Check For Plagiarism</input>'; - my (undef, undef, $fullname) = &getclasslist($getsec,'1'); + my ($classlist, 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>'.&nameUserString('header').'</td>'; + '<td>'.&nameUserString('header').' Section/Group</td>'; if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { foreach (sort(@$partlist)) { my $display_part=&get_display_part((split(/_/))[0],$url,$symb); @@ -695,10 +699,12 @@ LISTJAVASCRIPT (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist); my $submitted = 0; my $graded = 0; + my $incorrect = 0; foreach (keys(%status)) { $submitted = 1 if ($status{$_} ne 'nothing'); - $graded = 1 if ($status{$_} !~ /^correct/); - + $graded = 1 if ($status{$_} =~ /^ungraded/); + $incorrect = 1 if ($status{$_} =~ /^incorrect/); + my ($foo,$partid,$foo1) = split(/\./,$_); if ($status{'resource.'.$partid.'.submitted_by'} ne '') { $submitted = 0; @@ -708,20 +714,25 @@ LISTJAVASCRIPT $status{'resource.'.$partid.'.submitted_by'}.'" />'; } } + next if (!$submitted && ($submitonly eq 'yes' || $submitonly eq 'incorrect' || $submitonly eq 'graded')); - next if (!$graded && ($submitonly eq 'graded' || - $submitonly eq 'incorrect')); + next if (!$graded && ($submitonly eq 'graded')); + next if (!$incorrect && $submitonly eq 'incorrect'); } $ctr++; + my $section = $classlist->{$student}->[&Apache::loncoursedata::CL_SECTION()]; + if ( $perm{'vgr'} eq 'F' ) { $gradeTable.='<tr bgcolor="#ffffe6">' if ($ctr%2 ==1); $gradeTable.='<td align="right">'.$ctr.' </td>'. - '<td align="center"><input type=checkbox name="stuinfo" value="'. - $student.':'.$$fullname{$student}.' "></td>'."\n". - '<td>'.&nameUserString(undef,$$fullname{$student},$uname,$udom).'</td>'."\n"; + '<td align="center"><label><input type=checkbox name="stuinfo" value="'. + $student.':'.$$fullname{$student}.':::SECTION'.$section. + ') " /> </label></td>'."\n".'<td>'. + &nameUserString(undef,$$fullname{$student},$uname,$udom). + ' '.$section.'</td>'."\n"; if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { foreach (sort keys(%status)) { @@ -743,7 +754,7 @@ LISTJAVASCRIPT $gradeTable.='</tr>'; } - $gradeTable.='</table></td></tr></table>'. + $gradeTable.='</table></td></tr></table>'."\n". '<input type="button" '. 'onClick="javascript:checkSelect(this.form.stuinfo);" '. 'value="Next->" /></form>'."\n"; @@ -768,6 +779,52 @@ LISTJAVASCRIPT } #---- Called from the listStudents routine + +sub check_script { + my ($form, $type)=@_; + my $chkallscript='<script type="text/javascript"> + function checkall() { + for (i=0; i<document.forms.'.$form.'.elements.length; i++) { + ele = document.forms.'.$form.'.elements[i]; + if (ele.name == "'.$type.'") { + document.forms.'.$form.'.elements[i].checked=true; + } + } + } + + function checksec() { + for (i=0; i<document.forms.'.$form.'.elements.length; i++) { + ele = document.forms.'.$form.'.elements[i]; + string = document.forms.'.$form.'.chksec.value; + if + (ele.value.indexOf(":::SECTION"+string)>0) { + document.forms.'.$form.'.elements[i].checked=true; + } + } + } + + + function uncheckall() { + for (i=0; i<document.forms.'.$form.'.elements.length; i++) { + ele = document.forms.'.$form.'.elements[i]; + if (ele.name == "'.$type.'") { + document.forms.'.$form.'.elements[i].checked=false; + } + } + } + +</script>'."\n"; + return $chkallscript; +} + +sub check_buttons { + my $buttons.='<input type="button" onclick="checkall()" value="Check All" />'; + $buttons.='<input type="button" onclick="uncheckall()" value="Uncheck All" /> '; + $buttons.='<input type="button" onclick="checksec()" value="Check Section/Group" />'; + $buttons.='<input type="text" size="5" name="chksec" /> '; + return $buttons; +} + # Displays the submissions for one student or a group of students sub processGroup { my ($request) = shift; @@ -2006,10 +2063,12 @@ sub processHandGrade { # my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname); my %status=&student_gradeStatus($url,$symb,$udom,$uname,$partlist); my $submitted = 0; - my $graded = 1; + my $ungraded = 0; + my $incorrect = 0; foreach (keys(%status)) { $submitted = 1 if ($status{$_} ne 'nothing'); - $graded = 0 if ($status{$_} =~ /^correct/); + $ungraded = 1 if ($status{$_} =~ /^ungraded/); + $incorrect = 1 if ($status{$_} =~ /^incorrect/); my ($foo,$partid,$foo1) = split(/\./,$_); if ($status{'resource.'.$partid.'.submitted_by'} ne '') { $submitted = 0; @@ -2018,8 +2077,8 @@ sub processHandGrade { next if (!$submitted && ($submitonly eq 'yes' || $submitonly eq 'incorrect' || $submitonly eq 'graded')); - next if (!$graded && ($submitonly eq 'graded' || - $submitonly eq 'incorrect')); + next if (!$ungraded && ($submitonly eq 'graded')); + next if (!$incorrect && $submitonly eq 'incorrect'); } push @nextlist,$student if ($ctr < $ntstu); last if ($ctr == $ntstu); @@ -2651,26 +2710,26 @@ sub split_part_type { # #--- Javascript to handle csv upload sub csvupload_javascript_reverse_associate { + my $error1=&mt('You need to specify the username or ID'); + my $error2=&mt('You need to specify at least one grading field'); return(<<ENDPICK); function verify(vf) { var foundsomething=0; var founduname=0; var foundID=0; - var founddomain=0; for (i=0;i<=vf.nfields.value;i++) { tw=eval('vf.f'+i+'.selectedIndex'); if (i==0 && tw!=0) { foundID=1; } if (i==1 && tw!=0) { founduname=1; } - if (i==2 && tw!=0) { founddomain=1; } if (i!=0 && i!=1 && i!=2 && tw!=0) { foundsomething=1; } } - if ((founduname==0 && foundID==0) || founddomain==0) { - alert('You need to specify the domain and either the username or ID'); - return; + if (founduname==0 && foundID==0) { + alert('$error1'); + return; } if (foundsomething==0) { - alert('You need to specify at least one grading field'); - return; + alert('$error2'); + return; } vf.submit(); } @@ -2691,26 +2750,26 @@ ENDPICK } sub csvupload_javascript_forward_associate { + my $error1=&mt('You need to specify the username or ID'); + my $error2=&mt('You need to specify at least one grading field'); return(<<ENDPICK); function verify(vf) { var foundsomething=0; var founduname=0; var foundID=0; - var founddomain=0; for (i=0;i<=vf.nfields.value;i++) { tw=eval('vf.f'+i+'.selectedIndex'); if (tw==1) { foundID=1; } if (tw==2) { founduname=1; } - if (tw==3) { founddomain=1; } if (tw>3) { foundsomething=1; } } - if ((founduname==0 && foundID==0) || founddomain==0) { - alert('You need to specify the domain and either the username or ID'); - return; + if (founduname==0 && foundID==0) { + alert('$error1'); + return; } if (foundsomething==0) { - alert('You need to specify at least one grading field'); - return; + alert('$error2'); + return; } vf.submit(); } @@ -2737,7 +2796,8 @@ sub csvuploadmap_header { } my ($result) = &showResourceInfo($url,$ENV{'form.probTitle'}); - + my $checked=(($ENV{'form.noFirstLine'})?' checked="checked"':''); + my $ignore=&mt('Ignore First Line'); $request->print(<<ENDPICK); <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload"> <h3><font color="#339933">Uploading Class Grades</font></h3> @@ -2748,6 +2808,7 @@ Total number of records found in file: $ Enter as many fields as you can. The system will inform you and bring you back to this page if the data selected is insufficient to run your class.<hr /> <input type="button" value="Reverse Association" onClick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" /> +<label><input type="checkbox" name="noFirstLine" $checked />$ignore</label> <input type="hidden" name="associate" value="" /> <input type="hidden" name="phase" value="three" /> <input type="hidden" name="datatoken" value="$datatoken" /> @@ -2759,7 +2820,7 @@ to this page if the data selected is ins <input type="hidden" name="url" value="$url" /> <input type="hidden" name="saveState" value="$ENV{'form.saveState'}" /> <input type="hidden" name="probTitle" value="$ENV{'form.probTitle'}" /> -<input type="hidden" name="command" value="csvuploadassign" /> +<input type="hidden" name="command" value="csvuploadoptions" /> <hr /> <script type="text/javascript" language="Javascript"> $javascript @@ -2824,6 +2885,7 @@ CSVFORMJS '.</b></td></tr>'."\n"; $result.='<tr bgcolor=#ffffe6><td>'."\n"; my $upfile_select=&Apache::loncommon::upfile_select_html(); + my $ignore=&mt('Ignore First Line'); $result.=<<ENDUPFORM; <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload"> <input type="hidden" name="symb" value="$symb" /> @@ -2833,7 +2895,7 @@ CSVFORMJS <input type="hidden" name="saveState" value="$ENV{'form.saveState'}" /> $upfile_select <br /><input type="button" onClick="javascript:checkUpload(this.form);" value="Upload Scores" /> - +<label><input type="checkbox" name="noFirstLine" />$ignore</lable> </form> ENDUPFORM $result.='</td></tr></table>'."\n"; @@ -2856,6 +2918,7 @@ sub csvuploadmap { &Apache::loncommon::load_tmp_file($request); } my @records=&Apache::loncommon::upfile_record_sep(); + if ($ENV{'form.noFirstLine'}) { shift(@records); } &csvuploadmap_header($request,$symb,$url,$datatoken,$#records+1); my ($i,$keyfields); if (@records) { @@ -2881,14 +2944,51 @@ sub csvuploadmap { return ''; } -sub csvuploadassign { +sub csvuploadoptions { my ($request)= @_; my ($symb,$url)=&get_symb_and_url($request); - if (!$symb) {return '';} - &Apache::loncommon::load_tmp_file($request); - my @gradedata = &Apache::loncommon::upfile_record_sep(); + my $checked=(($ENV{'form.noFirstLine'})?'1':'0'); + my $ignore=&mt('Ignore First Line'); + $request->print(<<ENDPICK); +<form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload"> +<h3><font color="#339933">Uploading Class Grade Options</font></h3> +<input type="hidden" name="command" value="csvuploadassign" /> +<input type="submit" value="Assign Grades" /><br /> +<p> +<label> + <input type="checkbox" name="show_full_results" /> + Show a table of all changes +</label> +</p> +<p> +<label> + <input type="checkbox" name="overwite_scores" checked="checked" /> + Overwrite any existing score +</label> +</p> +ENDPICK + my %fields=&get_fields(); + if (!defined($fields{'domain'})) { + my $domform = &Apache::loncommon::select_dom_form($ENV{'request.role.domain'},'default_domain'); + $request->print("\n<p> Users are in domain: ".$domform."</p>\n"); + } + foreach my $key (sort(keys(%ENV))) { + if ($key !~ /^form\.(.*)$/) { next; } + my $cleankey=$1; + if ($cleankey eq 'command') { next; } + $request->print('<input type="hidden" name="'.$cleankey. + '" value="'.$ENV{$key}.'" />'."\n"); + } + # FIXME do a check for any duplicated user ids... + # FIXME do a check for any invalid user ids?... + $request->print("<hr /></form>\n"); + $request->print(&show_grading_menu_form($symb,$url)); + return ''; +} + +sub get_fields { + my %fields; my @keyfields = split(/\,/,$ENV{'form.keyfields'}); - my %fields=(); for (my $i=0; $i<=$ENV{'form.nfields'}; $i++) { if ($ENV{'form.upfile_associate'} eq 'reverse') { if ($ENV{'form.f'.$i} ne 'none') { @@ -2900,6 +3000,17 @@ sub csvuploadassign { } } } + return %fields; +} + +sub csvuploadassign { + my ($request)= @_; + my ($symb,$url)=&get_symb_and_url($request); + if (!$symb) {return '';} + &Apache::loncommon::load_tmp_file($request); + my @gradedata = &Apache::loncommon::upfile_record_sep(); + if ($ENV{'form.noFirstLine'}) { shift(@gradedata); } + my %fields=&get_fields(); $request->print('<h3>Assigning Grades</h3>'); my $courseid=$ENV{'request.course.id'}; my ($classlist) = &getclasslist('all',0); @@ -2908,17 +3019,29 @@ sub csvuploadassign { my $countdone=0; foreach my $grade (@gradedata) { my %entries=&Apache::loncommon::record_sep($grade); - my $domain=$entries{$fields{'domain'}}; + my $domain; + if ($entries{$fields{'domain'}}) { + $domain=$entries{$fields{'domain'}}; + } else { + $domain=$ENV{'form.default_domain'}; + } $domain=~s/\s//g; my $username=$entries{$fields{'username'}}; $username=~s/\s//g; if (!$username) { my $id=$entries{$fields{'ID'}}; + $id=~s/\s//g; my %ids=&Apache::lonnet::idget($domain,$id); $username=$ids{$id}; } if (!exists($$classlist{"$username:$domain"})) { - push(@skipped,"$username:$domain"); + my $id=$entries{$fields{'ID'}}; + $id=~s/\s//g; + if ($id) { + push(@skipped,"$id:$domain"); + } else { + push(@skipped,"$username:$domain"); + } next; } my $usec=$classlist->{"$username:$domain"}[5]; @@ -2936,6 +3059,7 @@ sub csvuploadassign { my $part=$1; my $wgt =&Apache::lonnet::EXT('resource.'.$part.'.weight', $symb,$domain,$username); + $entries{$fields{$dest}}=~s/\s//g; my $pcr=$entries{$fields{$dest}} / $wgt; my $award='correct_by_override'; $grades{"resource.$part.awarded"}=$pcr; @@ -5139,9 +5263,9 @@ sub handler { $request->print(&csvupload($request)); } elsif ($command eq 'csvuploadmap' && $perm{'mgr'} ) { $request->print(&csvuploadmap($request)); - } elsif ($command eq 'csvuploadassign' && $perm{'mgr'}) { + } elsif ($command eq 'csvuploadoptions' && $perm{'mgr'}) { if ($ENV{'form.associate'} ne 'Reverse Association') { - $request->print(&csvuploadassign($request)); + $request->print(&csvuploadoptions($request)); } else { if ( $ENV{'form.upfile_associate'} ne 'reverse' ) { $ENV{'form.upfile_associate'} = 'reverse'; @@ -5150,6 +5274,8 @@ sub handler { } $request->print(&csvuploadmap($request)); } + } elsif ($command eq 'csvuploadassign' && $perm{'mgr'} ) { + $request->print(&csvuploadassign($request)); } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) { $request->print(&scantron_selectphase($request)); } elsif ($command eq 'scantron_warning' && $perm{'mgr'}) {