Annotation of loncom/homework/grades.pm, revision 1.33
1.17 albertel 1: # The LearningOnline Network with CAPA
1.13 albertel 2: # The LON-CAPA Grading handler
1.17 albertel 3: #
1.33 ! ng 4: # $Id: grades.pm,v 1.32 2002/06/26 21:25:31 ng Exp $
1.17 albertel 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
1.13 albertel 28: # 2/9,2/13 Guy Albertelli
1.8 www 29: # 6/8 Gerd Kortemeyer
1.13 albertel 30: # 7/26 H.K. Ng
1.14 www 31: # 8/20 Gerd Kortemeyer
1.30 ng 32: # Year 2002
33: # June 2002 H.K. Ng
34: #
1.1 albertel 35:
36: package Apache::grades;
37: use strict;
38: use Apache::style;
39: use Apache::lonxml;
40: use Apache::lonnet;
1.3 albertel 41: use Apache::loncommon;
1.1 albertel 42: use Apache::lonhomework;
43: use Apache::Constants qw(:common);
44:
1.2 albertel 45: sub moreinfo {
1.13 albertel 46: my ($request,$reason) = @_;
47: $request->print("Unable to process request: $reason");
48: if ( $Apache::grades::viewgrades eq 'F' ) {
49: $request->print('<form action="/adm/grades" method="post">'."\n");
1.16 albertel 50: if ($ENV{'form.url'}) {
51: $request->print('<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />'."\n");
52: }
53: if ($ENV{'form.symb'}) {
54: $request->print('<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />'."\n");
55: }
56: $request->print('<input type="hidden" name="command" value="'.$ENV{'form.command'}.'" />'."\n");
57: $request->print("Student:".'<input type="text" name="student" value="'.$ENV{'form.student'}.'" />'."<br />\n");
58: $request->print("Domain:".'<input type="text" name="domain" value="'.$ENV{'user.domain'}.'" />'."<br />\n");
59: $request->print('<input type="submit" name="submit" value="ReSubmit" />'."<br />\n");
1.13 albertel 60: $request->print('</form>');
61: }
62: return '';
1.2 albertel 63: }
64:
1.23 www 65: sub verifyreceipt {
66: my $request=shift;
67: my $courseid=$ENV{'request.course.id'};
68: my $cdom=$ENV{"course.$courseid.domain"};
69: my $cnum=$ENV{"course.$courseid.num"};
70: my $receipt=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}).'-'.
71: $ENV{'form.receipt'};
72: $receipt=~s/[^\-\d]//g;
73: my $symb=$ENV{'form.symb'};
74: unless ($symb) {
75: $symb=&Apache::lonnet::symbread($ENV{'form.url'});
76: }
77: if ((&Apache::lonnet::allowed('mgr',$courseid)) && ($symb)) {
78: $request->print('<h1>Verifying Submission Receipt '.$receipt.'</h1>');
79: my $matches=0;
1.24 albertel 80: my (%classlist) = &getclasslist($cdom,$cnum,'0');
1.23 www 81: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
82: my ($uname,$udom)=split(/\:/,$student);
83: if ($receipt eq
84: &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb)) {
85: $request->print('Matching '.$student.'<br>');
86: $matches++;
87: }
88: }
1.30 ng 89: $request->printf('<p>'.$matches." match%s</p>",$matches <= 1 ? '' : 'es');
1.33 ! ng 90: # needs to print who is matched
1.23 www 91: }
92: return '';
93: }
1.13 albertel 94:
1.30 ng 95: sub receiptInput {
1.13 albertel 96: my ($request) = shift;
1.23 www 97: my $cdom=$ENV{"course.$ENV{'request.course.id'}.domain"};
98: my $cnum=$ENV{"course.$ENV{'request.course.id'}.num"};
99: my $hostver=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'});
100: $request->print(<<ENDHEADER);
1.28 ng 101: <h2><font color="#339933">Verify a Submission Receipt Issued by this Server</font></h2>
1.23 www 102: <form action="/adm/grades" method="post">
103: <tt>$hostver-<input type="text" name="receipt" size="4"></tt>
104: <input type="submit" name="submit" value="Verify">
105: <input type="hidden" name="command" value="verify">
106: ENDHEADER
107: if ($ENV{'form.url'}) {
108: $request->print(
109: '<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />');
110: }
111: if ($ENV{'form.symb'}) {
112: $request->print(
113: '<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />');
114: }
1.30 ng 115: # $request->print(<<ENDTABLEST);
116: $request->print('</form>');
117: return '';
118: }
119:
1.32 ng 120: sub student_gradeStatus {
121: my ($url,$udom,$uname) = @_;
122: my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));
123: my %record= &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);
124: foreach my $part (&getpartlist($url)) {
125: my ($temp,$part,$type)=split(/_/,$part);
126: if ($type eq 'solved') {
127: my ($status,$foo)=split(/_/,$record{"resource.$part.$type"},2);
128: $status = 'nothing' if ($status eq '');
129: return $type,$status;
130: }
131: }
132: return '';
133: }
134:
1.30 ng 135: sub listStudents {
136: my ($request) = shift;
137: my $cdom=$ENV{"course.$ENV{'request.course.id'}.domain"};
138: my $cnum=$ENV{"course.$ENV{'request.course.id'}.num"};
139:
1.23 www 140: $request->print(<<ENDTABLEST);
1.28 ng 141: <h2><font color="#339933">Show Student Submissions on Assessment</font></h2>
142:
1.32 ng 143: <table border="0"><tr><td bgcolor="#777777">
1.29 albertel 144: <table border="0">
1.32 ng 145: <tr bgcolor="#e6ffff"><td colspan="7"><b>Resource: </b> $ENV{'form.url'}</td></tr>
1.30 ng 146: <tr bgcolor="#e6ffff"><td><b>Username</b></td><td><b>Name</b></td><td><b>Domain</b></td>
1.32 ng 147: <td><b>View Problem</b></td><td><b>Submissions</b></td>
148: <td><b>Grade Status</b></td><td><b>Action</b></td></tr>
1.23 www 149: ENDTABLEST
1.24 albertel 150: my (%classlist) = &getclasslist($cdom,$cnum,'0');
1.13 albertel 151: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
152: my ($sname,$sdom) = split(/:/,$student);
153:
1.25 albertel 154: my %name=&Apache::lonnet::get('environment', ['lastname','generation',
155: 'firstname','middlename'],
156: $sdom,$sname);
157: my $fullname;
158: my ($tmp) = keys(%name);
159: if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
160: $fullname=$name{'lastname'}.$name{'generation'};
1.28 ng 161: if ($fullname =~ /[^\s]+/) { $fullname.=', '; }
1.25 albertel 162: $fullname.=$name{'firstname'}.' '.$name{'middlename'};
163: }
1.13 albertel 164: if ( $Apache::grades::viewgrades eq 'F' ) {
1.32 ng 165: $request->print("\n".'<tr bgcolor=#ffffe6>'."<td>$sname</td><td>$fullname</td><td align=\"middle\">$sdom</td>".
1.21 albertel 166: '<form action="/adm/grades" method="post">');
1.16 albertel 167: if ($ENV{'form.url'}) {
1.19 www 168: $request->print(
1.30 ng 169: '<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />');
1.16 albertel 170: }
171: if ($ENV{'form.symb'}) {
1.19 www 172: $request->print(
1.30 ng 173: '<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />');
1.16 albertel 174: }
1.19 www 175: $request->print(
1.30 ng 176: '<input type="hidden" name="command" value="'.$ENV{'form.command'}.'" />');
1.19 www 177: $request->print(
1.30 ng 178: '<input type="hidden" name="student" value="'.$sname.'" />');
1.19 www 179: $request->print(
1.30 ng 180: '<input type="hidden" name="fullname" value="'.$fullname.'" />');
1.28 ng 181: $request->print(
1.30 ng 182: '<input type="hidden" name="domain" value="'.$sdom.'" />');
183: $request->print('<td>'.
184: '<input type="radio" name="vProb" value="no" checked> no '.
185: '<input type="radio" name="vProb" value="yes"> yes </td>');
186: $request->print('<td>'.
1.33 ! ng 187: '<input type="radio" name="lastSub" value="last" checked> last '.
! 188: '<input type="radio" name="lastSub" value="all"> all </td>');
1.32 ng 189: my ($type,$status) = &student_gradeStatus($ENV{'form.url'},$cdom,$sname);
190: $request->print(
191: '<td align="middle">'.$status.' </td>');
1.19 www 192: $request->print(
1.30 ng 193: '<td><input type="submit" name="submit" value="View/Grade" />');
1.28 ng 194: $request->print('</td></tr></form>');
195: # $request->print('</form></td></tr>');
1.13 albertel 196: }
197: }
1.28 ng 198: $request->print('</table></td></tr></table>');
1.10 ng 199: }
200:
1.13 albertel 201:
1.7 albertel 202: #FIXME - needs to handle multiple matches
1.2 albertel 203: sub finduser {
1.13 albertel 204: my ($name) = @_;
205: my $domain = '';
206:
207: if ( $Apache::grades::viewgrades eq 'F' ) {
208: #get classlist
209: my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});
1.24 albertel 210: #print "Found $cdom:$cnum<br />";
211: my (%classlist) = &getclasslist($cdom,$cnum,'0');
1.13 albertel 212: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
213: my ($posname,$posdomain) = split(/:/,$student);
214: if ($posname =~ $name) { $name=$posname; $domain=$posdomain; last; }
1.7 albertel 215: }
1.13 albertel 216: return ($name,$domain);
217: } else {
218: return ($ENV{'user.name'},$ENV{'user.domain'});
219: }
1.5 albertel 220: }
221:
222: sub getclasslist {
1.24 albertel 223: my ($coursedomain,$coursenum,$hideexpired) = @_;
224: my %classlist=&Apache::lonnet::dump('classlist',$coursedomain,$coursenum);
1.13 albertel 225: my $now = time;
1.24 albertel 226: foreach my $student (keys(%classlist)) {
227: my ($end,$start)=split(/:/,$classlist{$student});
1.13 albertel 228: # still a student?
229: if (($hideexpired) && ($end) && ($end < $now)) {
1.15 albertel 230: #print "Skipping:$name:$end:$now<br />\n";
1.13 albertel 231: next;
232: }
1.15 albertel 233: #print "record=$record<br>";
1.24 albertel 234: push( @{ $classlist{'allids'} }, $student);
1.13 albertel 235: }
236: return (%classlist);
1.5 albertel 237: }
238:
239: sub getpartlist {
1.13 albertel 240: my ($url) = @_;
241: my @parts =();
242: my (@metakeys) = split(/,/,&Apache::lonnet::metadata($url,'keys'));
243: foreach my $key (@metakeys) {
1.30 ng 244: if ( $key =~ m/stores_([0-9]+)_.*/) {
1.13 albertel 245: push(@parts,$key);
1.6 albertel 246: }
1.13 albertel 247: }
248: return @parts;
1.5 albertel 249: }
250:
251: sub viewstudentgrade {
1.13 albertel 252: my ($url,$symb,$courseid,$student,@parts) = @_;
253: my $result ='';
254: my $cellclr = '"#ffffdd"';
1.28 ng 255: my ($username,$domain) = split(/:/,$student);
1.13 albertel 256:
1.28 ng 257: my (@requests) = ('lastname','firstname','middlename','generation');
258: my (%name) = &Apache::lonnet::get('environment',\@requests,$domain,$username);
259: my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$username);
1.32 ng 260:
1.28 ng 261: my $fullname=$name{'lastname'}.$name{'generation'};
262: if ($fullname =~ /[^\s]+/) { $fullname.=', '; }
263: $fullname.=$name{'firstname'}.' '.$name{'middlename'};
1.13 albertel 264:
1.28 ng 265: $result.="<tr bgcolor=$cellclr><td>$username</td><td>$fullname</td><td align=\"middle\">$domain</td>\n";
1.13 albertel 266: foreach my $part (@parts) {
267: my ($temp,$part,$type)=split(/_/,$part);
1.31 ng 268: my $score=$record{"resource.$part.$type"};
269: if ($type eq 'awarded' || $type eq 'tries') {
270: $result.='<td align="middle"><input type="text" name="GRADE.'.$student.'.'.$part.'.'.$type.
271: '" value="'.$score.'" size="4" /></td>'."\n";
1.13 albertel 272: } elsif ($type eq 'solved') {
1.31 ng 273: my ($status,$foo)=split(/_/,$score,2);
1.28 ng 274: $result.="<td align=\"middle\"><select name=\"GRADE.$student.$part.$type\">\n";
1.31 ng 275: my $optsel = '<option>correct</option><option>incorrect</option><option>excused</option>'.
1.33 ! ng 276: '<option>ungraded</option><option>partial</option><option>nothing</option>'."\n";
1.31 ng 277: $status = 'nothing' if ($status eq '');
278: $optsel =~ s/<option>$status/<option selected="on">$status/;
279: $result.=$optsel;
1.13 albertel 280: $result.="</select></td>\n";
281: }
282: }
1.29 albertel 283: $result.='<td></td></tr>';
1.13 albertel 284: return $result;
1.5 albertel 285: }
1.31 ng 286:
287: #FIXME need to look at the metadata <stores> spec on what type of data to accept and provide an
1.6 albertel 288: #interface based on that, also do that to above function.
1.5 albertel 289: sub setstudentgrade {
1.13 albertel 290: my ($url,$symb,$courseid,$student,@parts) = @_;
291:
292: my $result ='';
293: my ($stuname,$domain) = split(/:/,$student);
294: my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$stuname);
295: my %newrecord;
296:
297: foreach my $part (@parts) {
298: my ($temp,$part,$type)=split(/_/,$part);
299: my $oldscore=$record{"resource.$part.$type"};
300: my $newscore=$ENV{"form.GRADE.$student.$part.$type"};
1.32 ng 301: print "old=$oldscore:new=$newscore:<br>";
1.13 albertel 302: if ($type eq 'solved') {
303: my $update=0;
304: if ($newscore eq 'nothing' ) {
305: if ($oldscore ne '') {
306: $update=1;
307: $newscore = '';
1.6 albertel 308: }
1.13 albertel 309: } elsif ($oldscore !~ m/^$newscore/) {
310: $update=1;
311: $result.="Updating $stuname to $newscore<br />\n";
312: if ($newscore eq 'correct') { $newscore = 'correct_by_override'; }
313: if ($newscore eq 'incorrect') { $newscore = 'incorrect_by_override'; }
314: if ($newscore eq 'excused') { $newscore = 'excused'; }
315: if ($newscore eq 'ungraded') { $newscore = 'ungraded_attempted'; }
316: } else {
317: #$result.="$stuname:$part:$type:unchanged $oldscore to $newscore:<br />\n";
318: }
319: if ($update) { $newrecord{"resource.$part.$type"}=$newscore; }
320: } else {
321: if ($oldscore ne $newscore) {
322: $newrecord{"resource.$part.$type"}=$newscore;
323: $result.="Updating $student"."'s status for $part.$type to $newscore<br />\n";
324: } else {
325: #$result.="$stuname:$part:$type:unchanged $oldscore to $newscore:<br />\n";
326: }
327: }
328: }
329: if ( scalar(keys(%newrecord)) > 0 ) {
1.32 ng 330: $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
331: print "grader=$newrecord{'resource.regrader'}:<br>records<br>";
332: while (my ($k,$v) = each %newrecord) {
333: print "k=$k:v=$v:<br>\n";
334: }
1.13 albertel 335: &Apache::lonnet::cstore(\%newrecord,$symb,$courseid,$domain,$stuname);
336:
337: $result.="Stored away ".scalar(keys(%newrecord))." elements.<br />\n";
338: }
339: return $result;
1.2 albertel 340: }
341:
1.33 ! ng 342: #
1.32 ng 343: # --------------------------- show submissions of a student, option to grade --------
1.2 albertel 344: sub submission {
1.13 albertel 345: my ($request) = @_;
1.33 ! ng 346:
1.31 ng 347: $request->print(<<JAVASCRIPT);
1.32 ng 348: <script type="text/javascript" language="javascript">
1.33 ! ng 349: function updateRadio(radioButton,formtextbox,formsel,wgt) {
! 350: var pts = formtextbox.value;
! 351: var resetbox =false;
! 352: if (isNaN(pts) || pts < 0) {
! 353: alert("A number equal or greater than 0 is expected. Entered value = "+pts);
! 354: for (var i=0; i<radioButton.length; i++) {
! 355: if (radioButton[i].checked) {
! 356: formtextbox.value = i;
! 357: resetbox = true;
! 358: }
1.32 ng 359: }
1.33 ! ng 360: if (!resetbox) {
! 361: formtextbox.value = "";
! 362: }
! 363: return;
! 364: }
1.32 ng 365:
1.33 ! ng 366: for (var i=0; i<radioButton.length; i++) {
! 367: radioButton[i].checked=false;
! 368: if (pts == i) {
! 369: radioButton[i].checked=true;
1.32 ng 370: }
1.31 ng 371: }
1.33 ! ng 372: updateSelect(formsel,pts,wgt);
! 373: }
! 374:
! 375: function writeBox(formrad,formsel,pts,wgt) {
! 376: formrad.value = pts;
! 377: updateSelect(formsel,pts,wgt);
! 378: return;
! 379: }
! 380:
! 381: function updateSelect(formsel,pts,wgt) {
! 382: if (pts == 0) {
! 383: formsel[1].selected = true;
! 384: }
! 385: if (pts > 0 && pts < wgt) {
! 386: formsel[4].selected = true;
! 387: }
! 388: if (pts == wgt) {
! 389: formsel[0].selected = true;
! 390: }
! 391: return;
! 392: }
1.32 ng 393:
1.31 ng 394: </script>
395: JAVASCRIPT
1.33 ! ng 396: (my $url=$ENV{'form.url'})=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
1.13 albertel 397: if ($ENV{'form.student'} eq '') { &moreinfo($request,"Need student login id"); return ''; }
1.33 ! ng 398: print "formstu=$ENV{'form.student'}:<br>";
1.13 albertel 399: my ($uname,$udom) = &finduser($ENV{'form.student'});
400: if ($uname eq '') { &moreinfo($request,"Unable to find student"); return ''; }
1.32 ng 401:
402: my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));
1.13 albertel 403: if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }
1.31 ng 404: #
405: # header info
1.28 ng 406: my $result='<h2><font color="#339933">Submission Record</font></h2>';
1.33 ! ng 407: $result.='<table border="0"><tr><td><b>Username: </b>'.$uname.
! 408: '</td><td><b>Fullname: </b>'.$ENV{'form.fullname'}.'</td><td><b>Domain: </b>'.$udom.'</td></tr>';
1.30 ng 409: $result.='<tr><td colspan=3><b>Resource: </b>'.$url.'</td></tr></table>';
1.31 ng 410: #
411: # option to display problem
1.30 ng 412: if ($ENV{'form.vProb'} eq 'yes') {
413: my $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom,
1.17 albertel 414: $ENV{'request.course.id'});
1.30 ng 415: my $companswer=&Apache::loncommon::get_student_answers($symb,$uname,$udom,
416: $ENV{'request.course.id'});
1.33 ! ng 417: $result.='<table border="0" width="100%"><tr><td bgcolor="#777777">';
! 418: $result.='<table border="0" width="100%"><tr><td bgcolor="#e6ffff">';
1.31 ng 419: $result.='<b>Student\'s view of the problem</b></td></tr><tr><td bgcolor="#ffffff">'.$rendered.'<br />';
1.30 ng 420: $result.='<b>Correct answer:</b><br />'.$companswer;
421: $result.='</td></tr></table>';
422: $result.='</td></tr></table><br />';
423: }
1.33 ! ng 424: my $last = ($ENV{'form.lastSub'} eq 'last' ? 'last' : '');
1.30 ng 425: my $answer=&Apache::loncommon::get_previous_attempt($symb,$uname,$udom,
426: $ENV{'request.course.id'},$last);
1.31 ng 427: $result.=$answer;
1.18 albertel 428:
1.32 ng 429: my $wgt = &Apache::lonnet::EXT('resource.partid.weight',$symb,$udom,$uname);
1.31 ng 430: my %record= &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);
1.32 ng 431: my $score = $record{'resource.0.awarded'}*$wgt;
1.30 ng 432:
1.31 ng 433: $result.= '<form action="/adm/grades" method="post" name="SCORE">'."\n".
1.30 ng 434: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
435: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
1.33 ! ng 436: '<input type="hidden" name="vProb" value="'.$ENV{'form.vProb'}.'" />'."\n".
! 437: '<input type="hidden" name="lastSub" value="'.$last.'" />'."\n".
! 438: '<input type="hidden" name="command" value="handgrade" />'."\n".
! 439: '<input type="hidden" name="NCT"'.
! 440: ' value="'.($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1').'" />'."\n";
! 441:
! 442: my $counter = 0;
! 443: $result.='<input type="hidden" name="WGT'.$counter.'" value="'.$wgt.'" />'.
! 444: '<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':'.$udom.'" />'."\n";
1.32 ng 445: $result.='<table border="0"><tr><td><b>Points</b></td><td>';
1.31 ng 446: my $ctr = 0;
1.32 ng 447: while ($ctr<=$wgt) {
1.33 ! ng 448: $result.= '<input type="radio" name="RADVAL'.$counter.'" '.
! 449: 'onclick="javascript:writeBox(this.form.GRADE_BOX'.$counter.
! 450: ',this.form.GRADE_SEL'.$counter.',\''.$ctr.'\',\''.$wgt.'\')" '.
! 451: ($score == $ctr? 'checked':'').' /> '.$ctr."\n";
1.31 ng 452: $ctr++;
453: }
454: $result.='</td><td> <b>or</b> </td>';
1.33 ! ng 455: $result.='<td><input type="text" name="GRADE_BOX'.$counter.'"'.
1.32 ng 456: ($score ne ''? ' value = "'.$score.'"':'').' size="4" '.
1.33 ! ng 457: 'onChange="javascript:updateRadio(this.form.RADVAL'.$counter.
! 458: ',this.form.GRADE_BOX'.$counter.
! 459: ',this.form.GRADE_SEL'.$counter.',\''.$wgt.'\')" /></td>'."\n";
! 460: $result.='<td>/'.($wgt > 0 ? $wgt.' (problem weight)' : '<font color="red">invalid problem weight</font>' ).
! 461: ' </td><td>';
! 462:
! 463: foreach my $part (&getpartlist($url)) {
! 464: my ($temp,$part,$type)=split(/_/,$part);
! 465: if ($type eq 'solved') {
! 466: my ($status,$foo)=split(/_/,$record{"resource.$part.$type"},2);
! 467: $result.='<select name="GRADE_SEL'.$counter.'">'."\n";
! 468: my $optsel = '<option>correct</option><option>incorrect</option>'.
! 469: '<option>excused</option><option>ungraded</option>'.
! 470: '<option>partial</option><option>nothing</option>'."\n";
! 471: $status = 'nothing' if ($status eq '');
! 472: $optsel =~ s/<option>$status/<option selected="on">$status/;
! 473: $result.=$optsel;
! 474: $result.="</select></td></tr>\n";
! 475: }
! 476: }
1.32 ng 477:
1.33 ! ng 478: $result.='<tr><td colspan="6"><input type="submit" name="gradeOpt" value="Save & Next" />';
! 479: my $ntstu ='<select name="NTSTU">'.
! 480: '<option>1</option><option>2</option>'.
! 481: '<option>3</option><option>5</option>'.
! 482: '<option>7</option><option>10</option></select>'."\n";
! 483: my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1');
! 484: $ntstu =~ s/<option>$nsel/<option selected="on">$nsel/;
! 485: $result.=$ntstu.'student(s) '."\n <br />";
1.32 ng 486: $result.='<input type="submit" name="gradeOpt" value="Next" /> ';
487: $result.='<input type="submit" name="gradeOpt" value="Previous" /> ';
1.33 ! ng 488: $result.='(Next and Previous do not save the scores.)';
1.32 ng 489: $result.='</td><tr></table></form>';
490: return $result;
491: }
1.30 ng 492:
1.32 ng 493: sub processHandGrade {
1.33 ! ng 494: my ($request) = @_;
! 495: my $result='';
! 496:
! 497: my $url = $ENV{'form.url'};
! 498: my $symb = $ENV{'form.symb'};
! 499: my $button = $ENV{'form.gradeOpt'};
! 500: my $ngrade = $ENV{'form.NCT'};
! 501: my $ntstu = $ENV{'form.NTSTU'};
! 502: my $vProb = $ENV{'form.vProb'};
! 503: my $lastSub= $ENV{'form.lastSub'};
! 504:
! 505: my (@parts) = sort(&getpartlist($url));
! 506: if ($button eq 'Save & Next') {
! 507: my $ctr = 0;
! 508: while ($ctr < $ENV{'form.NCT'}) {
! 509: my $pts = ($ENV{'form.GRADE_BOX'.$ctr} ne '' ? $ENV{'form.GRADE_BOX'.$ctr} : $ENV{'form.RADVAL'.$ctr});
! 510: my $wgt = $ENV{'form.WGT'.$ctr};
! 511: my $sel = $ENV{'form.GRADE_SEL'.$ctr};
! 512: my $score = $pts/$wgt if ($wgt != 0);
! 513: my ($uname,$udom) = split(/:/,$ENV{'form.unamedom'.$ctr});
! 514: &saveHandGrade($url,$symb,$uname,$udom,$score,@parts);
! 515: $ctr++;
! 516: }
! 517: }
! 518: my $firststu = $ENV{'form.unamedom0'};
! 519: my $laststu = $ENV{'form.unamedom'.($ngrade-1)};
! 520:
! 521: #get classlist
! 522: my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});
! 523: my (%classlist) = &getclasslist($cdom,$cnum,'0');
! 524:
! 525: my (@nextlist,@prevlist);
! 526: my ($nextflg,$prevflg,$ctr) = (0,0,0);
! 527: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
! 528: my ($uname,$udom) = split(/:/,$student);
! 529: if ($nextflg == 1 && $button =~ /Next$/) {
! 530: push @nextlist,$uname if ($ctr < $ENV{'form.NTSTU'});
! 531: $ctr++;
! 532: }
! 533: $nextflg = 1 if ($student eq $laststu);
! 534: $prevflg = 1 if ($student eq $firststu);
! 535: }
! 536: foreach my $student (@nextlist) {
! 537: $ENV{'form.student'} = $student;
! 538: $request->print(&submission($request));
! 539: }
! 540: $request->print ("<h2><font color=\"#339933\">Grading</font></h2>");
! 541:
! 542: #get info for each student
! 543: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
! 544: my $display=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},$student,@parts);
! 545: print "ID=$ENV{'request.course.id'}:STU=$student:DIS=$display:<br>\n";
! 546: # $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},$student,@parts);
! 547: }
! 548:
! 549: return 'The End';
! 550: # return $result;
! 551: }
! 552:
! 553: sub saveHandGrade {
! 554: my ($url,$symb,$stuname,$domain,$newscore,@parts) = @_;
1.32 ng 555:
1.33 ! ng 556: # my ($stuname,$domain) = split(/:/,$student);
! 557: my %record=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},$domain,$stuname);
1.32 ng 558: my %newrecord;
559:
560: foreach my $part (@parts) {
1.31 ng 561: my ($temp,$part,$type)=split(/_/,$part);
1.32 ng 562: my $oldscore=$record{"resource.$part.$type"};
1.31 ng 563: if ($type eq 'solved') {
1.32 ng 564: my $update=0;
565: if ($newscore eq 'nothing' ) {
566: if ($oldscore ne '') {
567: $update=1;
568: $newscore = '';
569: }
570: } elsif ($oldscore !~ m/^$newscore/) {
571: $update=1;
572: if ($newscore eq 'correct') { $newscore = 'correct_by_override'; }
573: if ($newscore eq 'incorrect') { $newscore = 'incorrect_by_override'; }
574: if ($newscore eq 'excused') { $newscore = 'excused'; }
575: if ($newscore eq 'ungraded') { $newscore = 'ungraded_attempted'; }
1.33 ! ng 576: if ($newscore eq 'partial') { $newscore = 'partial_correct'; }
1.32 ng 577: }
578: if ($update) { $newrecord{"resource.$part.$type"}=$newscore; }
579: } else {
580: if ($oldscore ne $newscore) {
581: $newrecord{"resource.$part.$type"}=$newscore;
1.33 ! ng 582: }
1.32 ng 583: }
1.33 ! ng 584: if ( scalar(keys(%newrecord)) > 0 ) {
! 585: $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
! 586: # print "grader=$newrecord{'resource.regrader'}:<br>records<br>";
! 587: # while (my ($k,$v) = each %newrecord) {
! 588: # print "k=$k:v=$v:<br>\n";
! 589: # }
! 590: # &Apache::lonnet::cstore(\%newrecord,$symb,$courseid,$domain,$stuname);
1.31 ng 591: }
1.33 ! ng 592: return '';
1.31 ng 593: }
1.2 albertel 594: }
595:
1.26 albertel 596: sub get_symb_and_url {
597: my ($request) = @_;
1.13 albertel 598: my $url=$ENV{'form.url'};
599: $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
1.32 ng 600: # my $symb=$ENV{'form.symb'};
601: # if (!$symb) { $symb=&Apache::lonnet::symbread($url); }
602: my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));
1.13 albertel 603: if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }
1.26 albertel 604: return ($symb,$url);
605: }
1.13 albertel 606:
1.29 albertel 607: sub view_edit_entire_class_form {
608: my ($symb,$url)=@_;
609: my $result.='<form action="/adm/grades" method="post">'."\n".
610: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
611: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
612: '<input type="hidden" name="command" value="viewgrades" />'."\n".
1.30 ng 613: '<input type="submit" name="submit" value="View/Grade Entire Class" />'."\n".
1.29 albertel 614: '</form>'."\n";
615: return $result;
616: }
617:
618: sub show_grading_menu_form {
619: my ($symb,$url)=@_;
620: my $result.='<form action="/adm/grades" method="post">'."\n".
621: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
622: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
623: '<input type="hidden" name="command" value="gradingmenu" />'."\n".
624: '<input type="submit" name="submit" value="Grading Menu" />'."\n".
625: '</form>'."\n";
626: return $result;
627: }
628:
1.26 albertel 629: sub gradingmenu {
630: my ($request) = @_;
631: my ($symb,$url)=&get_symb_and_url($request);
632: if (!$symb) {return '';}
1.28 ng 633:
634: my $result='<h2> <font color="#339933">Select a Grading Method</font></h2><br />';
1.32 ng 635: $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n";
1.28 ng 636: $result.='<table width=100% border=0><tr><td bgcolor=#e6ffff>'."\n";
637: $result.=' <b>Resource :</b> '.$url.'</td></tr>'."\n";
638: $result.='<tr bgcolor=#ffffe6><td>'."\n";
1.29 albertel 639: $result.=&view_edit_entire_class_form($symb,$url);
1.26 albertel 640: $result.='<form action="/adm/grades" method="post">'."\n".
641: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
642: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
643: '<input type="hidden" name="command" value="csvupload" />'."\n".
644: '<input type="submit" name="submit" value="Upload Scores" />'."\n".
1.28 ng 645: '</form>'."\n";
1.26 albertel 646: $result.='<form action="/adm/grades" method="post">'."\n".
647: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
648: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
649: '<input type="hidden" name="command" value="submission" />'."\n".
1.30 ng 650: '<input type="submit" name="submit" value="View/Grade A Student" />'."\n".
651: '</form>'."\n";
652: $result.='<form action="/adm/grades" method="post">'."\n".
653: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
654: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
655: '<input type="hidden" name="command" value="receiptInput" />'."\n".
656: '<input type="submit" name="submit" value="Verify Receipt" />'."\n".
1.28 ng 657: '</form>'."\n";
658: $result.='</td></tr></table>'."\n";
659: $result.='</td></tr></table>'."\n";
1.26 albertel 660: return $result;
661: }
662:
663: sub viewgrades {
664: my ($request) = @_;
665: my $result='';
666:
667: #get resource reference
668: my ($symb,$url)=&get_symb_and_url($request);
669: if (!$symb) {return '';}
1.13 albertel 670: #get classlist
671: my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});
1.24 albertel 672: #print "Found $cdom:$cnum<br />";
673: my (%classlist) = &getclasslist($cdom,$cnum,'0');
1.13 albertel 674: my $headerclr = '"#ccffff"';
675: my $cellclr = '"#ffffcc"';
676:
677: #get list of parts for this problem
1.29 albertel 678: my (@parts) = sort(&getpartlist($url));
1.13 albertel 679:
1.28 ng 680: $request->print ("<h2><font color=\"#339933\">Manual Grading</font></h2>");
1.13 albertel 681:
682: #start the form
683: $result = '<form action="/adm/grades" method="post">'."\n".
1.16 albertel 684: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
685: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
1.13 albertel 686: '<input type="hidden" name="command" value="editgrades" />'."\n".
687: '<input type="submit" name="submit" value="Submit Changes" />'."\n".
1.32 ng 688: '<table border=0><tr><td bgcolor="#777777">'."\n".
1.13 albertel 689: '<table border=0>'."\n".
1.28 ng 690: '<tr bgcolor='.$headerclr.'><td><b>Username</b></td><td><b>Name</b></td><td><b>Domain</b></td>'."\n";
1.29 albertel 691: foreach my $part (@parts) {
1.13 albertel 692: my $display=&Apache::lonnet::metadata($url,$part.'.display');
693: if (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); }
1.31 ng 694: print "Manual grading:$url:$part:$display:<br>";
1.28 ng 695: $result.='<td><b>'.$display.'</b></td>'."\n";
1.30 ng 696: }
1.28 ng 697: $result.='</tr>';
1.13 albertel 698: #get info for each student
699: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
1.31 ng 700: my $display=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},$student,@parts);
701: # print "ID=$ENV{'request.course.id'}:STU=$student:DIS=$display:<br>\n";
1.13 albertel 702: $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},$student,@parts);
703: }
1.31 ng 704: $result.='</table></td></tr></table>';
705: $result.='<input type="submit" name="submit" value="Submit Changes" /></form>';
1.29 albertel 706: $result.=&show_grading_menu_form($symb,$url);
1.13 albertel 707: return $result;
1.5 albertel 708: }
709:
710: sub editgrades {
1.13 albertel 711: my ($request) = @_;
712: my $result='';
1.5 albertel 713:
1.13 albertel 714: my $symb=$ENV{'form.symb'};
715: if ($symb eq '') { $request->print("Unable to handle ambiguous references:$symb:$ENV{'form.url'}"); return ''; }
716: my $url=$ENV{'form.url'};
717: #get classlist
718: my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});
1.24 albertel 719: #print "Found $cdom:$cnum<br />";
720: my (%classlist) = &getclasslist($cdom,$cnum,'0');
1.13 albertel 721:
722: #get list of parts for this problem
723: my (@parts) = &getpartlist($url);
724:
725: $result.='<form action="/adm/grades" method="post">'."\n".
726: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
727: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
728: '<input type="hidden" name="command" value="viewgrades" />'."\n".
729: '<input type="submit" name="submit" value="See Grades" /> <br />'."\n";
730:
731: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
732: $result.=&setstudentgrade($url,$symb,$ENV{'request.course.id'},$student,@parts);
733: }
1.5 albertel 734:
1.13 albertel 735: $result.='<input type="submit" name="submit" value="See Grades" /></table></form>';
736: return $result;
1.5 albertel 737: }
738:
1.26 albertel 739: sub csvupload {
740: my ($request)= @_;
741: my $result;
742: my ($symb,$url)=&get_symb_and_url($request);
743: if (!$symb) {return '';}
744: my $upfile_select=&Apache::loncommon::upfile_select_html();
745: $result.=<<ENDUPFORM;
746: <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
747: <input type="hidden" name="symb" value="$symb" />
748: <input type="hidden" name="url" value="$url" />
749: <input type="hidden" name="command" value="csvuploadmap" />
750: <hr />
751: <h3>Specify a file containing the class grades for resource $url</h3>
752: $upfile_select
753: <p><input type="submit" name="submit" value="Upload Grades" />
754: ENDUPFORM
755: return $result;
756: }
757:
1.27 albertel 758: sub csvupload_javascript_reverse_associate {
759: return(<<ENDPICK);
760: function verify(vf) {
761: var foundsomething=0;
762: var founduname=0;
763: var founddomain=0;
764: for (i=0;i<=vf.nfields.value;i++) {
765: tw=eval('vf.f'+i+'.selectedIndex');
766: if (i==0 && tw!=0) { founduname=1; }
767: if (i==1 && tw!=0) { founddomain=1; }
768: if (i!=0 && i!=1 && tw!=0) { foundsomething=1; }
769: }
770: if (founduname==0 || founddomain==0) {
771: alert('You need to specify at both the username and domain');
772: return;
773: }
774: if (foundsomething==0) {
775: alert('You need to specify at least one grading field');
776: return;
777: }
778: vf.submit();
779: }
780: function flip(vf,tf) {
781: var nw=eval('vf.f'+tf+'.selectedIndex');
782: var i;
783: for (i=0;i<=vf.nfields.value;i++) {
784: //can not pick the same destination field for both name and domain
785: if (((i ==0)||(i ==1)) &&
786: ((tf==0)||(tf==1)) &&
787: (i!=tf) &&
788: (eval('vf.f'+i+'.selectedIndex')==nw)) {
789: eval('vf.f'+i+'.selectedIndex=0;')
790: }
791: }
792: }
793: ENDPICK
794: }
795:
796: sub csvupload_javascript_forward_associate {
797: return(<<ENDPICK);
798: function verify(vf) {
799: var foundsomething=0;
800: var founduname=0;
801: var founddomain=0;
802: for (i=0;i<=vf.nfields.value;i++) {
803: tw=eval('vf.f'+i+'.selectedIndex');
804: if (tw==1) { founduname=1; }
805: if (tw==2) { founddomain=1; }
806: if (tw>2) { foundsomething=1; }
807: }
808: if (founduname==0 || founddomain==0) {
809: alert('You need to specify at both the username and domain');
810: return;
811: }
812: if (foundsomething==0) {
813: alert('You need to specify at least one grading field');
814: return;
815: }
816: vf.submit();
817: }
818: function flip(vf,tf) {
819: var nw=eval('vf.f'+tf+'.selectedIndex');
820: var i;
821: //can not pick the same destination field twice
822: for (i=0;i<=vf.nfields.value;i++) {
823: if ((i!=tf) && (eval('vf.f'+i+'.selectedIndex')==nw)) {
824: eval('vf.f'+i+'.selectedIndex=0;')
825: }
826: }
827: }
828: ENDPICK
829: }
830:
1.26 albertel 831: sub csvuploadmap_header {
832: my ($request,$symb,$url,$datatoken,$distotal)= @_;
833: my $result;
834: my $javascript;
835: if ($ENV{'form.upfile_associate'} eq 'reverse') {
1.27 albertel 836: $javascript=&csvupload_javascript_reverse_associate();
1.26 albertel 837: } else {
1.27 albertel 838: $javascript=&csvupload_javascript_forward_associate();
1.26 albertel 839: }
840: $request->print(<<ENDPICK);
841: <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
842: <h3>Uploading Class Grades for resource $url</h3>
843: <hr>
844: <h3>Identify fields</h3>
845: Total number of records found in file: $distotal <hr />
846: Enter as many fields as you can. The system will inform you and bring you back
847: to this page if the data selected is insufficient to run your class.<hr />
848: <input type="button" value="Reverse Association" onClick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" />
849: <input type="hidden" name="associate" value="" />
850: <input type="hidden" name="phase" value="three" />
851: <input type="hidden" name="datatoken" value="$datatoken" />
852: <input type="hidden" name="fileupload" value="$ENV{'form.fileupload'}" />
853: <input type="hidden" name="upfiletype" value="$ENV{'form.upfiletype'}" />
854: <input type="hidden" name="upfile_associate"
855: value="$ENV{'form.upfile_associate'}" />
856: <input type="hidden" name="symb" value="$symb" />
857: <input type="hidden" name="url" value="$url" />
858: <input type="hidden" name="command" value="csvuploadassign" />
859: <hr />
860: <script type="text/javascript" language="Javascript">
861: $javascript
862: </script>
863: ENDPICK
864: return '';
865:
866: }
867:
868: sub csvupload_fields {
869: my ($url) = @_;
870: my (@parts) = &getpartlist($url);
1.27 albertel 871: my @fields=(['username','Student Username'],['domain','Student Domain']);
872: foreach my $part (sort(@parts)) {
1.26 albertel 873: my @datum;
874: my $display=&Apache::lonnet::metadata($url,$part.'.display');
1.27 albertel 875: my $name=$part;
1.26 albertel 876: if (!$display) { $display = $name; }
877: @datum=($name,$display);
878: push(@fields,\@datum);
879: }
880: return (@fields);
881: }
882:
883: sub csvuploadmap_footer {
884: my ($request,$i,$keyfields) =@_;
885: $request->print(<<ENDPICK);
886: </table>
887: <input type="hidden" name="nfields" value="$i" />
888: <input type="hidden" name="keyfields" value="$keyfields" />
889: <input type="button" onClick="javascript:verify(this.form)" value="Assign Grades" /><br />
890: </form>
891: ENDPICK
892: }
893:
894: sub csvuploadmap {
895: my ($request)= @_;
896: my ($symb,$url)=&get_symb_and_url($request);
897: if (!$symb) {return '';}
898: my $datatoken;
899: if (!$ENV{'form.datatoken'}) {
900: $datatoken=&Apache::loncommon::upfile_store($request);
901: } else {
902: $datatoken=$ENV{'form.datatoken'};
903: &Apache::loncommon::load_tmp_file($request);
904: }
905: my @records=&Apache::loncommon::upfile_record_sep();
906: &csvuploadmap_header($request,$symb,$url,$datatoken,$#records+1);
907: my $i;
908: my $keyfields;
909: if (@records) {
910: my @fields=&csvupload_fields($url);
911: if ($ENV{'form.upfile_associate'} eq 'reverse') {
912: &Apache::loncommon::csv_print_samples($request,\@records);
913: $i=&Apache::loncommon::csv_print_select_table($request,\@records,
914: \@fields);
915: foreach (@fields) { $keyfields.=$_->[0].','; }
916: chop($keyfields);
917: } else {
918: unshift(@fields,['none','']);
919: $i=&Apache::loncommon::csv_samples_select_table($request,\@records,
920: \@fields);
921: my %sone=&Apache::loncommon::record_sep($records[0]);
922: $keyfields=join(',',sort(keys(%sone)));
923: }
924: }
925: &csvuploadmap_footer($request,$i,$keyfields);
926: return '';
1.27 albertel 927: }
928:
929: sub csvuploadassign {
930: my ($request)= @_;
931: my ($symb,$url)=&get_symb_and_url($request);
932: if (!$symb) {return '';}
933: &Apache::loncommon::load_tmp_file($request);
934: my @gradedata=&Apache::loncommon::upfile_record_sep();
935: my @keyfields = split(/\,/,$ENV{'form.keyfields'});
936: my %fields=();
937: for (my $i=0; $i<=$ENV{'form.nfields'}; $i++) {
938: if ($ENV{'form.upfile_associate'} eq 'reverse') {
939: if ($ENV{'form.f'.$i} ne 'none') {
940: $fields{$keyfields[$i]}=$ENV{'form.f'.$i};
941: }
942: } else {
943: if ($ENV{'form.f'.$i} ne 'none') {
944: $fields{$ENV{'form.f'.$i}}=$keyfields[$i];
945: }
946: }
947: }
948: $request->print('<h3>Assigning Grades</h3>');
949: my $courseid=$ENV{'request.course.id'};
950: my $cdom=$ENV{"course.$courseid.domain"};
951: my $cnum=$ENV{"course.$courseid.num"};
952: my (%classlist) = &getclasslist($cdom,$cnum,'1');
1.29 albertel 953: my @skipped;
954: my $countdone=0;
955: foreach my $grade (@gradedata) {
956: my %entries=&Apache::loncommon::record_sep($grade);
957: my $username=$entries{$fields{'username'}};
958: my $domain=$entries{$fields{'domain'}};
959: if (!exists($classlist{"$username:$domain"})) {
960: push(@skipped,"$username:$domain");
961: next;
1.27 albertel 962: }
1.29 albertel 963: my %grades;
964: foreach my $dest (keys(%fields)) {
965: if ($dest eq 'username' || $dest eq 'domain') { next; }
966: if ($entries{$fields{$dest}} eq '') { next; }
967: my $store_key=$dest;
968: $store_key=~s/^stores/resource/;
969: $store_key=~s/_/\./g;
970: $grades{$store_key}=$entries{$fields{$dest}};
971: }
972: $grades{"resource.regrader"}="$ENV{'user.name'}:$ENV{'user.domain'}";
973: &Apache::lonnet::cstore(\%grades,$symb,$ENV{'request.course.id'},
974: $domain,$username);
975: $request->print('.');
976: $request->rflush();
977: $countdone++;
978: }
979: $request->print("<br />Stored $countdone students\n");
980: if (@skipped) {
981: $request->print('<br /><font size="+1"><b>Skipped Students</b></font><br />');
982: foreach my $student (@skipped) { $request->print("<br />$student"); }
1.27 albertel 983: }
1.29 albertel 984: $request->print(&view_edit_entire_class_form($symb,$url));
985: $request->print(&show_grading_menu_form($symb,$url));
986: return '';
1.26 albertel 987: }
988:
1.2 albertel 989: sub send_header {
1.13 albertel 990: my ($request)= @_;
991: $request->print(&Apache::lontexconvert::header());
1.6 albertel 992: # $request->print("
993: #<script>
994: #remotewindow=open('','homeworkremote');
995: #remotewindow.close();
996: #</script>");
1.13 albertel 997: $request->print('<body bgcolor="#FFFFFF">');
1.2 albertel 998: }
999:
1000: sub send_footer {
1.13 albertel 1001: my ($request)= @_;
1.2 albertel 1002: $request->print('</body>');
1003: $request->print(&Apache::lontexconvert::footer());
1004: }
1005:
1.1 albertel 1006: sub handler {
1.13 albertel 1007: my $request=$_[0];
1008:
1009: if ($ENV{'browser.mathml'}) {
1010: $request->content_type('text/xml');
1011: } else {
1012: $request->content_type('text/html');
1013: }
1014: $request->send_http_header;
1015: return OK if $request->header_only;
1.16 albertel 1016: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
1.13 albertel 1017: my $url=$ENV{'form.url'};
1018: my $symb=$ENV{'form.symb'};
1019: my $command=$ENV{'form.command'};
1.16 albertel 1020: if (!$url) {
1021: my ($temp1,$temp2);
1022: ($temp1,$temp2,$ENV{'form.url'})=split(/___/,$symb);
1023: $url = $ENV{'form.url'};
1024: }
1.13 albertel 1025: &send_header($request);
1026: if ($url eq '' && $symb eq '') {
1.14 www 1027: if ($ENV{'user.adv'}) {
1028: if (($ENV{'form.codeone'}) && ($ENV{'form.codetwo'}) &&
1029: ($ENV{'form.codethree'})) {
1030: my $token=$ENV{'form.codeone'}.'*'.$ENV{'form.codetwo'}.'*'.
1031: $ENV{'form.codethree'};
1032: my ($tsymb,$tuname,$tudom,$tcrsid)=
1033: &Apache::lonnet::checkin($token);
1034: if ($tsymb) {
1035: my ($map,$id,$url)=split(/\_\_\_/,$tsymb);
1036: if (&Apache::lonnet::allowed('mgr',$tcrsid)) {
1037: $request->print(
1038: &Apache::lonnet::ssi('/res/'.$url,
1039: ('grade_username' => $tuname,
1040: 'grade_domain' => $tudom,
1041: 'grade_courseid' => $tcrsid,
1042: 'grade_symb' => $tsymb)));
1043: } else {
1044: $request->print('<h1>Not authorized: '.$token.'</h1>');
1045: }
1046: } else {
1047: $request->print('<h1>Not a valid DocID: '.$token.'</h1>');
1048: }
1049: } else {
1050: $request->print(&Apache::lonxml::tokeninputfield());
1051: }
1052: }
1.13 albertel 1053: } else {
1.29 albertel 1054: #&Apache::lonhomework::showhashsubset(\%ENV,'^form');
1.13 albertel 1055: $Apache::grades::viewgrades=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'});
1056: if ($command eq 'submission') {
1.20 albertel 1057: &listStudents($request) if ($ENV{'form.student'} eq '');
1.13 albertel 1058: $request->print(&submission($request)) if ($ENV{'form.student'} ne '');
1.26 albertel 1059: } elsif ($command eq 'gradingmenu') {
1060: $request->print(&gradingmenu($request));
1.13 albertel 1061: } elsif ($command eq 'viewgrades') {
1062: $request->print(&viewgrades($request));
1.33 ! ng 1063: } elsif ($command eq 'handgrade') {
! 1064: $request->print(&processHandGrade($request));
1.13 albertel 1065: } elsif ($command eq 'editgrades') {
1066: $request->print(&editgrades($request));
1.23 www 1067: } elsif ($command eq 'verify') {
1068: $request->print(&verifyreceipt($request));
1.26 albertel 1069: } elsif ($command eq 'csvupload') {
1070: $request->print(&csvupload($request));
1071: } elsif ($command eq 'csvuploadmap') {
1072: $request->print(&csvuploadmap($request));
1.30 ng 1073: } elsif ($command eq 'receiptInput') {
1074: &receiptInput($request);
1.26 albertel 1075: } elsif ($command eq 'csvuploadassign') {
1076: if ($ENV{'form.associate'} ne 'Reverse Association') {
1077: $request->print(&csvuploadassign($request));
1078: } else {
1079: if ( $ENV{'form.upfile_associate'} ne 'reverse' ) {
1080: $ENV{'form.upfile_associate'} = 'reverse';
1081: } else {
1082: $ENV{'form.upfile_associate'} = 'forward';
1083: }
1084: $request->print(&csvuploadmap($request));
1085: }
1.12 harris41 1086: } else {
1.23 www 1087: $request->print("Unknown action: $command:");
1.2 albertel 1088: }
1.13 albertel 1089: }
1090: &send_footer($request);
1091: return OK;
1.1 albertel 1092: }
1093:
1094: 1;
1095:
1.13 albertel 1096: __END__;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>