Annotation of loncom/homework/grades.pm, revision 1.31

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>