--- loncom/homework/grades.pm 2005/05/15 01:42:31 1.266 +++ loncom/homework/grades.pm 2005/09/23 15:19:05 1.288 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.266 2005/05/15 01:42:31 albertel Exp $ +# $Id: grades.pm,v 1.288 2005/09/23 15:19:05 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -152,6 +152,7 @@ sub get_display_part { } return $display; } + #--- Show resource title #--- and parts and response type sub showResourceInfo { @@ -284,6 +285,11 @@ sub cleanRecord { } $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; } @@ -465,6 +471,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=''; @@ -626,24 +636,24 @@ LISTJAVASCRIPT 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"; + $gradeTable.=''."\n"; } 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". @@ -671,7 +681,7 @@ LISTJAVASCRIPT 'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n". 'value="Next->" />
'."\n"; $gradeTable.=&check_buttons(); - $gradeTable.='Check For Plagiarism'; + $gradeTable.=''; my ($classlist, undef, $fullname) = &getclasslist($getsec,'1'); $gradeTable.=''."\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.='"; 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_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 $pcr = $awarded/($weight{$_} ne '0' ? $weight{$_} : 1); my $partial = $awarded eq '' ? '' : $pcr; @@ -2707,6 +2830,13 @@ sub editgrades { $newrecord{'resource.'.$_.'.awarded'} = 0; $newrecord{'resource.'.$_.'.regrader'}="$env{'user.name'}:$env{'user.domain'}"; $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 ''; @@ -2746,6 +2876,11 @@ sub editgrades { $noupdate.=''.$line; $noupdateCtr++; } + if ($aggregateflag) { + &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, + $env{'course.'.$env{'request.course.id'}.'.domain'}, + $env{'course.'.$env{'request.course.id'}.'.num'}); + } } if ($noupdate) { # my $numcols=(scalar(@partid)*(scalar(@parts)-1)*2)+3; @@ -2930,10 +3065,7 @@ sub csvuploadmap_footer { ENDPICK } -sub upcsvScores_form { - my ($request) = shift; - my ($symb,$url)=&get_symb_and_url($request); - if (!$symb) {return '';} +sub checkforfile_js { my $result =< function checkUpload(formname) { @@ -2945,6 +3077,14 @@ sub upcsvScores_form { } CSVFORMJS + 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; @@ -2964,7 +3104,7 @@ CSVFORMJS $upfile_select
-
'. ''; @@ -737,7 +747,7 @@ LISTJAVASCRIPT 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); @@ -1346,16 +1356,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.='
 '.$status{$_}.'  '.$status{$_}.' 
'. '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++; } @@ -1384,7 +1402,11 @@ sub gradeBox { $result.=''."\n". ''."\n". ''."\n"; + $$record{'resource.'.$partid.'.solved'}.'" />'."\n". + ''."\n". + ''."\n"; $result.='
'.$ctr."
'."\n"; return $result; } @@ -1593,7 +1615,6 @@ KEYWORDS } my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname); - my ($partlist,$handgrade,$responseType) = &response_type($url,$symb); # Display student info @@ -2117,6 +2138,8 @@ sub saveHandGrade { my @parts_graded; my %newrecord = (); my ($pts,$wgt) = ('',''); + my %aggregate = (); + my $aggregateflag = 0; foreach my $new_part (split(/:/,$env{'form.partlist'.$newflg})) { #collaborator may vary for different parts if ($submitter && $new_part ne $part) { next; } @@ -2136,6 +2159,21 @@ sub saveHandGrade { } $newrecord{'resource.'.$new_part.'.regrader'}= "$env{'user.name'}:$env{'user.domain'}"; + my $totaltries = $record{'resource.'.$part.'.tries'}; + + my %last_resets = &get_last_resets($symb,$env{'request.course.id'}, + [$new_part]); + my $aggtries =$totaltries; + if ($last_resets{$new_part}) { + $aggtries = &get_num_tries(\%record,$last_resets{$new_part}, + $new_part); + } + + my $solvedstatus = $record{'resource.'.$new_part.'.solved'}; + if ($aggtries > 0) { + &decrement($symb,$new_part,\%aggregate,$aggtries,$totaltries,$solvedstatus); + $aggregateflag = 1; + } } elsif ($dropMenu eq '') { $pts = ($env{'form.GD_BOX'.$newflg.'_'.$new_part} ne '' ? $env{'form.GD_BOX'.$newflg.'_'.$new_part} : @@ -2184,9 +2222,73 @@ sub saveHandGrade { &Apache::lonnet::cstore(\%newrecord,$symb, $env{'request.course.id'},$domain,$stuname); } + if ($aggregateflag) { + &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, + $env{'course.'.$env{'request.course.id'}.'.domain'}, + $env{'course.'.$env{'request.course.id'}.'.num'}); + } return '',$pts,$wgt; } +# ----------- Provides number of tries since last reset. +sub get_num_tries { + my ($record,$last_reset,$part) = @_; + my $timestamp = ''; + my $num_tries = 0; + if ($$record{'version'}) { + for (my $version=$$record{'version'};$version>=1;$version--) { + if (exists($$record{$version.':resource.'.$part.'.solved'})) { + $timestamp = $$record{$version.':timestamp'}; + if ($timestamp > $last_reset) { + $num_tries ++; + } else { + last; + } + } + } + } + return $num_tries; +} + +# ----------- Determine decrements required in aggregate totals +sub decrement_aggs { + my ($symb,$part,$aggregate,$aggtries,$totaltries,$solvedstatus) = @_; + my %decrement = ( + attempts => 0, + users => 0, + correct => 0 + ); + $decrement{'attempts'} = $aggtries; + if ($solvedstatus =~ /^correct/) { + $decrement{'correct'} = 1; + } + if ($aggtries == $totaltries) { + $decrement{'users'} = 1; + } + foreach my $type (keys (%decrement)) { + $$aggregate{$symb."\0".$part."\0".$type} = -$decrement{$type}; + } + return; +} + +# ----------- Determine timestamps for last reset of aggregate totals for parts +sub get_last_resets { + my ($symb,$courseid,$partids) =@_; + my %last_resets; + my $cdom = $env{'course.'.$courseid.'.domain'}; + my $cname = $env{'course.'.$courseid.'.num'}; + my @keys; + foreach my $part (@{$partids}) { + push(@keys,"$symb\0$part\0resettime"); + } + my %results=&Apache::lonnet::get('nohist_resourcetracker',\@keys, + $cdom,$cname); + foreach my $part (@{$partids}) { + $last_resets{$part}=$results{"$symb\0$part\0resettime"}; + } + return %last_resets; +} + # ----------- Handles creating versions for portfolio files as answers sub version_portfiles { my ($record, $parts_graded, $courseid, $symb, $domain, $stuname, $v_flag) = @_; @@ -2195,12 +2297,13 @@ sub version_portfiles { my $portfolio_root = &Apache::loncommon::propath($domain, $stuname). '/userfiles/portfolio'; - foreach my $key(keys %$record) { + foreach my $key (keys(%$record)) { my $new_portfiles; + if ($key =~ /^resource\.($version_parts)\./ && $key =~ /\.portfiles$/ ) { my @v_portfiles; my @portfiles = split(/,/,$$record{$key}); - # &Apache::lonnet::logthis("should be unmarking and remarking"); + &Apache::lonnet::logthis("should be unmarking and remarking $key",@portfiles); foreach my $file (@portfiles) { &Apache::lonnet::unmark_as_readonly($domain,$stuname,[$symb,$env{'request.course.id'}],$file); my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*$)/); @@ -2223,14 +2326,13 @@ sub version_portfiles { } } $version++; - my $home_server = &Apache::lonnet::homeserver($stuname,$domain,undef); $env{'form.copy'} = &Apache::lonnet::getfile("/uploaded/$domain/$stuname/portfolio$directory$answer_file"); if($env{'form.copy'} eq '-1') { &Apache::lonnet::logthis('problem getting file '.$directory.$answer_file); } else { - my $copy_result = &Apache::lonnet::finishuserfileupload($stuname,$domain,$home_server,'copy', + my $copy_result = &Apache::lonnet::finishuserfileupload($stuname,$domain,'copy', '/portfolio'.$directory.$answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]); - push(@v_portfiles, $answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]); + push(@v_portfiles, $directory.$answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]); &Apache::lonnet::mark_as_readonly($domain,$stuname, ['/portfolio'.$directory.$answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]], [$symb,$env{'request.course.id'},'graded']); @@ -2376,7 +2478,7 @@ sub viewgrades_js { if (selval[2].selected) { document.classgrade["GD_"+user+'_'+partid+"_tries"].value = "0"; } - } + } } function resetEntry(numpart) { @@ -2477,9 +2579,9 @@ sub viewgrades { $result.=''; my $ctr = 0; while ($ctr<=$weight{$partid}) { # display radio buttons in a nice table 10 across - $result.= '\n"; + ','.$ctr.')" />'.$ctr."\n"; $result.=(($ctr+1)%10 == 0 ? '' : ''); $ctr++; } @@ -2509,11 +2611,13 @@ sub viewgrades { '
'.$ctr."
'. '\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'); @@ -2534,7 +2641,7 @@ sub viewgrades { foreach (sort {lc($$fullname{$a}) cmp lc($$fullname{$b}) } keys %$fullname) { $ctr++; $result.=&viewstudentgrade($url,$symb,$env{'request.course.id'}, - $_,$$fullname{$_},\@parts,\%weight,$ctr); + $_,$$fullname{$_},\@parts,\%weight,$ctr,\%last_resets); } $result.='
 No. '.&nameUserString('header')."Score Part: '.$display_part. @@ -2527,6 +2631,9 @@ sub viewgrades { } $result.='
'; $result.=''."\n"; @@ -2551,20 +2658,36 @@ 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 %aggregates = (); my $result='
'. ''. "\n".$ctr.'  '. ''.$fullname.' '. '('.$uname.($env{'user.domain'} eq $udom ? '' : ':'.$udom).')'; + $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.='Not allowed to modify student
 '.$noupdateCtr.' 
'."\n"; @@ -3225,13 +3365,13 @@ 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". @@ -3259,8 +3399,8 @@ LISTJAVASCRIPT my ($uname,$udom) = split(/:/,$student); $studentTable.=($ptr%2 == 1 ? '' : ''); $studentTable.=''.$ptr.' '; - $studentTable.='  ' - .&nameUserString(undef,$$fullname{$student},$uname,$udom)."\n"; + $studentTable.=' \n"; $studentTable.=($ptr%2 == 0 ? '' : ''); $ptr++; } @@ -3332,7 +3472,11 @@ sub displayPage { my $navmap = Apache::lonnavmaps::navmap->new(); 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()); @@ -3538,7 +3682,12 @@ sub updateGradeByPage { my $navmap = Apache::lonnavmaps::navmap->new(); 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()); @@ -3566,6 +3715,8 @@ 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}; @@ -3592,6 +3743,14 @@ sub updateGradeByPage { $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()); @@ -3617,6 +3776,11 @@ sub updateGradeByPage { &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.=''.$displayPts[0].''. ''.$displayPts[1].''. @@ -3718,6 +3882,7 @@ sub scantron_CODElist { my $namechoice=''; foreach my $name (sort {uc($a) cmp uc($b)} @names) { if ($name =~ /^error: 2 /) { next; } + if ($name =~ /^type\0/) { next; } $namechoice.=''; } $namechoice=''; @@ -3726,12 +3891,12 @@ sub scantron_CODElist { sub scantron_CODEunique { my $result=' - Yes + - No + '; return $result; } @@ -3781,8 +3946,8 @@ sub scantron_selectphase { Options: - Do only previously skipped records
- Remove all exisiting corrections +
+ @@ -3961,7 +4126,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'); } @@ -3986,8 +4158,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'}); @@ -4022,8 +4197,12 @@ sub scantron_parse_scanline { substr($questions,0,$$scantron_config{'Qlength'})=''; if (length($currentquest) < $$scantron_config{'Qlength'}) { next; } if ($$scantron_config{'Qon'} eq 'letter') { - if (!$currentquest || $currentquest eq $$scantron_config{'Qoff'} || - $currentquest !~ /^[A-Z]$/) { + 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); @@ -4032,8 +4211,12 @@ sub scantron_parse_scanline { $record{"scantron.$questnum.answer"}=$currentquest; } } elsif ($$scantron_config{'Qon'} eq 'number') { - if (!$currentquest || $currentquest eq $$scantron_config{'Qoff'} || - $currentquest !~ /^\d$/) { + 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); @@ -4150,7 +4333,7 @@ sub scantron_process_corrections { } } 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); @@ -4204,14 +4387,26 @@ sub check_for_error { sub scantron_warning_screen { my ($button_text)=@_; 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= + 'List of CODES to validate against:'. + $CODElist.''; + } return (< Please double check the information below before clicking on '$button_text'

- + +$CODElist
Sequence To be Graded:$title
Sequence to be Graded:$title
Data File that will be used:$env{'form.scantron_selectfile'}

@@ -4418,9 +4613,8 @@ 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); + &Apache::lonnet::finishuserfileupload($docuname,$docudom,'sillywaytopassafilearound',$filename); } @@ -4588,19 +4782,24 @@ sub scantron_get_correction { $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(< @@ -4619,9 +4818,9 @@ ENDSCRIPT "&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 "); + $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"); @@ -4654,21 +4853,26 @@ ENDSCRIPT sub scantron_bubble_selector { my ($r,$scan_config,$quest,@selected)=@_; my $max=$$scan_config{'Qlength'}; + + my $scmode=$$scan_config{'Qon'}; + if ($scmode eq 'number' || $scmode eq 'letter') { $max=10; } + my @alphabet=('A'..'Z'); $r->print(""); for (my $i=0;$i<$max+1;$i++) { - $r->print(''); } - $r->print(''); + $r->print(''); for (my $i=0;$i<$max;$i++) { - $r->print('"); + $r->print("\n". + '"); } - $r->print(''); + $r->print(''); $r->print('
$quest'); + $r->print("\n".''); if ($selected[0] eq $alphabet[$i]) { $r->print('X'); shift(@selected) } else { $r->print(' '); } $r->print('
'.$alphabet[$i]." No bubble
'); } @@ -4694,11 +4898,24 @@ 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; } @@ -4988,8 +5205,6 @@ sub scantron_upload_scantron_data_save { } my %coursedata=&Apache::lonnet::coursedescription($env{'form.domainid'}.'_'.$env{'form.courseid'}); $r->print("Doing upload to ".$coursedata{'description'}."
"); - my $home=&Apache::lonnet::homeserver($env{'form.courseid'}, - $env{'form.domainid'}); my $fname=$env{'form.upfile.filename'}; #FIXME #copied from lonnet::userfileupload() @@ -5009,7 +5224,7 @@ sub scantron_upload_scantron_data_save { 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.""); } else { @@ -5184,10 +5399,10 @@ GRADINGMENUJS $result.=''; - $result.=''. + $result.=''."\n"; $result.=''. - ' '. - 'The complete set/page/sequence: For one student'."\n"; + 'The complete set/page/sequence: For one student'."\n"; $result.='
'. ''. @@ -5233,6 +5448,9 @@ GRADINGMENUJS $result.=''. ' access times.'."\n"; + $result.=''. + ' saved CODEs.'."\n"; $result.=''."\n". ''."\n". @@ -5240,10 +5458,32 @@ GRADINGMENUJS return $result; } +sub reset_perm { + undef(%perm); +} + +sub init_perm { + &reset_perm(); + 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'}); + } + } +} + sub handler { my $request=$_[0]; - undef(%perm); + &reset_perm(); if ($env{'browser.mathml'}) { &Apache::loncommon::content_type($request,'text/xml'); } else { @@ -5292,20 +5532,7 @@ 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)); } elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {