--- loncom/homework/grades.pm 2003/03/11 19:32:02 1.71
+++ loncom/homework/grades.pm 2003/04/01 05:21:48 1.82
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Grading handler
#
-# $Id: grades.pm,v 1.71 2003/03/11 19:32:02 ng Exp $
+# $Id: grades.pm,v 1.82 2003/04/01 05:21:48 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -113,7 +113,7 @@ sub response_type {
#--- Dumps the class list with usernames,list of sections,
#--- section, ids and fullnames for each user.
sub getclasslist {
- my ($getsec,$hideexpired) = @_;
+ my ($getsec,$filterlist) = @_;
my $classlist=&Apache::loncoursedata::get_classlist();
# Bail out if we were unable to get the classlist
return if (! defined($classlist));
@@ -124,11 +124,13 @@ sub getclasslist {
# the following undefs are for 'domain', and 'username' respectively.
my (undef,undef,$end,$start,$id,$section,$fullname,$status)=
@{$classlist->{$_}};
- # still a student?
- if (($hideexpired) && ($status ne 'Active')) {
- delete ($classlist->{$_});
- next;
- }
+ # 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}++;
@@ -209,6 +211,8 @@ sub jscriptNform {
$jscript.= '
';
-# $result.='To assign the same score for all the students use the radio buttons or '.
-# 'text box below. To assign scores individually fill in the score boxes for '.
-# 'each student in the table below. A part that has already '.
-# 'been graded does not get changed using the radio buttons or text box. '.
-# 'If needed, it has to be changed individually.';
-# $result.='
';
#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'});
@@ -1813,7 +1850,7 @@ sub viewgrades {
#get info for each student
#list all the students - with points and grade status
- my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'0');
+ 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,$udom) = split(/:/);
@@ -1884,10 +1921,8 @@ sub editgrades {
my $symb=$ENV{'form.symb'};
my $url =$ENV{'form.url'};
my $title='
'."\n".
+ &show_grading_menu_form ($symb,$url);
my $msg = 'Number of records updated = '.$rec_update.
' for '.$count.' student'.($count <= 1 ? '' : 's').'. '.
'Total number of students = '.$ENV{'form.total'}.' ';
@@ -2109,8 +2145,7 @@ sub csvuploadmap_header {
}
my $result='
';
my ($partlist,$handgrade) = &response_type($url);
my ($resptype,$hdgrade)=('','no');
for (sort keys(%$handgrade)) {
@@ -2141,6 +2176,8 @@ to this page if the data selected is ins
value="$ENV{'form.upfile_associate'}" />
+
+
'."\n";
-
- $result.='
'."\n";
- $result.='
'."\n";
- $result.=' Specify a file containing the class scores for above resource
'."\n";
- return $result;
-}
-
+#-------------- Next few routines handles grading by page/sequence
+#
+#--- Select a page/sequence and a student to grade
sub pickStudentPage {
my ($request) = shift;
@@ -2455,8 +2323,7 @@ sub pickStudentPage {
LISTJAVASCRIPT
- my ($symb,$url) = &get_symb_and_url();
+ 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'};
@@ -2497,9 +2370,9 @@ LISTJAVASCRIPT
my $result='
'.
'Manual Grading by Page or Sequence
';
- $result.='
'." \n";
+ $result.='
'."\n";
$result.=' Problems from:
'."\n".
' 0);
+ $seen{$_}++;
+ push @correctParts,$_;
+ }
+ return \@correctParts;
+}
+
sub updateGradeByPage {
my ($request) = shift;
@@ -2767,7 +2668,7 @@ sub updateGradeByPage {
my $cnum = $ENV{"course.$ENV{'request.course.id'}.num"};
my $getsec = $ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'};
my $pageTitle = $ENV{'form.page'};
- my (undef,undef,$fullname) = &getclasslist($getsec,'0');
+ my (undef,undef,$fullname) = &getclasslist($getsec,'1');
my ($uname,$udom) = split(/:/,$ENV{'form.student'});
my $result='
'.$ENV{'form.title'}.'
';
@@ -2776,8 +2677,7 @@ sub updateGradeByPage {
$request->print($result);
- my $navmap = Apache::lonnavmaps::navmap-> new(
- $ENV{'request.course.fn'}.'.db',
+ my $navmap = Apache::lonnavmaps::navmap-> new($ENV{'request.course.fn'}.'.db',
$ENV{'request.course.fn'}.'_parms.db',1, 1);
my ($mapUrl, $id, $resUrl) = split(/___/, $ENV{'form.page'});
my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps
@@ -2801,7 +2701,7 @@ sub updateGradeByPage {
if (ref($curRes) && $curRes->is_problem() && !$curRes->randomout) {
my $parts = $curRes->parts();
- if (scalar(@{$parts}) > 1) { shift @{$parts}; }
+ $parts = &temp_parts_fix($parts); # remove line when lonnavmap is fixed
my $title = $curRes->compTitle();
my $symbx = $curRes->symb();
$studentTable.='
'.$question.
@@ -2844,11 +2744,11 @@ sub updateGradeByPage {
}
$newrecord{'resource.'.$partid.'.awarded'} = $partial if $partial ne '';
$newrecord{'resource.'.$partid.'.solved'} = $score;
+ $newrecord{'resource.'.$partid.'.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
$changeflag++;
}
if (scalar(keys(%newrecord)) > 0) {
- $newrecord{'resource.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
&Apache::lonnet::cstore(\%newrecord,$symbx,$ENV{'request.course.id'},
$udom,$uname);
}
@@ -2860,53 +2760,517 @@ sub updateGradeByPage {
$curRes = $iterator->next();
$ctr++;
}
- $navmap->init();
$studentTable.='
';
- $studentTable.=($changeflag == 0 ? 'No score was changed or updated.' :
- 'The scores were changed for '.
- $changeflag.' problem'.($changeflag == 1 ? '.' : 's.'));
$studentTable.=&show_grading_menu_form($ENV{'form.symb'},$ENV{'form.url'});
- $request->print($studentTable);
+ my $grademsg=($changeflag == 0 ? 'No score was changed or updated.' :
+ 'The scores were changed for '.
+ $changeflag.' problem'.($changeflag == 1 ? '.' : 's.'));
+ $request->print($grademsg.$studentTable);
return '';
}
+#-------- end of section for handling grading by page/sequence ---------
+#
+#-------------------------------------------------------------------
-#--- Form to input a receipt number ---
-sub verifyReceipt_form {
- my ($symb,$url) = @_;
- my $result = ''."\n";
+#--------------------Scantron Grading-----------------------------------
+#
+#------ start of section for handling grading by page/sequence ---------
+
+sub defaultFormData {
+ my ($symb,$url)=@_;
+ return '
+ '."\n".
+ ''."\n".
+ ''."\n".
+ ''."\n";
+}
- my $hostver=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'});
+sub getSequenceDropDown {
+ my ($request,$symb)=@_;
+ my $result='';
+ return $result;
+}
- $result.='
'."\n";
- $result.='
'."\n";
- $result.=' Verify a Submission Receipt Issued by this Server
'."\n";
- $result.='
'."\n";
- $result.='
'."\n";
- $result.=' '.$hostver.'- '."\n";
- $result.=' '."\n";
- $result.=''."\n";
- if ($ENV{'form.url'}) {
- $result.='';
+sub scantron_uploads {
+ if (!-e $Apache::lonnet::perlvar{'lonScansDir'}) { return ''};
+ my $result= '";
+ return $result;
+}
+
+sub scantron_scantab {
+ my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
+ my $result='
';
- $result.='
'."\n";
- $result.='
'."\n";
+ $result.=''."\n";
+
+ return $result;
+}
+
+sub scantron_selectphase {
+ my ($r) = @_;
+ my ($symb,$url)=&get_symb_and_url($r);
+ if (!$symb) {return '';}
+ my $sequence_selector=&getSequenceDropDown($r,$symb);
+ my $default_form_data=&defaultFormData($symb,$url);
+ my $grading_menu_button=&show_grading_menu_form($symb,$url);
+ my $file_selector=&scantron_uploads();
+ my $format_selector=&scantron_scantab();
+ my $result;
+ $result.= <
+
+ $default_form_data
+
+
+
+
+
+
+ Specify file location and which Folder/Sequence to grade
+
+
+
+
+ Sequence to grade: $sequence_selector
+
+
+
+
+ Filename of scoring office file: $file_selector
+
+
+
+
+ Format of data file: $format_selector
+
+
+
+
+
+
+
+
+$grading_menu_button
+SCANTRONFORM
+
+ return $result;
+}
+
+sub get_scantron_config {
+ my ($which) = @_;
+ my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
+ my %config;
+ foreach my $line (<$fh>) {
+ my ($name,$descrip)=split(/:/,$line);
+ if ($name ne $which ) { next; }
+ chomp($line);
+ my @config=split(/:/,$line);
+ $config{'name'}=$config[0];
+ $config{'description'}=$config[1];
+ $config{'CODElocation'}=$config[2];
+ $config{'CODEstart'}=$config[3];
+ $config{'CODElength'}=$config[4];
+ $config{'IDstart'}=$config[5];
+ $config{'IDlength'}=$config[6];
+ $config{'Qstart'}=$config[7];
+ $config{'Qlength'}=$config[8];
+ $config{'Qoff'}=$config[9];
+ $config{'Qon'}=$config[10];
+ last;
+ }
+ return %config;
+}
+
+sub username_to_idmap {
+ my ($classlist)= @_;
+ my %idmap;
+ foreach my $student (keys(%$classlist)) {
+ $idmap{$classlist->{$student}->[&Apache::loncoursedata::CL_ID]}=
+ $student;
+ }
+ return %idmap;
+}
+
+sub scantron_parse_scanline {
+ my ($line,$scantron_config)=@_;
+ my %record;
+ my $questions=substr($line,$$scantron_config{'Qstart'}-1);
+ my $data=substr($line,0,$$scantron_config{'Qstart'}-1);
+ if ($$scantron_config{'CODElocation'} ne 0) {
+ if ($$scantron_config{'CODElocation'} < 0) {
+ $record{'CODE'}=substr($data,$$scantron_config{'CODEstart'}-1,
+ $$scantron_config{'CODElength'});
+ } else {
+ #FIXME interpret first N questions
+ }
+ }
+ $record{'ID'}=substr($data,$$scantron_config{'IDstart'}-1,
+ $$scantron_config{'IDlength'});
+ my @alphabet=('A'..'Z');
+ my $questnum=0;
+ while ($questions) {
+ $questnum++;
+ my $currentquest=substr($questions,0,$$scantron_config{'Qlength'});
+ substr($questions,0,$$scantron_config{'Qlength'})='';
+ my (@array)=split(/$$scantron_config{'Qon'}/,$currentquest);
+ if (scalar(@array) gt 2) {
+ #FIXME do something intelligent with double bubbles
+ Apache->request->print(" Wha!!! ".scalar(@array).
+ '-'.$questions.'-'.$currentquest.'-'.$questnum.
+ '-'.length($questions).
+ '-'.$line.'-'.length($line).'-'.
+ '-'.$data.'-'.length($data).'-'.
+ ' ');
+ }
+ if (length($array[0]) eq $$scantron_config{'Qlength'}) {
+ $record{"$questnum.answer"}='';
+ } else {
+ $record{"$questnum.answer"}=$alphabet[length($array[0])];
+ }
+ }
+ $record{'maxquest'}=$questnum;
+ $Apache::lonxml::debug=1;
+ &Apache::lonhomework::showhash(%record);
+ $Apache::lonxml::debug=0;
+ return %record;
+}
+
+sub scantron_add_delay {
+}
+
+sub scantron_find_student {
+}
+
+sub scantron_process_students {
+ my ($r) = @_;
+ my (undef,undef,$sequence)=split(/___/,$ENV{'form.selectpage'});
+ my ($symb,$url)=&get_symb_and_url($r);
+ if (!$symb) {return '';}
+ my $default_form_data=&defaultFormData($symb,$url);
+
+ my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'});
+ my $scanlines=Apache::File->new($Apache::lonnet::perlvar{'lonScansDir'}."/$ENV{'form.scantron_selectfile'}");
+ my $classlist=&Apache::loncoursedata::get_classlist();
+ my %idmap=&username_to_idmap($classlist);
+ my $result= <
+
+ $default_form_data
+SCANTRONFORM
+ $r->print($result);
+
+ my @delayqueue;
+
+ foreach my $line (<$scanlines>) {
+ my $scan_record=&scantron_parse_scanline($line,\%scantron_config);
+ my ($uname,$udom);
+ if ($uname=&scantron_find_student($scan_record,\%idmap)) {
+ &scantron_add_delay(\@delayqueue,$line,
+ 'Unable to find a student that matches');
+ }
+ ($uname,$udom)=split(/:/,$uname);
+ #FIXME
+ #get iterator for $sequence
+ #foreach question 'submit' the students answer to the server
+ # through grade target {
+ # generate data to pass back that includes grade recevied
+ #}
+ }
+ foreach my $delay (@delayqueue) {
+ #FIXME
+ #print out each delayed student with interface to select how
+ # to repair student provided info
+ #Expected errors include
+ # 1 bad/no stuid/username
+ # 2 invalid bubblings
+
+ }
+ #FIXME
+ # if delay queue exists 2 submits one to process delayed students one
+ # to ignore delayed students, possibly saving the delay queue for later
+
+}
+#-------- end of section for handling grading scantron forms -------
+#
+#-------------------------------------------------------------------
+
+
+#-------------------------- Menu interface -------------------------
+#
+#--- Show a Grading Menu button - Calls the next routine ---
+sub show_grading_menu_form {
+ my ($symb,$url)=@_;
+ my $result.='