--- loncom/homework/grades.pm 2002/07/01 21:20:29 1.34
+++ loncom/homework/grades.pm 2003/06/13 21:29:30 1.97
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Grading handler
#
-# $Id: grades.pm,v 1.34 2002/07/01 21:20:29 ng Exp $
+# $Id: grades.pm,v 1.97 2003/06/13 21:29:30 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -30,7 +30,9 @@
# 7/26 H.K. Ng
# 8/20 Gerd Kortemeyer
# Year 2002
-# June 2002 H.K. Ng
+# June-August H.K. Ng
+# Year 2003
+# February, March H.K. Ng
#
package Apache::grades;
@@ -39,814 +41,2107 @@ use Apache::style;
use Apache::lonxml;
use Apache::lonnet;
use Apache::loncommon;
+use Apache::lonnavmaps;
use Apache::lonhomework;
+use Apache::loncoursedata;
+use Apache::lonmsg qw(:user_normal_msg);
use Apache::Constants qw(:common);
+use String::Similarity;
-sub moreinfo {
- my ($request,$reason) = @_;
- $request->print("Unable to process request: $reason");
- if ( $Apache::grades::viewgrades eq 'F' ) {
- $request->print('
');
- }
- return '';
-}
+my %oldessays=();
-sub verifyreceipt {
- my $request=shift;
- my $courseid=$ENV{'request.course.id'};
-# my $cdom=$ENV{"course.$courseid.domain"};
-# my $cnum=$ENV{"course.$courseid.num"};
- my $receipt=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}).'-'.
- $ENV{'form.receipt'};
- $receipt=~s/[^\-\d]//g;
- my $symb=$ENV{'form.symb'};
- unless ($symb) {
- $symb=&Apache::lonnet::symbread($ENV{'form.url'});
- }
- if ((&Apache::lonnet::allowed('mgr',$courseid)) && ($symb)) {
- $request->print('
Verifying Submission Receipt '.$receipt.'
');
- my $matches=0;
- my ($classlist) = &getclasslist('all','0');
- foreach my $student ( sort(@{ $$classlist{'all'} }) ) {
- my ($uname,$udom)=split(/\:/,$student);
- if ($receipt eq
- &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb)) {
- $request->print('Matching '.$student.' ');
- $matches++;
- }
- }
- $request->printf('
'.$matches." match%s
",$matches <= 1 ? '' : 'es');
-# needs to print who is matched
+# ----- These first few routines are general use routines.----
+#
+# --- Retrieve the parts that matches stores_\d+ from the metadata file.---
+sub getpartlist {
+ my ($url) = @_;
+ my @parts =();
+ my (@metakeys) = split(/,/,&Apache::lonnet::metadata($url,'keys'));
+ foreach my $key (@metakeys) {
+ if ( $key =~ m/stores_(\w+)_.*/) {
+ push(@parts,$key);
+ }
}
- return '';
+ return @parts;
}
-sub student_gradeStatus {
- my ($url,$udom,$uname) = @_;
- my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));
- my %record= &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);
- foreach my $part (&getpartlist($url)) {
- my ($temp,$part,$type)=split(/_/,$part);
- if ($type eq 'solved') {
- my ($status,$foo)=split(/_/,$record{"resource.$part.$type"},2);
- $status = 'partial' if ($foo =~ /^partially/);
- $status = 'nothing' if ($status eq '');
- return $type,$status;
- }
- }
- return '';
+# --- Get the symbolic name of a problem and the url
+sub get_symb_and_url {
+ my ($request) = @_;
+ (my $url=$ENV{'form.url'}) =~ s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
+ my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));
+ if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }
+ return ($symb,$url);
}
+# --- Retrieve the fullname for a user. Return lastname, first middle ---
+# --- Generation is attached next to the lastname if it exists. ---
sub get_fullname {
- my ($sname,$sdom) = @_;
+ my ($uname,$udom) = @_;
my %name=&Apache::lonnet::get('environment', ['lastname','generation',
'firstname','middlename'],
- $sdom,$sname);
+ $udom,$uname);
my $fullname;
my ($tmp) = keys(%name);
if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
- $fullname=$name{'lastname'}.$name{'generation'};
- if ($fullname =~ /[^\s]+/) { $fullname.=', '; }
- $fullname.=$name{'firstname'}.' '.$name{'middlename'};
+ $fullname = &Apache::loncoursedata::ProcessFullName
+ (@name{qw/lastname generation firstname middlename/});
+ } else {
+ &Apache::lonnet::logthis('grades.pm: no name data for '.$uname.
+ '@'.$udom.':'.$tmp);
}
return $fullname;
}
-sub listStudents {
- my ($request) = shift;
- my $cdom =$ENV{"course.$ENV{'request.course.id'}.domain"};
- my $cnum =$ENV{"course.$ENV{'request.course.id'}.num"};
- my $getsec =$ENV{'form.section'};
- my $submitonly=$ENV{'form.submitonly'};
-
- $request->print(< View Submissions for a Student or a Group of Students
- Resource: $ENV{'form.url'}
-
- View Problem: no
- yes
- Submissions: last
- all
-
-
-
-
-
Select
Username
-
Fullname
Domain
-
Grade Status
-ENDTABLEST
- if ($ENV{'form.url'}) {
- $request->print(''."\n");
- }
- if ($ENV{'form.symb'}) {
- $request->print(''."\n");
- }
- $request->print(''."\n");
-
- my ($classlist) = &getclasslist($getsec,'0');
- foreach my $student ( sort(@{ $$classlist{$getsec} }) ) {
- my ($sname,$sdom) = split(/:/,$student);
- my ($type,$status) = &student_gradeStatus($ENV{'form.url'},$cdom,$sname);
- next if ($status eq 'nothing' && $submitonly eq 'yes');
-
- my $fullname = &get_fullname($sname,$sdom);
- if ( $Apache::grades::viewgrades eq 'F' ) {
- $request->print("\n".'
'.
- '
'."\n".
- '
'.$sname.'
'."\n".
- '
'.$fullname.'
'."\n".
- '
'.$sdom.'
'."\n");
- $request->print('
'.$status.'
'."\n");
-
- $request->print('
');
- }
- }
- $request->print('
');
- $request->print('');
+#--- Get the partlist and the response type for a given problem. ---
+#--- Indicate if a response type is coded handgraded or not. ---
+sub response_type {
+ my ($url) = shift;
+ my $allkeys = &Apache::lonnet::metadata($url,'keys');
+ my %seen = ();
+ my (@partlist,%handgrade);
+ foreach (split(/,/,&Apache::lonnet::metadata($url,'packages'))) {
+ if (/^\w+response_\w+.*/) {
+ my ($responsetype,$part) = split(/_/,$_,2);
+ my ($partid,$respid) = split(/_/,$part);
+ $handgrade{$part} = $responsetype.':'.($allkeys =~ /parameter_$part\_handgrade/ ? 'yes' : 'no');
+ next if ($seen{$partid} > 0);
+ $seen{$partid}++;
+ push @partlist,$partid;
+ }
+ }
+ return \@partlist,\%handgrade;
}
-sub processGroup {
- my ($request) = shift;
- my $ctr = 0;
- my @stuchecked = (ref($ENV{'form.stuinfo'}) ? @{$ENV{'form.stuinfo'}}
- : ($ENV{'form.stuinfo'}) );
- my $total = scalar(@stuchecked)-1;
- foreach my $student (@stuchecked) {
- my ($sname,$sdom,$fullname) = split(/:/,$student);
- $ENV{'form.student'} = $sname;
- $ENV{'form.fullname'} = $fullname;
- &submission($request,$ctr,$total);
- $ctr++;
- }
-
- return 'The End';
+#--- Dumps the class list with usernames,list of sections,
+#--- section, ids and fullnames for each user.
+sub getclasslist {
+ my ($getsec,$filterlist) = @_;
+ my $classlist=&Apache::loncoursedata::get_classlist();
+ # Bail out if we were unable to get the classlist
+ return if (! defined($classlist));
+ #
+ my %sections;
+ my %fullnames;
+ foreach (keys(%$classlist)) {
+ # the following undefs are for 'domain', and 'username' respectively.
+ my (undef,undef,$end,$start,$id,$section,$fullname,$status)=
+ @{$classlist->{$_}};
+ # filter students according to status selected
+ if ($filterlist && $ENV{'form.status'} ne 'Any') {
+ if ($ENV{'form.status'} ne $status) {
+ delete ($classlist->{$_});
+ next;
+ }
+ }
+ $section = ($section ne '' ? $section : 'no');
+ if ($getsec eq 'all' || $getsec eq $section) {
+ $sections{$section}++;
+ $fullnames{$_}=$fullname;
+ } else {
+ delete($classlist->{$_});
+ }
+ }
+ my %seen = ();
+ my @sections = sort(keys(%sections));
+ return ($classlist,\@sections,\%fullnames);
}
-#FIXME - needs to handle multiple matches
+#find user domain
sub finduser {
- my ($name) = @_;
- my $domain = '';
+ my ($name) = @_;
+ my $domain = '';
+ if ( $Apache::grades::viewgrades eq 'F' ) {
+ my %classlist=&Apache::lonnet::dump('classlist',
+ $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
+ $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
+ my (@fields) = grep /^$name:/, keys %classlist;
+ ($name, $domain) = split(/:/,$fields[0]);
+ return ($name,$domain);
+ } else {
+ return ($ENV{'user.name'},$ENV{'user.domain'});
+ }
+}
- if ( $Apache::grades::viewgrades eq 'F' ) {
- #get classlist
-# my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});
- #print "Found $cdom:$cnum ";
- my ($classlist) = &getclasslist('all','0');
- foreach my $student ( sort(@{ $$classlist{'all'} }) ) {
- my ($posname,$posdomain) = split(/:/,$student);
- if ($posname =~ $name) { $name=$posname; $domain=$posdomain; last; }
- }
- return ($name,$domain);
- } else {
- return ($ENV{'user.name'},$ENV{'user.domain'});
- }
+#--- Prompts a user to enter a username.
+sub moreinfo {
+ my ($request,$reason) = @_;
+ $request->print("Unable to process request: $reason");
+ if ( $Apache::grades::viewgrades eq 'F' ) {
+ $request->print('');
+ }
+ return '';
}
-sub getclasslist {
- my ($getsec,$hideexpired) = @_;
- my ($coursedomain,$coursenum) = split(/_/,$ENV{'request.course.id'});
- my %classlist=&Apache::lonnet::dump('classlist',$coursedomain,$coursenum);
- my $now = time;
- my (@holdsec,@sections);
- foreach my $student (keys(%classlist)) {
- my ($end,$start)=split(/:/,$classlist{$student});
- # still a student?
- if (($hideexpired) && ($end) && ($end < $now)) {
- next;
- }
- my ($unam,$udom) = split(/:/,$student,2);
- my $section = &Apache::lonnet::usection($udom,$unam,$ENV{'request.course.id'});
- push @holdsec,$section;
- push (@{ $classlist{$getsec} }, $student) if ($getsec eq 'all' or $getsec == $section);
- }
- my %seen = ();
- foreach my $item (@holdsec) {
- push (@sections, $item) unless $seen{$item}++;
- }
- return (\%classlist,\@sections);
+#--- Retrieve the grade status of a student for all the parts
+sub student_gradeStatus {
+ my ($url,$symb,$udom,$uname,$partlist) = @_;
+ my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname);
+ my %partstatus = ();
+ foreach (@$partlist) {
+ my ($status,$foo) = split(/_/,$record{"resource.$_.solved"},2);
+ $status = 'nothing' if ($status eq '');
+ $partstatus{$_} = $status;
+ my $subkey = "resource.$_.submitted_by";
+ $partstatus{$subkey} = $record{$subkey} if ($record{$subkey} ne '');
+ }
+ return %partstatus;
+}
+
+# hidden form and javascript that calls the form
+# Use by verifyscript and viewgrades
+# Shows a student's view of problem and submission
+sub jscriptNform {
+ my ($url,$symb) = @_;
+ my $jscript=''."\n";
+ $jscript.= ''."\n";
+ return $jscript;
}
-sub getpartlist {
- my ($url) = @_;
- my @parts =();
- my (@metakeys) = split(/,/,&Apache::lonnet::metadata($url,'keys'));
- foreach my $key (@metakeys) {
- if ( $key =~ m/stores_([0-9]+)_.*/) {
- push(@parts,$key);
+#------------------ End of general use routines --------------------
+
+#
+# Find most similar essay
+#
+
+sub most_similar {
+ my ($uname,$udom,$uessay)=@_;
+
+# ignore spaces and punctuation
+
+ $uessay=~s/\W+/ /gs;
+
+# these will be returned. Do not care if not at least 50 percent similar
+ my $limit=0.6;
+ my $sname='';
+ my $sdom='';
+ my $scrsid='';
+ my $sessay='';
+# go through all essays ...
+ foreach my $tkey (keys %oldessays) {
+ my ($tname,$tdom,$tcrsid)=split(/\./,$tkey);
+# ... except the same student
+ if (($tname ne $uname) || ($tdom ne $udom)) {
+ my $tessay=$oldessays{$tkey};
+ $tessay=~s/\W+/ /gs;
+# String similarity gives up if not even limit
+ my $tsimilar=&String::Similarity::similarity($uessay,$tessay,$limit);
+# Found one
+ if ($tsimilar>$limit) {
+ $limit=$tsimilar;
+ $sname=$tname;
+ $sdom=$tdom;
+ $scrsid=$tcrsid;
+ $sessay=$oldessays{$tkey};
+ }
+ }
+ }
+ if ($limit>0.6) {
+ return ($sname,$sdom,$scrsid,$sessay,$limit);
+ } else {
+ return ('','','','',0);
}
- }
- return @parts;
}
-sub viewstudentgrade {
- my ($url,$symb,$courseid,$student,@parts) = @_;
- my $result ='';
- my $cellclr = '"#ffffdd"';
- my ($username,$domain) = split(/:/,$student);
-
- my $fullname = &get_fullname($username,$domain);
- my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$username);
-
- $result.="
$username
$fullname
$domain
\n";
- foreach my $part (@parts) {
- my ($temp,$part,$type)=split(/_/,$part);
- my $score=$record{"resource.$part.$type"};
- if ($type eq 'awarded' || $type eq 'tries') {
- $result.='
\n";
+#-------------------------------------------------------------------
+
+#------------------------------------ Receipt Verification Routines
+#
+#--- Check whether a receipt number is valid.---
+sub verifyreceipt {
+ my $request = shift;
+
+ my $courseid = $ENV{'request.course.id'};
+ my $receipt = unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}).'-'.
+ $ENV{'form.receipt'};
+ $receipt =~ s/[^\-\d]//g;
+ my $url = $ENV{'form.url'};
+ my $symb = $ENV{'form.symb'};
+ unless ($symb) {
+ $symb = &Apache::lonnet::symbread($url);
}
- }
- $result.='
';
- return $result;
-}
-#FIXME need to look at the metadata spec on what type of data to accept and provide an
-#interface based on that, also do that to above function.
-sub setstudentgrade {
- my ($url,$symb,$courseid,$student,@parts) = @_;
- print "set student grade parts=@parts ";
- my $result ='';
- my ($stuname,$domain) = split(/:/,$student);
- my %record=&Apache::lonnet::restore($symb,$courseid,$domain,$stuname);
- my %newrecord;
-
- foreach my $part (@parts) {
- my ($temp,$part,$type)=split(/_/,$part);
- my $oldscore=$record{"resource.$part.$type"};
- my $newscore=$ENV{"form.GRADE.$student.$part.$type"};
- print "old=$oldscore:new=$newscore: ";
- if ($type eq 'solved') {
- my $update=0;
- if ($newscore eq 'nothing' ) {
- if ($oldscore ne '') {
- $update=1;
- $newscore = '';
- }
- } elsif ($oldscore !~ m/^$newscore/) {
- $update=1;
- $result.="Updating $stuname to $newscore \n";
- if ($newscore eq 'correct') { $newscore = 'correct_by_override'; }
- if ($newscore eq 'incorrect') { $newscore = 'incorrect_by_override'; }
- if ($newscore eq 'excused') { $newscore = 'excused'; }
- if ($newscore eq 'ungraded') { $newscore = 'ungraded_attempted'; }
- if ($newscore eq 'partial') { $newscore = 'correct_partially_by_override'; }
- } else {
- #$result.="$stuname:$part:$type:unchanged $oldscore to $newscore: \n";
- }
- if ($update) { $newrecord{"resource.$part.$type"}=$newscore; }
+ my $title.='
Verifying Submission Receipt '.
+ $receipt.'
'."\n".
+ 'Problem: '.$ENV{'form.probTitle'}.'
'."\n";
+
+ my ($string,$contents,$matches) = ('','',0);
+ my (undef,undef,$fullname) = &getclasslist('all','0');
+
+ foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {
+ my ($uname,$udom)=split(/\:/);
+ if ($receipt eq
+ &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb)) {
+ $contents.='
'."\n";
+
+ $matches++;
+ }
+ }
+ if ($matches == 0) {
+ $string = $title.'No match found for the above receipt.';
} else {
- if ($oldscore ne $newscore) {
- $newrecord{"resource.$part.$type"}=$newscore;
- $result.="Updating $student"."'s status for $part.$type to $newscore \n";
- } else {
- #$result.="$stuname:$part:$type:unchanged $oldscore to $newscore: \n";
- }
+ $string = &jscriptNform($url,$symb).$title.
+ 'The above receipt matches the following student'.
+ ($matches <= 1 ? '.' : 's.')."\n".
+ '
'."\n".
+ '
'."\n".
+ '
Fullname
'."\n".
+ '
Username
'."\n".
+ '
Domain
'."\n".
+ $contents.
+ '
'."\n";
+ }
+ return $string.&show_grading_menu_form($symb,$url);
+}
+
+#--- This is called by a number of programs.
+#--- Called from the Grading Menu - View/Grade an individual student
+#--- Also called directly when one clicks on the subm button
+# on the problem page.
+sub listStudents {
+ my ($request) = shift;
+
+ my ($symb,$url) = &get_symb_and_url($request);
+ my $cdom = $ENV{"course.$ENV{'request.course.id'}.domain"};
+ my $cnum = $ENV{"course.$ENV{'request.course.id'}.num"};
+ my $getsec = $ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'};
+ my $submitonly= $ENV{'form.submitonly'} eq '' ? 'all' : $ENV{'form.submitonly'};
+
+ my $result;
+ my ($partlist,$handgrade) = &response_type($url);
+ for (sort keys(%$handgrade)) {
+ my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});
+ $ENV{'form.handgrade'} = 'yes' if ($handgrade eq 'yes');
+ $result.='
';
+ return $result;
+}
+
+# --------------------------- show submissions of a student, option to grade
+sub submission {
+ my ($request,$counter,$total) = @_;
+
+ (my $url=$ENV{'form.url'})=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
+ my ($uname,$udom) = ($ENV{'form.student'},$ENV{'form.userdom'});
+ ($uname,$udom) = &finduser($uname) if $udom eq '';
+ $ENV{'form.fullname'} = &get_fullname ($uname,$udom) if $ENV{'form.fullname'} eq '';
+
+ my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));
+ if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }
+ my $last = ($ENV{'form.lastSub'} eq 'last' ? 'last' : '');
+
+ # header info
+ if ($counter == 0) {
+ &sub_page_js($request);
+ &sub_page_kw_js($request);
+ $ENV{'form.probTitle'} = $ENV{'form.probTitle'} eq '' ?
+ &Apache::lonnet::gettitle($symb) : $ENV{'form.probTitle'};
+
+ $request->print('
Submission Record
'."\n".
+ ' Problem: '.$ENV{'form.probTitle'}.''."\n");
+
+ # option to display problem, only once else it cause problems
+ # with the form later since the problem has a form.
+ if ($ENV{'form.vProb'} eq 'yes' or !$ENV{'form.vProb'}) {
+ $request->print(&show_problem($request,$symb,$uname,$udom,0,1));
+ }
+
+ # kwclr is the only variable that is guaranteed to be non blank
+ # if this subroutine has been called once.
+ my %keyhash = ();
+ if ($ENV{'form.kwclr'} eq '') {
+ %keyhash = &Apache::lonnet::dump('nohist_handgrade',
+ $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
+ $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
+
+ my $loginuser = $ENV{'user.name'}.':'.$ENV{'user.domain'};
+ $ENV{'form.keywords'} = $keyhash{$symb.'_keywords'} ne '' ? $keyhash{$symb.'_keywords'} : '';
+ $ENV{'form.kwclr'} = $keyhash{$loginuser.'_kwclr'} ne '' ? $keyhash{$loginuser.'_kwclr'} : 'red';
+ $ENV{'form.kwsize'} = $keyhash{$loginuser.'_kwsize'} ne '' ? $keyhash{$loginuser.'_kwsize'} : '0';
+ $ENV{'form.kwstyle'} = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : '';
+ $ENV{'form.msgsub'} = $keyhash{$symb.'_subject'} ne '' ?
+ $keyhash{$symb.'_subject'} : $ENV{'form.probTitle'};
+ $ENV{'form.savemsgN'} = $keyhash{$symb.'_savemsgN'} ne '' ? $keyhash{$symb.'_savemsgN'} : '0';
+
+ }
+
+ $request->print('
'."\n");
+
+ # print end of form
+ if ($counter == $total) {
+ my $endform='
'.
+ ''."\n";
+ if ($ENV{'form.handgrade'} eq 'yes') {
+ $endform.=' '."\n";
+ my $ntstu =''."\n";
+ my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1');
+ $ntstu =~ s/
';
+ $endform.=&show_grading_menu_form($symb,$url);
+ $request->print($endform);
+ }
+ return '';
}
+#--- Retrieve the last submission for all the parts
+sub get_last_submission {
+ my (%returnhash)=@_;
+ my (@string,$timestamp);
+ if ($returnhash{'version'}) {
+ my %lasthash=();
+ my ($version);
+ for ($version=1;$version<=$returnhash{'version'};$version++) {
+ foreach (sort(split(/\:/,$returnhash{$version.':keys'}))) {
+ $lasthash{$_}=$returnhash{$version.':'.$_};
+ $timestamp = scalar(localtime($returnhash{$version.':timestamp'}));
+ }
+ }
+ foreach ((keys %lasthash)) {
+ if ($_ =~ /\.submission$/) {
+ my ($partid,$foo) = split(/submission$/,$_);
+ my $draft = $lasthash{$partid.'awarddetail'} eq 'DRAFT' ?
+ 'Draft Copy ' : '';
+ push @string, (join(':',$_,$draft.$lasthash{$_}));
+ }
+ }
+ }
+ @string = $string[0] eq '' ? 'Nothing submitted - no attempts.' : @string;
+ return \@string,\$timestamp;
+}
+
+#--- High light keywords, with style choosen by user.
+sub keywords_highlight {
+ my $string = shift;
+ my $size = $ENV{'form.kwsize'} eq '0' ? '' : 'size='.$ENV{'form.kwsize'};
+ my $styleon = $ENV{'form.kwstyle'} eq '' ? '' : $ENV{'form.kwstyle'};
+ (my $styleoff = $styleon) =~ s/\\<\//;
+ my @keylist = split(/[,\s+]/,$ENV{'form.keywords'});
+ foreach (@keylist) {
+ $string =~ s/\b\Q$_\E(\b|\.)/\$styleon$_$styleoff\<\/font\>/gi;
+ }
+ # This is not really the right place to do this, but I cannot find a
+ # better one at this time. So here we go - the m in the s:::mg causes
+ # ^ to match the beginning of a new line. So we replace(???) the beginning
+ # of the line with to make things formatted a little better.
+ $string =~ s:^: :mg;
+ return $string;
+}
+
+#--- Called from submission routine
sub processHandGrade {
- my ($request) = shift;
- my $url = $ENV{'form.url'};
- my $symb = $ENV{'form.symb'};
- my $button = $ENV{'form.gradeOpt'};
- my $ngrade = $ENV{'form.NCT'};
- my $ntstu = $ENV{'form.NTSTU'};
-# my $vProb = $ENV{'form.vProb'};
-# my $lastSub= $ENV{'form.lastSub'};
-
- my (@parts) = sort(&getpartlist($url));
-
- if ($button eq 'Save & Next') {
- my $ctr = 0;
- while ($ctr < $ENV{'form.NCT'}) {
-# my $pts = ($ENV{'form.GRADE_BOX'.$ctr} ne '' ? $ENV{'form.GRADE_BOX'.$ctr} : $ENV{'form.RADVAL'.$ctr});
-# my $wgt = $ENV{'form.WGT'.$ctr};
-# my $sel = $ENV{'form.GRADE_SEL'.$ctr};
-# my $score = $pts/$wgt if ($wgt != 0);
- my ($uname,$udom) = split(/:/,$ENV{'form.unamedom'.$ctr});
- &saveHandGrade($url,$symb,$uname,$udom,$ctr,@parts);
-# &saveHandGrade($url,$symb,$uname,$udom,$score,@parts);
- $ctr++;
- }
- }
- my $firststu = $ENV{'form.unamedom0'};
- my $laststu = $ENV{'form.unamedom'.($ngrade-1)};
+ my ($request) = shift;
+ my $url = $ENV{'form.url'};
+ my $symb = $ENV{'form.symb'};
+ my $button = $ENV{'form.gradeOpt'};
+ my $ngrade = $ENV{'form.NCT'};
+ my $ntstu = $ENV{'form.NTSTU'};
+
+ if ($button eq 'Save & Next') {
+ my $ctr = 0;
+ while ($ctr < $ngrade) {
+ my ($uname,$udom) = split(/:/,$ENV{'form.unamedom'.$ctr});
+ my ($errorflag,$pts,$wgt) = &saveHandGrade($request,$url,$symb,$uname,$udom,$ctr);
+ if ($errorflag eq 'no_score') {
+ $ctr++;
+ next;
+ }
+ my $includemsg = $ENV{'form.includemsg'.$ctr};
+ my ($subject,$message,$msgstatus) = ('','','');
+ if ($includemsg =~ /savemsg|newmsg\Q$ctr\E/) {
+ $subject = $ENV{'form.msgsub'} if ($includemsg =~ /^msgsub/);
+ my (@msgnum) = split(/,/,$includemsg);
+ foreach (@msgnum) {
+ $message.=$ENV{'form.'.$_} if ($_ =~ /savemsg|newmsg/ && $_ ne '');
+ }
+ $message =&Apache::lonfeedback::clear_out_html($message);
+ $message.="\n\nPoint".($pts > 1 ? 's':'').' awarded = '.$pts.' out of '.$wgt;
+ $message.=" for $ENV{'form.probTitle'}";
+ $msgstatus = &Apache::lonmsg::user_normal_msg ($uname,$udom,
+ $ENV{'form.msgsub'},$message);
+ }
+ if ($ENV{'form.collaborator'.$ctr}) {
+ my (@collaborators) = split(/:/,$ENV{'form.collaborator'.$ctr});
+ foreach (@collaborators) {
+ &saveHandGrade($request,$url,$symb,$_,$udom,$ctr,
+ $ENV{'form.unamedom'.$ctr});
+ if ($message ne '') {
+ $msgstatus = &Apache::lonmsg::user_normal_msg ($_,$udom,
+ $ENV{'form.msgsub'},
+ $message);
+ }
+ }
+ }
+ $ctr++;
+ }
+ }
- #get classlist
-# my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});
- my ($classlist) = &getclasslist('all','0');
-
- my (@nextlist,@prevlist);
- my ($nextflg,$prevflg,$ctr,$ctprev) = (0,0,0,0);
- foreach my $student ( sort(@{ $$classlist{'all'} }) ) {
- my ($uname,$udom) = split(/:/,$student);
- if ($nextflg == 1 && $button =~ /Next$/) {
- push @nextlist,$uname if ($ctr < $ntstu);
- $ctr++;
- }
- $nextflg = 1 if ($student eq $laststu);
- $prevflg = 1 if ($student eq $firststu);
- if ($prevflg == 0 && $button eq 'Previous') {
- push @prevlist,$uname;
- $ctprev++;
- }
- }
- if ($button eq 'Previous') {
- if ($ctprev <= $ntstu) {
- @nextlist = @prevlist;
- } else {
- my $idx = 0;
- my $start = $ctprev - $ntstu;
- while ($idx < $ntstu) {
- $nextlist[$idx] = $prevlist[$start+$idx];
- $idx++;
- }
- }
- }
- $ctr = 0;
- my $total = scalar(@nextlist)-1;
- foreach my $student (@nextlist) {
- $ENV{'form.student'} = $student;
- &submission($request,$ctr,$total);
- $ctr++;
- }
+ # Keywords sorted in alphabatical order
+ my $loginuser = $ENV{'user.name'}.':'.$ENV{'user.domain'};
+ my %keyhash = ();
+ $ENV{'form.keywords'} =~ s/,\s{0,}|\s+/ /g;
+ $ENV{'form.keywords'} =~ s/^\s+|\s+$//;
+ my (@keywords) = sort(split(/\s+/,$ENV{'form.keywords'}));
+ $ENV{'form.keywords'} = join(' ',@keywords);
+ $keyhash{$symb.'_keywords'} = $ENV{'form.keywords'};
+ $keyhash{$symb.'_subject'} = $ENV{'form.msgsub'};
+ $keyhash{$loginuser.'_kwclr'} = $ENV{'form.kwclr'};
+ $keyhash{$loginuser.'_kwsize'} = $ENV{'form.kwsize'};
+ $keyhash{$loginuser.'_kwstyle'} = $ENV{'form.kwstyle'};
+
+ # message center - Order of message gets changed. Blank line is eliminated.
+ # New messages are saved in ENV for the next student.
+ # All messages are saved in nohist_handgrade.db
+ my ($ctr,$idx) = (1,1);
+ while ($ctr <= $ENV{'form.savemsgN'}) {
+ if ($ENV{'form.savemsg'.$ctr} ne '') {
+ $keyhash{$symb.'_savemsg'.$idx} = $ENV{'form.savemsg'.$ctr};
+ $idx++;
+ }
+ $ctr++;
+ }
+ $ctr = 0;
+ while ($ctr < $ngrade) {
+ if ($ENV{'form.newmsg'.$ctr} ne '') {
+ $keyhash{$symb.'_savemsg'.$idx} = $ENV{'form.newmsg'.$ctr};
+ $ENV{'form.savemsg'.$idx} = $ENV{'form.newmsg'.$ctr};
+ $idx++;
+ }
+ $ctr++;
+ }
+ $ENV{'form.savemsgN'} = --$idx;
+ $keyhash{$symb.'_savemsgN'} = $ENV{'form.savemsgN'};
+ my $putresult = &Apache::lonnet::put
+ ('nohist_handgrade',\%keyhash,
+ $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
+ $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
+
+ # Called by Save & Refresh from Highlight Attribute Window
+ my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'0');
+ if ($ENV{'form.refresh'} eq 'on') {
+ my ($ctr,$total) = (0,0);
+ while ($ctr < $ngrade) {
+ $total++ if $ENV{'form.unamedom'.$ctr} ne '';
+ $ctr++;
+ }
+ $ENV{'form.NTSTU'}=$ngrade;
+ $ctr = 0;
+ while ($ctr < $total) {
+ my $processUser = $ENV{'form.unamedom'.$ctr};
+ ($ENV{'form.student'},$ENV{'form.userdom'}) = split(/:/,$processUser);
+ $ENV{'form.fullname'} = $$fullname{$processUser};
+ &submission($request,$ctr,$total-1);
+ $ctr++;
+ }
+ return '';
+ }
- return 'The End';
+ # Get the next/previous one or group of students
+ my $firststu = $ENV{'form.unamedom0'};
+ my $laststu = $ENV{'form.unamedom'.($ngrade-1)};
+ $ctr = 2;
+ while ($laststu eq '') {
+ $laststu = $ENV{'form.unamedom'.($ngrade-$ctr)};
+ $ctr++;
+ $laststu = $firststu if ($ctr > $ngrade);
+ }
+
+ my (@parsedlist,@nextlist);
+ my ($nextflg) = 0;
+ foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {
+ if ($nextflg == 1 && $button =~ /Next$/) {
+ push @parsedlist,$_;
+ }
+ $nextflg = 1 if ($_ eq $laststu);
+ if ($button eq 'Previous') {
+ last if ($_ eq $firststu);
+ push @parsedlist,$_;
+ }
+ }
+ $ctr = 0;
+ my ($partlist,$handgrade) = &response_type($ENV{'form.url'});
+ @parsedlist = reverse @parsedlist if ($button eq 'Previous');
+ foreach my $student (@parsedlist) {
+ my ($uname,$udom) = split(/:/,$student);
+ if ($ENV{'form.submitonly'} eq 'yes') {
+ my (%status) = &student_gradeStatus($ENV{'form.url'},$symb,$udom,$uname,$partlist) ;
+ my $statusflg = '';
+ foreach (keys(%status)) {
+ $statusflg = 1 if ($status{$_} ne 'nothing');
+ my ($foo,$partid,$foo1) = split(/\./);
+ $statusflg = '' if ($status{'resource.'.$partid.'.submitted_by'} ne '');
+ }
+ next if ($statusflg eq '');
+ }
+ push @nextlist,$student if ($ctr < $ntstu);
+ $ctr++;
+ }
+
+ $ctr = 0;
+ my $total = scalar(@nextlist)-1;
+
+ foreach (sort @nextlist) {
+ my ($uname,$udom,$submitter) = split(/:/);
+ $ENV{'form.student'} = $uname;
+ $ENV{'form.userdom'} = $udom;
+ $ENV{'form.fullname'} = $$fullname{$_};
+ &submission($request,$ctr,$total);
+ $ctr++;
+ }
+ if ($total < 0) {
+ my $the_end = '
LON-CAPA User Message
'."\n";
+ $the_end.='Message: No more students for this section or class.
'."\n";
+ $the_end.='Click on the button below to return to the grading menu.
'."\n";
+ $the_end.=&show_grading_menu_form ($symb,$url);
+ $request->print($the_end);
+ }
+ return '';
}
+#---- Save the score and award for each student, if changed
sub saveHandGrade {
- my ($url,$symb,$stuname,$domain,$newflg,@parts) = @_;
-# my ($stuname,$domain) = split(/:/,$student);
- my %record=&Apache::lonnet::restore($symb,$ENV{'request.course.id'},$domain,$stuname);
- my %newrecord;
-
- foreach my $part (@parts) {
- my ($temp,$part,$type)=split(/_/,$part);
- my $oldscore=$record{"resource.$part.$type"};
- my $newscore;
- if ($type eq 'awarded' && $newflg >= 0) {
- my $pts = ($ENV{'form.GRADE_BOX'.$newflg} ne '' ? $ENV{'form.GRADE_BOX'.$newflg} : $ENV{'form.RADVAL'.$newflg});
- my $wgt = $ENV{'form.WGT'.$newflg};
-# my $sel = $ENV{'form.GRADE_SEL'.$newflg};
- $newscore = $pts/$wgt if ($wgt != 0);
- }
- if ($type eq 'solved') {
- $newscore = $ENV{'form.GRADE_SEL'.$newflg} if ($newflg >= 0);
- my $update=0;
- if ($newscore eq 'nothing' ) {
- if ($oldscore ne '') {
- $update=1;
- $newscore = '';
- }
- } elsif ($oldscore !~ m/^$newscore/) {
- $update=1;
- if ($newscore eq 'correct') { $newscore = 'correct_by_override'; }
- if ($newscore eq 'incorrect') { $newscore = 'incorrect_by_override'; }
- if ($newscore eq 'excused') { $newscore = 'excused'; }
- if ($newscore eq 'ungraded') { $newscore = 'ungraded_attempted'; }
- if ($newscore eq 'partial') { $newscore = 'correct_partially_by_override'; }
- }
- if ($update) { $newrecord{"resource.$part.$type"}=$newscore; }
- } else {
- if ($oldscore ne $newscore) {
- $newrecord{"resource.$part.$type"}=$newscore;
- }
+ my ($request,$url,$symb,$stuname,$domain,$newflg,$submitter) = @_;
+ my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$domain,$stuname);
+ my %newrecord = ();
+ my ($pts,$wgt) = ('','');
+ foreach (split(/:/,$ENV{'form.partlist'.$newflg})) {
+ if ($ENV{'form.GD_SEL'.$newflg.'_'.$_} eq 'excused') {
+ if ($record{'resource.'.$_.'.solved'} ne 'excused') {
+ $newrecord{'resource.'.$_.'.solved'} = 'excused';
+ if (exists($record{'resource.'.$_.'.awarded'})) {
+ $newrecord{'resource.'.$_.'.awarded'} = '';
+ }
+ }
+ } else {
+ $pts = ($ENV{'form.GD_BOX'.$newflg.'_'.$_} ne '' ?
+ $ENV{'form.GD_BOX'.$newflg.'_'.$_} :
+ $ENV{'form.RADVAL'.$newflg.'_'.$_});
+ return 'no_score' if ($pts eq '' && $ENV{'form.GD_SEL'.$newflg.'_'.$_} eq '');
+ $wgt = $ENV{'form.WGT'.$newflg.'_'.$_} eq '' ? 1 :
+ $ENV{'form.WGT'.$newflg.'_'.$_};
+ my $partial= $pts/$wgt;
+ $newrecord{'resource.'.$_.'.awarded'} = $partial
+ if ($record{'resource.'.$_.'.awarded'} ne $partial);
+ my $reckey = 'resource.'.$_.'.solved';
+ if ($partial == 0) {
+ $newrecord{$reckey} = 'incorrect_by_override'
+ if ($record{$reckey} ne 'incorrect_by_override');
+ } else {
+ $newrecord{$reckey} = 'correct_by_override'
+ if ($record{$reckey} ne 'correct_by_override');
+ }
+ $newrecord{'resource.'.$_.'.submitted_by'} = $submitter
+ if ($submitter && ($record{'resource.'.$_.'.submitted_by'} ne $submitter));
+ $newrecord{'resource.'.$_.'regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
+ }
}
- }
- if ( scalar(keys(%newrecord)) > 0 ) {
- $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
- while (my ($k,$v) = each %newrecord) {
- print "k=$k:v=$v: \n";
- }
- print "symb=$symb,courseid=$ENV{'request.course.id'},dom=$domain,name=$stuname ";
-# &Apache::lonnet::cstore(\%newrecord,$symb,$ENV{'request.course.id'},$domain,$stuname);
- }
- return '';
-}
-sub get_symb_and_url {
- my ($request) = @_;
- (my $url=$ENV{'form.url'}) =~ s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
- my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url)));
- if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; }
- return ($symb,$url);
+ if (scalar(keys(%newrecord)) > 0) {
+ &Apache::lonnet::cstore(\%newrecord,$symb,
+ $ENV{'request.course.id'},$domain,$stuname);
+ }
+ return '',$pts,$wgt;
}
-sub show_grading_menu_form {
- my ($symb,$url)=@_;
- my $result.=''."\n";
- return $result;
-}
+#--------------------------------------------------------------------------------------
+#
+#-------------------------- Next few routines handles grading by section or whole class
+#
+#--- Javascript to handle grading by section or whole class
+sub viewgrades_js {
+ my ($request) = shift;
-sub gradingmenu {
- my ($request) = @_;
- my ($symb,$url)=&get_symb_and_url($request);
- if (!$symb) {return '';}
-
- my $result='
'."\n";
- return $result;
-}
+ $request->print(<
+ function writePoint(partid,weight,point) {
+ var radioButton = eval("document.classgrade.RADVAL_"+partid);
+ var textbox = eval("document.classgrade.TEXTVAL_"+partid);
+ if (point == "textval") {
+ var point = eval("document.classgrade.TEXTVAL_"+partid+".value");
+ if (isNaN(point) || point < 0) {
+ alert("A number equal or greater than 0 is expected. Entered value = "+point);
+ var resetbox = false;
+ for (var i=0; i weight) {
+ var resp = confirm("You entered a value ("+point+
+ ") greater than the weight for the part. Accept?");
+ if (resp == false) {
+ textbox.value = "";
+ return;
+ }
+ }
+ for (var i=0; i
'."\n";
- $result.='
'."\n";
- $result.=' Specify a file containing the class scores for above resource
'."\n";
- return $result;
-}
-
-sub viewGradeaStu_form {
- my ($symb,$url) = @_;
- my ($classlist,$sections) = &getclasslist('all','0');
- my $result.='
'."\n";
- $result.='
'."\n";
- $result.=' View/Grade an Individual Student\'s Submission
'."\n";
- $result.='
'."\n";
- $result.=''."\n";
- $result.='
'."\n";
- $result.='
'."\n";
- return $result;
-}
-
-sub verifyReceipt_form {
- my ($symb,$url) = @_;
- my $cdom=$ENV{"course.$ENV{'request.course.id'}.domain"};
- my $cnum=$ENV{"course.$ENV{'request.course.id'}.num"};
- my $hostver=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'});
-
- my $result.='
'."\n";
- $result.='
'."\n";
- $result.=' Verify a Submission Receipt Issued by this Server
'."\n";
- $result.='
'."\n";
- $result.='';
- $result.='
'."\n";
- $result.='
'."\n";
- return $result;
+ } else {
+ textbox.value = point;
+ }
+ for (i=0;i weight) {
+ var resp = confirm("You entered a value ("+point+
+ ") greater than the weight of the part. Accept?");
+ if (resp == false) {
+ textbox.value = "";
+ return;
+ }
+ }
+ selval[0].selected = true;
+ }
+
+ function changeOneScore(partid,user) {
+ var selval = eval("document.classgrade.GD_"+user+'_'+partid+"_solved");
+ if (selval[1].selected) {
+ var boxval = eval("document.classgrade.GD_"+user+'_'+partid+"_awarded");
+ boxval.value = "";
+ }
+ }
+
+ function resetEntry(numpart) {
+ for (ctpart=0;ctpart
+VIEWJAVASCRIPT
}
+#--- show scores for a section or whole class w/ option to change/update a score
sub viewgrades {
- my ($request) = @_;
- my $result='';
+ my ($request) = shift;
+ &viewgrades_js($request);
+
+ my ($symb,$url) = ($ENV{'form.symb'},$ENV{'form.url'});
+ my $result='
Manual Grading
';
- #get resource reference
- my ($symb,$url)=&get_symb_and_url($request);
- if (!$symb) {return '';}
- #get classlist
- my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});
- #print "Found $cdom:$cnum ";
- my ($classlist) = &getclasslist('all','0');
- my $headerclr = '"#ccffff"';
- my $cellclr = '"#ffffcc"';
-
- #get list of parts for this problem
- my (@parts) = sort(&getpartlist($url));
-
- $request->print ("
Assign Common Grade To ';
+ if ($ENV{'form.section'} eq 'all') {
+ $result.='Class
';
+ } elsif ($ENV{'form.section'} eq 'no') {
+ $result.='Students in no Section ';
+ } else {
+ $result.='Students in Section '.$ENV{'form.section'}.'';
+ }
+ $result.= '
'."\n".
+ '
';
+ #radio buttons/text box for assigning points for a section or class.
+ #handles different parts of a problem
+ my ($partlist,$handgrade) = &response_type($ENV{'form.url'});
+ my %weight = ();
+ my $ctsparts = 0;
+ $result.='
';
+ my %seen = ();
+ for (sort keys(%$handgrade)) {
+ my ($partid,$respid) = split (/_/,$_,2);
+ next if $seen{$partid};
+ $seen{$partid}++;
+ my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});
+ my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb);
+ $weight{$partid} = $wgt eq '' ? '1' : $wgt;
+
+ $result.=''."\n";
+ $result.=''."\n";
+ $result.='
Part '.$partid.' Point:
';
+ $result.='
';
+ my $ctr = 0;
+ while ($ctr<=$weight{$partid}) { # display radio buttons in a nice table 10 across
+ $result.= '
'.$ctr."
\n";
+ $result.=(($ctr+1)%10 == 0 ? '
' : '');
+ $ctr++;
+ }
+ $result.='
';
+ $result.= '
or /'.
+ $weight{$partid}.' (problem weight)
'."\n";
+ $result.= '
'."\n";
+ $ctsparts++;
+ }
+ $result.='
'.'
'.'
'."\n".
+ '';
+ $result.=' ';
+ $result.=''."\n";
+
+ #table listing all the students in a section/class
+ #header of table
+ $result.= '
Assign Grade to Specific Students in ';
+ if ($ENV{'form.section'} eq 'all') {
+ $result.='the Class
';
+
+ #get info for each student
+ #list all the students - with points and grade status
+ my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'1');
+ my $ctr = 0;
+ foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) {
+ my $uname = $_;
+ $uname=~s/:/_/;
+ $result.=''."\n";
+ $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'},
+ $_,$$fullname{$_},\@parts,\%weight);
+ $ctr++;
+ }
+ $result.='
';
+ $result.=''."\n";
+ $result.=''."\n";
+ if (scalar(%$fullname) eq 0) {
+ my $colspan=3+scalar(@parts);
+ $result='There are no students in section "'.$ENV{'form.section'}.'" with enrollment status "'.$ENV{'form.status'}.'" to modify or grade.';
+ }
+ $result.=&show_grading_menu_form($symb,$url);
+ return $result;
}
+#--- call by previous routine to display each student
+sub viewstudentgrade {
+ my ($url,$symb,$courseid,$student,$fullname,$parts,$weight) = @_;
+ my ($uname,$udom) = split(/:/,$student);
+ $student=~s/:/_/;
+ my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname);
+ my $result='
';
+ return $result;
+}
+
+#--- change scores for all the students in a section/class
+# record does not get update if unchanged
sub editgrades {
- my ($request) = @_;
- my $result='';
+ my ($request) = @_;
- my $symb=$ENV{'form.symb'};
- if ($symb eq '') { $request->print("Unable to handle ambiguous references:$symb:$ENV{'form.url'}"); return ''; }
- my $url=$ENV{'form.url'};
- #get classlist
-# my ($cdom,$cnum) = split(/_/,$ENV{'request.course.id'});
- #print "Found $cdom:$cnum ";
- my ($classlist) = &getclasslist('all','0');
-
- #get list of parts for this problem
- my (@parts) = &getpartlist($url);
-
- $result.='';
- return $result;
-}
+#----------------------------------------------------------------------------
+#
+#-------------------------- Next few routines handles grading by csv upload
+#
+#--- Javascript to handle csv upload
sub csvupload_javascript_reverse_associate {
return(<print(<';
+ $result.='
Problem: '.$ENV{'form.probTitle'}.'
';
+ my ($partlist,$handgrade) = &response_type($url);
+ my ($resptype,$hdgrade)=('','no');
+ for (sort keys(%$handgrade)) {
+ my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});
+ $resptype = $responsetype;
+ $hdgrade = $handgrade if ($handgrade eq 'yes');
+ $result.='
Part '.(split(/_/))[0].'
'.
+ '
Type: '.$responsetype.'
'.
+ '
Handgrade: '.$handgrade.'
';
+ }
+ $result.='';
+ $request->print(<
-
Uploading Class Grades for resource $url
+
Uploading Class Grades
+$result
Identify fields
Total number of records found in file: $distotal
@@ -947,34 +2256,36 @@ to this page if the data selected is ins
value="$ENV{'form.upfile_associate'}" />
+
+
ENDPICK
- return '';
+return '';
}
sub csvupload_fields {
- my ($url) = @_;
- my (@parts) = &getpartlist($url);
- my @fields=(['username','Student Username'],['domain','Student Domain']);
- foreach my $part (sort(@parts)) {
- my @datum;
- my $display=&Apache::lonnet::metadata($url,$part.'.display');
- my $name=$part;
- if (!$display) { $display = $name; }
- @datum=($name,$display);
- push(@fields,\@datum);
- }
- return (@fields);
+ my ($url) = @_;
+ my (@parts) = &getpartlist($url);
+ my @fields=(['username','Student Username'],['domain','Student Domain']);
+ foreach my $part (sort(@parts)) {
+ my @datum;
+ my $display=&Apache::lonnet::metadata($url,$part.'.display');
+ my $name=$part;
+ if (!$display) { $display = $name; }
+ @datum=($name,$display);
+ push(@fields,\@datum);
+ }
+ return (@fields);
}
sub csvuploadmap_footer {
- my ($request,$i,$keyfields) =@_;
- $request->print(<print(<
@@ -983,206 +2294,1220 @@ sub csvuploadmap_footer {
ENDPICK
}
+sub upcsvScores_form {
+ my ($request) = shift;
+ my ($symb,$url)=&get_symb_and_url($request);
+ if (!$symb) {return '';}
+ my $result =<
+ function checkUpload(formname) {
+ if (formname.upfile.value == "") {
+ alert("Please use the browse button to select a file from your local directory.");
+ return false;
+ }
+ formname.submit();
+ }
+
+CSVFORMJS
+ $ENV{'form.probTitle'} = &Apache::lonnet::gettitle($symb);
+ $result.='
'."\n";
+ $result.='
'."\n";
+ $result.=' Specify a file containing the class scores for problem - '.$ENV{'form.probTitle'}.
+ '.