--- loncom/homework/grades.pm 2002/07/01 21:20:29 1.34
+++ loncom/homework/grades.pm 2003/07/23 18:04:51 1.124
@@ -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.124 2003/07/23 18:04:51 ng 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,2336 @@ use Apache::style;
use Apache::lonxml;
use Apache::lonnet;
use Apache::loncommon;
+use Apache::lonhtmlcommon;
+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=();
+my %perm=();
-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");
+#--- 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);
+ $responsetype =~ s/response$//; # make it compatible w/ navmaps - should move to that!!
+ $handgrade{$part} = $responsetype.':'.($allkeys =~ /parameter_$part\_handgrade/ ? 'yes' : 'no');
+ next if ($seen{$partid} > 0);
+ $seen{$partid}++;
+ push @partlist,$partid;
+ }
+ }
+ return \@partlist,\%handgrade;
+}
- $request->print('
');
- }
- }
- $request->print('
');
- $request->print('');
+#--- Show resource title
+#--- and parts and response type
+sub showResourceInfo {
+ my ($url,$probTitle) = @_;
+ my $result ='
'.
+ '
Current Resource: '.$probTitle.'
'."\n";
+ my ($partlist,$handgrade) = &response_type($url);
+ my %resptype = (); #,$hdgrade)=('','no');
+ my $hdgrade='no';
+ for (sort keys(%$handgrade)) {
+ my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});
+ my $partID = (split(/_/))[0];
+ $resptype{$partID} = $responsetype;
+ $hdgrade = $handgrade if ($handgrade eq 'yes');
+ $result.='
Part '.$partID.'
'.
+ '
Type: '.$responsetype.'
';
+# '
Handgrade: '.$handgrade.'
';
+ }
+ $result.='
'."\n";
+ return $result,\%resptype,$hdgrade,$partlist,$handgrade;
+}
+
+#--- Clean response type for display
+#--- Currently filters option response type only.
+sub cleanRecord {
+ my ($answer,$response,$symb) = @_;
+ if ($response eq 'option') {
+ my (@IDs,@ans);
+ foreach (split(/\&/,&Apache::lonnet::unescape($answer))) {
+ my ($optionID,$ans) = split(/=/);
+ push @IDs,$optionID.'';
+ push @ans,$ans;
+ }
+ my $grayFont = '';
+ return '
'.
+ '
Answer
'.
+ (join '
',@ans).'
'.
+ '
'.$grayFont.'Option ID
'.$grayFont.
+ (join '
'.$grayFont,@IDs).'
'.
+ '
';
+ }
+ if ($response eq 'essay') {
+ if (! exists ($ENV{'form.'.$symb})) {
+ my (%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.'.$symb} = 1; # so that we don't have to read it from disk for multiple sub of the same prob.
+ }
+ return &keywords_highlight($answer);
+ }
+ return $answer;
}
-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++;
- }
+#-- A couple of common js functions
+sub commonJSfunctions {
+ my $request = shift;
+ $request->print(<
+ function radioSelection(radioButton) {
+ var selection=null;
+ if (radioButton.length > 1) {
+ for (var i=0; i 1) {
+ for (var i=0; i
+COMMONJSFUNCTIONS
}
-#FIXME - needs to handle multiple matches
-sub finduser {
- my ($name) = @_;
- my $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'});
- }
+#--- Dumps the class list with usernames,list of sections,
+#--- section, ids and fullnames for each user.
+sub getclasslist {
+ my ($getsec,$filterlist) = @_;
+ $getsec = $getsec eq '' ? 'all' : $getsec;
+ 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 (&canview($section)) {
+ if ($getsec eq 'all' || $getsec eq $section) {
+ $sections{$section}++;
+ $fullnames{$_}=$fullname;
+ } else {
+ delete($classlist->{$_});
+ }
+ } else {
+ delete($classlist->{$_});
+ }
+ }
+ my %seen = ();
+ my @sections = sort(keys(%sections));
+ return ($classlist,\@sections,\%fullnames);
}
-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);
+sub canmodify {
+ my ($sec)=@_;
+ if ($perm{'mgr'}) {
+ if (!defined($perm{'mgr_section'})) {
+ # can modify whole class
+ return 1;
+ } else {
+ if ($sec eq $perm{'mgr_section'}) {
+ #can modify the requested section
+ return 1;
+ } else {
+ # can't modify the request section
+ return 0;
+ }
+ }
+ }
+ #can't modify
+ return 0;
}
-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);
+sub canview {
+ my ($sec)=@_;
+ if ($perm{'vgr'}) {
+ if (!defined($perm{'vgr_section'})) {
+ # can modify whole class
+ return 1;
+ } else {
+ if ($sec eq $perm{'vgr_section'}) {
+ #can modify the requested section
+ return 1;
+ } else {
+ # can't modify the request section
+ return 0;
+ }
+ }
}
- }
- return @parts;
+ #can't modify
+ return 0;
}
-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.="
'."\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 $viewgrade = $ENV{'form.showgrading'} eq 'yes' ? 'View/Grade/Regrade' : 'View';
+ $ENV{'form.probTitle'} = $ENV{'form.probTitle'} eq '' ?
+ &Apache::lonnet::gettitle($symb) : $ENV{'form.probTitle'};
+
+ my $result='
'.$viewgrade.
+ ' Submissions for a Student or a Group of Students
';
+
+ my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($url,$ENV{'form.probTitle'});
+ $result.=$table;
+
+ $request->print(<
+ function checkSelect(checkBox) {
+ var ctr=0;
+ var sense="";
+ if (checkBox.length > 1) {
+ for (var i=0; i 0 ) {
- $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
- print "grader=$newrecord{'resource.regrader'}: records ";
- while (my ($k,$v) = each %newrecord) {
- print "k=$k:v=$v: \n";
+
+ function reLoadList(formname) {
+ if (formname.saveStatusOld.value == pullDownSelection(formname.Status)) {return;}
+ formname.command.value = 'submission';
+ formname.submit();
}
-# &Apache::lonnet::cstore(\%newrecord,$symb,$courseid,$domain,$stuname);
+
+LISTJAVASCRIPT
- $result.="Stored away ".scalar(keys(%newrecord))." elements. \n";
- }
- return $result;
+ &commonJSfunctions($request);
+ $request->print($result);
+
+ my $checkhdgrade = ($ENV{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1 ) ? 'checked' : '';
+ my $checklastsub = $checkhdgrade eq '' ? 'checked' : '';
+ my $gradeTable=''."\n";
+ if ($ctr == 0) {
+ my $num_students=(scalar(keys(%$fullname)));
+ if ($num_students eq 0) {
+ $gradeTable=' There are no students currently enrolled.';
+ } else {
+ $gradeTable=' '.
+ 'No submissions found for this resource for any students. ('.$num_students.
+ ' checked for submissions ';
+ }
+ } elsif ($ctr == 1) {
+ $gradeTable =~ s/type=checkbox/type=checkbox checked/;
+ }
+ $gradeTable.=&show_grading_menu_form($symb,$url);
+ $request->print($gradeTable);
+ return '';
}
-#
-# --------------------------- show submissions of a student, option to grade --------
-sub submission {
- my ($request,$counter,$total) = @_;
+#---- Called from the listStudents routine
+# Displays the submissions for one student or a group of students
+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 (@stuchecked) {
+ my ($uname,$udom,$fullname) = split(/:/);
+ $ENV{'form.student'} = $uname;
+ $ENV{'form.userdom'} = $udom;
+ $ENV{'form.fullname'} = $fullname;
+ &submission($request,$ctr,$total);
+ $ctr++;
+ }
+ return '';
+}
- if ($counter == 0) {
- $request->print(<print(<
- function updateRadio(radioButton,formtextbox,formsel,wgt) {
- var pts = formtextbox.value;
- var resetbox =false;
- if (isNaN(pts) || pts < 0) {
- alert("A number equal or greater than 0 is expected. Entered value = "+pts);
+ function updateRadio(formname,id,weight) {
+ var gradeBox = eval("formname.GD_BOX"+id);
+ var radioButton = eval("formname.RADVAL"+id);
+ var oldpts = eval("formname.oldpts"+id+".value");
+ var pts = checkSolved(formname,id) == 'update' ? gradeBox.value : oldpts;
+ gradeBox.value = pts;
+ var resetbox = false;
+ if (isNaN(pts) || pts < 0) {
+ alert("A number equal or greater than 0 is expected. Entered value = "+pts);
+ for (var i=0; i weight) {
+ var resp = confirm("You entered a value ("+pts+
+ ") greater than the weight for the part. Accept?");
+ if (resp == false) {
+ gradeBox.value = "";
+ return;
+ }
+ }
+
for (var i=0; i
+SUBJAVASCRIPT
+}
+
+#--- javascript for essay type problem --
+sub sub_page_kw_js {
+ my $request = shift;
+ my $iconpath = $request->dir_config('lonIconsURL');
+ &commonJSfunctions($request);
+ $request->print(<
+
+//===================== Show list of keywords ====================
+ function keywords(formname) {
+ var nret = prompt("Keywords list, separated by a space. Add/delete to list if desired.",formname.keywords.value);
+ if (nret==null) return;
+ formname.keywords.value = nret;
+
+ formname.refresh.value = "on";
+ if (formname.keywords.value != "") {
+ formname.submit();
+ }
+ return;
}
- function writeBox(formrad,formsel,pts,wgt) {
- formrad.value = pts;
- updateSelect(formsel,pts,wgt);
+//===================== Script to view submitted by ==================
+ function viewSubmitter(submitter) {
+ document.SCORE.refresh.value = "on";
+ document.SCORE.NCT.value = "1";
+ document.SCORE.unamedom0.value = submitter;
+ document.SCORE.submit();
return;
}
- function updateSelect(formsel,pts,wgt) {
- if (pts == 0) {
- formsel[1].selected = true;
- }
- if (pts > 0 && pts < wgt) {
- formsel[4].selected = true;
+//===================== Script to add keyword(s) ==================
+ function getSel() {
+ if (document.getSelection) txt = document.getSelection();
+ else if (document.selection) txt = document.selection.createRange().text;
+ else return;
+ var cleantxt = txt.replace(new RegExp('([\\f\\n\\r\\t\\v ])+', 'g')," ");
+ if (cleantxt=="") {
+ alert("Please select a word or group of words from document and then click this link.");
+ return;
}
- if (pts == wgt) {
- formsel[0].selected = true;
+ var nret = prompt("Add selection to keyword list? Edit if desired.",cleantxt);
+ if (nret==null) return;
+ var curlist = document.SCORE.keywords.value;
+ document.SCORE.keywords.value = curlist+" "+nret;
+ document.SCORE.refresh.value = "on";
+ if (document.SCORE.keywords.value != "") {
+ document.SCORE.submit();
}
return;
}
+//====================== Script for composing message ==============
+ // preload images
+ img1 = new Image();
+ img1.src = "$iconpath/mailbkgrd.gif";
+ img2 = new Image();
+ img2.src = "$iconpath/mailto.gif";
+
+ function msgCenter(msgform,usrctr,fullname) {
+ var Nmsg = msgform.savemsgN.value;
+ savedMsgHeader(Nmsg,usrctr,fullname);
+ var subject = msgform.msgsub.value;
+ var rtrchk = eval("document.SCORE.includemsg"+usrctr);
+ var msgchk = rtrchk.value;
+ re = /msgsub/;
+ var shwsel = "";
+ if (re.test(msgchk)) { shwsel = "checked" }
+ subject = (document.SCORE.shownSub.value == 0 ? checkEntities(subject) : subject);
+ displaySubject(checkEntities(subject),shwsel);
+ for (var i=1; i<=Nmsg; i++) {
+ var testmsg = "savemsg"+i+",";
+ re = new RegExp(testmsg,"g");
+ shwsel = "";
+ if (re.test(msgchk)) { shwsel = "checked" }
+ var message = eval("document.SCORE.savemsg"+i+".value");
+ var shownOnce = eval("document.SCORE.shownOnce"+i+".value");
+ message = (shownOnce == 0 ? checkEntities(message) : message);
+ displaySavedMsg(i,message,shwsel); //I do not get it. w/o checkEntities on saved messages,
+ //any < is already converted to <, etc. However, only once!!
+ }
+ newmsg = eval("document.SCORE.newmsg"+usrctr+".value");
+ shwsel = "";
+ re = /newmsg/;
+ if (re.test(msgchk)) { shwsel = "checked" }
+ newMsg(newmsg,shwsel);
+ msgTail();
+ return;
+ }
+
+ function checkEntities(strx) {
+ if (strx.length == 0) return strx;
+ var orgStr = ["&", "<", ">", '"'];
+ var newStr = ["&", "<", ">", """];
+ var counter = 0;
+ while (counter < 4) {
+ strx = strReplace(strx,orgStr[counter],newStr[counter]);
+ counter++;
+ }
+ return strx;
+ }
+
+ function strReplace(strx, orgStr, newStr) {
+ return strx.split(orgStr).join(newStr);
+ }
+
+ function savedMsgHeader(Nmsg,usrctr,fullname) {
+ var height = 70*Nmsg+250;
+ var scrollbar = "no";
+ if (height > 600) {
+ height = 600;
+ scrollbar = "yes";
+ }
+// if (window.pWin) {window.pWin.close(); window.pWin=null}
+ var xpos = (screen.width-600)/2;
+ xpos = (xpos < 0) ? '0' : xpos;
+ var ypos = (screen.height-height)/2-30;
+ ypos = (ypos < 0) ? '0' : ypos;
+
+ pWin = window.open('', 'MessageCenter', 'toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=600,height='+height);
+ pWin.focus();
+ pDoc = pWin.document;
+ pDoc.write("");
+ pDoc.write("Message Central");
+
+ pDoc.write("
-JAVASCRIPT
+SUBJAVASCRIPT
}
- (my $url=$ENV{'form.url'})=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
- if ($ENV{'form.student'} eq '') { &moreinfo($request,"Need student login id"); return ''; }
- my ($uname,$udom) = &finduser($ENV{'form.student'});
- if ($uname eq '') { &moreinfo($request,"Unable to find student"); return ''; }
-
- 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) {
- $request->print('
Submission Record
');
- }
+#--- displays the grading box, used in essay type problem and grading by page/sequence
+sub gradeBox {
+ my ($request,$symb,$uname,$udom,$counter,$partid,$record) = @_;
+
+ my $checkIcon = '';
+
+ my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb,$udom,$uname);
+ my $wgtmsg = ($wgt > 0 ? '(problem weight)' :
+ 'problem weight assigned by computer');
+ $wgt = ($wgt > 0 ? $wgt : '1');
+ my $score = ($$record{'resource.'.$partid.'.awarded'} eq '' ?
+ '' : $$record{'resource.'.$partid.'.awarded'}*$wgt);
+ my $result=''."\n";
+
+ $result.='
'.
+ 'Part '.$partid.' Points:
'."\n";
+
+ my $ctr = 0;
+ $result.='
'."\n"; # display radio buttons in a nice table 10 across
+ while ($ctr<=$wgt) {
+ $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) || parseFloat(point) < 0) {
+ alert("A number equal or greater than 0 is expected. Entered value = "+parseFloat(point));
+ var resetbox = false;
+ for (var i=0; i parseFloat(weight)) {
+ var resp = confirm("You entered a value ("+parseFloat(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 parseFloat(weight)) {
+ var resp = confirm("You entered a value ("+parseFloat(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);
- #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.='';
+
+ #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(<print(<
-
Uploading Class Grades for resource $url
+
Uploading Class Grades
+$result
Identify fields
Total number of records found in file: $distotal
@@ -947,34 +2474,37 @@ to this page if the data selected is ins
value="$ENV{'form.upfile_associate'}" />
+
+
ENDPICK
- return '';
+ $request->print(&show_grading_menu_form($symb,$url));
+ 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 +2513,1171 @@ 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);
+ my ($table) = &showResourceInfo($url,$ENV{'form.probTitle'});
+ $result.=$table;
+ $result.='
'."\n";
+ $result.='
'."\n";
+ $result.=' Specify a file containing the class scores for current resource'.
+ '.