--- loncom/homework/grades.pm 2006/02/28 16:21:51 1.324 +++ loncom/homework/grades.pm 2006/04/10 06:34:07 1.349 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.324 2006/02/28 16:21:51 albertel Exp $ +# $Id: grades.pm,v 1.349 2006/04/10 06:34:07 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -118,9 +118,10 @@ sub response_type { my %seen = (); my (@partlist,%handgrade,%responseType); foreach (split(/,/,&Apache::lonnet::metadata($url,'packages'))) { - if (/^\w+response_.*/) { + if (/^\w+response_.*/ || /^Task_/) { my ($responsetype,$part) = split(/_/,$_,2); my ($partid,$respid) = split(/_/,$part); + if ($responsetype eq 'Task') { $respid='0'; } if (&Apache::loncommon::check_if_partid_hidden($partid,$symb)) { next; } @@ -205,9 +206,11 @@ sub get_order { return ($analyze{"$partid.$respid.shown"}); } #--- Clean response type for display -#--- Currently filters option/rank/radiobutton/match/essay response types only. +#--- Currently filters option/rank/radiobutton/match/essay/Task +# response types only. sub cleanRecord { - my ($answer,$response,$symb,$partid,$respid,$record,$order,$version) = @_; + my ($answer,$response,$symb,$partid,$respid,$record,$order,$version, + $uname,$udom) = @_; my $grayFont = ''; if ($response =~ /^(option|rank)$/) { my %answer=&Apache::lonnet::str2hash($answer); @@ -288,6 +291,37 @@ sub cleanRecord { my $jme=$record->{$version."resource.$partid.$respid.molecule"}; $result.=&Apache::chemresponse::jme_img($jme,$answer,400); return $result; + } elsif ( $response eq 'Task') { + if ( $answer eq 'SUBMITTED') { + my $files = $record->{$version."resource.$respid.$partid.bridgetask.portfiles"}; + my $result = &Apache::bridgetask::file_list($files,$uname,$udom); + return $result; + } elsif ( grep(/^\Q$version\E.*?\.instance$/, keys(%{$record})) ) { + my @matches = grep(/^\Q$version\E.*?\.instance$/, + keys(%{$record})); + return join('
',($version,@matches)); + + + } else { + my $result = + '

' + .&mt('Overall result: [_1]', + $record->{$version."resource.$respid.$partid.status"}) + .'

'; + + $result .= ''; + return $result; + } + } return $answer; } @@ -556,7 +590,7 @@ sub verifyreceipt { 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'); @@ -688,7 +722,14 @@ LISTJAVASCRIPT $gradeTable.=''."\n". ''."\n". ''."\n". - ''."\n". + '
'."\n". + ' Grading Increments: '. + ''."\n". ''."\n". '
'."\n". @@ -1264,7 +1305,7 @@ sub sub_page_kw_js { pDoc.write("
"); pDoc.write(""); - pDoc.write(" Compose Message for \"+fullname+\"

"); + pDoc.write(" Compose Message for \"+fullname+\"

"); pDoc.write("
"); pDoc.write(""); @@ -1299,7 +1340,7 @@ sub sub_page_kw_js { pDoc.write("
"); pDoc.write("
 "); pDoc.write("  "); - pDoc.write("

"); + pDoc.write("

"); pDoc.write("
"); pDoc.write(""); pDoc.close(); @@ -1368,7 +1409,7 @@ sub sub_page_kw_js { hDoc.write(""); hDoc.write("
"); - hDoc.write(" Keyword Highlight Options

"); + hDoc.write(" Keyword Highlight Options

"); hDoc.write("
"); hDoc.write(""); @@ -1392,7 +1433,7 @@ sub sub_page_kw_js { hDoc.write("
"); hDoc.write("
 "); hDoc.write("  "); - hDoc.write("

"); + hDoc.write("

"); hDoc.write("
"); hDoc.write(""); hDoc.close(); @@ -1402,6 +1443,15 @@ sub sub_page_kw_js { SUBJAVASCRIPT } +sub get_increment { + my $increment = $env{'form.increment'}; + if ($increment != 1 && $increment != .5 && $increment != .25 && + $increment != .1) { + $increment = 1; + } + return $increment; +} + #--- displays the grading box, used in essay type problem and grading by page/sequence sub gradeBox { my ($request,$symb,$uname,$udom,$counter,$partid,$record) = @_; @@ -1424,13 +1474,16 @@ sub gradeBox { $result.='
'. 'Part: '.$display_part.' Points: '."\n"; my $ctr = 0; + my $thisweight = 0; + my $increment = &get_increment(); $result.=''."\n"; # display radio buttons in a nice table 10 across - while ($ctr<=$wgt) { + while ($thisweight<=$wgt) { $result.= '\n"; + $thisweight.')" value="'.$thisweight.'" '. + ($score eq $thisweight ? 'checked':'').' /> '.$thisweight."\n"; $result.=(($ctr+1)%10 == 0 ? '' : ''); + $thisweight += $increment; $ctr++; } $result.='
'; @@ -1483,7 +1536,10 @@ sub handback_box { next if (!@$files); my $file_counter = 1; foreach my $file (@$files) { - my ($file_disp) = ($file =~ m|.+/(.+)$|); + my ($file_path, $file_disp) = ($file =~ m|(.+/)(.+)$|); + my ($name,$version,$ext) = &file_name_version_ext($file_disp); + $file_disp = "$name.$ext"; + $file = $file_path.$file_disp; $result.=&mt('Return commented version of [_1] to student.', ''.$file_disp.''); $result.=''."\n"; @@ -1497,6 +1553,7 @@ sub handback_box { sub show_problem { my ($request,$symb,$uname,$udom,$removeform,$viewon,$mode) = @_; my $rendered; + &Apache::lonxml::remember_problem_counter(); if ($mode eq 'both' or $mode eq 'text') { $rendered=&Apache::loncommon::get_student_view($symb,$uname,$udom, $env{'request.course.id'}); @@ -1508,6 +1565,7 @@ sub show_problem { } my $companswer; if ($mode eq 'both' or $mode eq 'answer') { + &Apache::lonxml::restore_problem_counter(); $companswer=&Apache::loncommon::get_student_answers($symb,$uname,$udom, $env{'request.course.id'}); } @@ -1594,6 +1652,7 @@ sub submission { } elsif ($env{'form.vAns'} eq 'yes') { $mode='answer'; } + &Apache::lonxml::clear_problem_counter(); $request->print(&show_problem($request,$symb,$uname,$udom,0,1,$mode)); } @@ -1630,9 +1689,9 @@ sub submission { ''."\n". ''."\n". ''."\n". - ''."\n". - ''."\n". - ''."\n". + ''."\n". + ''."\n". + ''."\n". ''."\n"); if ($env{'form.handgrade'} eq 'yes') { @@ -1692,6 +1751,7 @@ KEYWORDS } elsif ($env{'form.vAns'} eq 'all') { $mode='answer'; } + &Apache::lonxml::clear_problem_counter(); $request->print(&show_problem($request,$symb,$uname,$udom,1,1,$mode)); } @@ -1700,8 +1760,8 @@ KEYWORDS # Display student info $request->print(($counter == 0 ? '' : '
')); - my $result='
'."\n". - '
'."\n"; + my $result='
'."\n". + '
'."\n"; $result.='Fullname: '.&nameUserString(undef,$env{'form.fullname'},$uname,$udom).'
'."\n"; $result.=' '.$file.''; + $lastsubonly.='
'.$file.''; } $lastsubonly.='
'; } @@ -1954,6 +2014,8 @@ KEYWORDS '  '; $endform.='(Next and Previous (student) do not save the scores.)'."\n" ; + $endform.=""; $endform.='
'; $endform.=&show_grading_menu_form($symb); $request->print($endform); @@ -2231,20 +2293,19 @@ sub processHandGrade { #---- Save the score and award for each student, if changed sub saveHandGrade { my ($request,$symb,$stuname,$domain,$newflg,$submitter,$part) = @_; - my @v_flag; + my @version_parts; my $usec = &Apache::lonnet::getsection($domain,$stuname, $env{'request.course.id'}); if (!&canmodify($usec)) { return('not_allowed'); } - my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$domain,$stuname); + my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$domain,$stuname); my @parts_graded; my %newrecord = (); my ($pts,$wgt) = ('',''); my %aggregate = (); my $aggregateflag = 0; - my @parts = split(/:/,$env{'form.partlist'.$newflg}); foreach my $new_part (@parts) { - #collaborator may vary for different parts + #collaborator ($submi may vary for different parts if ($submitter && $new_part ne $part) { next; } my $dropMenu = $env{'form.GD_SEL'.$newflg.'_'.$new_part}; if ($dropMenu eq 'excused') { @@ -2274,7 +2335,7 @@ sub saveHandGrade { my $solvedstatus = $record{'resource.'.$new_part.'.solved'}; if ($aggtries > 0) { - &decrement($symb,$new_part,\%aggregate,$aggtries,$totaltries,$solvedstatus); + &decrement_aggs($symb,$new_part,\%aggregate,$aggtries,$totaltries,$solvedstatus); $aggregateflag = 1; } } elsif ($dropMenu eq '') { @@ -2289,6 +2350,7 @@ sub saveHandGrade { my $partial= $pts/$wgt; if ($partial eq $record{'resource.'.$new_part.'.awarded'}) { #do not update score for part if not changed. + &handback_files($request,$symb,$stuname,$domain,$newflg,$new_part,\%newrecord); next; } else { push @parts_graded, $new_part; @@ -2312,43 +2374,26 @@ sub saveHandGrade { } $newrecord{'resource.'.$new_part.'.regrader'}= "$env{'user.name'}:$env{'user.domain'}"; + &handback_files($request,$symb,$stuname,$domain,$newflg,$new_part,\%newrecord); } - my ($partlist,$handgrade,$responseType) = &response_type($symb); - foreach my $part_resp (sort(keys(%$handgrade))) { - my ($part_id, $resp_id) = split(/_/,$part_resp); - &Apache::lonnet::logthis('form.'.$newflg.'_'.$part_resp.'_returndoc1'); - &Apache::lonnet::logthis("new part is $new_part and partid is $part_id"); - if (($env{'form.'.$newflg.'_'.$part_resp.'_returndoc1'}) && ($new_part == $part_id)) { - # if multiple files are uploaded names will be 'returndoc2','returndoc3' - my $file_counter = 1; - while ($env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$file_counter}) { - my $fname=$env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$file_counter.'.filename'}; - $newrecord{"resource.$new_part.$resp_id.handback"} = $env{'form.returndocorig'.$file_counter}; - $request->print("
".$fname." will be the uploaded file name"); - $request->print("Will upload document".$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$file_counter}); - $file_counter++; - } - } - } - # unless problem has been graded, set flag to version the submitted files unless ($record{'resource.'.$new_part.'.solved'} =~ /^correct_/ || $record{'resource.'.$new_part.'.solved'} eq 'incorrect_by_override' || $dropMenu eq 'reset status') { - push (@v_flag,$new_part); + push (@version_parts,$new_part); } } my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; - if (scalar(keys(%newrecord)) > 0) { - if (scalar(@v_flag)) { - &version_portfiles(\%record, \@parts_graded, $env{'request.course.id'}, $symb, $domain, $stuname, \@v_flag); + if (%newrecord) { + if (@version_parts) { + my @changed_keys = &version_portfiles(\%record, \@parts_graded, $env{'request.course.id'}, $symb, $domain, $stuname, \@version_parts); + @newrecord{@changed_keys} = @record{@changed_keys}; } &Apache::lonnet::cstore(\%newrecord,$symb, $env{'request.course.id'},$domain,$stuname); - my @ungraded_parts; foreach my $part (@parts) { if ( !defined($record{'resource.'.$part.'.awarded'}) @@ -2368,6 +2413,47 @@ sub saveHandGrade { return ('',$pts,$wgt); } +sub handback_files { + my ($request,$symb,$stuname,$domain,$newflg,$new_part,$newrecord) = @_; + my $portfolio_root = &Apache::loncommon::propath($domain, + $stuname). + '/userfiles/portfolio'; + my ($partlist,$handgrade,$responseType) = &response_type($symb); + foreach my $part_resp (sort(keys(%$handgrade))) { + my ($part_id, $resp_id) = split(/_/,$part_resp); + if (($env{'form.'.$newflg.'_'.$part_resp.'_returndoc1'}) && ($new_part == $part_id)) { + # if multiple files are uploaded names will be 'returndoc2','returndoc3' + my $file_counter = 1; + while ($env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$file_counter}) { + my $fname=$env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$file_counter.'.filename'}; + my ($directory,$answer_file) = + ($env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$file_counter} =~ /^(.*?)([^\/]*)$/); + my ($answer_name,$answer_ver,$answer_ext) = + &file_name_version_ext($answer_file); + $directory =~ /^.+$stuname\/portfolio(.*)/; + my $portfolio_path = $1; + my @dir_list = &Apache::lonnet::dirlist($portfolio_path,$domain,$stuname,$portfolio_root); + my $version = &get_next_version($answer_name, $answer_ext, \@dir_list); + my $new_answer = &version_selected_portfile($domain, $stuname, $portfolio_path, $answer_file, $version); + $$newrecord{"resource.$new_part.$resp_id.handback"} = $new_answer; + # set the filename to match the submitted file name + $env{'form.'.$newflg.'_'.$part_resp.'_returndoc1.filename'} = $env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$file_counter}; + my $result=&Apache::lonnet::userfileupload($newflg.'_'.$part_resp.'_returndoc'.$file_counter,'', + 'portfolio',undef,undef,undef,$stuname,$domain); + if ($result !~ m|^/uploaded/|) { + $request->print(' An errror occured ('.$result. + ') while trying to upload '.&display_file().'
'); + # $request->print(&done('Back')); + } + $request->print("
".$fname." will be the uploaded file name"); + $request->print("Will upload document ".$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$file_counter}); + $file_counter++; + } + } + } + return; +} + sub get_submitted_files { my ($udom,$uname,$partid,$respid,$record) = @_; my @files; @@ -2446,6 +2532,7 @@ sub get_last_resets { sub version_portfiles { my ($record, $parts_graded, $courseid, $symb, $domain, $stu_name, $v_flag) = @_; my $version_parts = join('|',@$v_flag); + my @returned_keys; my $parts = join('|', @$parts_graded); my $portfolio_root = &Apache::loncommon::propath($domain, $stu_name). @@ -2453,33 +2540,32 @@ sub version_portfiles { foreach my $key (keys(%$record)) { my $new_portfiles; if ($key =~ /^resource\.($version_parts)\./ && $key =~ /\.portfiles$/ ) { - my @v_portfiles; + my @versioned_portfiles; my @portfiles = split(/,/,$$record{$key}); foreach my $file (@portfiles) { &Apache::lonnet::unmark_as_readonly($domain,$stu_name,[$symb,$env{'request.course.id'}],$file); my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*)$/); - my $version = 0; my ($answer_name,$answer_ver,$answer_ext) = &file_name_version_ext($answer_file); my @dir_list = &Apache::lonnet::dirlist($directory,$domain,$stu_name,$portfolio_root); - $version = &get_next_version($answer_name, $answer_ext, \@dir_list); + my $version = &get_next_version($answer_name, $answer_ext, \@dir_list); my $new_answer = &version_selected_portfile($domain, $stu_name, $directory, $answer_file, $version); if ($new_answer ne 'problem getting file') { - push(@v_portfiles, $directory.$new_answer); + push(@versioned_portfiles, $directory.$new_answer); &Apache::lonnet::mark_as_readonly($domain,$stu_name, ['/portfolio'.$directory.$new_answer], [$symb,$env{'request.course.id'},'graded']); } - } - $$record{$key} = join(',',@v_portfiles); + $$record{$key} = join(',',@versioned_portfiles); + push(@returned_keys,$key); } } - return 'ok'; + return (@returned_keys); } sub get_next_version { - my ($answer_name, $answer_ext, $dir_list); + my ($answer_name, $answer_ext, $dir_list) = @_; my $version; foreach my $row (@$dir_list) { my ($file) = split(/\&/,$row,2); @@ -3233,7 +3319,7 @@ sub csvuploadmap_header {

Uploading Class Grades

$result -
+

Identify fields

Total number of records found in file: $distotal
Enter as many fields as you can. The system will inform you and bring you back @@ -3315,8 +3401,8 @@ sub upcsvScores_form { $env{'form.probTitle'} = &Apache::lonnet::gettitle($symb); my ($table) = &showResourceInfo($symb,$env{'form.probTitle'}); $result.=$table; - $result.='
'."\n"; - $result.='
'."\n"; + $result.='
'."\n"; + $result.=''."\n"; $result.='
'."\n"; $result.=' Specify a file containing the class scores for current resource'. '.
'."\n"; @@ -3449,6 +3535,7 @@ sub csvuploadassign { my ($request)= @_; my ($symb)=&get_symb($request); if (!$symb) {return '';} + my $error_msg = ''; &Apache::loncommon::load_tmp_file($request); my @gradedata = &Apache::loncommon::upfile_record_sep(); if ($env{'form.noFirstLine'}) { shift(@gradedata); } @@ -3501,12 +3588,20 @@ sub csvuploadassign { 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; + if ($wgt) { + $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 { + $error_msg = "
" . + &mt("Some point values were assigned" + ." for problems with a weight " + ."of zero. These values were " + ."ignored."); + } } else { if ($dest=~/stores_(.*)_awarded/) { if ($points{$1}) {next;} } if ($dest=~/stores_(.*)_solved/) { if ($points{$1}) {next;} } @@ -3537,7 +3632,7 @@ sub csvuploadassign { } $request->print("
Stored $countdone students\n"); if (@skipped) { - $request->print('Skipped Students

'); + $request->print('

Skipped Students

'); foreach my $student (@skipped) { $request->print("$student
\n"); } } if (@notallowed) { @@ -3546,7 +3641,7 @@ sub csvuploadassign { } $request->print("
\n"); $request->print(&show_grading_menu_form($symb)); - return ''; + return $error_msg; } #------------- end of section for handling csv file upload --------- # @@ -3597,7 +3692,7 @@ LISTJAVASCRIPT '>'.$showtitle.''."\n"; $ctr++; } - $result.= ''."
\n"; + $result.= ''."
\n"; $ctr=0; foreach (@$titles) { my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/); @@ -3627,7 +3722,7 @@ LISTJAVASCRIPT $request->print($result); - my $studentTable.=' Select a student you wish to grade and then click on the Next button.
'. + my $studentTable.=' Select a student you wish to grade and then click on the Next button.
'. '
'. ''. ''. @@ -3748,6 +3843,7 @@ sub displayPage { ''. ''; + &Apache::lonxml::clear_problem_counter(); my ($depth,$question,$prob) = (1,1,1); $iterator->next(); # skip the first BEGIN_MAP my $curRes = $iterator->next(); # for "current resource" @@ -3760,7 +3856,7 @@ sub displayPage { my $title = $curRes->compTitle(); my $symbx = $curRes->symb(); $studentTable.=''; + (scalar(@{$parts}) == 1 ? '' : '
('.scalar(@{$parts}).' parts)').''; $studentTable.='
 No. Prob.  '.($env{'form.vProb'} eq 'no' ? 'Title' : 'Problem Text').'/Grade
'.$prob. - (scalar(@{$parts}) == 1 ? '' : '
('.scalar(@{$parts}).' parts)').'
'; if ($env{'form.vProb'} eq 'yes' ) { $studentTable.=&show_problem($request,$symbx,$uname,$udom,1, @@ -3771,10 +3867,10 @@ sub displayPage { $companswer =~ s|||g; # while ($companswer =~ /()/s) { #\n"); +# $request->print('match='.$1."
\n"); # } # $companswer =~ s||
|g; - $studentTable.=' '.$title.' 
 Correct answer:
'.$companswer; + $studentTable.=' '.$title.' 
 Correct answer:
'.$companswer; } my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname); @@ -3830,6 +3926,7 @@ sub displayPage { sub displaySubByDates { my ($symb,$record,$parts,$responseType,$checkIcon,$uname,$udom) = @_; my $isCODE=0; + my $isTask = ($symb =~/\.task$/); if (exists($record->{'resource.CODE'})) { $isCODE=1; } my $studentTable='
'. ''. @@ -3844,8 +3941,17 @@ sub displaySubByDates { if (!exists($$record{'1:timestamp'})) { return '
 Nothing submitted - no attempts
'; } + + my $interaction; for ($version=1;$version<=$$record{'version'};$version++) { my $timestamp = scalar(localtime($$record{$version.':timestamp'})); + if (exists($$record{$version.':resource.0.version'})) { + $interaction = $$record{$version.':resource.0.version'}; + } + + my $where = ($isTask ? "$version:resource.$interaction" + : "$version:resource"); + #&Apache::lonnet::logthis(" got $where"); $studentTable.=''; if ($isCODE) { $studentTable.=''; @@ -3853,40 +3959,57 @@ sub displaySubByDates { my @versionKeys = split(/\:/,$$record{$version.':keys'}); my @displaySub = (); foreach my $partid (@{$parts}) { - my @matchKey = sort(grep /^resource\.\Q$partid\E\..*?\.submission$/,@versionKeys); + my @matchKey = ($isTask ? sort(grep /^resource\.\d+\.\Q$partid\E\.award$/,@versionKeys) + : sort(grep /^resource\.\Q$partid\E\..*?\.submission$/,@versionKeys)); + + # next if ($$record{"$version:resource.$partid.solved"} eq ''); my $display_part=&get_display_part($partid,$symb); foreach my $matchKey (@matchKey) { if (exists($$record{$version.':'.$matchKey}) && $$record{$version.':'.$matchKey} ne '') { - my ($responseId)=($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/); + + my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/) + : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/)); + #&Apache::lonnet::logthis("match $matchKey $responseId (".$$record{$version.':'.$matchKey}); $displaySub[0].='Part: '.$display_part.' '; $displaySub[0].='(ID '. $responseId.') '; - if ($$record{"$version:resource.$partid.tries"} eq '') { + if ($$record{"$where.$partid.tries"} eq '') { $displaySub[0].='Trial not counted'; } else { $displaySub[0].='Trial '. - $$record{"$version:resource.$partid.tries"}; + $$record{"$where.$partid.tries"}; } - my $responseType=$responseType->{$partid}->{$responseId}; + my $responseType=($isTask ? 'Task' + : $responseType->{$partid}->{$responseId}); if (!exists($orders{$partid})) { $orders{$partid}={}; } if (!exists($orders{$partid}->{$responseId})) { $orders{$partid}->{$responseId}= &get_order($partid,$responseId,$symb,$uname,$udom); } $displaySub[0].='  '. - &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:").'
'; + &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:",$uname,$udom).'
'; } } - if (exists $$record{"$version:resource.$partid.award"}) { + if (exists($$record{"$where.$partid.checkedin"})) { + $displaySub[1].='Checked in by '. + $$record{"$where.$partid.checkedin"}.' into slot '. + $$record{"$where.$partid.checkedin.slot"}. + '
'; + } + if (exists $$record{"$where.$partid.award"}) { $displaySub[1].='Part: '.$display_part.'  '. - lc($$record{"$version:resource.$partid.award"}).' '. - $mark{$$record{"$version:resource.$partid.solved"}}. + lc($$record{"$where.$partid.award"}).' '. + $mark{$$record{"$where.$partid.solved"}}. '
'; } - if (exists $$record{"$version:resource.$partid.regrader"}) { - $displaySub[2].=$$record{"$version:resource.$partid.regrader"}. + if (exists $$record{"$where.$partid.regrader"}) { + $displaySub[2].=$$record{"$where.$partid.regrader"}. + ' ('.&mt('Part').': '.$display_part.')'; + } elsif ($$record{"$version:resource.$partid.regrader"} =~ /\S/) { + $displaySub[2].= + $$record{"$version:resource.$partid.regrader"}. ' ('.&mt('Part').': '.$display_part.')'; } } @@ -3957,7 +4080,7 @@ sub updateGradeByPage { my $title = $curRes->compTitle(); my $symbx = $curRes->symb(); $studentTable.=''; + (scalar(@{$parts}) == 1 ? '' : '
('.scalar(@{$parts}).' parts)').''; $studentTable.=''; my %newrecord=(); @@ -4003,10 +4126,10 @@ sub updateGradeByPage { my $oldstatus = $env{'form.solved'.$question.'_'.$partid}; $displayPts[0].=' Part: '.$display_part.' = '. (($oldstatus eq 'excused') ? 'excused' : $oldpts). - ' 
'; + ' 
'; $displayPts[1].=' Part: '.$display_part.' = '. (($score eq 'excused') ? 'excused' : $newpts). - ' 
'; + ' 
'; $question++; next if ($dropMenu eq 'reset status' || ($newpts == $oldpts && $score ne 'excused')); @@ -4192,7 +4315,8 @@ sub scantron_selectphase { @@ -4521,8 +4645,15 @@ sub scantron_find_student { sub scantron_filter { my ($curres)=@_; - # randomout is dysfunctional at best for this purpose - if (ref($curres) && $curres->is_problem()) { #&& !$curres->randomout) { + + if (ref($curres) && $curres->is_problem()) { + # if the user has asked to not have either hidden + # or 'randomout' controlled resources to be graded + # don't include them + if ($env{'form.scantron_options_hidden'} eq 'ignore_hidden' + && $curres->randomout) { + return 0; + } return 1; } return 0; @@ -4617,7 +4748,6 @@ sub remember_current_skipped { $to_remember{$i}=1; } } - &Apache::lonnet::logthis('remembering '.join(':',%to_remember)); &scan_data($scan_data,'remember_skipping',join(':',%to_remember)); &scantron_putfile(undef,$scan_data); } @@ -4705,6 +4835,7 @@ sub scantron_form_start { + SCANTRONFORM return $result; } @@ -4739,11 +4870,12 @@ sub scantron_validate_file { $r->print("

Gathering neccessary info.

");$r->rflush(); #get the student pick code ready $r->print(&Apache::loncommon::studentbrowser_javascript()); - my $max_bubble=&scantron_get_maxbubble($r); + my $max_bubble=&scantron_get_maxbubble(); my $result=&scantron_form_start($max_bubble).$default_form_data; $r->print($result); - my @validate_phases=( 'ID', + my @validate_phases=( 'sequence', + 'ID', 'CODE', 'doublebubble', 'missingbubbles'); @@ -4776,10 +4908,17 @@ STUFF $r->print(""); } if ($stop) { - $r->print(''); - $r->print(' using corrected info
'); - $r->print(""); - $r->print(" this scanline saving it for later."); + if ($validate_phases[$currentphase] eq 'sequence') { + $r->print(''); + $r->print(' this error
'); + + $r->print("

Or click the 'Grading Menu' button to start over.

"); + } else { + $r->print(''); + $r->print(' using corrected info
'); + $r->print(""); + $r->print(" this scanline saving it for later."); + } } $r->print("
".&show_grading_menu_form($symb). ""); @@ -4912,6 +5051,45 @@ sub scantron_put_line { $scanlines->{'corrected'}[$i]=$newline; } +sub scantron_filter_not_exam { + my ($curres)=@_; + + if (ref($curres) && $curres->is_problem() && !$curres->is_exam()) { + # if the user has asked to not have either hidden + # or 'randomout' controlled resources to be graded + # don't include them + if ($env{'form.scantron_options_hidden'} eq 'ignore_hidden' + && $curres->randomout) { + return 0; + } + return 1; + } + return 0; +} + +sub scantron_validate_sequence { + my ($r,$currentphase) = @_; + + my $navmap=Apache::lonnavmaps::navmap->new(); + my (undef,undef,$sequence)= + &Apache::lonnet::decode_symb($env{'form.selectpage'}); + + my $map=$navmap->getResourceByUrl($sequence); + + $r->print(''); + if ($env{'form.validate_sequence_exam'} ne 'ignore') { + my @resources= + $navmap->retrieveResources($map,\&scantron_filter_not_exam,1,0); + if (@resources) { + $r->print("

".&mt('Some resource in the sequece currently are not set to exam mode. Grading these resources currently may not work correctly.')."

"); + return (1,$currentphase); + } + } + + return (0,$currentphase+1); +} + sub scantron_validate_ID { my ($r,$currentphase) = @_; @@ -4982,7 +5160,7 @@ sub scantron_get_correction { #the previous one or the current one $r->print("

An error was detected ($error)"); - if ( defined($$scan_record{'scantron.PaperID'}) ) { + if ( $$scan_record{'scantron.PaperID'} =~ /\S/) { $r->print(" for PaperID ". $$scan_record{'scantron.PaperID'}." \n"); } else { @@ -5063,8 +5241,10 @@ 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(" Selected CODE is "); - $r->print("\n
"); + if ($env{'form.scantron_CODElist'} =~ /\S/) { + $r->print(" Selected CODE is "); + $r->print("\n
"); + } $r->print(" as the CODE."); $r->print("\n

"); } elsif ($error eq 'doublebubble') { @@ -5238,28 +5418,29 @@ sub scantron_validate_doublebubble { return (0,$currentphase+1); } -sub scantron_get_maxbubble { - my ($r)=@_; +sub scantron_get_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'}); + my $map=$navmap->getResourceByUrl($sequence); my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); - &Apache::lonnet::delenv('form.counter'); + + &Apache::lonxml::clear_problem_counter(); + foreach my $resource (@resources) { - my $result=&Apache::lonnet::ssi($resource->src().'?symb='.&Apache::lonnet::escape($resource->symb())); + my $result=&Apache::lonnet::ssi($resource->src(), + ('symb' => $resource->symb())); } &Apache::lonnet::delenv('scantron\.'); - 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; + $env{'form.scantron_maxbubble'} = + &Apache::lonxml::get_problem_counter()-1; + return $env{'form.scantron_maxbubble'}; } @@ -5353,7 +5534,8 @@ SCANTRONFORM next; } ($uname,$udom)=split(/:/,$uname); - &Apache::lonnet::delenv('form.counter'); + + &Apache::lonxml::clear_problem_counter(); &Apache::lonnet::appenv(%$scan_record); my $i=0; @@ -5381,7 +5563,7 @@ SCANTRONFORM $completedstudents{$uname}={'line'=>$line}; if (&Apache::loncommon::connection_aborted($r)) { last; } } continue { - &Apache::lonnet::delenv('form.counter'); + &Apache::lonxml::clear_problem_counter(); &Apache::lonnet::delenv('scantron\.'); } &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); @@ -5487,7 +5669,6 @@ sub scantron_upload_scantron_data_save { sub valid_file { my ($requested_file)=@_; foreach my $filename (sort(&scantron_filenames())) { - &Apache::lonnet::logthis("$requested_file $filename"); if ($requested_file eq $filename) { return 1; } } return 0; @@ -5622,12 +5803,12 @@ GRADINGMENUJS ''."\n". ''."\n"; - $result.='

'.$timestamp.''.$record->{$version.':resource.CODE'}.'
'.$prob. - (scalar(@{$parts}) == 1 ? '' : '
('.scalar(@{$parts}).' parts)').'
 '.$title.'  Options:
- +
+
'."\n". - '
'."\n". + $result.='
'."\n". + ''."\n". '
'."\n". ' Select a Grading/Viewing Option
'."\n"; - $result.=''; + $result.='
'; $result.=''."\n"; + ($saveSub eq 'all' ? 'selected="on"' : '').' />'.&mt('with any status').''."\n"; $result.=''."\n"; $result.=''."\n"; $result.='
'."\n". ' '.&mt('Select Section').':
'. '
'. '

'. @@ -5673,7 +5854,7 @@ GRADINGMENUJS $result.='
'; - $result.=''; + $result.='
'; $result.=''."\n"; @@ -5687,7 +5868,7 @@ GRADINGMENUJS ''. ' '.&mt('receipt').': '. &Apache::lonnet::recprefix($env{'request.course.id'}). - '-'. + '-'. ''."\n"; } $result.='
'. ''. ' '.&mt('scores from file').'
'. @@ -5840,19 +6021,14 @@ sub handler { sub send_header { my ($request)= @_; - $request->print(&Apache::lontexconvert::header()); -# $request->print(" -#"); - $request->print(&Apache::loncommon::bodytag('Grading')); + &Apache::lontexconvert::init_tth(); + $request->print(&Apache::loncommon::start_page('Grading')); $request->rflush(); } sub send_footer { my ($request)= @_; - $request->print(''); + $request->print(&Apache::loncommon::end_page()); } 1;