--- loncom/homework/grades.pm 2004/09/29 05:45:34 1.204.2.7 +++ loncom/homework/grades.pm 2006/02/07 14:18:18 1.311 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.204.2.7 2004/09/29 05:45:34 albertel Exp $ +# $Id: grades.pm,v 1.311 2006/02/07 14:18:18 banghart Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,16 +25,6 @@ # # http://www.lon-capa.org/ # -# 2/9,2/13 Guy Albertelli -# 6/8 Gerd Kortemeyer -# 7/26 H.K. Ng -# 8/20 Gerd Kortemeyer -# Year 2002 -# June-August H.K. Ng -# Year 2003 -# February, March H.K. Ng -# July, H. K. Ng -# package Apache::grades; use strict; @@ -90,8 +80,8 @@ sub getpartlist { # --- Get the symbolic name of a problem and the url sub get_symb_and_url { my ($request,$silent) = @_; - (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))); + (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 '') { if (!$silent) { $request->print("Unable to handle ambiguous references:$url:."); @@ -101,34 +91,15 @@ sub get_symb_and_url { 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 ($uname,$udom) = @_; - my %name=&Apache::lonnet::get('environment', ['lastname','generation', - 'firstname','middlename'], - $udom,$uname); - my $fullname; - my ($tmp) = keys(%name); - if ($tmp !~ /^(con_lost|error|no_such_host)/i) { - $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; -} - #--- Format fullname, username:domain if different for display #--- Use anywhere where the student names are listed sub nameUserString { my ($type,$fullname,$uname,$udom) = @_; if ($type eq 'header') { - return ' Fullname (Username) '; + return ' Fullname (Username)'; } else { return ' '.$fullname.' ('.$uname. - ($ENV{'user.domain'} eq $udom ? '' : ' ('.$udom.')').')'; + ($env{'user.domain'} eq $udom ? '' : ' ('.$udom.')').')'; } } @@ -136,7 +107,7 @@ sub nameUserString { #--- Indicate if a response type is coded handgraded or not. --- sub response_type { my ($url,$symb) = shift; - $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url))) if ($symb eq ''); + $symb=($env{'form.symb'} ne '' ? $env{'form.symb'} : (&Apache::lonnet::symbread($url))) if ($symb eq ''); my $allkeys = &Apache::lonnet::metadata($url,'keys'); my %vPart; foreach my $partid (&Apache::loncommon::get_env_multiple('form.vPart')) { @@ -170,11 +141,10 @@ sub response_type { sub get_display_part { my ($partID,$url,$symb)=@_; if (!defined($symb) || $symb eq '') { - $symb=$ENV{'form.symb'}; + $symb=$env{'form.symb'}; if ($symb eq '') { $symb=&Apache::lonnet::symbread($url) } } my $display=&Apache::lonnet::EXT('resource.'.$partID.'.display',$symb); - &Apache::lonnet::logthis("\nsymb $symb\n url $url\npartID $partID\ndisplay $display \n"); if (defined($display) and $display ne '') { $display.= " (id $partID)"; } else { @@ -182,6 +152,7 @@ sub get_display_part { } return $display; } + #--- Show resource title #--- and parts and response type sub showResourceInfo { @@ -229,7 +200,7 @@ sub get_order { ('grade_domain' => $udom), ('grade_symb' => $symb), ('grade_courseid' => - $ENV{'request.course.id'}), + $env{'request.course.id'}), ('grade_username' => $uname)); (undef,$subresult)=split(/_HASH_REF__/,$subresult,2); my %analyze=&Apache::lonnet::str2hash($subresult); @@ -300,20 +271,25 @@ sub cleanRecord { ''.$grayFont.'Option ID'. $grayFont.$bottomrow.''.''; } elsif ($response eq 'essay') { - if (! exists ($ENV{'form.'.$symb})) { + 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'}); + $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. + 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. } $answer =~ s-\n-
-g; return '

'.&keywords_highlight($answer).'
'; + } elsif ( $response eq 'organic') { + my $result='Smile representation: "'.$answer.'"'; + my $jme=$record->{$version."resource.$partid.$respid.molecule"}; + $result.=&Apache::chemresponse::jme_img($jme,$answer,400); + return $result; } return $answer; } @@ -358,34 +334,52 @@ COMMONJSFUNCTIONS #--- section, ids and fullnames for each user. sub getclasslist { my ($getsec,$filterlist) = @_; - $getsec = $getsec eq '' ? 'all' : $getsec; + my @getsec; + if (!ref($getsec)) { + if ($getsec ne '' && $getsec ne 'all') { + @getsec=($getsec); + } + } else { + @getsec=@{$getsec}; + } + if (grep(/^all$/,@getsec)) { undef(@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->{$_}}; + foreach my $student (keys(%$classlist)) { + my $end = + $classlist->{$student}->[&Apache::loncoursedata::CL_END()]; + my $start = + $classlist->{$student}->[&Apache::loncoursedata::CL_START()]; + my $id = + $classlist->{$student}->[&Apache::loncoursedata::CL_ID()]; + my $section = + $classlist->{$student}->[&Apache::loncoursedata::CL_SECTION()]; + my $fullname = + $classlist->{$student}->[&Apache::loncoursedata::CL_FULLNAME()]; + my $status = + $classlist->{$student}->[&Apache::loncoursedata::CL_STATUS()]; # filter students according to status selected - if ($filterlist && $ENV{'form.Status'} ne 'Any') { - if ($ENV{'form.Status'} ne $status) { - delete ($classlist->{$_}); + if ($filterlist && $env{'form.Status'} ne 'Any') { + if ($env{'form.Status'} ne $status) { + delete ($classlist->{$student}); next; } } - $section = ($section ne '' ? $section : 'no'); + $section = ($section ne '' ? $section : 'none'); if (&canview($section)) { - if ($getsec eq 'all' || $getsec eq $section) { + if (!@getsec || grep(/^\Q$section\E$/,@getsec)) { $sections{$section}++; - $fullnames{$_}=$fullname; + $fullnames{$student}=$fullname; } else { - delete($classlist->{$_}); + delete($classlist->{$student}); } } else { - delete($classlist->{$_}); + delete($classlist->{$student}); } } my %seen = (); @@ -436,7 +430,7 @@ sub canview { #--- 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 %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname); my %partstatus = (); foreach (@$partlist) { my ($status,undef) = split(/_/,$record{"resource.$_.solved"},2); @@ -463,9 +457,9 @@ sub jscriptNform { $jscript.= '
'."\n". ''."\n". ''."\n". - ''."\n". - ''."\n". - ''."\n". + ''."\n". + ''."\n". + ''."\n". ''."\n". ''."\n". ''."\n". @@ -486,6 +480,10 @@ sub most_similar { $uessay=~s/\W+/ /gs; +# ignore empty submissions (occuring when only files are sent) + + unless ($uessay=~/\w+/) { return ''; } + # these will be returned. Do not care if not at least 50 percent similar my $limit=0.6; my $sname=''; @@ -526,28 +524,34 @@ sub most_similar { sub verifyreceipt { my $request = shift; - my $courseid = $ENV{'request.course.id'}; + my $courseid = $env{'request.course.id'}; my $receipt = &Apache::lonnet::recprefix($courseid).'-'. - $ENV{'form.receipt'}; + $env{'form.receipt'}; $receipt =~ s/[^\-\d]//g; - my $url = $ENV{'form.url'}; - my $symb = $ENV{'form.symb'}; + my $url = $env{'form.url'}; + my $symb = $env{'form.symb'}; unless ($symb) { $symb = &Apache::lonnet::symbread($url); } my $title.='

Verifying Submission Receipt '. $receipt.'

'."\n". - 'Resource: '.$ENV{'form.probTitle'}.'

'."\n"; + 'Resource: '.$env{'form.probTitle'}.'

'."\n"; my ($string,$contents,$matches) = ('','',0); my (undef,undef,$fullname) = &getclasslist('all','0'); my $receiptparts=0; - if ($ENV{"course.$courseid.receiptalg"} eq 'receipt2') { $receiptparts=1; } + if ($env{"course.$courseid.receiptalg"} eq 'receipt2') { $receiptparts=1; } my $parts=['0']; if ($receiptparts) { ($parts)=&response_type($url,$symb); } - foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) { + foreach (sort + { + if (lc($$fullname{$a}) ne lc($$fullname{$b})) { + return (lc($$fullname{$a}) cmp lc($$fullname{$b})); + } + return $a cmp $b; + } (keys(%$fullname))) { my ($uname,$udom)=split(/\:/); foreach my $part (@$parts) { if ($receipt eq &Apache::lonnet::ireceipt($uname,$udom,$courseid,$symb,$part)) { @@ -593,19 +597,19 @@ 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 $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'},($ENV{'form.showgrading'} eq 'yes')); + my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($url,$env{'form.probTitle'},($env{'form.showgrading'} eq 'yes')); $request->print(< @@ -643,40 +647,40 @@ LISTJAVASCRIPT &commonJSfunctions($request); $request->print($result); - my $checkhdgrade = ($ENV{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1 ) ? 'checked' : ''; + my $checkhdgrade = ($env{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1 ) ? 'checked' : ''; my $checklastsub = $checkhdgrade eq '' ? 'checked' : ''; my $gradeTable=''. "\n".$table. - ' View Problem Text: no '."\n". - ' one student '."\n". - ' all students
'."\n". - ' View Answer: no '."\n". - ' one student '."\n". - ' all students
'."\n". + ' View Problem Text: '."\n". + ''."\n". + '
'."\n". + ' View Answer: '."\n". + ''."\n". + '
'."\n". ' Submissions: '."\n"; - if ($ENV{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1) { - $gradeTable.=' essay part only'."\n"; + if ($env{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1) { + $gradeTable.=''."\n"; } - my $saveStatus = $ENV{'form.Status'} eq '' ? 'Active' : $ENV{'form.Status'}; - $ENV{'form.Status'} = $saveStatus; + my $saveStatus = $env{'form.Status'} eq '' ? 'Active' : $env{'form.Status'}; + $env{'form.Status'} = $saveStatus; - $gradeTable.=' last submission only'."\n". - ' last submission & parts info'."\n". - ' by dates and submissions'."\n". - ' all details'."\n". + $gradeTable.=''."\n". + ''."\n". + ''."\n". + ''."\n". ''."\n". ''."\n". - '
'."\n". - '
'."\n". - ''."\n". - ''."\n". + '
'."\n". + '
'."\n". + ''."\n". + ''."\n". ''."\n". ''."\n". ''."\n"; - if (exists($ENV{'form.gradingMenu'}) && exists($ENV{'form.Status'})) { - $gradeTable.=''."\n"; + if (exists($env{'form.gradingMenu'}) && exists($env{'form.Status'})) { + $gradeTable.=''."\n"; } else { $gradeTable.='Student Status: '. &Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,'javascript:reLoadList(this.form);').'
'; @@ -685,23 +689,31 @@ LISTJAVASCRIPT $gradeTable.='To '.lc($viewgrade).' a submission or a group of submissions, click on the check box(es) '. 'next to the student\'s name(s). Then click on the Next button.
'."\n". ''."\n"; + +# checkall buttons + $gradeTable.=&check_script('gradesub', 'stuinfo'); $gradeTable.=''."\n"; - $gradeTable.='Check For Plagiarism'; - my (undef, undef, $fullname) = &getclasslist($getsec,'1'); + 'value="Next->" />
'."\n"; + $gradeTable.=&check_buttons(); + $gradeTable.=''; + my ($classlist, undef, $fullname) = &getclasslist($getsec,'1'); $gradeTable.='
'. ''; my $loop = 0; while ($loop < 2) { $gradeTable.=''. - ''; - if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { + ''; + if ($env{'form.showgrading'} eq 'yes' + && $submitonly ne 'queued' + && $submitonly ne 'all') { foreach (sort(@$partlist)) { my $display_part=&get_display_part((split(/_/))[0],$url,$symb); $gradeTable.=''; } + } elsif ($submitonly eq 'queued') { + $gradeTable.=''; } $loop++; # $gradeTable.='' if ($loop%2 ==1); @@ -709,17 +721,38 @@ LISTJAVASCRIPT $gradeTable.=''."\n"; my $ctr = 0; - foreach my $student (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) { + foreach my $student (sort + { + if (lc($$fullname{$a}) ne lc($$fullname{$b})) { + return (lc($$fullname{$a}) cmp lc($$fullname{$b})); + } + return $a cmp $b; + } + (keys(%$fullname))) { my ($uname,$udom) = split(/:/,$student); + my %status = (); - if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { + + if ($submitonly eq 'queued') { + my %queue_status = + &Apache::bridgetask::get_student_status($symb,$cdom,$cnum, + $udom,$uname); + next if (!defined($queue_status{'gradingqueue'})); + $status{'gradingqueue'} = $queue_status{'gradingqueue'}; + } + + if ($env{'form.showgrading'} eq 'yes' + && $submitonly ne 'queued' + && $submitonly ne 'all') { (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist); my $submitted = 0; my $graded = 0; + my $incorrect = 0; foreach (keys(%status)) { $submitted = 1 if ($status{$_} ne 'nothing'); - $graded = 1 if ($status{$_} !~ /^correct/); - + $graded = 1 if ($status{$_} =~ /^ungraded/); + $incorrect = 1 if ($status{$_} =~ /^incorrect/); + my ($foo,$partid,$foo1) = split(/\./,$_); if ($status{'resource.'.$partid.'.submitted_by'} ne '') { $submitted = 0; @@ -729,25 +762,30 @@ LISTJAVASCRIPT $status{'resource.'.$partid.'.submitted_by'}.'" />'; } } + next if (!$submitted && ($submitonly eq 'yes' || $submitonly eq 'incorrect' || $submitonly eq 'graded')); - next if (!$graded && ($submitonly eq 'graded' || - $submitonly eq 'incorrect')); + next if (!$graded && ($submitonly eq 'graded')); + next if (!$incorrect && $submitonly eq 'incorrect'); } $ctr++; + my $section = $classlist->{$student}->[&Apache::loncoursedata::CL_SECTION()]; + if ( $perm{'vgr'} eq 'F' ) { $gradeTable.='' if ($ctr%2 ==1); $gradeTable.=''. - ''."\n". - ''."\n"; + ''."\n".''."\n"; - if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { + if ($env{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { foreach (sort keys(%status)) { next if (/^resource.*?submitted_by$/); - $gradeTable.=''."\n"; + $gradeTable.=''."\n"; } } # $gradeTable.='' if ($ctr%2 ==1); @@ -756,15 +794,19 @@ LISTJAVASCRIPT } if ($ctr%2 ==1) { $gradeTable.=''; - if ($ENV{'form.showgrading'} eq 'yes' && $submitonly ne 'all') { + if ($env{'form.showgrading'} eq 'yes' + && $submitonly ne 'queued' + && $submitonly ne 'all') { foreach (@$partlist) { $gradeTable.=''; } + } elsif ($submitonly eq 'queued') { + $gradeTable.=''; } $gradeTable.=''; } - $gradeTable.='
 No.  Select '.&nameUserString('header').''.&nameUserString('header').' Section/Group Part: '.$display_part. ' Status  '.&mt('Queue Status').' 
'.$ctr.' '.&nameUserString(undef,$$fullname{$student},$uname,$udom).''. + &nameUserString(undef,$$fullname{$student},$uname,$udom). + ' '.$section.' '.$status{$_}.'  '.$status{$_}.'      
'. + $gradeTable.=''."\n". ''."\n"; @@ -776,6 +818,7 @@ LISTJAVASCRIPT my $submissions='submissions'; if ($submitonly eq 'incorrect') { $submissions = 'incorrect submissions'; } if ($submitonly eq 'graded' ) { $submissions = 'ungraded submissions'; } + if ($submitonly eq 'queued' ) { $submissions = 'queued submissions'; } $gradeTable='
 '. 'No '.$submissions.' found for this resource for any students. ('.$num_students. ' students checked for '.$submissions.')
'; @@ -789,6 +832,52 @@ LISTJAVASCRIPT } #---- Called from the listStudents routine + +sub check_script { + my ($form, $type)=@_; + my $chkallscript=''."\n"; + return $chkallscript; +} + +sub check_buttons { + my $buttons.=''; + $buttons.=' '; + $buttons.=''; + $buttons.=' '; + return $buttons; +} + # Displays the submissions for one student or a group of students sub processGroup { my ($request) = shift; @@ -798,9 +887,9 @@ sub processGroup { foreach (@stuchecked) { my ($uname,$udom,$fullname) = split(/:/); - $ENV{'form.student'} = $uname; - $ENV{'form.userdom'} = $udom; - $ENV{'form.fullname'} = $fullname; + $env{'form.student'} = $uname; + $env{'form.userdom'} = $udom; + $env{'form.fullname'} = $fullname; &submission($request,$ctr,$total); $ctr++; } @@ -993,6 +1082,8 @@ sub sub_page_kw_js { my $request = shift; my $iconpath = $request->dir_config('lonIconsURL'); &commonJSfunctions($request); + my $docopen=&Apache::lonhtmlcommon::javascript_docopen(); + $docopen=~s/^document\.//; $request->print(< @@ -1105,7 +1196,7 @@ sub sub_page_kw_js { pWin = window.open('', 'MessageCenter', 'resizable=yes,toolbar=no,location=no,scrollbars='+scrollbar+',screenx='+xpos+',screeny='+ypos+',width=600,height='+height); pWin.focus(); pDoc = pWin.document; - pDoc.open('text/html','replace'); + pDoc.$docopen; pDoc.write(""); pDoc.write("Message Central"); @@ -1236,7 +1327,7 @@ sub sub_page_kw_js { hwdWin = window.open('', 'KeywordHighlightCentral', 'resizeable=yes,toolbar=no,location=no,scrollbars=no,width=400,height=300,screenx='+xpos+',screeny='+ypos); hwdWin.focus(); var hDoc = hwdWin.document; - hDoc.open('text/html','replace'); + hDoc.$docopen; hDoc.write(""); hDoc.write("Highlight Central"); @@ -1308,16 +1399,24 @@ sub gradeBox { my $result=''."\n"; my $display_part=&get_display_part($partid,undef,$symb); + + my %last_resets = &get_last_resets($symb,$env{'request.course.id'}, + [$partid]); + my $aggtries = $$record{'resource.'.$partid.'.tries'}; + if ($last_resets{$partid}) { + $aggtries = &get_num_tries($record,$last_resets{$partid},$partid); + } + $result.=''; + $result.=$env{'form.fullname'}.''; } if ($mode eq 'both') { $result.='
'. 'Part: '.$display_part.' Points: '."\n"; my $ctr = 0; $result.=''."\n"; # display radio buttons in a nice table 10 across while ($ctr<=$wgt) { - $result.= '\n"; + ($score eq $ctr ? 'checked':'').' /> '.$ctr."\n"; $result.=(($ctr+1)%10 == 0 ? '' : ''); $ctr++; } @@ -1346,7 +1445,11 @@ sub gradeBox { $result.=''."\n". ''."\n". ''."\n"; + $$record{'resource.'.$partid.'.solved'}.'" />'."\n". + ''."\n". + ''."\n"; $result.='
'.$ctr."
'."\n"; return $result; } @@ -1356,7 +1459,7 @@ sub show_problem { my $rendered; if ($mode eq 'both' or $mode eq 'text') { $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom, - $ENV{'request.course.id'}); + $env{'request.course.id'}); } if ($removeform) { $rendered=~s|||g; @@ -1366,7 +1469,7 @@ sub show_problem { my $companswer; if ($mode eq 'both' or $mode eq 'answer') { $companswer=&Apache::loncommon::get_student_answers($symb,$uname,$udom, - $ENV{'request.course.id'}); + $env{'request.course.id'}); } if ($removeform) { $companswer=~s|||g; @@ -1382,7 +1485,7 @@ sub show_problem { } else { $result.='Correct answer: '; } - $result.=$ENV{'form.fullname'}.'
'.$rendered.'
'; @@ -1401,40 +1504,41 @@ sub show_problem { 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'}); - $udom = ($udom eq '' ? $ENV{'user.domain'} : $udom); #has form.userdom changed for a student? - my $usec = &Apache::lonnet::getsection($udom,$uname,$ENV{'request.course.id'}); - $ENV{'form.fullname'} = &get_fullname ($uname,$udom) if $ENV{'form.fullname'} eq ''; + (my $url=$env{'form.url'})=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--; + my ($uname,$udom) = ($env{'form.student'},$env{'form.userdom'}); + $udom = ($udom eq '' ? $env{'user.domain'} : $udom); #has form.userdom changed for a student? + my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'}); + $env{'form.fullname'} = &Apache::loncommon::plainname($uname,$udom,'lastname') if $env{'form.fullname'} eq ''; - my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url))); + 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 ''; } if (!&canview($usec)) { $request->print('Unable to view requested student.('. - $uname.$udom.$usec.$ENV{'request.course.id'}.')'); + $uname.'@'.$udom.' in section '.$usec.' in course id '. + $env{'request.course.id'}.')'); $request->print(&show_grading_menu_form($symb,$url)); return; } - if (!$ENV{'form.lastSub'}) { $ENV{'form.lastSub'} = 'datesub'; } - if (!$ENV{'form.vProb'}) { $ENV{'form.vProb'} = 'yes'; } - if (!$ENV{'form.vAns'}) { $ENV{'form.vAns'} = 'yes'; } - my $last = ($ENV{'form.lastSub'} eq 'last' ? 'last' : ''); + if (!$env{'form.lastSub'}) { $env{'form.lastSub'} = 'datesub'; } + if (!$env{'form.vProb'}) { $env{'form.vProb'} = 'yes'; } + if (!$env{'form.vAns'}) { $env{'form.vAns'} = 'yes'; } + my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : ''); my $checkIcon = ''; # header info if ($counter == 0) { &sub_page_js($request); - &sub_page_kw_js($request) if ($ENV{'form.handgrade'} eq 'yes'); - $ENV{'form.probTitle'} = $ENV{'form.probTitle'} eq '' ? - &Apache::lonnet::gettitle($symb) : $ENV{'form.probTitle'}; + &sub_page_kw_js($request) if ($env{'form.handgrade'} eq 'yes'); + $env{'form.probTitle'} = $env{'form.probTitle'} eq '' ? + &Apache::lonnet::gettitle($symb) : $env{'form.probTitle'}; $request->print('

 Submission Record

'."\n". - ' Resource: '.$ENV{'form.probTitle'}.''."\n"); + ' Resource: '.$env{'form.probTitle'}.''."\n"); - if ($ENV{'form.handgrade'} eq 'no') { + if ($env{'form.handgrade'} eq 'no') { my $checkMark='

 Note: Part(s) graded correct by the computer is marked with a '. $checkIcon.' symbol.'."\n"; $request->print($checkMark); @@ -1442,13 +1546,13 @@ sub submission { # 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.vAns'} eq 'yes') { + if ($env{'form.vProb'} eq 'yes' or $env{'form.vAns'} eq 'yes') { my $mode; - if ($ENV{'form.vProb'} eq 'yes' && $ENV{'form.vAns'} eq 'yes') { + if ($env{'form.vProb'} eq 'yes' && $env{'form.vAns'} eq 'yes') { $mode='both'; - } elsif ($ENV{'form.vProb'} eq 'yes') { + } elsif ($env{'form.vProb'} eq 'yes') { $mode='text'; - } elsif ($ENV{'form.vAns'} eq 'yes') { + } elsif ($env{'form.vAns'} eq 'yes') { $mode='answer'; } $request->print(&show_problem($request,$symb,$uname,$udom,0,1,$mode)); @@ -1457,60 +1561,60 @@ sub submission { # 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 '' && $ENV{'form.handgrade'} eq 'yes') { + if ($env{'form.kwclr'} eq '' && $env{'form.handgrade'} eq 'yes') { %keyhash = &Apache::lonnet::dump('nohist_handgrade', - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); + $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'; + 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'; } - my $overRideScore = $ENV{'form.overRideScore'} eq '' ? 'no' : $ENV{'form.overRideScore'}; + my $overRideScore = $env{'form.overRideScore'} eq '' ? 'no' : $env{'form.overRideScore'}; - $request->print('
'."\n". + $request->print(''."\n". ''."\n". - ''."\n". - ''."\n". + ''."\n". + ''."\n". ''."\n". - ''."\n". + ''."\n". ''."\n". ''."\n". ''."\n". ''."\n". ''."\n". - ''."\n". - ''."\n". - ''."\n". - ''."\n". - ''."\n". - ''."\n". - ''."\n". + ''."\n". + ''."\n". + ''."\n". + ''."\n". + ''."\n". + ''."\n". + ''."\n". ''."\n"); - if ($ENV{'form.handgrade'} eq 'yes') { - $request->print(''."\n". - ''."\n". - ''."\n". - ''."\n". - ''."\n". + ' value="'.($env{'form.NTSTU'} ne '' ? $env{'form.NTSTU'} : $total+1).'" />'."\n"); + if ($env{'form.handgrade'} eq 'yes') { + $request->print(''."\n". + ''."\n". + ''."\n". + ''."\n". + ''."\n". ''."\n". - ''."\n"); + ''."\n"); foreach my $partid (&Apache::loncommon::get_env_multiple('form.vPart')) { $request->print(''."\n"); } } my ($cts,$prnmsg) = (1,''); - while ($cts <= $ENV{'form.savemsgN'}) { + while ($cts <= $env{'form.savemsgN'}) { $prnmsg.=''."\n". ''."\n"; @@ -1518,7 +1622,7 @@ sub submission { } $request->print($prnmsg); - if ($ENV{'form.handgrade'} eq 'yes' && $ENV{'form.showgrading'} eq 'yes') { + if ($env{'form.handgrade'} eq 'yes' && $env{'form.showgrading'} eq 'yes') { # # Print out the keyword options line # @@ -1540,21 +1644,20 @@ KEYWORDS } } - if ($ENV{'form.vProb'} eq 'all' or $ENV{'form.vAns'} eq 'all') { + if ($env{'form.vProb'} eq 'all' or $env{'form.vAns'} eq 'all') { $request->print('


') if ($counter > 0); my $mode; - if ($ENV{'form.vProb'} eq 'all' && $ENV{'form.vAns'} eq 'all') { + if ($env{'form.vProb'} eq 'all' && $env{'form.vAns'} eq 'all') { $mode='both'; - } elsif ($ENV{'form.vProb'} eq 'all' ) { + } elsif ($env{'form.vProb'} eq 'all' ) { $mode='text'; - } elsif ($ENV{'form.vAns'} eq 'all') { + } elsif ($env{'form.vAns'} eq 'all') { $mode='answer'; } $request->print(&show_problem($request,$symb,$uname,$udom,1,1,$mode)); } - my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname); - + my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname); my ($partlist,$handgrade,$responseType) = &response_type($url,$symb); # Display student info @@ -1562,14 +1665,14 @@ KEYWORDS my $result='
'."\n". '
'."\n"; - $result.='Fullname: '.&nameUserString(undef,$ENV{'form.fullname'},$uname,$udom).'
'."\n"; + $result.='Fullname: '.&nameUserString(undef,$env{'form.fullname'},$uname,$udom).'
'."\n"; $result.=''."\n"; + '" value="'.$env{'form.fullname'}.'" />'."\n"; # If any part of the problem is an essay-response (handgraded), then check for collaborators my @col_fullnames; my ($classlist,$fullname); - if ($ENV{'form.handgrade'} eq 'yes') { + if ($env{'form.handgrade'} eq 'yes') { ($classlist,undef,$fullname) = &getclasslist('all','0'); for (keys (%$handgrade)) { my $ncol = &Apache::lonnet::EXT('resource.'.$_. @@ -1630,7 +1733,7 @@ KEYWORDS # (for multi-response type part) # (3) Last submission plus the parts info # (4) The whole record for this student - if ($ENV{'form.lastSub'} =~ /^(lastonly|hdgrade)$/) { + if ($env{'form.lastSub'} =~ /^(lastonly|hdgrade)$/) { my ($string,$timestamp)= &get_last_submission(\%record); my $lastsubonly=''. ($$timestamp eq '' ? '' : 'Date Submitted: '. @@ -1642,15 +1745,15 @@ KEYWORDS for my $part (sort keys(%$handgrade)) { my ($partid,$respid) = split(/_/,$part); my $display_part=&get_display_part($partid,$url,$symb); - if ($ENV{"form.$uname:$udom:$partid:submitted_by"}) { + if ($env{"form.$uname:$udom:$partid:submitted_by"}) { if (exists($seenparts{$partid})) { next; } $seenparts{$partid}=1; my $submitby='Part: '.$display_part. ' Collaborative submission by: '. ''. - $$fullname{$ENV{"form.$uname:$udom:$partid:submitted_by"}}.'
'; + $$fullname{$env{"form.$uname:$udom:$partid:submitted_by"}}.'
'; $request->print($submitby); next; } @@ -1668,7 +1771,7 @@ KEYWORDS my ($ressub,$subval) = split(/:/,$_,2); # Similarity check my $similar=''; - if($ENV{'form.checkPlag'}){ + if($env{'form.checkPlag'}){ my ($oname,$odom,$ocrsid,$oessay,$osim)= &most_similar($uname,$udom,$subval); if ($osim) { @@ -1682,17 +1785,39 @@ KEYWORDS } } my $order=&get_order($partid,$respid,$symb,$uname,$udom); - if ($ENV{'form.lastSub'} eq 'lastonly' || - ($ENV{'form.lastSub'} eq 'hdgrade' && + if ($env{'form.lastSub'} eq 'lastonly' || + ($env{'form.lastSub'} eq 'hdgrade' && $$handgrade{$part} eq 'yes')) { my $display_part=&get_display_part($partid,$url,$symb); $lastsubonly.='
Part: '. $display_part.' ( ID '.$respid. ' )   '; + my @files; + if ($record{"resource.$partid.$respid.portfiles"}) { + my $file_url = '/uploaded/'.$udom.'/'.$uname.'/portfolio'; + foreach my $file (split(',',$record{"resource.$partid.$respid.portfiles"})) { + push(@files,$file_url.$file); + + &Apache::lonnet::logthis("found a portfolio file".$record{"resource.$partid.$respid.portfiles"}); + &Apache::lonnet::logthis("uploaded URL file".$record{"resource.$partid.$respid.uploadedurl"}); + } + } if ($record{"resource.$partid.$respid.uploadedurl"}) { - &Apache::lonnet::allowuploaded('/adm/grades', - $record{"resource.$partid.$respid.uploadedurl"}); - $lastsubonly.=' File uploaded by student Like all files provided by users, this file may contain virusses
'; + push(@files,$record{"resource.$partid.$respid.uploadedurl"}); + } + if (@files) { + $lastsubonly.='
Like all files provided by users, this file may contain virusses
'; + my $file_counter = 0; + foreach my $file (@files) { + $file_counter ++; + &Apache::lonnet::allowuploaded('/adm/grades',$file); + $lastsubonly.='
'.$file.''; + $lastsubonly.=' Return commented document to student. '."\n"; + $lastsubonly.=''; + + } + $lastsubonly.='
'; } $lastsubonly.='Submitted Answer: '. &cleanRecord($subval,$responsetype,$symb,$partid, @@ -1704,12 +1829,12 @@ KEYWORDS } $lastsubonly.='
'."\n"; $request->print($lastsubonly); - } elsif ($ENV{'form.lastSub'} eq 'datesub') { + } elsif ($env{'form.lastSub'} eq 'datesub') { my (undef,$responseType,undef,$parts) = &showResourceInfo($url); $request->print(&displaySubByDates($symb,\%record,$parts,$responseType,$checkIcon,$uname,$udom)); - } elsif ($ENV{'form.lastSub'} =~ /^(last|all)$/) { + } elsif ($env{'form.lastSub'} =~ /^(last|all)$/) { $request->print(&Apache::loncommon::get_previous_attempt($symb,$uname,$udom, - $ENV{'request.course.id'}, + $env{'request.course.id'}, $last,'.submission', 'Apache::grades::keywords_highlight')); } @@ -1718,13 +1843,13 @@ KEYWORDS .$udom.'" />'."\n"); # return if view submission with no grading option - if ($ENV{'form.showgrading'} eq '' || (!&canmodify($usec))) { + if ($env{'form.showgrading'} eq '' || (!&canmodify($usec))) { my $toGrade.='  '."\n" if (&canmodify($usec)); $toGrade.='
'."\n"; - if (($ENV{'form.command'} eq 'submission') || - ($ENV{'form.command'} eq 'processGroup' && $counter == $total)) { + if (($env{'form.command'} eq 'submission') || + ($env{'form.command'} eq 'processGroup' && $counter == $total)) { $toGrade.='
'.&show_grading_menu_form($symb,$url) } $request->print($toGrade); @@ -1734,8 +1859,8 @@ KEYWORDS } # essay grading message center - if ($ENV{'form.handgrade'} eq 'yes') { - my ($lastname,$givenn) = split(/,/,$ENV{'form.fullname'}); + if ($env{'form.handgrade'} eq 'yes') { + my ($lastname,$givenn) = split(/,/,$env{'form.fullname'}); my $msgfor = $givenn.' '.$lastname; if (scalar(@col_fullnames) > 0) { my $lastone = pop @col_fullnames; @@ -1746,13 +1871,24 @@ KEYWORDS ''."\n"; $result.=' '. - 'Compose Message to student'.(scalar(@col_fullnames) >= 1 ? 's' : '').'  '. + &mt('Compose message to student').(scalar(@col_fullnames) >= 1 ? 's' : '').' ('. + &mt('incl. grades').' )'. ''."\n". - '
 (Message will be sent when you click on Save & Next below.)'."\n" - if ($ENV{'form.handgrade'} eq 'yes'); + '
 ('. + &mt('Message will be sent when you click on Save & Next below.').")\n"; $request->print($result); } + if ($perm{'vgr'}) { + $request->print('
'. + &Apache::loncommon::track_student_link(&mt('View recent activity'), + $uname,$udom,'check')); + } + if ($perm{'opa'}) { + $request->print('
'. + &Apache::loncommon::pprmlink(&mt('Set/Change parameters'), + $uname,$udom,$symb,'check')); + } my %seen = (); my @partlist; @@ -1761,7 +1897,7 @@ KEYWORDS my ($partid,$respid) = split(/_/); next if ($seen{$partid} > 0); $seen{$partid}++; - next if ($$handgrade{$_} =~ /:no$/ && $ENV{'form.lastSub'} =~ /^(hdgrade)$/); + next if ($$handgrade{$_} =~ /:no$/ && $env{'form.lastSub'} =~ /^(hdgrade)$/); push @partlist,$partid; push @gradePartRespid,$partid.'.'.$respid; @@ -1789,7 +1925,7 @@ KEYWORDS ''. ''. ''."\n"; - my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1'); + my $nsel = ($env{'form.NTSTU'} ne '' ? $env{'form.NTSTU'} : '1'); $ntstu =~ s/
'."\n". @@ -2383,11 +2772,13 @@ sub viewgrades { ''. '\n"; my (@parts) = sort(&getpartlist($url,$symb)); + my @partids = (); foreach my $part (@parts) { my $display=&Apache::lonnet::metadata($url,$part.'.display'); $display =~ s|^Number of Attempts|Tries
|; # makes the column narrower if (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); } my ($partid) = &split_part_type($part); + push(@partids, $partid); my $display_part=&get_display_part($partid,$url,$symb); if ($display =~ /^Partial Credit Factor/) { $result.=''; + my %last_resets = + &get_last_resets($symb,$env{'request.course.id'},\@partids); + #get info for each student #list all the students - with points and grade status - my (undef,undef,$fullname) = &getclasslist($ENV{'form.section'},'1'); + 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"; + foreach (sort + { + if (lc($$fullname{$a}) ne lc($$fullname{$b})) { + return (lc($$fullname{$a}) cmp lc($$fullname{$b})); + } + return $a cmp $b; + } (keys(%$fullname))) { $ctr++; - $result.=&viewstudentgrade($url,$symb,$ENV{'request.course.id'}, - $_,$$fullname{$_},\@parts,\%weight,$ctr); + $result.=&viewstudentgrade($url,$symb,$env{'request.course.id'}, + $_,$$fullname{$_},\@parts,\%weight,$ctr,\%last_resets); } $result.='
 No. '.&nameUserString('header')."Score Part: '.$display_part. @@ -2401,17 +2792,23 @@ sub viewgrades { } $result.='
'; $result.=''."\n"; @@ -2419,8 +2816,8 @@ sub viewgrades { 'onClick="javascript:submit();" TARGET=_self />'."\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='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; @@ -2428,22 +2825,41 @@ sub viewgrades { #--- call by previous routine to display each student sub viewstudentgrade { - my ($url,$symb,$courseid,$student,$fullname,$parts,$weight,$ctr) = @_; + my ($url,$symb,$courseid,$student,$fullname,$parts,$weight,$ctr,$last_resets) = @_; my ($uname,$udom) = split(/:/,$student); - $student=~s/:/_/; my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname); - my $result=''.$ctr.'  '. + my %aggregates = (); + my $result=''. + ''. + "\n".$ctr.'  '. ''.$fullname.' '. - '('.$uname.($ENV{'user.domain'} eq $udom ? '' : ':'.$udom).')'."\n"; + '('.$uname.($env{'user.domain'} eq $udom ? '' : ':'.$udom).')'."\n"; + $student=~s/:/_/; # colon doen't work in javascript for names foreach my $apart (@$parts) { my ($part,$type) = &split_part_type($apart); my $score=$record{"resource.$part.$type"}; + $result.=''; + my ($aggtries,$totaltries); + unless (exists($aggregates{$part})) { + $totaltries = $record{'resource.'.$part.'.tries'}; + + $aggtries = $totaltries; + if ($$last_resets{$part}) { + $aggtries = &get_num_tries(\%record,$$last_resets{$part}, + $part); + } + $result.=''."\n"; + $result.=''."\n"; + $aggregates{$part} = 1; + } if ($type eq 'awarded') { my $pts = $score eq '' ? '' : $score*$$weight{$part}; $result.=''."\n"; - $result.=''."\n"; @@ -2452,7 +2868,7 @@ sub viewstudentgrade { $status = 'nothing' if ($status eq ''); $result.=''."\n"; - $result.=' '. "\n"; - $result.=''."\n"; } @@ -2477,11 +2893,11 @@ sub viewstudentgrade { sub editgrades { my ($request) = @_; - my $symb=$ENV{'form.symb'}; - my $url =$ENV{'form.url'}; + my $symb=$env{'form.symb'}; + my $url =$env{'form.url'}; my $title='

Current Grade Status

'; - $title.='Current Resource: '.$ENV{'form.probTitle'}.'
'."\n"; - $title.='Section: '.$ENV{'form.section'}.''."\n"; + $title.='Current Resource: '.$env{'form.probTitle'}.'
'."\n"; + $title.='Section: '.$env{'form.section'}.''."\n"; my $result= ' + + + SCANTRONFORM $r->print($result); - if (&Apache::lonnet::allowed('usc',$ENV{'request.role.domain'}) || - &Apache::lonnet::allowed('usc',$ENV{'request.course.id'})) { + if (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) || + &Apache::lonnet::allowed('usc',$env{'request.course.id'})) { $r->print(< @@ -3590,8 +4197,8 @@ SCANTRONFORM + + SCANTRONFORM $r->print(< - $grading_menu_button SCANTRONFORM @@ -3738,7 +4344,14 @@ sub scantron_fixup_scanline { &scan_data($scan_data, "$whichline.no_bubble.".$args->{'question'},'1'); } else { - substr($answer,$args->{'response'},1)=$on; + if ($on eq 'letter') { + my @alphabet=('A'..'Z'); + $answer=$alphabet[$args->{'response'}]; + } elsif ($on eq 'number') { + $answer=$args->{'response'}+1; + } else { + substr($answer,$args->{'response'},1)=$on; + } &scan_data($scan_data, "$whichline.no_bubble.".$args->{'question'},undef,'1'); } @@ -3750,7 +4363,7 @@ sub scantron_fixup_scanline { sub scan_data { my ($scan_data,$key,$value,$delete)=@_; - my $filename=$ENV{'form.scantron_selectfile'}; + my $filename=$env{'form.scantron_selectfile'}; if (defined($value)) { $scan_data->{$filename.'_'.$key} = $value; } @@ -3763,8 +4376,11 @@ sub scantron_parse_scanline { 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) { + if (!($$scantron_config{'CODElocation'} eq 0 || + $$scantron_config{'CODElocation'} eq 'none')) { + if ($$scantron_config{'CODElocation'} < 0 || + $$scantron_config{'CODElocation'} eq 'letter' || + $$scantron_config{'CODElocation'} eq 'number') { $record{'scantron.CODE'}=substr($data, $$scantron_config{'CODEstart'}-1, $$scantron_config{'CODElength'}); @@ -3798,25 +4414,57 @@ sub scantron_parse_scanline { 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,-1); - if (length($array[0]) eq $$scantron_config{'Qlength'}) { - $record{"scantron.$questnum.answer"}=''; - if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) { - push(@{$record{"scantron.missingerror"}},$questnum); - } + if ($$scantron_config{'Qon'} eq 'letter') { + if ($currentquest eq '?') { + push(@{$record{'scantron.doubleerror'}},$questnum); + $record{"scantron.$questnum.answer"}=''; + } elsif (!$currentquest + || $currentquest eq $$scantron_config{'Qoff'} + || $currentquest !~ /^[A-Z]$/) { + $record{"scantron.$questnum.answer"}=''; + if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) { + push(@{$record{"scantron.missingerror"}},$questnum); + } + } else { + $record{"scantron.$questnum.answer"}=$currentquest; + } + } elsif ($$scantron_config{'Qon'} eq 'number') { + if ($currentquest eq '?') { + push(@{$record{'scantron.doubleerror'}},$questnum); + $record{"scantron.$questnum.answer"}=''; + } elsif (!$currentquest + || $currentquest eq $$scantron_config{'Qoff'} + || $currentquest !~ /^\d$/) { + $record{"scantron.$questnum.answer"}=''; + if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) { + push(@{$record{"scantron.missingerror"}},$questnum); + } + } else { + $record{"scantron.$questnum.answer"}= + $alphabet[$currentquest-1]; + } } else { - $record{"scantron.$questnum.answer"}=$alphabet[length($array[0])]; + my @array=split($$scantron_config{'Qon'},$currentquest,-1); + if (length($array[0]) eq $$scantron_config{'Qlength'}) { + $record{"scantron.$questnum.answer"}=''; + if (!&scan_data($scan_data,"$whichline.no_bubble.$questnum")) { + push(@{$record{"scantron.missingerror"}},$questnum); + } + } else { + $record{"scantron.$questnum.answer"}= + $alphabet[length($array[0])]; + } + if (scalar(@array) gt 2) { + push(@{$record{'scantron.doubleerror'}},$questnum); + my @ans=@array; + my $i=length($ans[0]);shift(@ans); + while ($#ans) { + $i+=length($ans[0])+1; + $record{"scantron.$questnum.answer"}.=$alphabet[$i]; + shift(@ans); + } + } } - if (scalar(@array) gt 2) { - push(@{$record{'scantron.doubleerror'}},$questnum); - my @ans=@array; - my $i=length($ans[0]);shift(@ans); - while ($#ans) { - $i+=length($ans[0])+1; - $record{"scantron.$questnum.answer"}.=$alphabet[$i]; - shift(@ans); - } - } } $record{'scantron.maxquest'}=$questnum; return \%record; @@ -3855,55 +4503,55 @@ sub scantron_filter { sub scantron_process_corrections { my ($r) = @_; - my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'}); + my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); my ($scanlines,$scan_data)=&scantron_getfile(); my $classlist=&Apache::loncoursedata::get_classlist(); - my $which=$ENV{'form.scantron_line'}; + my $which=$env{'form.scantron_line'}; my $line=&scantron_get_line($scanlines,$scan_data,$which); my ($skip,$err,$errmsg); - if ($ENV{'form.scantron_skip_record'}) { + if ($env{'form.scantron_skip_record'}) { $skip=1; - } elsif ($ENV{'form.scantron_corrections'} =~ /^(duplicate|incorrect)ID$/) { - my $newstudent=$ENV{'form.scantron_username'}.':'. - $ENV{'form.scantron_domain'}; + } elsif ($env{'form.scantron_corrections'} =~ /^(duplicate|incorrect)ID$/) { + my $newstudent=$env{'form.scantron_username'}.':'. + $env{'form.scantron_domain'}; my $newid=$classlist->{$newstudent}->[&Apache::loncoursedata::CL_ID]; ($line,$err,$errmsg)= &scantron_fixup_scanline(\%scantron_config,$scan_data,$line,$which, 'ID',{'newid'=>$newid, - 'username'=>$ENV{'form.scantron_username'}, - 'domain'=>$ENV{'form.scantron_domain'}}); - } elsif ($ENV{'form.scantron_corrections'} =~ /^(duplicate|incorrect)CODE$/) { - my $resolution=$ENV{'form.scantron_CODE_resolution'}; + 'username'=>$env{'form.scantron_username'}, + 'domain'=>$env{'form.scantron_domain'}}); + } elsif ($env{'form.scantron_corrections'} =~ /^(duplicate|incorrect)CODE$/) { + my $resolution=$env{'form.scantron_CODE_resolution'}; my $newCODE; my %args; if ($resolution eq 'use_unfound') { $newCODE='use_unfound'; } elsif ($resolution eq 'use_found') { - $newCODE=$ENV{'form.scantron_CODE_selectedvalue'}; + $newCODE=$env{'form.scantron_CODE_selectedvalue'}; } elsif ($resolution eq 'use_typed') { - $newCODE=$ENV{'form.scantron_CODE_newvalue'}; + $newCODE=$env{'form.scantron_CODE_newvalue'}; } elsif ($resolution =~ /^use_closest_(\d+)/) { - $newCODE=$ENV{"form.scantron_CODE_closest_$1"}; + $newCODE=$env{"form.scantron_CODE_closest_$1"}; } - if ($ENV{'form.scantron_corrections'} eq 'duplicateCODE') { + if ($env{'form.scantron_corrections'} eq 'duplicateCODE') { $args{'CODE_ignore_dup'}=1; } $args{'CODE'}=$newCODE; ($line,$err,$errmsg)= &scantron_fixup_scanline(\%scantron_config,$scan_data,$line,$which, 'CODE',\%args); - } elsif ($ENV{'form.scantron_corrections'} =~ /^(missing|double)bubble$/) { - foreach my $question (split(',',$ENV{'form.scantron_questions'})) { + } elsif ($env{'form.scantron_corrections'} =~ /^(missing|double)bubble$/) { + foreach my $question (split(',',$env{'form.scantron_questions'})) { ($line,$err,$errmsg)= &scantron_fixup_scanline(\%scantron_config,$scan_data,$line, $which,'answer', { 'question'=>$question, - 'response'=>$ENV{"form.scantron_correct_Q_$question"}}); + 'response'=>$env{"form.scantron_correct_Q_$question"}}); if ($err) { last; } } } if ($err) { - $r->print("Unable to accept last correction, an error occurred :$errmsg:"); + $r->print("Unable to accept last correction, an error occurred :$errmsg:"); } else { &scantron_put_line($scanlines,$scan_data,$which,$line,$skip); &scantron_putfile($scanlines,$scan_data); @@ -3925,7 +4573,7 @@ sub allow_skipping { sub should_be_skipped { my ($scan_data,$i)=@_; - if ($ENV{'form.scantron_options_redo'} !~ /^redo_/) { + if ($env{'form.scantron_options_redo'} !~ /^redo_/) { # not redoing old skips return 0; } @@ -3956,15 +4604,27 @@ sub check_for_error { sub scantron_warning_screen { my ($button_text)=@_; - my $title=&Apache::lonnet::gettitle($ENV{'form.selectpage'}); + my $title=&Apache::lonnet::gettitle($env{'form.selectpage'}); + my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); + my $CODElist="a"; + if ($scantron_config{'CODElocation'} && + $scantron_config{'CODEstart'} && + $scantron_config{'CODElength'}) { + $CODElist=$env{'form.scantron_CODElist'}; + if ($CODElist eq '') { $CODElist='None'; } + $CODElist= + ''; + } return (< Please double check the information below before clicking on '$button_text'

'."\n"; $result.= ''. @@ -2495,7 +2911,7 @@ sub editgrades { 'ungraded' =>'ungraded_attempted', 'nothing' => '', ); - my ($classlist,undef,$fullname) = &getclasslist($ENV{'form.section'},'0'); + my ($classlist,undef,$fullname) = &getclasslist($env{'form.section'},'0'); my (@partid); my %weight = (); @@ -2504,10 +2920,10 @@ sub editgrades { my (@parts) = sort(&getpartlist($url,$symb)); my $header; - while ($ctr < $ENV{'form.totalparts'}) { - my $partid = $ENV{'form.partid_'.$ctr}; + while ($ctr < $env{'form.totalparts'}) { + my $partid = $env{'form.partid_'.$ctr}; push @partid,$partid; - $weight{$partid} = $ENV{'form.weight_'.$partid}; + $weight{$partid} = $env{'form.weight_'.$partid}; $ctr++; } foreach my $partid (@partid) { @@ -2538,49 +2954,57 @@ sub editgrades { $result .= ''."\n"; my $noupdate; my ($updateCtr,$noupdateCtr) = (1,1); - for ($i=0; $i<$ENV{'form.total'}; $i++) { + for ($i=0; $i<$env{'form.total'}; $i++) { my $line; - my $user = $ENV{'form.ctr'.$i}; - my $usercolon = $user; - $usercolon =~s/_/:/; - my ($uname,$udom)=split(/_/,$user); + my $user = $env{'form.ctr'.$i}; + my ($uname,$udom)=split(/:/,$user); my %newrecord; my $updateflag = 0; - $line .= ''; + $line .= ''; my $usec=$classlist->{"$uname:$udom"}[5]; if (!&canmodify($usec)) { my $numcols=scalar(@partid)*4+2; $noupdate.=$line.""; next; } + my %aggregate = (); + my $aggregateflag = 0; + $user=~s/:/_/; # colon doen't work in javascript for names foreach (@partid) { - my $old_aw = $ENV{'form.GD_'.$user.'_'.$_.'_awarded_s'}; + my $old_aw = $env{'form.GD_'.$user.'_'.$_.'_awarded_s'}; my $old_part_pcr = $old_aw/($weight{$_} ne '0' ? $weight{$_}:1); my $old_part = $old_aw eq '' ? '' : $old_part_pcr; - my $old_score = $scoreptr{$ENV{'form.GD_'.$user.'_'.$_.'_solved_s'}}; - - my $awarded = $ENV{'form.GD_'.$user.'_'.$_.'_awarded'}; + my $old_score = $scoreptr{$env{'form.GD_'.$user.'_'.$_.'_solved_s'}}; + my $awarded = $env{'form.GD_'.$user.'_'.$_.'_awarded'}; my $pcr = $awarded/($weight{$_} ne '0' ? $weight{$_} : 1); my $partial = $awarded eq '' ? '' : $pcr; my $score; if ($partial eq '') { - $score = $scoreptr{$ENV{'form.GD_'.$user.'_'.$_.'_solved_s'}}; + $score = $scoreptr{$env{'form.GD_'.$user.'_'.$_.'_solved_s'}}; } elsif ($partial > 0) { $score = 'correct_by_override'; } elsif ($partial == 0) { $score = 'incorrect_by_override'; } - my $dropMenu = $ENV{'form.GD_'.$user.'_'.$_.'_solved'}; + my $dropMenu = $env{'form.GD_'.$user.'_'.$_.'_solved'}; $score = 'excused' if (($dropMenu eq 'excused') && ($score ne 'excused')); + $newrecord{'resource.'.$_.'.regrader'}= + "$env{'user.name'}:$env{'user.domain'}"; if ($dropMenu eq 'reset status' && $old_score ne '') { # ignore if no previous attempts => nothing to reset - $newrecord{'resource.'.$_.'.tries'} = 0; + $newrecord{'resource.'.$_.'.tries'} = ''; $newrecord{'resource.'.$_.'.solved'} = ''; $newrecord{'resource.'.$_.'.award'} = ''; - $newrecord{'resource.'.$_.'.awarded'} = 0; - $newrecord{'resource.'.$_.'.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}"; + $newrecord{'resource.'.$_.'.awarded'} = ''; $updateflag = 1; + if ($env{'form.GD_'.$user.'_'.$_.'_aggtries'} > 0) { + my $aggtries = $env{'form.GD_'.$user.'_'.$_.'_aggtries'}; + my $totaltries = $env{'form.GD_'.$user.'_'.$_.'_totaltries'}; + my $solvedstatus = $env{'form.GD_'.$user.'_'.$_.'_solved_s'}; + &decrement_aggs($symb,$_,\%aggregate,$aggtries,$totaltries,$solvedstatus); + $aggregateflag = 1; + } } elsif (!($old_part eq $partial && $old_score eq $score)) { $updateflag = 1; $newrecord{'resource.'.$_.'.awarded'} = $partial if $partial ne ''; @@ -2598,11 +3022,11 @@ sub editgrades { my ($part,$type) = &split_part_type($stores); if ($part !~ m/^\Q$partid\E/) { next;} if ($type eq 'awarded' || $type eq 'solved') { next; } - my $old_aw = $ENV{'form.GD_'.$user.'_'.$part.'_'.$type.'_s'}; - my $awarded = $ENV{'form.GD_'.$user.'_'.$part.'_'.$type}; + my $old_aw = $env{'form.GD_'.$user.'_'.$part.'_'.$type.'_s'}; + my $awarded = $env{'form.GD_'.$user.'_'.$part.'_'.$type}; if ($awarded ne '' && $awarded ne $old_aw) { $newrecord{'resource.'.$part.'.'.$type}= $awarded; - $newrecord{'resource.'.$part.'.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}"; + $newrecord{'resource.'.$part.'.regrader'}="$env{'user.name'}:$env{'user.domain'}"; $updateflag=1; } $line .= ''. @@ -2610,16 +3034,48 @@ sub editgrades { } } $line.=''."\n"; + + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + if ($updateflag) { $count++; - &Apache::lonnet::cstore(\%newrecord,$symb,$ENV{'request.course.id'}, + &Apache::lonnet::cstore(\%newrecord,$symb,$env{'request.course.id'}, $udom,$uname); + + if (&Apache::bridgetask::in_queue('gradingqueue',$symb,$cdom, + $cnum,$udom,$uname)) { + # need to figure out if should be in queue. + my %record = + &Apache::lonnet::restore($symb,$env{'request.course.id'}, + $udom,$uname); + my $all_graded = 1; + my $none_graded = 1; + foreach my $part (@parts) { + if ( $record{'resource.'.$part.'.awarded'} eq '' ) { + $all_graded = 0; + } else { + $none_graded = 0; + } + } + + if ($all_graded || $none_graded) { + &Apache::bridgetask::remove_from_queue('gradingqueue', + $symb,$cdom,$cnum, + $udom,$uname); + } + } + $result.=''.$line; $updateCtr++; } else { $noupdate.=''.$line; $noupdateCtr++; } + if ($aggregateflag) { + &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, + $cdom,$cnum); + } } if ($noupdate) { # my $numcols=(scalar(@partid)*(scalar(@parts)-1)*2)+3; @@ -2630,7 +3086,7 @@ sub editgrades { &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'}.'
'; + 'Total number of students = '.$env{'form.total'}.'
'; return $title.$msg.$result; } @@ -2653,24 +3109,26 @@ sub split_part_type { # #--- Javascript to handle csv upload sub csvupload_javascript_reverse_associate { + my $error1=&mt('You need to specify the username or ID'); + my $error2=&mt('You need to specify at least one grading field'); return(<2) { foundsomething=1; } - } - if (founduname==0 || founddomain==0) { - alert('You need to specify at both the username and domain'); - return; + if (tw==1) { foundID=1; } + if (tw==2) { founduname=1; } + if (tw>3) { foundsomething=1; } + } + if (founduname==0 && foundID==0) { + alert('$error1'); + return; } if (foundsomething==0) { - alert('You need to specify at least one grading field'); - return; + alert('$error2'); + return; } vf.submit(); } @@ -2728,14 +3188,15 @@ ENDPICK sub csvuploadmap_header { my ($request,$symb,$url,$datatoken,$distotal)= @_; my $javascript; - if ($ENV{'form.upfile_associate'} eq 'reverse') { + if ($env{'form.upfile_associate'} eq 'reverse') { $javascript=&csvupload_javascript_reverse_associate(); } else { $javascript=&csvupload_javascript_forward_associate(); } - my ($result) = &showResourceInfo($url,$ENV{'form.probTitle'}); - + my ($result) = &showResourceInfo($url,$env{'form.probTitle'}); + my $checked=(($env{'form.noFirstLine'})?' checked="checked"':''); + my $ignore=&mt('Ignore First Line'); $request->print(<

Uploading Class Grades

@@ -2746,18 +3207,19 @@ Total number of records found in file: $ Enter as many fields as you can. The system will inform you and bring you back to this page if the data selected is insufficient to run your class.
+ - - + + + value="$env{'form.upfile_associate'}" /> - - - + + +
CSVFORMJS - $ENV{'form.probTitle'} = &Apache::lonnet::gettitle($symb); - my ($table) = &showResourceInfo($url,$ENV{'form.probTitle'}); + return $result; +} + +sub upcsvScores_form { + my ($request) = shift; + my ($symb,$url)=&get_symb_and_url($request); + if (!$symb) {return '';} + my $result=&checkforfile_js(); + $env{'form.probTitle'} = &Apache::lonnet::gettitle($symb); + my ($table) = &showResourceInfo($url,$env{'form.probTitle'}); $result.=$table; $result.='
'.&nameUserString(undef,$$fullname{$usercolon},$uname,$udom).''.&nameUserString(undef,$$fullname{$user},$uname,$udom).'Not allowed to modify student
'.$old_aw.' 
 '.$updateCtr.' 
 '.$noupdateCtr.' 
' : ''); $studentTable.=''; - $studentTable.='' : ''); $ptr++; } @@ -3062,7 +3642,8 @@ sub getSymbMap { my $minder = 0; # Gather every sequence that has problems. - my @sequences = $navmap->retrieveResources(undef, sub { shift->is_map(); }, 1); + my @sequences = $navmap->retrieveResources(undef, sub { shift->is_map(); }, + 1,0,1); for my $sequence ($navmap->getById('0.0'), @sequences) { if ($navmap->hasResource($sequence, sub { shift->is_problem(); }, 0) ) { my $title = $minder.'.'.$sequence->compTitle(); @@ -3071,8 +3652,6 @@ sub getSymbMap { $minder++; } } - - $navmap->untieHashes(); return \@titles,\%symbx; } @@ -3082,49 +3661,53 @@ sub displayPage { 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 $pageTitle = $ENV{'form.page'}; + 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 $pageTitle = $env{'form.page'}; my ($classlist,undef,$fullname) = &getclasslist($getsec,'1'); - my ($uname,$udom) = split(/:/,$ENV{'form.student'}); - my $usec=$classlist->{$ENV{'form.student'}}[5]; + my ($uname,$udom) = split(/:/,$env{'form.student'}); + my $usec=$classlist->{$env{'form.student'}}[5]; #need to make sure we have the correct data for later EXT calls, #thus invalidate the cache &Apache::lonnet::devalidatecourseresdata( - $ENV{'course.'.$ENV{'request.course.id'}.'.num'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}); + $env{'course.'.$env{'request.course.id'}.'.num'}, + $env{'course.'.$env{'request.course.id'}.'.domain'}); &Apache::lonnet::clear_EXT_cache_status(); if (!&canview($usec)) { - $request->print('Unable to view requested student.('.$ENV{'form.student'}.')'); + $request->print('Unable to view requested student.('.$env{'form.student'}.')'); $request->print(&show_grading_menu_form($symb,$url)); return; } - my $result='

 '.$ENV{'form.title'}.'

'; - $result.='

 Student: '.&nameUserString(undef,$$fullname{$ENV{'form.student'}},$uname,$udom). + my $result='

 '.$env{'form.title'}.'

'; + $result.='

 Student: '.&nameUserString(undef,$$fullname{$env{'form.student'}},$uname,$udom). '

'."\n"; &sub_page_js($request); $request->print($result); my $navmap = Apache::lonnavmaps::navmap->new(); - my ($mapUrl, $id, $resUrl)=&Apache::lonnet::decode_symb($ENV{'form.page'}); + my ($mapUrl, $id, $resUrl)=&Apache::lonnet::decode_symb($env{'form.page'}); my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps - + if (!$map) { + $request->print('Unable to view requested sequence. ('.$resUrl.')'); + $request->print(&show_grading_menu_form($symb,$url)); + return; + } my $iterator = $navmap->getIterator($map->map_start(), $map->map_finish()); my $studentTable=''."\n". ''."\n". - ''."\n". - ''."\n". + ''."\n". + ''."\n". ''."\n". - ''."\n". + ''."\n". ''."\n". ''."\n". ''."\n". - ''."\n"; + ''."\n"; my $checkIcon = ''; @@ -3134,7 +3717,7 @@ sub displayPage { '
'."\n"; $result.=''."\n"; $result.='
'."\n"; @@ -2817,16 +3289,17 @@ CSVFORMJS '.
'."\n"; my $upfile_select=&Apache::loncommon::upfile_select_html(); + my $ignore=&mt('Ignore First Line'); $result.=< - - + + $upfile_select
- + ENDUPFORM $result.='
'."\n"; @@ -2842,19 +3315,20 @@ sub csvuploadmap { if (!$symb) {return '';} my $datatoken; - if (!$ENV{'form.datatoken'}) { + if (!$env{'form.datatoken'}) { $datatoken=&Apache::loncommon::upfile_store($request); } else { - $datatoken=$ENV{'form.datatoken'}; + $datatoken=$env{'form.datatoken'}; &Apache::loncommon::load_tmp_file($request); } my @records=&Apache::loncommon::upfile_record_sep(); + if ($env{'form.noFirstLine'}) { shift(@records); } &csvuploadmap_header($request,$symb,$url,$datatoken,$#records+1); my ($i,$keyfields); if (@records) { my @fields=&csvupload_fields($url,$symb); - if ($ENV{'form.upfile_associate'} eq 'reverse') { + if ($env{'form.upfile_associate'} eq 'reverse') { &Apache::loncommon::csv_print_samples($request,\@records); $i=&Apache::loncommon::csv_print_select_table($request,\@records, \@fields); @@ -2864,8 +3338,13 @@ sub csvuploadmap { unshift(@fields,['none','']); $i=&Apache::loncommon::csv_samples_select_table($request,\@records, \@fields); - my %sone=&Apache::loncommon::record_sep($records[0]); - $keyfields=join(',',sort(keys(%sone))); + foreach my $rec (@records) { + my %temp = &Apache::loncommon::record_sep($rec); + if (%temp) { + $keyfields=join(',',sort(keys(%temp))); + last; + } + } } } &csvuploadmap_footer($request,$i,$keyfields); @@ -2874,39 +3353,106 @@ sub csvuploadmap { return ''; } -sub csvuploadassign { +sub csvuploadoptions { my ($request)= @_; my ($symb,$url)=&get_symb_and_url($request); - if (!$symb) {return '';} - &Apache::loncommon::load_tmp_file($request); - my @gradedata = &Apache::loncommon::upfile_record_sep(); - my @keyfields = split(/\,/,$ENV{'form.keyfields'}); - my %fields=(); - for (my $i=0; $i<=$ENV{'form.nfields'}; $i++) { - if ($ENV{'form.upfile_associate'} eq 'reverse') { - if ($ENV{'form.f'.$i} ne 'none') { - $fields{$keyfields[$i]}=$ENV{'form.f'.$i}; + my $checked=(($env{'form.noFirstLine'})?'1':'0'); + my $ignore=&mt('Ignore First Line'); + $request->print(< +

Uploading Class Grade Options

+ + +

+ +

+ENDPICK + my %fields=&get_fields(); + if (!defined($fields{'domain'})) { + my $domform = &Apache::loncommon::select_dom_form($env{'request.role.domain'},'default_domain'); + $request->print("\n

Users are in domain: ".$domform."

\n"); + } + foreach my $key (sort(keys(%env))) { + if ($key !~ /^form\.(.*)$/) { next; } + my $cleankey=$1; + if ($cleankey eq 'command') { next; } + $request->print(''."\n"); + } + # FIXME do a check for any duplicated user ids... + # FIXME do a check for any invalid user ids?... + $request->print('
+
'."\n"); + $request->print(&show_grading_menu_form($symb,$url)); + return ''; +} + +sub get_fields { + my %fields; + my @keyfields = split(/\,/,$env{'form.keyfields'}); + for (my $i=0; $i<=$env{'form.nfields'}; $i++) { + if ($env{'form.upfile_associate'} eq 'reverse') { + if ($env{'form.f'.$i} ne 'none') { + $fields{$keyfields[$i]}=$env{'form.f'.$i}; } } else { - if ($ENV{'form.f'.$i} ne 'none') { - $fields{$ENV{'form.f'.$i}}=$keyfields[$i]; + if ($env{'form.f'.$i} ne 'none') { + $fields{$env{'form.f'.$i}}=$keyfields[$i]; } } } + return %fields; +} + +sub csvuploadassign { + my ($request)= @_; + my ($symb,$url)=&get_symb_and_url($request); + if (!$symb) {return '';} + &Apache::loncommon::load_tmp_file($request); + my @gradedata = &Apache::loncommon::upfile_record_sep(); + if ($env{'form.noFirstLine'}) { shift(@gradedata); } + my %fields=&get_fields(); $request->print('

Assigning Grades

'); - my $courseid=$ENV{'request.course.id'}; + my $courseid=$env{'request.course.id'}; my ($classlist) = &getclasslist('all',0); my @notallowed; my @skipped; my $countdone=0; foreach my $grade (@gradedata) { my %entries=&Apache::loncommon::record_sep($grade); + my $domain; + if ($entries{$fields{'domain'}}) { + $domain=$entries{$fields{'domain'}}; + } else { + $domain=$env{'form.default_domain'}; + } + $domain=~s/\s//g; my $username=$entries{$fields{'username'}}; $username=~s/\s//g; - my $domain=$entries{$fields{'domain'}}; - $domain=~s/\s//g; + if (!$username) { + my $id=$entries{$fields{'ID'}}; + $id=~s/\s//g; + my %ids=&Apache::lonnet::idget($domain,$id); + $username=$ids{$id}; + } if (!exists($$classlist{"$username:$domain"})) { - push(@skipped,"$username:$domain"); + my $id=$entries{$fields{'ID'}}; + $id=~s/\s//g; + if ($id) { + push(@skipped,"$id:$domain"); + } else { + push(@skipped,"$username:$domain"); + } next; } my $usec=$classlist->{"$username:$domain"}[5]; @@ -2914,19 +3460,47 @@ sub csvuploadassign { push(@notallowed,"$username:$domain"); next; } + my %points; my %grades; foreach my $dest (keys(%fields)) { - if ($dest eq 'username' || $dest eq 'domain') { next; } - if ($entries{$fields{$dest}} eq '') { next; } - my $store_key=$dest; - $store_key=~s/^stores/resource/; - $store_key=~s/_/\./g; - $grades{$store_key}=$entries{$fields{$dest}}; - } - $grades{"resource.regrader"}="$ENV{'user.name'}:$ENV{'user.domain'}"; - &Apache::lonnet::cstore(\%grades,$symb,$ENV{'request.course.id'}, - $domain,$username); - $request->print('.'); + if ($dest eq 'ID' || $dest eq 'username' || + $dest eq 'domain') { next; } + if ($entries{$fields{$dest}} =~ /^\s*$/) { next; } + if ($dest=~/stores_(.*)_points/) { + my $part=$1; + my $wgt =&Apache::lonnet::EXT('resource.'.$part.'.weight', + $symb,$domain,$username); + $entries{$fields{$dest}}=~s/\s//g; + my $pcr=$entries{$fields{$dest}} / $wgt; + my $award='correct_by_override'; + $grades{"resource.$part.awarded"}=$pcr; + $grades{"resource.$part.solved"}=$award; + $points{$part}=1; + } else { + if ($dest=~/stores_(.*)_awarded/) { if ($points{$1}) {next;} } + if ($dest=~/stores_(.*)_solved/) { if ($points{$1}) {next;} } + my $store_key=$dest; + $store_key=~s/^stores/resource/; + $store_key=~s/_/\./g; + $grades{$store_key}=$entries{$fields{$dest}}; + } + } + if (! %grades) { push(@skipped,"$username:$domain no data to store"); } + $grades{"resource.regrader"}="$env{'user.name'}:$env{'user.domain'}"; +# &Apache::lonnet::logthis(" storing ".(join('-',%grades))); + my $result=&Apache::lonnet::cstore(\%grades,$symb, + $env{'request.course.id'}, + $domain,$username); + if ($result eq 'ok') { + $request->print('.'); + } else { + $request->print("

+ + Failed to store student $username\@$domain. + Message when trying to store was ($result) + +

" ); + } $request->rflush(); $countdone++; } @@ -2971,9 +3545,9 @@ function checkPickOne(formname) { LISTJAVASCRIPT &commonJSfunctions($request); 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 $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 $result='

 '. 'Manual Grading by Page or Sequence

'; @@ -3003,20 +3577,20 @@ LISTJAVASCRIPT $result.=''."\n". ''."\n"; - $result.=' View Problems Text: no '."\n". - ' yes '."
\n"; + $result.=' View Problems Text: '."\n". + ''."
\n"; $result.=' Submission Details: '. - ' none'."\n". - ' by dates and submissions'."\n". - ' all details'."\n"; + ''."\n". + ''."\n". + ''."\n"; $result.=''."\n". - ''."\n". + ''."\n". ''."\n". ''."\n". ''."\n". - ''."
\n"; + ''."
\n"; $result.=' 
'."\n"; @@ -3033,12 +3607,18 @@ LISTJAVASCRIPT my (undef,undef,$fullname) = &getclasslist($getsec,'1'); my $ptr = 1; - foreach my $student (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) { + foreach my $student (sort + { + if (lc($$fullname{$a}) ne lc($$fullname{$b})) { + return (lc($$fullname{$a}) cmp lc($$fullname{$b})); + } + return $a cmp $b; + } (keys(%$fullname))) { my ($uname,$udom) = split(/:/,$student); $studentTable.=($ptr%2 == 1 ? '
'.$ptr.'   ' - .&nameUserString(undef,$$fullname{$student},$uname,$udom)."\n"; + $studentTable.=' \n"; $studentTable.=($ptr%2 == 0 ? '
'. ''. ''. - ''; + ''; my ($depth,$question,$prob) = (1,1,1); $iterator->next(); # skip the first BEGIN_MAP @@ -3143,18 +3726,18 @@ sub displayPage { if($curRes == $iterator->BEGIN_MAP) { $depth++; } if($curRes == $iterator->END_MAP) { $depth--; } - if (ref($curRes) && $curRes->is_problem()) { + if (ref($curRes) && $curRes->is_problem() && !$curRes->randomout) { my $parts = $curRes->parts(); my $title = $curRes->compTitle(); my $symbx = $curRes->symb(); $studentTable.=''; $studentTable.='
 Prob.  '.($ENV{'form.vProb'} eq 'no' ? 'Title' : 'Problem Text').'/Grade
 '.($env{'form.vProb'} eq 'no' ? 'Title' : 'Problem Text').'/Grade
'.$prob. (scalar(@{$parts}) == 1 ? '' : '
('.scalar(@{$parts}).' parts)').'
'; - if ($ENV{'form.vProb'} eq 'yes' ) { + if ($env{'form.vProb'} eq 'yes' ) { $studentTable.=&show_problem($request,$symbx,$uname,$udom,1, undef,'both'); } else { - my $companswer = &Apache::loncommon::get_student_answers($symbx,$uname,$udom,$ENV{'request.course.id'}); + my $companswer = &Apache::loncommon::get_student_answers($symbx,$uname,$udom,$env{'request.course.id'}); $companswer =~ s|||g; $companswer =~ s|||g; # while ($companswer =~ /()/s) { #No recorded submission for this problem
'; } else { @@ -3184,10 +3767,10 @@ sub displayPage { $studentTable.= &displaySubByDates($symbx,\%record,$parts,\%responseType,$checkIcon,$uname,$udom); } - } elsif ($ENV{'form.lastSub'} eq 'all') { - my $last = ($ENV{'form.lastSub'} eq 'last' ? 'last' : ''); + } elsif ($env{'form.lastSub'} eq 'all') { + my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : ''); $studentTable.=&Apache::loncommon::get_previous_attempt($symbx,$uname,$udom, - $ENV{'request.course.id'}, + $env{'request.course.id'}, '','.submission'); } @@ -3205,8 +3788,6 @@ sub displayPage { $curRes = $iterator->next(); } - $navmap->untieHashes(); - $studentTable.='
'."\n". ''. @@ -3219,9 +3800,12 @@ sub displayPage { sub displaySubByDates { my ($symb,$record,$parts,$responseType,$checkIcon,$uname,$udom) = @_; + my $isCODE=0; + if (exists($record->{'resource.CODE'})) { $isCODE=1; } my $studentTable='
'. ''. ''. + ($isCODE?'':''). ''. ''; my ($version); @@ -3234,6 +3818,9 @@ sub displaySubByDates { for ($version=1;$version<=$$record{'version'};$version++) { my $timestamp = scalar(localtime($$record{$version.':timestamp'})); $studentTable.=''; + if ($isCODE) { + $studentTable.=''; + } my @versionKeys = split(/\:/,$$record{$version.':keys'}); my @displaySub = (); foreach my $partid (@{$parts}) { @@ -3292,28 +3879,33 @@ sub displaySubByDates { sub updateGradeByPage { 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'} eq '' ? 'all' : $ENV{'form.section'}; - my $pageTitle = $ENV{'form.page'}; + 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 $pageTitle = $env{'form.page'}; my ($classlist,undef,$fullname) = &getclasslist($getsec,'1'); - my ($uname,$udom) = split(/:/,$ENV{'form.student'}); - my $usec=$classlist->{$ENV{'form.student'}}[5]; + my ($uname,$udom) = split(/:/,$env{'form.student'}); + my $usec=$classlist->{$env{'form.student'}}[5]; if (!&canmodify($usec)) { - $request->print('Unable to modify requested student.('.$ENV{'form.student'}.''); - $request->print(&show_grading_menu_form($ENV{'form.symb'},$ENV{'form.url'})); + $request->print('Unable to modify requested student.('.$env{'form.student'}.''); + $request->print(&show_grading_menu_form($env{'form.symb'},$env{'form.url'})); return; } - my $result='

 '.$ENV{'form.title'}.'

'; - $result.='

 Student: '.&nameUserString(undef,$ENV{'form.fullname'},$uname,$udom). + my $result='

 '.$env{'form.title'}.'

'; + $result.='

 Student: '.&nameUserString(undef,$env{'form.fullname'},$uname,$udom). '

'."\n"; $request->print($result); my $navmap = Apache::lonnavmaps::navmap->new(); - my ($mapUrl, $id, $resUrl) = &Apache::lonnet::decode_symb( $ENV{'form.page'}); + my ($mapUrl, $id, $resUrl) = &Apache::lonnet::decode_symb( $env{'form.page'}); my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps - + if (!$map) { + $request->print('Unable to grade requested sequence. ('.$resUrl.')'); + my ($symb,$url)=&get_symb_and_url($request); + $request->print(&show_grading_menu_form($symb,$url)); + return; + } my $iterator = $navmap->getIterator($map->map_start(), $map->map_finish()); @@ -3341,12 +3933,14 @@ sub updateGradeByPage { my %newrecord=(); my @displayPts=(); + my %aggregate = (); + my $aggregateflag = 0; foreach my $partid (@{$parts}) { - my $newpts = $ENV{'form.GD_BOX'.$question.'_'.$partid}; - my $oldpts = $ENV{'form.oldpts'.$question.'_'.$partid}; + my $newpts = $env{'form.GD_BOX'.$question.'_'.$partid}; + my $oldpts = $env{'form.oldpts'.$question.'_'.$partid}; - my $wgt = $ENV{'form.WGT'.$question.'_'.$partid} != 0 ? - $ENV{'form.WGT'.$question.'_'.$partid} : 1; + my $wgt = $env{'form.WGT'.$question.'_'.$partid} != 0 ? + $env{'form.WGT'.$question.'_'.$partid} : 1; my $partial = $newpts/$wgt; my $score; if ($partial > 0) { @@ -3354,23 +3948,31 @@ sub updateGradeByPage { } elsif ($newpts ne '') { #empty is taken as 0 $score = 'incorrect_by_override'; } - my $dropMenu = $ENV{'form.GD_SEL'.$question.'_'.$partid}; + my $dropMenu = $env{'form.GD_SEL'.$question.'_'.$partid}; if ($dropMenu eq 'excused') { $partial = ''; $score = 'excused'; } elsif ($dropMenu eq 'reset status' - && $ENV{'form.solved'.$question.'_'.$partid} ne '') { #update only if previous record exists + && $env{'form.solved'.$question.'_'.$partid} ne '') { #update only if previous record exists $newrecord{'resource.'.$partid.'.tries'} = 0; $newrecord{'resource.'.$partid.'.solved'} = ''; $newrecord{'resource.'.$partid.'.award'} = ''; $newrecord{'resource.'.$partid.'.awarded'} = 0; - $newrecord{'resource.'.$partid.'.regrader'} = "$ENV{'user.name'}:$ENV{'user.domain'}"; + $newrecord{'resource.'.$partid.'.regrader'} = "$env{'user.name'}:$env{'user.domain'}"; $changeflag++; $newpts = ''; + + my $aggtries = $env{'form.aggtries'.$question.'_'.$partid}; + my $totaltries = $env{'form.totaltries'.$question.'_'.$partid}; + my $solvedstatus = $env{'form.solved'.$question.'_'.$partid}; + if ($aggtries > 0) { + &decrement_aggs($symbx,$partid,\%aggregate,$aggtries,$totaltries,$solvedstatus); + $aggregateflag = 1; + } } my $display_part=&get_display_part($partid,undef, $curRes->symb()); - my $oldstatus = $ENV{'form.solved'.$question.'_'.$partid}; + my $oldstatus = $env{'form.solved'.$question.'_'.$partid}; $displayPts[0].=' Part: '.$display_part.' = '. (($oldstatus eq 'excused') ? 'excused' : $oldpts). ' 
'; @@ -3383,15 +3985,20 @@ sub updateGradeByPage { $newrecord{'resource.'.$partid.'.awarded'} = $partial if $partial ne ''; $newrecord{'resource.'.$partid.'.solved'} = $score if $score ne ''; - $newrecord{'resource.'.$partid.'.regrader'} = "$ENV{'user.name'}:$ENV{'user.domain'}" + $newrecord{'resource.'.$partid.'.regrader'} = "$env{'user.name'}:$env{'user.domain'}" if (scalar(keys(%newrecord)) > 0); $changeflag++; } if (scalar(keys(%newrecord)) > 0) { - &Apache::lonnet::cstore(\%newrecord,$symbx,$ENV{'request.course.id'}, + &Apache::lonnet::cstore(\%newrecord,$symbx,$env{'request.course.id'}, $udom,$uname); } + if ($aggregateflag) { + &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, + $env{'course.'.$env{'request.course.id'}.'.domain'}, + $env{'course.'.$env{'request.course.id'}.'.num'}); + } $studentTable.=''. ''. @@ -3402,10 +4009,8 @@ sub updateGradeByPage { $curRes = $iterator->next(); } - $navmap->untieHashes(); - $studentTable.='
Date/TimeCODESubmissionStatus 
'.$timestamp.''.$record->{$version.':resource.CODE'}.''.$displayPts[0].''.$displayPts[1].'
'; - $studentTable.=&show_grading_menu_form($ENV{'form.symb'},$ENV{'form.url'}); + $studentTable.=&show_grading_menu_form($env{'form.symb'},$env{'form.url'}); my $grademsg=($changeflag == 0 ? 'No score was changed or updated.' : 'The scores were changed for '. $changeflag.' problem'.($changeflag == 1 ? '.' : 's.')); @@ -3427,8 +4032,8 @@ sub defaultFormData { return ' '."\n". ''."\n". - ''."\n". - ''."\n"; + ''."\n". + ''."\n"; } sub getSequenceDropDown { @@ -3449,8 +4054,8 @@ sub getSequenceDropDown { } sub scantron_filenames { - my $cdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; - my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'}; + my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cname=$env{'course.'.$env{'request.course.id'}.'.num'}; my @files=&Apache::lonnet::dirlist('userfiles',$cdom,$cname, &Apache::loncommon::propath($cdom,$cname)); my @possiblenames; @@ -3464,10 +4069,11 @@ sub scantron_filenames { } sub scantron_uploads { + my ($file2grade) = @_; my $result= '"; return $result; @@ -3488,12 +4094,13 @@ sub scantron_scantab { } sub scantron_CODElist { - my $cdom = $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; - my $cnum = $ENV{'course.'.$ENV{'request.course.id'}.'.num'}; + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; my @names=&Apache::lonnet::getkeys('CODEs',$cdom,$cnum); my $namechoice=''; - foreach my $name (sort(@names)) { + foreach my $name (sort {uc($a) cmp uc($b)} @names) { if ($name =~ /^error: 2 /) { next; } + if ($name =~ /^type\0/) { next; } $namechoice.=''; } $namechoice=''; @@ -3502,24 +4109,24 @@ sub scantron_CODElist { sub scantron_CODEunique { my $result=' - Yes + - No + '; return $result; } sub scantron_selectphase { - my ($r) = @_; + my ($r,$file2grade) = @_; 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 $file_selector=&scantron_uploads($file2grade); my $format_selector=&scantron_scantab(); my $CODE_selector=&scantron_CODElist(); my $CODE_unique=&scantron_CODEunique(); @@ -3529,8 +4136,8 @@ sub scantron_selectphase { $result.= <
- $default_form_data @@ -3557,25 +4164,25 @@ sub scantron_selectphase {
Options: - Do only previously skipped records
- Remove all exisiting corrections +
+
- +
- -
SCANTRONFORM my $default_form_data=&defaultFormData(&get_symb_and_url($r,1)); - my $cdom= $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; - my $cnum= $ENV{'course.'.$ENV{'request.course.id'}.'.num'}; + my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum= $env{'course.'.$env{'request.course.id'}.'.num'}; $r->print(< function checkUpload(formname) { @@ -3624,8 +4231,8 @@ SCANTRONFORM } $r->print(< - -
+ +
@@ -3638,18 +4245,17 @@ SCANTRONFORM
- +
- -
List of CODES to validate against:'. + $CODElist.'
- - + + +$CODElist
Sequence To be Graded:$title
Data File that will be used:$ENV{'form.scantron_selectfile'}
Sequence to be Graded:$title
Data File that will be used:$env{'form.scantron_selectfile'}

@@ -3981,14 +4641,28 @@ sub scantron_do_warning { if (!$symb) {return '';} my $default_form_data=&defaultFormData($symb,$url); $r->print(&scantron_form_start().$default_form_data); - my $warning=&scantron_warning_screen('Validate Records'); - $r->print(<print("

You have forgetten to specify some information. Please go Back and try again.

"); + if ( $env{'form.selectpage'} eq '') { + $r->print('

You have not selected a Sequence to grade

'); + } + if ( $env{'form.scantron_selectfile'} eq '') { + $r->print('

You have not selected a file that contains the student\'s response data.

'); + } + if ( $env{'form.scantron_format'} eq '') { + $r->print('

You have not selected a the format of the student\'s response data.

'); + } + } else { + my $warning=&scantron_warning_screen('Grading: Validate Records'); + $r->print(< + - STUFF - $r->print("
".&show_grading_menu_form($symb,$url).""); + } + $r->print("
".&show_grading_menu_form($symb,$url).""); return ''; } @@ -3996,14 +4670,14 @@ sub scantron_form_start { my ($max_bubble)=@_; my $result= < - - - + + + - - - - + + + + SCANTRONFORM return $result; } @@ -4016,23 +4690,23 @@ sub scantron_validate_file { # do the detection of only doing skipped records first befroe we delete # them when doing the corrections reset - if ($ENV{'form.scantron_options_redo'} ne 'redo_skipped_ready') { + if ($env{'form.scantron_options_redo'} ne 'redo_skipped_ready') { &reset_skipping_status(); } - if ($ENV{'form.scantron_options_redo'} eq 'redo_skipped') { + if ($env{'form.scantron_options_redo'} eq 'redo_skipped') { &remember_current_skipped(); &scantron_remove_file('skipped'); - $ENV{'form.scantron_options_redo'}='redo_skipped_ready'; + $env{'form.scantron_options_redo'}='redo_skipped_ready'; } - if ($ENV{'form.scantron_options_ignore'} eq 'ignore_corrections') { + if ($env{'form.scantron_options_ignore'} eq 'ignore_corrections') { &check_for_error($r,&scantron_remove_file('corrected')); &check_for_error($r,&scantron_remove_file('skipped')); &check_for_error($r,&scantron_remove_scan_data()); - $ENV{'form.scantron_options_ignore'}='done'; + $env{'form.scantron_options_ignore'}='done'; } - if ($ENV{'form.scantron_corrections'}) { + if ($env{'form.scantron_corrections'}) { &scantron_process_corrections($r); } $r->print("

Gathering neccessary info.

");$r->rflush(); @@ -4046,10 +4720,10 @@ sub scantron_validate_file { 'CODE', 'doublebubble', 'missingbubbles'); - if (!$ENV{'form.validatepass'}) { - $ENV{'form.validatepass'} = 0; + if (!$env{'form.validatepass'}) { + $env{'form.validatepass'} = 0; } - my $currentphase=$ENV{'form.validatepass'}; + my $currentphase=$env{'form.validatepass'}; my $stop=0; while (!$stop && $currentphase < scalar(@validate_phases)) { @@ -4087,27 +4761,27 @@ STUFF sub scantron_remove_file { my ($which)=@_; - my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'}; - my $cdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; + my $cname=$env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'}; my $file='scantron_'; if ($which eq 'corrected' || $which eq 'skipped') { $file.=$which.'_'; } else { return 'refused'; } - $file.=$ENV{'form.scantron_selectfile'}; + $file.=$env{'form.scantron_selectfile'}; return &Apache::lonnet::removeuserfile($cname,$cdom,$file); } sub scantron_remove_scan_data { - my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'}; - my $cdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; + my $cname=$env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'}; my @keys=&Apache::lonnet::getkeys('nohist_scantrondata',$cdom,$cname); my @todelete; - my $filename=$ENV{'form.scantron_selectfile'}; + my $filename=$env{'form.scantron_selectfile'}; foreach my $key (@keys) { if ($key=~/^\Q$filename\E_/) { - if ($ENV{'form.scantron_options_redo'} eq 'redo_skipped_ready' && + if ($env{'form.scantron_options_redo'} eq 'redo_skipped_ready' && $key=~/remember_skipping/) { next; } @@ -4123,25 +4797,25 @@ sub scantron_remove_scan_data { sub scantron_getfile { #FIXME really would prefer a scantron directory - my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'}; - my $cdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; + my $cname=$env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'}; my $lines; $lines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'. - 'scantron_orig_'.$ENV{'form.scantron_selectfile'}); + 'scantron_orig_'.$env{'form.scantron_selectfile'}); my %scanlines; $scanlines{'orig'}=[(split("\n",$lines,-1))]; my $temp=$scanlines{'orig'}; $scanlines{'count'}=$#$temp; $lines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'. - 'scantron_corrected_'.$ENV{'form.scantron_selectfile'}); + 'scantron_corrected_'.$env{'form.scantron_selectfile'}); if ($lines eq '-1') { $scanlines{'corrected'}=[]; } else { $scanlines{'corrected'}=[(split("\n",$lines,-1))]; } $lines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'. - 'scantron_skipped_'.$ENV{'form.scantron_selectfile'}); + 'scantron_skipped_'.$env{'form.scantron_selectfile'}); if ($lines eq '-1') { $scanlines{'skipped'}=[]; } else { @@ -4155,30 +4829,29 @@ sub scantron_getfile { sub lonnet_putfile { my ($contents,$filename)=@_; - my $docuname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'}; - my $docudom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; - my $docuhome=$ENV{'course.'.$ENV{'request.course.id'}.'.home'}; - $ENV{'form.sillywaytopassafilearound'}=$contents; - &Apache::lonnet::finishuserfileupload($docuname,$docudom,$docuhome,'sillywaytopassafilearound',$filename); + my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'}; + my $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'}; + $env{'form.sillywaytopassafilearound'}=$contents; + &Apache::lonnet::finishuserfileupload($docuname,$docudom,'sillywaytopassafilearound',$filename); } sub scantron_putfile { my ($scanlines,$scan_data) = @_; #FIXME really would prefer a scantron directory - my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'}; - my $cdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; + my $cname=$env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'}; if ($scanlines) { my $prefix='scantron_'; # no need to update orig, shouldn't change # &lonnet_putfile(join("\n",@{$scanlines->{'orig'}}),$prefix.'orig_'. -# $ENV{'form.scantron_selectfile'}); +# $env{'form.scantron_selectfile'}); &lonnet_putfile(join("\n",@{$scanlines->{'corrected'}}), $prefix.'corrected_'. - $ENV{'form.scantron_selectfile'}); + $env{'form.scantron_selectfile'}); &lonnet_putfile(join("\n",@{$scanlines->{'skipped'}}), $prefix.'skipped_'. - $ENV{'form.scantron_selectfile'}); + $env{'form.scantron_selectfile'}); } &Apache::lonnet::put('nohist_scantrondata',$scan_data,$cdom,$cname); } @@ -4220,7 +4893,7 @@ sub scantron_validate_ID { my %idmap=&username_to_idmap($classlist); #get scantron line setup - my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'}); + my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); my ($scanlines,$scan_data)=&scantron_getfile(); my %found=('ids'=>{},'usernames'=>{}); @@ -4289,6 +4962,12 @@ sub scantron_get_correction { $r->print(" in scanline $i
".
 		  $line."
\n"); } + my $message="

The ID on the form is ". + $$scan_record{'scantron.ID'}."
\n". + "The name on the paper is ". + $$scan_record{'scantron.LastName'}.",". + $$scan_record{'scantron.FirstName'}."

"; + $r->print(''."\n"); $r->print(''."\n"); if ($error =~ /ID$/) { @@ -4297,11 +4976,7 @@ sub scantron_get_correction { } elsif ($error eq 'duplicateID') { $r->print("The encoded ID has also been used by a previous paper $arg

\n"); } - $r->print("

The ID on the form is ". - $$scan_record{'scantron.ID'}."
\n"); - $r->print("The name on the paper is ". - $$scan_record{'scantron.LastName'}.",". - $$scan_record{'scantron.FirstName'}."

"); + $r->print($message); $r->print("

How should I handle this?
\n"); $r->print("\n

  • "); #FIXME it would be nice if this sent back the user ID and @@ -4310,7 +4985,7 @@ sub scantron_get_correction { 'scantron_username','scantron_domain')); $r->print(": "); $r->print("\n@". - &Apache::loncommon::select_dom_form($ENV{'request.role.domain'},'scantron_domain')); + &Apache::loncommon::select_dom_form($env{'request.role.domain'},'scantron_domain')); $r->print('
  • '); } elsif ($error =~ /CODE$/) { @@ -4319,29 +4994,30 @@ sub scantron_get_correction { } elsif ($error eq 'duplicateCODE') { $r->print("

    The encoded CODE has also been used by a previous paper ".join(', ',@{$arg}).", and CODEs are supposed to be unique

    \n"); } - $r->print("

    The CODE on the form is ". - $$scan_record{'scantron.CODE'}."
    \n"); - $r->print("

    The ID on the form is ". - $$scan_record{'scantron.ID'}."
    \n"); - $r->print("The name on the paper is ". - $$scan_record{'scantron.LastName'}.",". - $$scan_record{'scantron.FirstName'}."

    "); + $r->print("

    The CODE on the form is '". + $$scan_record{'scantron.CODE'}."'
    \n"); + $r->print($message); $r->print("

    How should I handle this?
    \n"); $r->print("\n
    "); my $i=0; - if ($error eq 'incorrectCODE') { + if ($error eq 'incorrectCODE' + && $$scan_record{'scantron.CODE'}=~/\S/ ) { my ($max,$closest)=&scantron_get_closely_matching_CODEs($arg,$$scan_record{'scantron.CODE'}); - foreach my $testcode (@{$closest}) { - my $checked=''; - if (!$i) { $checked=' checked="on" '; } - $r->print(" Use the similar CODE ".$testcode." instead."); - $r->print("\n
    "); - $i++; + if ($closest > 0) { + foreach my $testcode (@{$closest}) { + my $checked=''; + if (!$i) { $checked=' checked="on" '; } + $r->print(""); + $r->print("\n
    "); + $i++; + } } } - my $checked; if (!$i) { $checked=' checked="on" '; } - $r->print(" Use the CODE ".$$scan_record{'scantron.CODE'}." that is was on the paper, ignoring the error."); - $r->print("\n
    "); + if ($$scan_record{'scantron.CODE'}=~/\S/ ) { + my $checked; if (!$i) { $checked=' checked="on" '; } + $r->print(""); + $r->print("\n
    "); + } $r->print(< @@ -4356,18 +5032,19 @@ function change_radio(field) { ENDSCRIPT my $href="/adm/pickcode?". "form=".&Apache::lonnet::escape("scantronupload"). - "&scantron_format=".&Apache::lonnet::escape($ENV{'form.scantron_format'}). - "&scantron_CODElist=".&Apache::lonnet::escape($ENV{'form.scantron_CODElist'}). + "&scantron_format=".&Apache::lonnet::escape($env{'form.scantron_format'}). + "&scantron_CODElist=".&Apache::lonnet::escape($env{'form.scantron_CODElist'}). "&curCODE=".&Apache::lonnet::escape($$scan_record{'scantron.CODE'}). - "&scantron_selectfile=".&Apache::lonnet::escape($ENV{'form.scantron_selectfile'}); - $r->print(" Select a CODE from the list of all CODEs and use it. Selected CODE is "); + "&scantron_selectfile=".&Apache::lonnet::escape($env{'form.scantron_selectfile'}); + $r->print(" Selected CODE is "); $r->print("\n
    "); - $r->print(" Use as the CODE."); + $r->print(" as the CODE."); $r->print("\n

    "); } elsif ($error eq 'doublebubble') { $r->print("

    There have been multiple bubbles scanned for a some question(s)

    \n"); $r->print(''); + $r->print($message); $r->print("

    Please indicate which bubble should be used for grading

    "); foreach my $question (@{$arg}) { my $selected=$$scan_record{"scantron.$question.answer"}; @@ -4375,6 +5052,7 @@ ENDSCRIPT } } elsif ($error eq 'missingbubble') { $r->print("

    There have been no bubbles scanned for some question(s)

    \n"); + $r->print($message); $r->print("

    Please indicate which bubble should be used for grading

    "); $r->print("Some questions have no scanned bubbles\n"); $r->print('$quest"); for (my $i=0;$i<$max+1;$i++) { - $r->print(''); + $r->print("\n".''); if ($selected[0] eq $alphabet[$i]) { $r->print('X'); shift(@selected) } else { $r->print(' '); } $r->print(''); } - $r->print(''); + $r->print(''); for (my $i=0;$i<$max;$i++) { - $r->print(''.$alphabet[$i].""); + $r->print("\n". + '"); } - $r->print(' No bubble '); + $r->print(''); $r->print(''); } @@ -4433,21 +5116,34 @@ sub scantron_get_closely_matching_CODEs } sub get_codes { - my $old_name=$ENV{'form.scantron_CODElist'}; - my $cdom =$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; - my $cnum =$ENV{'course.'.$ENV{'request.course.id'}.'.num'}; - my %result=&Apache::lonnet::get('CODEs',[$old_name],$cdom,$cnum); - my %allcodes=map {(&Apache::lonprintout::num_to_letters($_),1)} split(',',$result{$old_name}); + my ($old_name, $cdom, $cnum) = @_; + if (!$old_name) { + $old_name=$env{'form.scantron_CODElist'}; + } + if (!$cdom) { + $cdom =$env{'course.'.$env{'request.course.id'}.'.domain'}; + } + if (!$cnum) { + $cnum =$env{'course.'.$env{'request.course.id'}.'.num'}; + } + my %result=&Apache::lonnet::get('CODEs',[$old_name,"type\0$old_name"], + $cdom,$cnum); + my %allcodes; + if ($result{"type\0$old_name"} eq 'number') { + %allcodes=map {($_,1)} split(',',$result{$old_name}); + } else { + %allcodes=map {(&Apache::lonprintout::num_to_letters($_),1)} split(',',$result{$old_name}); + } return %allcodes; } sub scantron_validate_CODE { my ($r,$currentphase) = @_; - my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'}); + my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); if ($scantron_config{'CODElocation'} && $scantron_config{'CODEstart'} && $scantron_config{'CODElength'}) { - if (!defined($ENV{'form.scantron_CODElist'})) { + if (!defined($env{'form.scantron_CODElist'})) { &FIXME_blow_up() } } else { @@ -4466,14 +5162,21 @@ sub scantron_validate_CODE { $scan_data); my $CODE=$$scan_record{'scantron.CODE'}; my $error=0; - if (!exists($allcodes{$CODE}) && !$$scan_record{'scantron.useCODE'}) { + if (!&Apache::lonnet::validCODE($CODE)) { + &scantron_get_correction($r,$i,$scan_record, + \%scantron_config, + $line,'incorrectCODE',\%allcodes); + return(1,$currentphase); + } + if (%allcodes && !exists($allcodes{$CODE}) + && !$$scan_record{'scantron.useCODE'}) { &scantron_get_correction($r,$i,$scan_record, \%scantron_config, $line,'incorrectCODE',\%allcodes); return(1,$currentphase); } if (exists($usedCODEs{$CODE}) - && $ENV{'form.scantron_CODEunique'} eq 'yes' + && $env{'form.scantron_CODEunique'} eq 'yes' && !$$scan_record{'scantron.CODE_ignore_dup'}) { &scantron_get_correction($r,$i,$scan_record, \%scantron_config, @@ -4492,7 +5195,7 @@ sub scantron_validate_doublebubble { my %idmap=&username_to_idmap($classlist); #get scantron line setup - my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'}); + my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); my ($scanlines,$scan_data)=&scantron_getfile(); for (my $i=0;$i<=$scanlines->{'count'};$i++) { my $line=&scantron_get_line($scanlines,$scan_data,$i); @@ -4510,27 +5213,27 @@ sub scantron_validate_doublebubble { sub scantron_get_maxbubble { my ($r)=@_; - if (defined($ENV{'form.scantron_maxbubble'}) && - $ENV{'form.scantron_maxbubble'}) { - return $ENV{'form.scantron_maxbubble'}; + if (defined($env{'form.scantron_maxbubble'}) && + $env{'form.scantron_maxbubble'}) { + return $env{'form.scantron_maxbubble'}; } my $navmap=Apache::lonnavmaps::navmap->new(); my (undef,undef,$sequence)= - &Apache::lonnet::decode_symb($ENV{'form.selectpage'}); + &Apache::lonnet::decode_symb($env{'form.selectpage'}); my $map=$navmap->getResourceByUrl($sequence); my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); &Apache::lonnet::delenv('form.counter'); foreach my $resource (@resources) { - my $result=&Apache::lonnet::ssi($resource->src()); + my $result=&Apache::lonnet::ssi($resource->src().'?symb='.&Apache::lonnet::escape($resource->symb())); } &Apache::lonnet::delenv('scantron\.'); - my $envfile=$ENV{'user.environment'}; + my $envfile=$env{'user.environment'}; $envfile=~/\/([^\/]+)\.id$/; $envfile=$1; &Apache::lonnet::transfer_profile_to_env($r->dir_config('lonIDsDir'), $envfile); - $ENV{'form.scantron_maxbubble'}=$ENV{'form.counter'}-1; - return $ENV{'form.scantron_maxbubble'}; + $env{'form.scantron_maxbubble'}=$env{'form.counter'}-1; + return $env{'form.scantron_maxbubble'}; } sub scantron_validate_missingbubbles { @@ -4540,7 +5243,7 @@ sub scantron_validate_missingbubbles { my %idmap=&username_to_idmap($classlist); #get scantron line setup - my %scantron_config=&get_scantron_config($ENV{'form.scantron_format'}); + my %scantron_config=&get_scantron_config($env{'form.scantron_format'}); my ($scanlines,$scan_data)=&scantron_getfile(); my $max_bubble=&scantron_get_maxbubble(); if (!$max_bubble) { $max_bubble=2**31; } @@ -4567,12 +5270,12 @@ sub scantron_validate_missingbubbles { sub scantron_process_students { my ($r) = @_; - my (undef,undef,$sequence)=&Apache::lonnet::decode_symb($ENV{'form.selectpage'}); + my (undef,undef,$sequence)=&Apache::lonnet::decode_symb($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 %scantron_config=&get_scantron_config($env{'form.scantron_format'}); my ($scanlines,$scan_data)=&scantron_getfile(); my $classlist=&Apache::loncoursedata::get_classlist(); my %idmap=&username_to_idmap($classlist); @@ -4633,13 +5336,19 @@ SCANTRONFORM 'grade_target' =>'grade', 'grade_username'=>$uname, 'grade_domain' =>$udom, - 'grade_courseid'=>$ENV{'request.course.id'}, + 'grade_courseid'=>$env{'request.course.id'}, 'grade_symb' =>$resource->symb()); if (exists($scan_record->{'scantron.CODE'}) && $scan_record->{'scantron.CODE'}) { $form{'CODE'}=$scan_record->{'scantron.CODE'}; + } else { + $form{'CODE'}=''; } my $result=&Apache::lonnet::ssi($resource->src(),%form); + if ($result ne '') { + &Apache::lonnet::logthis("scantron grading error -> $result"); + &Apache::lonnet::logthis("scantron grading error info name $uname domain $udom course $env{'request.course.id'} url ".$resource->src()); + } if (&Apache::loncommon::connection_aborted($r)) { last; } } $completedstudents{$uname}={'line'=>$line}; @@ -4652,7 +5361,6 @@ SCANTRONFORM # my $lasttime = &Time::HiRes::time()-$start; # $r->print("

    took $lasttime

    "); - $navmap->untieHashes(); $r->print(""); $r->print(&show_grading_menu_form($symb,$url)); return ''; @@ -4660,11 +5368,11 @@ SCANTRONFORM sub scantron_upload_scantron_data { my ($r)=@_; - $r->print(&Apache::loncommon::coursebrowser_javascript($ENV{'request.role.domain'})); + $r->print(&Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'})); my $select_link=&Apache::loncommon::selectcourse_link('rules','courseid', 'domainid', 'coursename'); - my $domsel=&Apache::loncommon::select_dom_form($ENV{'request.role.domain'}, + my $domsel=&Apache::loncommon::select_dom_form($env{'request.role.domain'}, 'domainid'); my $default_form_data=&defaultFormData(&get_symb_and_url($r,1)); $r->print(<'."\n". ''."\n". ''."\n"; - if (!&Apache::lonnet::allowed('usc',$ENV{'form.domainid'}) && + if (!&Apache::lonnet::allowed('usc',$env{'form.domainid'}) && !&Apache::lonnet::allowed('usc', - $ENV{'form.domainid'}.'_'.$ENV{'form.courseid'})) { + $env{'form.domainid'}.'_'.$env{'form.courseid'})) { $r->print("You are not allowed to upload Scantron data to the requested course.
    "); if ($symb) { $r->print(&show_grading_menu_form($symb,$url)); @@ -4713,10 +5421,9 @@ sub scantron_upload_scantron_data_save { } return ''; } - $r->print("Doing upload to ".$ENV{'form.courseid'}."
    "); - my $home=&Apache::lonnet::homeserver($ENV{'form.courseid'}, - $ENV{'form.domainid'}); - my $fname=$ENV{'form.upfile.filename'}; + my %coursedata=&Apache::lonnet::coursedescription($env{'form.domainid'}.'_'.$env{'form.courseid'}); + $r->print("Doing upload to ".$coursedata{'description'}."
    "); + my $fname=$env{'form.upfile.filename'}; #FIXME #copied from lonnet::userfileupload() #make that function able to target a specified course @@ -4730,19 +5437,20 @@ sub scantron_upload_scantron_data_save { $fname=~s/[^\w\.\-]//g; # See if there is anything left unless ($fname) { return 'error: no uploaded file'; } + my $uploadedfile=$fname; $fname='scantron_orig_'.$fname; - if (length($ENV{'form.upfile'}) < 2) { - $r->print("Error: The file you attempted to upload, ".&HTML::Entities::encode($ENV{'form.upfile.filename'},'<>&"').", contained no information. Please check that you entered the correct filename."); + if (length($env{'form.upfile'}) < 2) { + $r->print("Error: The file you attempted to upload, ".&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').", contained no information. Please check that you entered the correct filename."); } else { - my $result=&Apache::lonnet::finishuserfileupload($ENV{'form.courseid'},$ENV{'form.domainid'},$home,'upfile',$fname); + my $result=&Apache::lonnet::finishuserfileupload($env{'form.courseid'},$env{'form.domainid'},'upfile',$fname); if ($result =~ m|^/uploaded/|) { - $r->print("Success: Successfully uploaded ".(length($ENV{'form.upfile'})-1)." bytes of data into location ".$result.""); + $r->print("Success: Successfully uploaded ".(length($env{'form.upfile'})-1)." bytes of data into location ".$result.""); } else { - $r->print("Error: An error (".$result.") occured when attempting to upload the file, ".&HTML::Entities::encode($ENV{'form.upfile.filename'},'<>&"').""); + $r->print("Error: An error (".$result.") occurred when attempting to upload the file, ".&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').""); } } if ($symb) { - $r->print(&show_grading_menu_form($symb,$url)); + $r->print(&scantron_selectphase($r,$uploadedfile)); } else { $r->print($doanotherupload); } @@ -4761,9 +5469,9 @@ sub valid_file { sub scantron_download_scantron_data { my ($r)=@_; my $default_form_data=&defaultFormData(&get_symb_and_url($r,1)); - my $cname=$ENV{'course.'.$ENV{'request.course.id'}.'.num'}; - my $cdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'}; - my $file=$ENV{'form.scantron_selectfile'}; + my $cname=$env{'course.'.$env{'request.course.id'}.'.num'}; + my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'}; + my $file=$env{'form.scantron_selectfile'}; if (! &valid_file($file)) { $r->print(< @@ -4798,7 +5506,6 @@ DOWNLOAD # #------------------------------------------------------------------- - #-------------------------- Menu interface ------------------------- # #--- Show a Grading Menu button - Calls the next routine --- @@ -4807,7 +5514,7 @@ sub show_grading_menu_form { my $result.='
    '."\n". ''."\n". ''."\n". - ''."\n". + ''."\n". ''."\n". ''."\n". '
    '."\n"; @@ -4817,8 +5524,8 @@ sub show_grading_menu_form { # -- Retrieve choices for grading form sub savedState { my %savedState = (); - if ($ENV{'form.saveState'}) { - foreach (split(/:/,$ENV{'form.saveState'})) { + if ($env{'form.saveState'}) { + foreach (split(/:/,$env{'form.saveState'})) { my ($key,$value) = split(/=/,$_,2); $savedState{$key} = $value; } @@ -4851,6 +5558,7 @@ sub gradingmenu { if (!checkReceiptNo(formname,'notOK')) { return false;} formname.submit(); } + if (val < 7) formname.submit(); } function checkReceiptNo(formname,nospace) { @@ -4903,37 +5611,36 @@ GRADINGMENUJS ($saveSec eq $_ ? 'selected="on"':'').'>'.$_.''."\n"; } } - $result.= '   '; $result.=&mt('Student Status').':'.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,1,undef); - if (ref($sections) && (grep /no/,@$sections)) { - $result.=' (Section "no" implies the students were not assigned a section.)
    '; - } $result.=''; - $result.=''. + $result.=''."\n"; $result.=''. - ' '. - 'The complete set/page/sequence: For one student'."\n"; + 'The complete set/page/sequence: For one student'."\n"; $result.='
    '. ''. @@ -4950,14 +5657,20 @@ GRADINGMENUJS ' scantron forms'."\n"; - if ((&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'})) && ($symb)) { + if ((&Apache::lonnet::allowed('mgr',$env{'request.course.id'})) && ($symb)) { $result.=''. ''. ' '.&mt('receipt').': '. - &Apache::lonnet::recprefix($ENV{'request.course.id'}). + &Apache::lonnet::recprefix($env{'request.course.id'}). '-'. ''."\n"; } + $result.=''. + ' access times.'."\n"; + $result.=''. + ' saved CODEs.'."\n"; $result.=''."\n". ''."\n". @@ -4965,11 +5678,33 @@ GRADINGMENUJS return $result; } +sub reset_perm { + undef(%perm); +} + +sub init_perm { + &reset_perm(); + foreach my $test_perm ('vgr','mgr','opa') { + + my $scope = $env{'request.course.id'}; + if (!($perm{$test_perm}=&Apache::lonnet::allowed($test_perm,$scope))) { + + $scope .= '/'.$env{'request.course.sec'}; + if ( $perm{$test_perm}= + &Apache::lonnet::allowed($test_perm,$scope)) { + $perm{$test_perm.'_section'}=$env{'request.course.sec'}; + } else { + delete($perm{$test_perm}); + } + } + } +} + sub handler { my $request=$_[0]; - undef(%perm); - if ($ENV{'browser.mathml'}) { + &reset_perm(); + if ($env{'browser.mathml'}) { &Apache::loncommon::content_type($request,'text/xml'); } else { &Apache::loncommon::content_type($request,'text/html'); @@ -4977,8 +5712,8 @@ sub handler { $request->send_http_header; return '' if $request->header_only; &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}); - my $url=$ENV{'form.url'}; - my $symb=$ENV{'form.symb'}; + my $url=$env{'form.url'}; + my $symb=$env{'form.symb'}; my @commands=&Apache::loncommon::get_env_multiple('form.command'); my $command=$commands[0]; if ($#commands > 0) { @@ -4986,16 +5721,16 @@ sub handler { } if (!$url) { my ($temp1,$temp2); - ($temp1,$temp2,$ENV{'form.url'})=&Apache::lonnet::decode_symb($symb); - $url = $ENV{'form.url'}; + ($temp1,$temp2,$env{'form.url'})=&Apache::lonnet::decode_symb($symb); + $url = $env{'form.url'}; } &send_header($request); if ($url eq '' && $symb eq '' && $command eq '') { - if ($ENV{'user.adv'}) { - if (($ENV{'form.codeone'}) && ($ENV{'form.codetwo'}) && - ($ENV{'form.codethree'})) { - my $token=$ENV{'form.codeone'}.'*'.$ENV{'form.codetwo'}.'*'. - $ENV{'form.codethree'}; + if ($env{'user.adv'}) { + if (($env{'form.codeone'}) && ($env{'form.codetwo'}) && + ($env{'form.codethree'})) { + my $token=$env{'form.codeone'}.'*'.$env{'form.codetwo'}.'*'. + $env{'form.codethree'}; my ($tsymb,$tuname,$tudom,$tcrsid)= &Apache::lonnet::checkin($token); if ($tsymb) { @@ -5017,22 +5752,9 @@ sub handler { } } } else { - if (!($perm{'vgr'}=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'}))) { - if ($perm{'vgr'}=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'}.'/'.$ENV{'request.course.sec'})) { - $perm{'vgr_section'}=$ENV{'request.course.sec'}; - } else { - delete($perm{'vgr'}); - } - } - if (!($perm{'mgr'}=&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'}))) { - if ($perm{'mgr'}=&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'}.'/'.$ENV{'request.course.sec'})) { - $perm{'mgr_section'}=$ENV{'request.course.sec'}; - } else { - delete($perm{'mgr'}); - } - } + &init_perm(); if ($command eq 'submission' && $perm{'vgr'}) { - ($ENV{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0)); + ($env{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0)); } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) { &pickStudentPage($request); } elsif ($command eq 'displayPage' && $perm{'vgr'}) { @@ -5057,17 +5779,19 @@ sub handler { $request->print(&csvupload($request)); } elsif ($command eq 'csvuploadmap' && $perm{'mgr'} ) { $request->print(&csvuploadmap($request)); - } elsif ($command eq 'csvuploadassign' && $perm{'mgr'}) { - if ($ENV{'form.associate'} ne 'Reverse Association') { - $request->print(&csvuploadassign($request)); + } elsif ($command eq 'csvuploadoptions' && $perm{'mgr'}) { + if ($env{'form.associate'} ne 'Reverse Association') { + $request->print(&csvuploadoptions($request)); } else { - if ( $ENV{'form.upfile_associate'} ne 'reverse' ) { - $ENV{'form.upfile_associate'} = 'reverse'; + if ( $env{'form.upfile_associate'} ne 'reverse' ) { + $env{'form.upfile_associate'} = 'reverse'; } else { - $ENV{'form.upfile_associate'} = 'forward'; + $env{'form.upfile_associate'} = 'forward'; } $request->print(&csvuploadmap($request)); } + } elsif ($command eq 'csvuploadassign' && $perm{'mgr'} ) { + $request->print(&csvuploadassign($request)); } elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) { $request->print(&scantron_selectphase($request)); } elsif ($command eq 'scantron_warning' && $perm{'mgr'}) { @@ -5077,15 +5801,15 @@ sub handler { } elsif ($command eq 'scantron_process' && $perm{'mgr'}) { $request->print(&scantron_process_students($request)); } elsif ($command eq 'scantronupload' && - (&Apache::lonnet::allowed('usc',$ENV{'request.role.domain'})|| - &Apache::lonnet::allowed('usc',$ENV{'request.course.id'}))) { + (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})|| + &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) { $request->print(&scantron_upload_scantron_data($request)); } elsif ($command eq 'scantronupload_save' && - (&Apache::lonnet::allowed('usc',$ENV{'request.role.domain'})|| - &Apache::lonnet::allowed('usc',$ENV{'request.course.id'}))) { + (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})|| + &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) { $request->print(&scantron_upload_scantron_data_save($request)); } elsif ($command eq 'scantron_download' && - &Apache::lonnet::allowed('usc',$ENV{'request.course.id'})) { + &Apache::lonnet::allowed('usc',$env{'request.course.id'})) { $request->print(&scantron_download_scantron_data($request)); } elsif ($command) { $request->print("Access Denied ($command)"); 500 Internal Server Error

    Internal Server Error

    The server encountered an internal error or misconfiguration and was unable to complete your request.

    Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

    More information about this error may be available in the server error log.