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