--- loncom/homework/grades.pm	2005/02/12 02:37:00	1.243
+++ loncom/homework/grades.pm	2005/02/17 08:58:16	1.247
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # The LON-CAPA Grading handler
 #
-# $Id: grades.pm,v 1.243 2005/02/12 02:37:00 albertel Exp $
+# $Id: grades.pm,v 1.247 2005/02/17 08:58:16 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2651,26 +2651,26 @@ sub split_part_type {
 #
 #--- Javascript to handle csv upload
 sub csvupload_javascript_reverse_associate {
+    my $error1=&mt('You need to specify the username or ID');
+    my $error2=&mt('You need to specify at least one grading field');
   return(<<ENDPICK);
   function verify(vf) {
     var foundsomething=0;
     var founduname=0;
     var foundID=0;
-    var founddomain=0;
     for (i=0;i<=vf.nfields.value;i++) {
       tw=eval('vf.f'+i+'.selectedIndex');
       if (i==0 && tw!=0) { foundID=1; }
       if (i==1 && tw!=0) { founduname=1; }
-      if (i==2 && tw!=0) { founddomain=1; }
       if (i!=0 && i!=1 && i!=2 && tw!=0) { foundsomething=1; }
     }
-    if ((founduname==0 && foundID==0) || founddomain==0) {
-      alert('You need to specify the domain and either the username or ID');
-      return;
+    if (founduname==0 && foundID==0) {
+	alert('$error1');
+	return;
     }
     if (foundsomething==0) {
-      alert('You need to specify at least one grading field');
-      return;
+	alert('$error2');
+	return;
     }
     vf.submit();
   }
@@ -2691,26 +2691,26 @@ ENDPICK
 }
 
 sub csvupload_javascript_forward_associate {
+    my $error1=&mt('You need to specify the username or ID');
+    my $error2=&mt('You need to specify at least one grading field');
   return(<<ENDPICK);
   function verify(vf) {
     var foundsomething=0;
     var founduname=0;
     var foundID=0;
-    var founddomain=0;
     for (i=0;i<=vf.nfields.value;i++) {
       tw=eval('vf.f'+i+'.selectedIndex');
       if (tw==1) { foundID=1; }
       if (tw==2) { founduname=1; }
-      if (tw==3) { founddomain=1; }
       if (tw>3) { foundsomething=1; }
     }
-    if ((founduname==0 && foundID==0) || founddomain==0) {
-      alert('You need to specify the domain and either the username or ID');
-      return;
+    if (founduname==0 && foundID==0) {
+	alert('$error1');
+	return;
     }
     if (foundsomething==0) {
-      alert('You need to specify at least one grading field');
-      return;
+	alert('$error2');
+	return;
     }
     vf.submit();
   }
@@ -2737,7 +2737,8 @@ sub csvuploadmap_header {
     }
 
     my ($result) = &showResourceInfo($url,$ENV{'form.probTitle'});
-
+    my $checked=(($ENV{'form.noFirstLine'})?' checked="checked"':'');
+    my $ignore=&mt('Ignore First Line');
     $request->print(<<ENDPICK);
 <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
 <h3><font color="#339933">Uploading Class Grades</font></h3>
@@ -2748,6 +2749,7 @@ Total number of records found in file: $
 Enter as many fields as you can. The system will inform you and bring you back
 to this page if the data selected is insufficient to run your class.<hr />
 <input type="button" value="Reverse Association" onClick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" />
+<label><input type="checkbox" name="noFirstLine" $checked />$ignore</label>
 <input type="hidden" name="associate"  value="" />
 <input type="hidden" name="phase"      value="three" />
 <input type="hidden" name="datatoken"  value="$datatoken" />
@@ -2759,7 +2761,7 @@ to this page if the data selected is ins
 <input type="hidden" name="url"        value="$url" />
 <input type="hidden" name="saveState"  value="$ENV{'form.saveState'}" />
 <input type="hidden" name="probTitle"  value="$ENV{'form.probTitle'}" />
-<input type="hidden" name="command"    value="csvuploadassign" />
+<input type="hidden" name="command"    value="csvuploadoptions" />
 <hr />
 <script type="text/javascript" language="Javascript">
 $javascript
@@ -2781,6 +2783,9 @@ sub csvupload_fields {
 	my $name=$part;
 	if  (!$display) { $display = $name; }
 	@datum=($name,$display);
+	if ($name=~/^stores_(.*)_awarded/) {
+	    push(@fields,['stores_'.$1.'_points',"Points [Part: $1]"]);
+	}
 	push(@fields,\@datum);
     }
     return (@fields);
@@ -2821,6 +2826,7 @@ CSVFORMJS
 	'.</b></td></tr>'."\n";
     $result.='<tr bgcolor=#ffffe6><td>'."\n";
     my $upfile_select=&Apache::loncommon::upfile_select_html();
+    my $ignore=&mt('Ignore First Line');
     $result.=<<ENDUPFORM;
 <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
 <input type="hidden" name="symb" value="$symb" />
@@ -2830,7 +2836,7 @@ CSVFORMJS
 <input type="hidden" name="saveState"  value="$ENV{'form.saveState'}" />
 $upfile_select
 <br /><input type="button" onClick="javascript:checkUpload(this.form);" value="Upload Scores" />
-
+<label><input type="checkbox" name="noFirstLine" />$ignore</lable>
 </form>
 ENDUPFORM
     $result.='</td></tr></table>'."\n";
@@ -2853,6 +2859,7 @@ sub csvuploadmap {
 	&Apache::loncommon::load_tmp_file($request);
     }
     my @records=&Apache::loncommon::upfile_record_sep();
+    if ($ENV{'form.noFirstLine'}) { shift(@records); }
     &csvuploadmap_header($request,$symb,$url,$datatoken,$#records+1);
     my ($i,$keyfields);
     if (@records) {
@@ -2878,14 +2885,51 @@ sub csvuploadmap {
     return '';
 }
 
-sub csvuploadassign {
+sub csvuploadoptions {
     my ($request)= @_;
     my ($symb,$url)=&get_symb_and_url($request);
-    if (!$symb) {return '';}
-    &Apache::loncommon::load_tmp_file($request);
-    my @gradedata = &Apache::loncommon::upfile_record_sep();
+    my $checked=(($ENV{'form.noFirstLine'})?'1':'0');
+    my $ignore=&mt('Ignore First Line');
+    $request->print(<<ENDPICK);
+<form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload">
+<h3><font color="#339933">Uploading Class Grade Options</font></h3>
+<input type="hidden" name="command"    value="csvuploadassign" />
+<input type="submit" value="Assign Grades" /><br />
+<p>
+<label>
+   <input type="checkbox" name="show_full_results" />
+   Show a table of all changes
+</label>
+</p>
+<p>
+<label>
+   <input type="checkbox" name="overwite_scores" checked="checked" />
+   Overwrite any existing score
+</label>
+</p>
+ENDPICK
+    my %fields=&get_fields();
+    if (!defined($fields{'domain'})) {
+	my $domform = &Apache::loncommon::select_dom_form($ENV{'request.role.domain'},'default_domain');
+	$request->print("\n<p> Users are in domain: ".$domform."</p>\n");
+    }
+    foreach my $key (sort(keys(%ENV))) {
+	if ($key !~ /^form\.(.*)$/) { next; }
+	my $cleankey=$1;
+	if ($cleankey eq 'command') { next; }
+	$request->print('<input type="hidden" name="'.$cleankey.
+			'"  value="'.$ENV{$key}.'" />'."\n");
+    }
+    # FIXME do a check for any duplicated user ids...
+    # FIXME do a check for any invalid user ids?...
+    $request->print("<hr /></form>\n");
+    $request->print(&show_grading_menu_form($symb,$url));
+    return '';
+}
+
+sub get_fields {
+    my %fields;
     my @keyfields = split(/\,/,$ENV{'form.keyfields'});
-    my %fields=();
     for (my $i=0; $i<=$ENV{'form.nfields'}; $i++) {
 	if ($ENV{'form.upfile_associate'} eq 'reverse') {
 	    if ($ENV{'form.f'.$i} ne 'none') {
@@ -2897,6 +2941,17 @@ sub csvuploadassign {
 	    }
 	}
     }
+    return %fields;
+}
+
+sub csvuploadassign {
+    my ($request)= @_;
+    my ($symb,$url)=&get_symb_and_url($request);
+    if (!$symb) {return '';}
+    &Apache::loncommon::load_tmp_file($request);
+    my @gradedata = &Apache::loncommon::upfile_record_sep();
+    if ($ENV{'form.noFirstLine'}) { shift(@gradedata); }
+    my %fields=&get_fields();
     $request->print('<h3>Assigning Grades</h3>');
     my $courseid=$ENV{'request.course.id'};
     my ($classlist) = &getclasslist('all',0);
@@ -2905,17 +2960,29 @@ sub csvuploadassign {
     my $countdone=0;
     foreach my $grade (@gradedata) {
 	my %entries=&Apache::loncommon::record_sep($grade);
-	my $domain=$entries{$fields{'domain'}};
+	my $domain;
+	if ($entries{$fields{'domain'}}) {
+	    $domain=$entries{$fields{'domain'}};
+	} else {
+	    $domain=$ENV{'form.default_domain'};
+	}
 	$domain=~s/\s//g;
 	my $username=$entries{$fields{'username'}};
 	$username=~s/\s//g;
 	if (!$username) {
 	    my $id=$entries{$fields{'ID'}};
+	    $id=~s/\s//g;
 	    my %ids=&Apache::lonnet::idget($domain,$id);
 	    $username=$ids{$id};
 	}
 	if (!exists($$classlist{"$username:$domain"})) {
-	    push(@skipped,"$username:$domain");
+	    my $id=$entries{$fields{'ID'}};
+	    $id=~s/\s//g;
+	    if ($id) {
+		push(@skipped,"$id:$domain");
+	    } else {
+		push(@skipped,"$username:$domain");
+	    }
 	    next;
 	}
 	my $usec=$classlist->{"$username:$domain"}[5];
@@ -2923,16 +2990,34 @@ sub csvuploadassign {
 	    push(@notallowed,"$username:$domain");
 	    next;
 	}
+	my %points;
 	my %grades;
 	foreach my $dest (keys(%fields)) {
-	    if ($dest eq 'username' || $dest eq 'domain') { next; }
-	    if ($entries{$fields{$dest}} eq '') { next; }
-	    my $store_key=$dest;
-	    $store_key=~s/^stores/resource/;
-	    $store_key=~s/_/\./g;
-	    $grades{$store_key}=$entries{$fields{$dest}};
+	    if ($dest eq 'ID' || $dest eq 'username' ||
+		$dest eq 'domain') { next; }
+	    if ($entries{$fields{$dest}} =~ /^\s*$/) { next; }
+	    if ($dest=~/stores_(.*)_points/) {
+		my $part=$1;
+		my $wgt =&Apache::lonnet::EXT('resource.'.$part.'.weight',
+					      $symb,$domain,$username);
+		$entries{$fields{$dest}}=~s/\s//g;
+		my $pcr=$entries{$fields{$dest}} / $wgt;
+		my $award='correct_by_override';
+		$grades{"resource.$part.awarded"}=$pcr;
+		$grades{"resource.$part.solved"}=$award;
+		$points{$part}=1;
+	    } else {
+		if ($dest=~/stores_(.*)_awarded/) { if ($points{$1}) {next;} }
+		if ($dest=~/stores_(.*)_solved/)  { if ($points{$1}) {next;} }
+		my $store_key=$dest;
+		$store_key=~s/^stores/resource/;
+		$store_key=~s/_/\./g;
+		$grades{$store_key}=$entries{$fields{$dest}};
+	    }
 	}
+	if (! %grades) { push(@skipped,"$username:$domain no data to store"); }
 	$grades{"resource.regrader"}="$ENV{'user.name'}:$ENV{'user.domain'}";
+#	&Apache::lonnet::logthis(" storing ".(join('-',%grades)));
 	&Apache::lonnet::cstore(\%grades,$symb,$ENV{'request.course.id'},
 				$domain,$username);
 	$request->print('.');
@@ -5119,9 +5204,9 @@ sub handler {
 	    $request->print(&csvupload($request));
 	} elsif ($command eq 'csvuploadmap' && $perm{'mgr'} ) {
 	    $request->print(&csvuploadmap($request));
-	} elsif ($command eq 'csvuploadassign' && $perm{'mgr'}) {
+	} elsif ($command eq 'csvuploadoptions' && $perm{'mgr'}) {
 	    if ($ENV{'form.associate'} ne 'Reverse Association') {
-		$request->print(&csvuploadassign($request));
+		$request->print(&csvuploadoptions($request));
 	    } else {
 		if ( $ENV{'form.upfile_associate'} ne 'reverse' ) {
 		    $ENV{'form.upfile_associate'} = 'reverse';
@@ -5130,6 +5215,8 @@ sub handler {
 		}
 		$request->print(&csvuploadmap($request));
 	    }
+	} elsif ($command eq 'csvuploadassign' && $perm{'mgr'} ) {
+	    $request->print(&csvuploadassign($request));
 	} elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) {
 	    $request->print(&scantron_selectphase($request));
  	} elsif ($command eq 'scantron_warning' && $perm{'mgr'}) {