Annotation of loncom/homework/grades.pm, revision 1.28
1.17 albertel 1: # The LearningOnline Network with CAPA
1.13 albertel 2: # The LON-CAPA Grading handler
1.17 albertel 3: #
1.28 ! ng 4: # $Id: grades.pm,v 1.27 2002/05/24 21:45:22 albertel 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.1 albertel 32:
33: package Apache::grades;
34: use strict;
35: use Apache::style;
36: use Apache::lonxml;
37: use Apache::lonnet;
1.3 albertel 38: use Apache::loncommon;
1.1 albertel 39: use Apache::lonhomework;
40: use Apache::Constants qw(:common);
41:
1.2 albertel 42: sub moreinfo {
1.13 albertel 43: my ($request,$reason) = @_;
44: $request->print("Unable to process request: $reason");
45: if ( $Apache::grades::viewgrades eq 'F' ) {
46: $request->print('<form action="/adm/grades" method="post">'."\n");
1.16 albertel 47: if ($ENV{'form.url'}) {
48: $request->print('<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />'."\n");
49: }
50: if ($ENV{'form.symb'}) {
51: $request->print('<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />'."\n");
52: }
53: $request->print('<input type="hidden" name="command" value="'.$ENV{'form.command'}.'" />'."\n");
54: $request->print("Student:".'<input type="text" name="student" value="'.$ENV{'form.student'}.'" />'."<br />\n");
55: $request->print("Domain:".'<input type="text" name="domain" value="'.$ENV{'user.domain'}.'" />'."<br />\n");
56: $request->print('<input type="submit" name="submit" value="ReSubmit" />'."<br />\n");
1.13 albertel 57: $request->print('</form>');
58: }
59: return '';
1.2 albertel 60: }
61:
1.23 www 62: sub verifyreceipt {
63: my $request=shift;
64: my $courseid=$ENV{'request.course.id'};
65: my $cdom=$ENV{"course.$courseid.domain"};
66: my $cnum=$ENV{"course.$courseid.num"};
67: my $receipt=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}).'-'.
68: $ENV{'form.receipt'};
69: $receipt=~s/[^\-\d]//g;
70: my $symb=$ENV{'form.symb'};
71: unless ($symb) {
72: $symb=&Apache::lonnet::symbread($ENV{'form.url'});
73: }
74: if ((&Apache::lonnet::allowed('mgr',$courseid)) && ($symb)) {
75: $request->print('<h1>Verifying Submission Receipt '.$receipt.'</h1>');
76: my $matches=0;
1.24 albertel 77: my (%classlist) = &getclasslist($cdom,$cnum,'0');
1.23 www 78: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
79: my ($uname,$udom)=split(/\:/,$student);
80: if ($receipt eq
81: &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb)) {
82: $request->print('Matching '.$student.'<br>');
83: $matches++;
84: }
85: }
86: $request->print('<p>'.$matches.' match(es)</p>');
87: }
88: return '';
89: }
1.13 albertel 90:
1.10 ng 91: sub listStudents {
1.13 albertel 92: my ($request) = shift;
1.23 www 93: my $cdom=$ENV{"course.$ENV{'request.course.id'}.domain"};
94: my $cnum=$ENV{"course.$ENV{'request.course.id'}.num"};
95: my $hostver=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'});
96: $request->print(<<ENDHEADER);
1.28 ! ng 97: <h2><font color="#339933">Verify a Submission Receipt Issued by this Server</font></h2>
1.23 www 98: <form action="/adm/grades" method="post">
99: <tt>$hostver-<input type="text" name="receipt" size="4"></tt>
100: <input type="submit" name="submit" value="Verify">
101: <input type="hidden" name="command" value="verify">
102: ENDHEADER
103: if ($ENV{'form.url'}) {
104: $request->print(
105: '<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />');
106: }
107: if ($ENV{'form.symb'}) {
108: $request->print(
109: '<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />');
110: }
111: $request->print(<<ENDTABLEST);
112: </form>
1.28 ! ng 113: <h2><font color="#339933">Show Student Submissions on Assessment</font></h2>
! 114:
! 115: <table border=0><tr><td bgcolor=#990404>
! 116: <table border=0>
! 117: <tr bgcolor=#e6ffff><td><b>Username</b></td><td><b>Name</b></td><td><b>Domain</b></td><td> </td></tr>
1.23 www 118: ENDTABLEST
1.24 albertel 119: my (%classlist) = &getclasslist($cdom,$cnum,'0');
1.13 albertel 120: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
121: my ($sname,$sdom) = split(/:/,$student);
122:
1.25 albertel 123: my %name=&Apache::lonnet::get('environment', ['lastname','generation',
124: 'firstname','middlename'],
125: $sdom,$sname);
126: my $fullname;
127: my ($tmp) = keys(%name);
128: if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
129: $fullname=$name{'lastname'}.$name{'generation'};
1.28 ! ng 130: if ($fullname =~ /[^\s]+/) { $fullname.=', '; }
1.25 albertel 131: $fullname.=$name{'firstname'}.' '.$name{'middlename'};
132: }
1.13 albertel 133: if ( $Apache::grades::viewgrades eq 'F' ) {
1.28 ! ng 134: $request->print("\n".'<tr bgcolor=#ffffe6>'."<td>$sname</td><td>$fullname</td><td>$sdom</td><td>".
1.21 albertel 135: '<form action="/adm/grades" method="post">');
1.16 albertel 136: if ($ENV{'form.url'}) {
1.19 www 137: $request->print(
138: '<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />');
1.16 albertel 139: }
140: if ($ENV{'form.symb'}) {
1.19 www 141: $request->print(
142: '<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />');
1.16 albertel 143: }
1.19 www 144: $request->print(
145: '<input type="hidden" name="command" value="'.$ENV{'form.command'}.'" />');
146: $request->print(
147: '<input type="hidden" name="student" value="'.$sname.'" />');
148: $request->print(
1.28 ! ng 149: '<input type="hidden" name="fullname" value="'.$fullname.'" />');
! 150: $request->print(
1.19 www 151: '<input type="hidden" name="domain" value="'.$sdom.'" />');
152: $request->print(
153: '<input type="submit" name="submit" value="View" />');
1.28 ! ng 154: $request->print('</td></tr></form>');
! 155: # $request->print('</form></td></tr>');
1.13 albertel 156: }
157: }
1.28 ! ng 158: $request->print('</table></td></tr></table>');
1.10 ng 159: }
160:
1.13 albertel 161:
1.7 albertel 162: #FIXME - needs to handle multiple matches
1.2 albertel 163: sub finduser {
1.13 albertel 164: my ($name) = @_;
165: my $domain = '';
166:
167: if ( $Apache::grades::viewgrades eq 'F' ) {
168: #get classlist
169: my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});
1.24 albertel 170: #print "Found $cdom:$cnum<br />";
171: my (%classlist) = &getclasslist($cdom,$cnum,'0');
1.13 albertel 172: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
173: my ($posname,$posdomain) = split(/:/,$student);
174: if ($posname =~ $name) { $name=$posname; $domain=$posdomain; last; }
1.7 albertel 175: }
1.13 albertel 176: return ($name,$domain);
177: } else {
178: return ($ENV{'user.name'},$ENV{'user.domain'});
179: }
1.5 albertel 180: }
181:
182: sub getclasslist {
1.24 albertel 183: my ($coursedomain,$coursenum,$hideexpired) = @_;
184: my %classlist=&Apache::lonnet::dump('classlist',$coursedomain,$coursenum);
1.13 albertel 185: my $now = time;
1.24 albertel 186: foreach my $student (keys(%classlist)) {
187: my ($end,$start)=split(/:/,$classlist{$student});
1.13 albertel 188: # still a student?
189: if (($hideexpired) && ($end) && ($end < $now)) {
1.15 albertel 190: #print "Skipping:$name:$end:$now<br />\n";
1.13 albertel 191: next;
192: }
1.15 albertel 193: #print "record=$record<br>";
1.24 albertel 194: push( @{ $classlist{'allids'} }, $student);
1.13 albertel 195: }
196: return (%classlist);
1.5 albertel 197: }
198:
199: sub getpartlist {
1.13 albertel 200: my ($url) = @_;
201: my @parts =();
202: my (@metakeys) = split(/,/,&Apache::lonnet::metadata($url,'keys'));
203: foreach my $key (@metakeys) {
204: if ( $key =~ m/stores_([0-9]+)_.*/ ) {
205: push(@parts,$key);
1.6 albertel 206: }
1.13 albertel 207: }
208: return @parts;
1.5 albertel 209: }
210:
211: sub viewstudentgrade {
1.13 albertel 212: my ($url,$symb,$courseid,$student,@parts) = @_;
213: my $result ='';
214: my $cellclr = '"#ffffdd"';
1.28 ! ng 215: my ($username,$domain) = split(/:/,$student);
1.13 albertel 216:
1.28 ! ng 217: my (@requests) = ('lastname','firstname','middlename','generation');
! 218: my (%name) = &Apache::lonnet::get('environment',\@requests,$domain,$username);
! 219: my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$username);
! 220: my $fullname=$name{'lastname'}.$name{'generation'};
! 221: if ($fullname =~ /[^\s]+/) { $fullname.=', '; }
! 222: $fullname.=$name{'firstname'}.' '.$name{'middlename'};
1.13 albertel 223:
1.28 ! ng 224: $result.="<tr bgcolor=$cellclr><td>$username</td><td>$fullname</td><td align=\"middle\">$domain</td>\n";
1.13 albertel 225: foreach my $part (@parts) {
226: my ($temp,$part,$type)=split(/_/,$part);
227: #print "resource.$part.$type = ".$record{"resource.$part.$type"}." <br />\n";
228: if ($type eq 'awarded') {
229: my $score=$record{"resource.$part.$type"};
1.28 ! ng 230: $result.="<td align=\"middle\"><input type=\"text\" name=\"GRADE.$student.$part.$type\" value=\"$score\" size=\"4\" /></td>\n";
1.13 albertel 231: } elsif ($type eq 'tries') {
232: my $score=$record{"resource.$part.$type"};
1.28 ! ng 233: $result.="<td align=\"middle\"><input type=\"text\" name=\"GRADE.$student.$part.$type\" value=\"$score\" size=\"4\" /></td>\n"
1.13 albertel 234: } elsif ($type eq 'solved') {
235: my $score=$record{"resource.$part.$type"};
1.28 ! ng 236: $result.="<td align=\"middle\"><select name=\"GRADE.$student.$part.$type\">\n";
1.13 albertel 237: if ($score =~ /^correct/) {
238: $result.="<option selected=\"on\">correct</option>\n<option>incorrect</option>\n<option>excused</option>\n<option>ungraded</option>\n<option>nothing</option>\n";
239: } elsif ($score =~ /^incorrect/) {
240: $result.="<option>correct</option>\n<option selected=\"on\">incorrect</option>\n<option>excused</option>\n<option>ungraded</option>\n<option>nothing</option>\n";
241: } elsif ($score eq '') {
242: $result.="<option>correct</option>\n<option>incorrect</option>\n<option>excused</option>\n<option>ungraded</option>\n<option selected=\"on\">nothing</option>\n";
243: } elsif ($score =~ /^excused/) {
244: $result.="<option>correct</option>\n<option>incorrect</option>\n<option selected=\"on\">excused</option>\n<option>ungraded</option>\n<option>nothing</option>\n";
245: } elsif ($score =~ /^ungraded/) {
246: $result.="<option>correct</option>\n<option>incorrect</option>\n<option>excused</option>\n<option selected=\"on\">ungraded</option>\n<option>nothing</option>\n";
247: }
248: $result.="</select></td>\n";
249: }
250: }
251: $result.='</tr>';
252: return $result;
1.5 albertel 253: }
1.13 albertel 254: #FIXME need to look at the meatdata <stores> spec on what type of data to accept and provide an
1.6 albertel 255: #interface based on that, also do that to above function.
1.5 albertel 256: sub setstudentgrade {
1.13 albertel 257: my ($url,$symb,$courseid,$student,@parts) = @_;
258:
259: my $result ='';
260:
261: my ($stuname,$domain) = split(/:/,$student);
262:
263: my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$stuname);
264:
265: my %newrecord;
266:
267: foreach my $part (@parts) {
268: my ($temp,$part,$type)=split(/_/,$part);
269: my $oldscore=$record{"resource.$part.$type"};
270: my $newscore=$ENV{"form.GRADE.$student.$part.$type"};
271: if ($type eq 'solved') {
272: my $update=0;
273: if ($newscore eq 'nothing' ) {
274: if ($oldscore ne '') {
275: $update=1;
276: $newscore = '';
1.6 albertel 277: }
1.13 albertel 278: } elsif ($oldscore !~ m/^$newscore/) {
279: $update=1;
280: $result.="Updating $stuname to $newscore<br />\n";
281: if ($newscore eq 'correct') { $newscore = 'correct_by_override'; }
282: if ($newscore eq 'incorrect') { $newscore = 'incorrect_by_override'; }
283: if ($newscore eq 'excused') { $newscore = 'excused'; }
284: if ($newscore eq 'ungraded') { $newscore = 'ungraded_attempted'; }
285: } else {
286: #$result.="$stuname:$part:$type:unchanged $oldscore to $newscore:<br />\n";
287: }
288: if ($update) { $newrecord{"resource.$part.$type"}=$newscore; }
289: } else {
290: if ($oldscore ne $newscore) {
291: $newrecord{"resource.$part.$type"}=$newscore;
292: $result.="Updating $student"."'s status for $part.$type to $newscore<br />\n";
293: } else {
294: #$result.="$stuname:$part:$type:unchanged $oldscore to $newscore:<br />\n";
295: }
296: }
297: }
298: if ( scalar(keys(%newrecord)) > 0 ) {
299: $newrecord{"resource.regrader"}="$ENV{'user.name'}:$ENV{'user.domain'}";
300: &Apache::lonnet::cstore(\%newrecord,$symb,$courseid,$domain,$stuname);
301:
302: $result.="Stored away ".scalar(keys(%newrecord))." elements.<br />\n";
303: }
304: return $result;
1.2 albertel 305: }
306:
307: sub submission {
1.13 albertel 308: my ($request) = @_;
309: my $url=$ENV{'form.url'};
310: $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
311: if ($ENV{'form.student'} eq '') { &moreinfo($request,"Need student login id"); return ''; }
1.10 ng 312: # if ($ENV{'form.student'} eq '') { &listStudents($request); return ''; }
1.13 albertel 313: my ($uname,$udom) = &finduser($ENV{'form.student'});
314: if ($uname eq '') { &moreinfo($request,"Unable to find student"); return ''; }
1.16 albertel 315: my $symb;
316: if ($ENV{'form.symb'}) {
317: $symb=$ENV{'form.symb'};
318: } else {
319: $symb=&Apache::lonnet::symbread($url);
320: }
1.13 albertel 321: if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }
322: my $answer=&Apache::loncommon::get_previous_attempt($symb,$uname,$udom,
323: $ENV{'request.course.id'});
1.28 ! ng 324: my $result='<h2><font color="#339933">Submission Record</font></h2>';
! 325: $result.='<b>Username : </b>'.$uname.'<br><b>Fullname : </b>'.$ENV{'form.fullname'}.'<br><b>Domain : </b>'.$udom.'<br><b>Resource : </b>'.$url.' <br />'.$answer;
1.17 albertel 326: my $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom,
327: $ENV{'request.course.id'});
1.22 albertel 328: $result.="Student's view of the problem:<br /> $rendered <br /> Correct answer:<br />";
1.18 albertel 329:
1.22 albertel 330: $answer=&Apache::loncommon::get_student_answers($symb,$uname,$udom,
1.18 albertel 331: $ENV{'request.course.id'});
332: $result.=$answer;
1.13 albertel 333: return $result;
1.2 albertel 334: }
335:
1.26 albertel 336: sub get_symb_and_url {
337: my ($request) = @_;
1.13 albertel 338: my $url=$ENV{'form.url'};
339: $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
340: my $symb=$ENV{'form.symb'};
341: if (!$symb) { $symb=&Apache::lonnet::symbread($url); }
342: if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }
1.26 albertel 343: return ($symb,$url);
344: }
1.13 albertel 345:
1.26 albertel 346: sub gradingmenu {
347: my ($request) = @_;
348: my ($symb,$url)=&get_symb_and_url($request);
349: if (!$symb) {return '';}
1.28 ! ng 350:
! 351: my $result='<h2> <font color="#339933">Select a Grading Method</font></h2><br />';
! 352: $result.='<table width=100% border=0><tr><td bgcolor=#990404>'."\n";
! 353: $result.='<table width=100% border=0><tr><td bgcolor=#e6ffff>'."\n";
! 354: $result.=' <b>Resource :</b> '.$url.'</td></tr>'."\n";
! 355: $result.='<tr bgcolor=#ffffe6><td>'."\n";
1.26 albertel 356: $result.='<form action="/adm/grades" method="post">'."\n".
357: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
358: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
359: '<input type="hidden" name="command" value="viewgrades" />'."\n".
360: '<input type="submit" name="submit" value="View/Edit Entire Class" />'."\n".
1.28 ! ng 361: '</form>'."\n";
1.26 albertel 362: $result.='<form action="/adm/grades" method="post">'."\n".
363: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
364: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
365: '<input type="hidden" name="command" value="csvupload" />'."\n".
366: '<input type="submit" name="submit" value="Upload Scores" />'."\n".
1.28 ! ng 367: '</form>'."\n";
1.26 albertel 368: $result.='<form action="/adm/grades" method="post">'."\n".
369: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
370: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
371: '<input type="hidden" name="command" value="submission" />'."\n".
372: '<input type="submit" name="submit" value="View/Edit Student" />'."\n".
1.28 ! ng 373: '</form>'."\n";
! 374: $result.='</td></tr></table>'."\n";
! 375: $result.='</td></tr></table>'."\n";
1.26 albertel 376: return $result;
377: }
378:
379: sub viewgrades {
380: my ($request) = @_;
381: my $result='';
382:
383: #get resource reference
384: my ($symb,$url)=&get_symb_and_url($request);
385: if (!$symb) {return '';}
1.13 albertel 386: #get classlist
387: my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});
1.24 albertel 388: #print "Found $cdom:$cnum<br />";
389: my (%classlist) = &getclasslist($cdom,$cnum,'0');
1.13 albertel 390: my $headerclr = '"#ccffff"';
391: my $cellclr = '"#ffffcc"';
392:
393: #get list of parts for this problem
394: my (@parts) = &getpartlist($url);
395:
1.28 ! ng 396: $request->print ("<h2><font color=\"#339933\">Manual Grading</font></h2>");
1.13 albertel 397:
398: #start the form
399: $result = '<form action="/adm/grades" method="post">'."\n".
1.16 albertel 400: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
401: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
1.13 albertel 402: '<input type="hidden" name="command" value="editgrades" />'."\n".
403: '<input type="submit" name="submit" value="Submit Changes" />'."\n".
1.28 ! ng 404: '<table border=0><tr><td bgcolor="#990404">'."\n".
1.13 albertel 405: '<table border=0>'."\n".
1.28 ! ng 406: '<tr bgcolor='.$headerclr.'><td><b>Username</b></td><td><b>Name</b></td><td><b>Domain</b></td>'."\n";
1.27 albertel 407: foreach my $part (sort(@parts)) {
1.13 albertel 408: my $display=&Apache::lonnet::metadata($url,$part.'.display');
409: if (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); }
1.28 ! ng 410: $result.='<td><b>'.$display.'</b></td>'."\n";
1.13 albertel 411: }
1.28 ! ng 412: $result.='</tr>';
1.13 albertel 413: #get info for each student
414: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
415: $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},$student,@parts);
416: }
417: $result.='</table></td></tr></table><input type="submit" name="submit" value="Submit Changes" /></form>';
1.5 albertel 418:
1.13 albertel 419: return $result;
1.5 albertel 420: }
421:
422: sub editgrades {
1.13 albertel 423: my ($request) = @_;
424: my $result='';
1.5 albertel 425:
1.13 albertel 426: my $symb=$ENV{'form.symb'};
427: if ($symb eq '') { $request->print("Unable to handle ambiguous references:$symb:$ENV{'form.url'}"); return ''; }
428: my $url=$ENV{'form.url'};
429: #get classlist
430: my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});
1.24 albertel 431: #print "Found $cdom:$cnum<br />";
432: my (%classlist) = &getclasslist($cdom,$cnum,'0');
1.13 albertel 433:
434: #get list of parts for this problem
435: my (@parts) = &getpartlist($url);
436:
437: $result.='<form action="/adm/grades" method="post">'."\n".
438: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n".
439: '<input type="hidden" name="url" value="'.$url.'" />'."\n".
440: '<input type="hidden" name="command" value="viewgrades" />'."\n".
441: '<input type="submit" name="submit" value="See Grades" /> <br />'."\n";
442:
443: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
444: $result.=&setstudentgrade($url,$symb,$ENV{'request.course.id'},$student,@parts);
445: }
1.5 albertel 446:
1.13 albertel 447: $result.='<input type="submit" name="submit" value="See Grades" /></table></form>';
448: return $result;
1.5 albertel 449: }
450:
1.26 albertel 451: sub csvupload {
452: my ($request)= @_;
453: my $result;
454: my ($symb,$url)=&get_symb_and_url($request);
455: if (!$symb) {return '';}
456: my $upfile_select=&Apache::loncommon::upfile_select_html();
457: $result.=<<ENDUPFORM;
458: <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
459: <input type="hidden" name="symb" value="$symb" />
460: <input type="hidden" name="url" value="$url" />
461: <input type="hidden" name="command" value="csvuploadmap" />
462: <hr />
463: <h3>Specify a file containing the class grades for resource $url</h3>
464: $upfile_select
465: <p><input type="submit" name="submit" value="Upload Grades" />
466: ENDUPFORM
467: return $result;
468: }
469:
1.27 albertel 470: sub csvupload_javascript_reverse_associate {
471: return(<<ENDPICK);
472: function verify(vf) {
473: var foundsomething=0;
474: var founduname=0;
475: var founddomain=0;
476: for (i=0;i<=vf.nfields.value;i++) {
477: tw=eval('vf.f'+i+'.selectedIndex');
478: if (i==0 && tw!=0) { founduname=1; }
479: if (i==1 && tw!=0) { founddomain=1; }
480: if (i!=0 && i!=1 && tw!=0) { foundsomething=1; }
481: }
482: if (founduname==0 || founddomain==0) {
483: alert('You need to specify at both the username and domain');
484: return;
485: }
486: if (foundsomething==0) {
487: alert('You need to specify at least one grading field');
488: return;
489: }
490: vf.submit();
491: }
492: function flip(vf,tf) {
493: var nw=eval('vf.f'+tf+'.selectedIndex');
494: var i;
495: for (i=0;i<=vf.nfields.value;i++) {
496: //can not pick the same destination field for both name and domain
497: if (((i ==0)||(i ==1)) &&
498: ((tf==0)||(tf==1)) &&
499: (i!=tf) &&
500: (eval('vf.f'+i+'.selectedIndex')==nw)) {
501: eval('vf.f'+i+'.selectedIndex=0;')
502: }
503: }
504: }
505: ENDPICK
506: }
507:
508: sub csvupload_javascript_forward_associate {
509: return(<<ENDPICK);
510: function verify(vf) {
511: var foundsomething=0;
512: var founduname=0;
513: var founddomain=0;
514: for (i=0;i<=vf.nfields.value;i++) {
515: tw=eval('vf.f'+i+'.selectedIndex');
516: if (tw==1) { founduname=1; }
517: if (tw==2) { founddomain=1; }
518: if (tw>2) { foundsomething=1; }
519: }
520: if (founduname==0 || founddomain==0) {
521: alert('You need to specify at both the username and domain');
522: return;
523: }
524: if (foundsomething==0) {
525: alert('You need to specify at least one grading field');
526: return;
527: }
528: vf.submit();
529: }
530: function flip(vf,tf) {
531: var nw=eval('vf.f'+tf+'.selectedIndex');
532: var i;
533: //can not pick the same destination field twice
534: for (i=0;i<=vf.nfields.value;i++) {
535: if ((i!=tf) && (eval('vf.f'+i+'.selectedIndex')==nw)) {
536: eval('vf.f'+i+'.selectedIndex=0;')
537: }
538: }
539: }
540: ENDPICK
541: }
542:
1.26 albertel 543: sub csvuploadmap_header {
544: my ($request,$symb,$url,$datatoken,$distotal)= @_;
545: my $result;
546: my $javascript;
547: if ($ENV{'form.upfile_associate'} eq 'reverse') {
1.27 albertel 548: $javascript=&csvupload_javascript_reverse_associate();
1.26 albertel 549: } else {
1.27 albertel 550: $javascript=&csvupload_javascript_forward_associate();
1.26 albertel 551: }
552: $request->print(<<ENDPICK);
553: <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
554: <h3>Uploading Class Grades for resource $url</h3>
555: <hr>
556: <h3>Identify fields</h3>
557: Total number of records found in file: $distotal <hr />
558: Enter as many fields as you can. The system will inform you and bring you back
559: to this page if the data selected is insufficient to run your class.<hr />
560: <input type="button" value="Reverse Association" onClick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" />
561: <input type="hidden" name="associate" value="" />
562: <input type="hidden" name="phase" value="three" />
563: <input type="hidden" name="datatoken" value="$datatoken" />
564: <input type="hidden" name="fileupload" value="$ENV{'form.fileupload'}" />
565: <input type="hidden" name="upfiletype" value="$ENV{'form.upfiletype'}" />
566: <input type="hidden" name="upfile_associate"
567: value="$ENV{'form.upfile_associate'}" />
568: <input type="hidden" name="symb" value="$symb" />
569: <input type="hidden" name="url" value="$url" />
570: <input type="hidden" name="command" value="csvuploadassign" />
571: <hr />
572: <script type="text/javascript" language="Javascript">
573: $javascript
574: </script>
575: ENDPICK
576: return '';
577:
578: }
579:
580: sub csvupload_fields {
581: my ($url) = @_;
582: my (@parts) = &getpartlist($url);
1.27 albertel 583: my @fields=(['username','Student Username'],['domain','Student Domain']);
584: foreach my $part (sort(@parts)) {
1.26 albertel 585: my @datum;
586: my $display=&Apache::lonnet::metadata($url,$part.'.display');
1.27 albertel 587: my $name=$part;
1.26 albertel 588: if (!$display) { $display = $name; }
589: @datum=($name,$display);
590: push(@fields,\@datum);
591: }
592: return (@fields);
593: }
594:
595: sub csvuploadmap_footer {
596: my ($request,$i,$keyfields) =@_;
597: $request->print(<<ENDPICK);
598: </table>
599: <input type="hidden" name="nfields" value="$i" />
600: <input type="hidden" name="keyfields" value="$keyfields" />
601: <input type="button" onClick="javascript:verify(this.form)" value="Assign Grades" /><br />
602: </form>
603: ENDPICK
604: }
605:
606: sub csvuploadmap {
607: my ($request)= @_;
608: my ($symb,$url)=&get_symb_and_url($request);
609: if (!$symb) {return '';}
610: my $datatoken;
611: if (!$ENV{'form.datatoken'}) {
612: $datatoken=&Apache::loncommon::upfile_store($request);
613: } else {
614: $datatoken=$ENV{'form.datatoken'};
615: &Apache::loncommon::load_tmp_file($request);
616: }
617: my @records=&Apache::loncommon::upfile_record_sep();
618: &csvuploadmap_header($request,$symb,$url,$datatoken,$#records+1);
619: my $i;
620: my $keyfields;
621: if (@records) {
622: my @fields=&csvupload_fields($url);
623: if ($ENV{'form.upfile_associate'} eq 'reverse') {
624: &Apache::loncommon::csv_print_samples($request,\@records);
625: $i=&Apache::loncommon::csv_print_select_table($request,\@records,
626: \@fields);
627: foreach (@fields) { $keyfields.=$_->[0].','; }
628: chop($keyfields);
629: } else {
630: unshift(@fields,['none','']);
631: $i=&Apache::loncommon::csv_samples_select_table($request,\@records,
632: \@fields);
633: my %sone=&Apache::loncommon::record_sep($records[0]);
634: $keyfields=join(',',sort(keys(%sone)));
635: }
636: }
637: &csvuploadmap_footer($request,$i,$keyfields);
638: return '';
1.27 albertel 639: }
640:
641: sub csvuploadassign {
642: my ($request)= @_;
643: my ($symb,$url)=&get_symb_and_url($request);
644: if (!$symb) {return '';}
645: &Apache::loncommon::load_tmp_file($request);
646: my @gradedata=&Apache::loncommon::upfile_record_sep();
647: my @keyfields = split(/\,/,$ENV{'form.keyfields'});
648: my %fields=();
649: for (my $i=0; $i<=$ENV{'form.nfields'}; $i++) {
650: if ($ENV{'form.upfile_associate'} eq 'reverse') {
651: if ($ENV{'form.f'.$i} ne 'none') {
652: $fields{$keyfields[$i]}=$ENV{'form.f'.$i};
653: }
654: } else {
655: if ($ENV{'form.f'.$i} ne 'none') {
656: $fields{$ENV{'form.f'.$i}}=$keyfields[$i];
657: }
658: }
659: }
660: $request->print('<h3>Assigning Grades</h3>');
661: &Apache::lonhomework::showhash(('1'=>\@keyfields));
662: &Apache::lonhomework::showhash(%fields);
663: my $courseid=$ENV{'request.course.id'};
664: my $cdom=$ENV{"course.$courseid.domain"};
665: my $cnum=$ENV{"course.$courseid.num"};
666: my (%classlist) = &getclasslist($cdom,$cnum,'1');
667: foreach my $student ( sort(@{ $classlist{'allids'} }) ) {
668: my %newhash;
669: foreach my $grade (@gradedata) {
670: my %entries=&Apache::loncommon::record_sep($grade);
671: foreach my $dest (keys(%fields)) {
672:
673: }
674: }
675: }
1.26 albertel 676: }
677:
1.2 albertel 678: sub send_header {
1.13 albertel 679: my ($request)= @_;
680: $request->print(&Apache::lontexconvert::header());
1.6 albertel 681: # $request->print("
682: #<script>
683: #remotewindow=open('','homeworkremote');
684: #remotewindow.close();
685: #</script>");
1.13 albertel 686: $request->print('<body bgcolor="#FFFFFF">');
1.2 albertel 687: }
688:
689: sub send_footer {
1.13 albertel 690: my ($request)= @_;
1.2 albertel 691: $request->print('</body>');
692: $request->print(&Apache::lontexconvert::footer());
693: }
694:
1.1 albertel 695: sub handler {
1.13 albertel 696: my $request=$_[0];
697:
698: if ( $ENV{'user.name'} eq 'albertel' ) {$Apache::lonxml::debug=1;} else {$Apache::lonxml::debug=0;}
699:
700: if ($ENV{'browser.mathml'}) {
701: $request->content_type('text/xml');
702: } else {
703: $request->content_type('text/html');
704: }
705: $request->send_http_header;
706: return OK if $request->header_only;
1.16 albertel 707: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
1.13 albertel 708: my $url=$ENV{'form.url'};
709: my $symb=$ENV{'form.symb'};
710: my $command=$ENV{'form.command'};
1.16 albertel 711: if (!$url) {
712: my ($temp1,$temp2);
713: ($temp1,$temp2,$ENV{'form.url'})=split(/___/,$symb);
714: $url = $ENV{'form.url'};
715: }
1.13 albertel 716: &send_header($request);
717: if ($url eq '' && $symb eq '') {
1.14 www 718: if ($ENV{'user.adv'}) {
719: if (($ENV{'form.codeone'}) && ($ENV{'form.codetwo'}) &&
720: ($ENV{'form.codethree'})) {
721: my $token=$ENV{'form.codeone'}.'*'.$ENV{'form.codetwo'}.'*'.
722: $ENV{'form.codethree'};
723: my ($tsymb,$tuname,$tudom,$tcrsid)=
724: &Apache::lonnet::checkin($token);
725: if ($tsymb) {
726: my ($map,$id,$url)=split(/\_\_\_/,$tsymb);
727: if (&Apache::lonnet::allowed('mgr',$tcrsid)) {
728: $request->print(
729: &Apache::lonnet::ssi('/res/'.$url,
730: ('grade_username' => $tuname,
731: 'grade_domain' => $tudom,
732: 'grade_courseid' => $tcrsid,
733: 'grade_symb' => $tsymb)));
734: } else {
735: $request->print('<h1>Not authorized: '.$token.'</h1>');
736: }
737: } else {
738: $request->print('<h1>Not a valid DocID: '.$token.'</h1>');
739: }
740: } else {
741: $request->print(&Apache::lonxml::tokeninputfield());
742: }
743: }
1.13 albertel 744: } else {
1.26 albertel 745: &Apache::lonhomework::showhashsubset(\%ENV,'^form');
1.13 albertel 746: $Apache::grades::viewgrades=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'});
747: if ($command eq 'submission') {
1.20 albertel 748: &listStudents($request) if ($ENV{'form.student'} eq '');
1.13 albertel 749: $request->print(&submission($request)) if ($ENV{'form.student'} ne '');
1.26 albertel 750: } elsif ($command eq 'gradingmenu') {
751: $request->print(&gradingmenu($request));
1.13 albertel 752: } elsif ($command eq 'viewgrades') {
753: $request->print(&viewgrades($request));
754: } elsif ($command eq 'editgrades') {
755: $request->print(&editgrades($request));
1.23 www 756: } elsif ($command eq 'verify') {
757: $request->print(&verifyreceipt($request));
1.26 albertel 758: } elsif ($command eq 'csvupload') {
759: $request->print(&csvupload($request));
760: } elsif ($command eq 'csvuploadmap') {
761: $request->print(&csvuploadmap($request));
762: } elsif ($command eq 'csvuploadassign') {
763: if ($ENV{'form.associate'} ne 'Reverse Association') {
764: $request->print(&csvuploadassign($request));
765: } else {
766: if ( $ENV{'form.upfile_associate'} ne 'reverse' ) {
767: $ENV{'form.upfile_associate'} = 'reverse';
768: } else {
769: $ENV{'form.upfile_associate'} = 'forward';
770: }
771: $request->print(&csvuploadmap($request));
772: }
1.12 harris41 773: } else {
1.23 www 774: $request->print("Unknown action: $command:");
1.2 albertel 775: }
1.13 albertel 776: }
777: &send_footer($request);
778: return OK;
1.1 albertel 779: }
780:
781: 1;
782:
1.13 albertel 783: __END__;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>