'.
''.
@@ -417,8 +429,13 @@ LISTJAVASCRIPT
'onClick="javascript:checkSelect(this.form.stuinfo);" '.
'value="'.$viewgrade.'" />'."\n";
if ($ctr == 0) {
- $gradeTable=' '.
- 'No submission found for this resource. ';
+ 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/;
}
@@ -626,13 +643,13 @@ SUBJAVASCRIPT
#--- javascript for essay type problem --
sub sub_page_kw_js {
my $request = shift;
+ my $iconpath = $request->dir_config('lonIconsURL');
$request->print(<
//===================== Show list of keywords ====================
function keywords(keyform) {
- var keywds = keyform.value;
- var nret = prompt("Keywords list, separated by a space. Add/delete to list if desired.",keywds);
+ var nret = prompt("Keywords list, separated by a space. Add/delete to list if desired.",keyform.value);
if (nret==null) return;
keyform.value = nret;
@@ -674,6 +691,12 @@ sub sub_page_kw_js {
}
//====================== 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);
@@ -701,91 +724,102 @@ sub sub_page_kw_js {
return;
}
+// var pWin = null;
function savedMsgHeader(Nmsg,usrctr,fullname) {
- var height = 50*Nmsg+250;
+ var height = 70*Nmsg+250;
var scrollbar = "no";
if (height > 600) {
height = 600;
scrollbar = "yes";
}
-/* if (window.pWin)
- window.pWin.close(); */
+// if (window.pWin) {window.pWin.close(); window.pWin=null}
pWin = window.open('', 'MessageCenter', 'toolbar=no,location=no,scrollbars='+scrollbar+',screenx=70,screeny=75,width=600,height='+height);
- pWin.document.write("");
- pWin.document.write("Message Central ");
-
- pWin.document.write("
@@ -974,7 +1013,7 @@ sub submission {
(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)));
@@ -985,6 +1024,9 @@ sub submission {
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");
@@ -1015,8 +1057,7 @@ sub submission {
$request->print('
';
- $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 '';
}
@@ -2767,6 +2846,318 @@ sub updateGradeByPage {
#
#-------------------------------------------------------------------
+#--------------------Scantron Grading-----------------------------------
+#
+#------ start of section for handling grading by page/sequence ---------
+
+sub defaultFormData {
+ my ($symb,$url)=@_;
+ return '
+ '."\n".
+ ' '."\n".
+ ' '."\n".
+ ' '."\n";
+}
+
+sub getSequenceDropDown {
+ my ($request,$symb)=@_;
+ my $result=''."\n";
+ my ($titles,$symbx) = &getSymbMap($request);
+ my ($curpage,$type,$mapId) = ($symb =~ /(.*?\.(page|sequence))___(\d+)___/);
+ my $ctr=0;
+ foreach (@$titles) {
+ my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
+ $result.=''.$showtitle.' '."\n";
+ $ctr++;
+ }
+ $result.= ' ';
+ return $result;
+}
+
+sub scantron_uploads {
+ if (!-e $Apache::lonnet::perlvar{'lonScansDir'}) { return ''};
+ my $result= '';
+ opendir(DIR,$Apache::lonnet::perlvar{'lonScansDir'});
+ my @files=sort(readdir(DIR));
+ foreach my $filename (@files) {
+ if ($filename eq '.' or $filename eq '..') { next; }
+ $result.="$filename \n";
+ }
+ closedir(DIR);
+ $result.=" ";
+ return $result;
+}
+
+sub scantron_scantab {
+ my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
+ my $result=''."\n";
+ foreach my $line (<$fh>) {
+ my ($name,$descrip)=split(/:/,$line);
+ if ($name =~ /^\#/) { next; }
+ $result.=''.$descrip.' '."\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{'scantron.CODE'}=substr($data,$$scantron_config{'CODEstart'}-1,
+ $$scantron_config{'CODElength'});
+ } else {
+ #FIXME interpret first N questions
+ }
+ }
+ $record{'scantron.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'})='';
+ if (length($currentquest) < $$scantron_config{'Qlength'}) { next; }
+ 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).
+ '-'.$currentquest.'-'.$questnum.' ');
+ }
+ if (length($array[0]) eq $$scantron_config{'Qlength'}) {
+ $record{"scantron.$questnum.answer"}='';
+ } else {
+ $record{"scantron.$questnum.answer"}=$alphabet[length($array[0])];
+ }
+ }
+ $record{'scantron.maxquest'}=$questnum;
+ return \%record;
+}
+
+sub scantron_add_delay {
+}
+
+sub scantron_find_student {
+ my ($scantron_record,$idmap)=@_;
+ my $scanID=$$scantron_record{'scantron.ID'};
+ foreach my $id (keys(%$idmap)) {
+ Apache->request->print('checking studnet -'.$id.'- againt -'.$scanID.'- ');
+ if (lc($id) eq lc($scanID)) { Apache->request->print('success');return $$idmap{$id}; }
+ }
+ return undef;
+}
+
+sub scantron_filter {
+ my ($curres)=@_;
+ if (ref($curres) && $curres->is_problem() && !$curres->randomout) {
+ return 1;
+ }
+ return 0;
+}
+
+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 @scanlines=<$scanlines>;
+ my $classlist=&Apache::loncoursedata::get_classlist();
+ my %idmap=&username_to_idmap($classlist);
+ my $navmap=Apache::lonnavmaps::navmap->new($ENV{'request.course.fn'}.'.db',$ENV{'request.course.fn'}.'_parms.db',1, 1);
+ my $map=$navmap->getResourceByUrl($sequence);
+ my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
+ $r->print("geto ".scalar(@resources)." ");
+ my $result= <
+
+ $default_form_data
+SCANTRONFORM
+ $r->print($result);
+
+ my @delayqueue;
+ my $totalcorrect;
+ my $totalincorrect;
+
+ my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,
+ 'Scantron Status','Scantron Progress',scalar(@scanlines));
+ foreach my $line (@scanlines) {
+ my $studentcorrect;
+ my $studentincorrect;
+
+ chomp($line);
+ 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');
+ }
+ $r->print('doing studnet'.$uname.' ');
+ ($uname,$udom)=split(/:/,$uname);
+ &Apache::lonnet::delenv('form.counter');
+ &Apache::lonnet::appenv(%$scan_record);
+# &Apache::lonhomework::showhash(%ENV);
+ $Apache::lonxml::debug=1;
+ &Apache::lonxml::debug("line is $line");
+
+ my $i=0;
+ foreach my $resource (@resources) {
+ $i++;
+ my $result=&Apache::lonnet::ssi($resource->src(),
+ ('submitted' =>'scantron',
+ 'grade_target' =>'grade',
+ 'grade_username'=>$uname,
+ 'grade_domain' =>$udom,
+ 'grade_courseid'=>$ENV{'request.course.id'},
+ 'grade_symb' =>$resource->symb()));
+ my %score=&Apache::lonnet::restore($resource->symb(),
+ $ENV{'request.course.id'},
+ $udom,$uname);
+ foreach my $part ($resource->{PARTS}) {
+ if ($score{'resource.'.$part.'.solved'} =~ /^correct/) {
+ $studentcorrect++;
+ $totalcorrect++;
+ } else {
+ $studentincorrect++;
+ $totalincorrect++;
+ }
+ }
+ $r->print(''.
+ $resource->symb().'-'.
+ $resource->src().'-'.' result is'.$result);
+ &Apache::lonhomework::showhash(%score);
+ # if ($i eq 3) {last;}
+ }
+ &Apache::lonnet::delenv('form.counter');
+ &Apache::lonnet::delenv('scantron\.');
+ &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
+ 'last student Who got a '.$studentcorrect.' correct and '.
+ $studentincorrect.' incorrect. The class has gotten '.
+ $totalcorrect.' correct and '.$totalincorrect.' incorrect');
+ last;
+ #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
+ #}
+ }
+ $Apache::lonxml::debug=0;
+ 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
+
+ $navmap->untieHashes();
+}
+#-------- end of section for handling grading scantron forms -------
+#
+#-------------------------------------------------------------------
+
+
#-------------------------- Menu interface -------------------------
#
#--- Show a Grading Menu button - Calls the next routine ---
@@ -2775,40 +3166,40 @@ sub show_grading_menu_form {
my $result.=''."\n".
' '."\n".
' '."\n".
- ' '."\n".
- ' '."\n".
+ ' '."\n".
' '."\n".
' '."\n".
' '."\n";
return $result;
}
+# -- Retrieve choices for grading form
+sub savedState {
+ my %savedState = ();
+ if ($ENV{'form.saveState'}) {
+ foreach (split(/:/,$ENV{'form.saveState'})) {
+ my ($key,$value) = split(/=/,$_,2);
+ $savedState{$key} = $value;
+ }
+ }
+ return \%savedState;
+}
+
#--- Displays the main menu page -------
sub gradingmenu {
my ($request) = @_;
my ($symb,$url)=&get_symb_and_url($request);
if (!$symb) {return '';}
+ my $probTitle = &Apache::lonnet::gettitle($symb);
$request->print(<
function checkChoice(formname) {
var cmd = formname.command;
- formname.lastCmd.value = radioSelection(formname.command);
- formname.lastSec.value = pullDownSelection(formname.section);
- if (cmd[0].checked || cmd[1].checked || cmd[2].checked) {
- formname.submit();
- }
-
- if (cmd[3].checked) {
- var url = "/adm/grades?command=csvform&symb="+formname.symb.value+"&url="+formname.url.value;
- var options = "width=620,height=340,screenx=70,screeny=75,";
- options += "resizable=no,scrollbars=no,status=no,";
- options += "menubar=no,toolbar=no,location=no,directories=no";
- var newWin = window.open(url, "CSVFile", options);
- newWin.focus();
- }
-
- if (cmd[4].checked) {
+ formname.saveState.value = "saveCmd="+radioSelection(cmd)+":saveSec="+pullDownSelection(formname.section)+
+ ":saveSub="+radioSelection(formname.submitonly)+":saveStatus="+pullDownSelection(formname.status);
+ if (cmd[0].checked || cmd[1].checked || cmd[2].checked || cmd[3].checked || cmd[4].checked) formname.submit();
+ if (cmd[5].checked) {
if (!checkReceiptNo(formname,'notOK')) { return false;}
formname.submit();
}
@@ -2825,35 +3216,43 @@ sub gradingmenu {
formname.receipt.focus();
return false;
}
- formname.command[4].checked = true;
+ formname.command[5].checked = true;
return true;
}
function radioSelection(radioButton) {
var selection=null;
- for (var i=0; i 1) {
+ for (var i=0; i 1) {
+ for (var i=0; i
GRADINGMENUJS
- my $probTitle = &Apache::lonnet::metadata($ENV{'form.url'},'title');
my $result=' Manual Grading/View Submission '.
''.
- 'Problem: '.$probTitle.' ';
+ 'Problem: '.$probTitle.' '."\n";
my ($partlist,$handgrade) = &response_type($url);
my ($resptype,$hdgrade)=('','no');
for (sort keys(%$handgrade)) {
@@ -2864,11 +3263,14 @@ GRADINGMENUJS
'Type: '.$responsetype.' '.
'Handgrade: '.$handgrade.' ';
}
- $result.='
';
+ $result.='