--- loncom/homework/grades.pm 2014/02/27 01:39:48 1.722 +++ loncom/homework/grades.pm 2015/03/18 12:53:24 1.735 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.722 2014/02/27 01:39:48 raeburn Exp $ +# $Id: grades.pm,v 1.735 2015/03/18 12:53:24 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -406,8 +406,7 @@ sub cleanRecord { $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(&HTML::Entities::encode($answer, '"<>&')).'
'; + return '

'.&keywords_highlight($answer).'
'; } elsif ( $response eq 'organic') { my $result=&mt('Smile representation: [_1]', @@ -1296,10 +1295,8 @@ sub sub_page_js { } } } - } } - } formname.submit(); } @@ -1814,7 +1811,7 @@ sub handback_box { if ($file =~ /\/portfolio\//) { $file_counter++; my ($file_path, $file_disp) = ($file =~ m|(.+/)(.+)$|); - my ($name,$version,$ext) = &file_name_version_ext($file_disp); + my ($name,$version,$ext) = &Apache::lonnet::file_name_version_ext($file_disp); $file_disp = "$name.$ext"; $file = $file_path.$file_disp; $result.=&mt('Return commented version of [_1] to student.', @@ -2227,7 +2224,7 @@ sub submission { foreach my $submission (@$string) { my ($partid,$respid) = ($submission =~ /^resource\.([^\.]*)\.([^\.]*)\.submission/); if (join('_',@{$part}) ne ($partid.'_'.$respid)) { next; } - my ($ressub,$hide,$subval) = split(/:/,$submission,3); + my ($ressub,$hide,$draft,$subval) = split(/:/,$submission,4); # Similarity check my $similar=''; my ($type,$trial,$rndseed); @@ -2296,9 +2293,17 @@ sub submission { if ($hide eq 'anon') { $lastsubonly.='
'.&mt('Anonymous Survey').''; } else { - $lastsubonly.='
'.&mt('Submitted Answer:').' '. + $lastsubonly.='
'.&mt('Submitted Answer:').' '; + if ($draft) { + $lastsubonly.= ' '.&mt('Draft Copy').''; + } + $subval = &cleanRecord($subval,$responsetype,$symb,$partid, $respid,\%record,$order,undef,$uname,$udom,$type,$trial,$rndseed); + if ($responsetype eq 'essay') { + $subval =~ s{\n}{
}g; + } + $lastsubonly.=$subval."\n"; } if ($similar) {$lastsubonly.="

$similar\n";} $lastsubonly.=''; @@ -2314,10 +2319,12 @@ sub submission { } if ($env{'form.lastSub'} =~ /^(last|all)$/) { + my $identifier = (&canmodify($usec)? $counter : ''); $request->print(&Apache::loncommon::get_previous_attempt($symb,$uname,$udom, $env{'request.course.id'}, $last,'.submission', - 'Apache::grades::keywords_highlight')); + 'Apache::grades::keywords_highlight', + $usec,$identifier)); } $request->print(''."\n"); @@ -2536,7 +2543,7 @@ sub get_last_submission { } unless ($hide) { if (@randomize) { - foreach my $id (@hidden) { + foreach my $id (@randomize) { if ($key =~ /^\Q$id\E/) { $hide = 'rand'; last; @@ -2545,10 +2552,8 @@ sub get_last_submission { } } my ($partid,$foo) = split(/submission$/,$key); - my $draft = $lasthash{$partid.'awarddetail'} eq 'DRAFT' ? - ''.&mt('Draft Copy').' ' : ''; - #push(@string, join(':', $key, $hide, $draft.$lasthash{$key})); - push(@string, join(':', $key, $hide, $draft.( + my $draft = $lasthash{$partid.'awarddetail'} eq 'DRAFT' ? 1 : 0; + push(@string, join(':', $key, $hide, $draft, ( ref($lasthash{$key}) eq 'ARRAY' ? join(',', @{$lasthash{$key}}) : $lasthash{$key}) )); } @@ -2769,7 +2774,8 @@ sub processHandGrade { my $ctr = 0; while ($ctr < $ngrade) { my ($uname,$udom) = split(/:/,$env{'form.unamedom'.$ctr}); - my ($errorflag,$pts,$wgt) = &saveHandGrade($request,$symb,$uname,$udom,$ctr); + my ($errorflag,$pts,$wgt,$numhidden) = + &saveHandGrade($request,$symb,$uname,$udom,$ctr); if ($errorflag eq 'no_score') { $ctr++; next; @@ -2782,6 +2788,12 @@ sub processHandGrade { $ctr++; next; } + if ($numhidden) { + $request->print( + '' + .&mt('For [_1]: [quant,_2,transaction] hidden',"$uname:$udom",$numhidden) + .'
'); + } my $includemsg = $env{'form.includemsg'.$ctr}; my ($subject,$message,$msgstatus) = ('','',''); my $restitle = &Apache::lonnet::gettitle($symb); @@ -3003,9 +3015,14 @@ sub saveHandGrade { my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$domain,$stuname); my @parts_graded; my %newrecord = (); - my ($pts,$wgt) = ('',''); + my ($pts,$wgt,$totchg) = ('','',0); my %aggregate = (); my $aggregateflag = 0; + if ($env{'form.HIDE'.$newflg}) { + my ($version,$parts) = split(/:/,$env{'form.HIDE'.$newflg},2); + my $numchgs = &makehidden($version,$parts,\%record,$symb,$domain,$stuname,1); + $totchg += $numchgs; + } my @parts = split(/:/,$env{'form.partlist'.$newflg}); foreach my $new_part (@parts) { #collaborator ($submi may vary for different parts @@ -3108,7 +3125,37 @@ sub saveHandGrade { &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, $cdom,$cnum); } - return ('',$pts,$wgt); + return ('',$pts,$wgt,$totchg); +} + +sub makehidden { + my ($version,$parts,$record,$symb,$domain,$stuname,$tolog) = @_; + return unless (ref($record) eq 'HASH'); + my %modified; + my $numchanged = 0; + if (exists($record->{$version.':keys'})) { + my $partsregexp = $parts; + $partsregexp =~ s/,/|/g; + foreach my $key (split(/\:/,$record->{$version.':keys'})) { + if ($key =~ /^resource\.(?:$partsregexp)\.([^\.]+)$/) { + my $item = $1; + unless (($item eq 'solved') || ($item =~ /^award(|msg|ed)$/)) { + $modified{$key} = $record->{$version.':'.$key}; + } + } elsif ($key =~ m{^(resource\.(?:$partsregexp)\.[^\.]+\.)(.+)$}) { + $modified{$1.'hidden'.$2} = $record->{$version.':'.$key}; + } elsif ($key =~ /^(ip|timestamp|host)$/) { + $modified{$key} = $record->{$version.':'.$key}; + } + } + if (keys(%modified)) { + if (&Apache::lonnet::putstore($env{'request.course.id'},$symb,$version,\%modified, + $domain,$stuname,$tolog) eq 'ok') { + $numchanged ++; + } + } + } + return $numchanged; } sub check_and_remove_from_queue { @@ -3152,13 +3199,13 @@ sub handback_files { my ($directory,$answer_file) = ($env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter} =~ /^(.*?)([^\/]*)$/); my ($answer_name,$answer_ver,$answer_ext) = - &file_name_version_ext($answer_file); + &Apache::lonnet::file_name_version_ext($answer_file); my ($portfolio_path) = ($directory =~ /^.+$stuname\/portfolio(.*)/); my $getpropath = 1; my ($dir_list,$listerror) = &Apache::lonnet::dirlist($portfolio_root.$portfolio_path, $domain,$stuname,$getpropath); - my $version = &get_next_version($answer_name,$answer_ext,$dir_list); + my $version = &Apache::lonnet::get_next_version($answer_name,$answer_ext,$dir_list); # fix filename my ($save_file_name) = (($directory.$answer_name.".$version.".$answer_ext) =~ /^.+\/${stuname}\/(.*)/); my $result=&Apache::lonnet::finishuserfileupload($stuname,$domain, @@ -3307,29 +3354,14 @@ sub version_portfiles { my $version_parts = join('|',@$v_flag); my @returned_keys; my $parts = join('|', @$parts_graded); - my $portfolio_root = '/userfiles/portfolio'; foreach my $key (keys(%$record)) { my $new_portfiles; if ($key =~ /^resource\.($version_parts)\./ && $key =~ /\.portfiles$/ ) { my @versioned_portfiles; my @portfiles = split(/\s*,\s*/,$$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 ($answer_name,$answer_ver,$answer_ext) = - &file_name_version_ext($answer_file); - my $getpropath = 1; - my ($dir_list,$listerror) = - &Apache::lonnet::dirlist($portfolio_root.$directory,$domain, - $stu_name,$getpropath); - 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(@versioned_portfiles, $directory.$new_answer); - &Apache::lonnet::mark_as_readonly($domain,$stu_name, - [$directory.$new_answer], - [$symb,$env{'request.course.id'},'graded']); - } + if (@portfiles) { + &Apache::lonnet::portfiles_versioning($symb,$domain,$stu_name,\@portfiles, + \@versioned_portfiles); } $$record{$key} = join(',',@versioned_portfiles); push(@returned_keys,$key); @@ -3338,64 +3370,6 @@ sub version_portfiles { return (@returned_keys); } -sub get_next_version { - my ($answer_name, $answer_ext, $dir_list) = @_; - my $version; - if (ref($dir_list) eq 'ARRAY') { - foreach my $row (@{$dir_list}) { - my ($file) = split(/\&/,$row,2); - my ($file_name,$file_version,$file_ext) = - &file_name_version_ext($file); - if (($file_name eq $answer_name) && - ($file_ext eq $answer_ext)) { - # gets here if filename and extension match, - # regardless of version - if ($file_version ne '') { - # a versioned file is found so save it for later - if ($file_version > $version) { - $version = $file_version; - } - } - } - } - } - $version ++; - return($version); -} - -sub version_selected_portfile { - my ($domain,$stu_name,$directory,$file_name,$version) = @_; - my ($answer_name,$answer_ver,$answer_ext) = - &file_name_version_ext($file_name); - my $new_answer; - $env{'form.copy'} = &Apache::lonnet::getfile("/uploaded/$domain/$stu_name/portfolio$directory$file_name"); - if($env{'form.copy'} eq '-1') { - $new_answer = 'problem getting file'; - } else { - $new_answer = $answer_name.'.'.$version.'.'.$answer_ext; - my $copy_result = &Apache::lonnet::finishuserfileupload( - $stu_name,$domain,'copy', - '/portfolio'.$directory.$new_answer); - } - return ($new_answer); -} - -sub file_name_version_ext { - my ($file)=@_; - my @file_parts = split(/\./, $file); - my ($name,$version,$ext); - if (@file_parts > 1) { - $ext=pop(@file_parts); - if (@file_parts > 1 && $file_parts[-1] =~ /^\d+$/) { - $version=pop(@file_parts); - } - $name=join('.',@file_parts); - } else { - $name=join('.',@file_parts); - } - return($name,$version,$ext); -} - #-------------------------------------------------------------------------------------- # #-------------------------- Next few routines handles grading by section or whole class @@ -4776,9 +4750,11 @@ sub displayPage { } } elsif ($env{'form.lastSub'} eq 'all') { my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : ''); + my $identifier = (&canmodify($usec)? $prob : ''); $studentTable.=&Apache::loncommon::get_previous_attempt($symbx,$uname,$udom, $env{'request.course.id'}, - '','.submission'); + '','.submission',undef, + $usec,$identifier); } if (&canmodify($usec)) { @@ -4830,7 +4806,7 @@ sub displaySubByDates { my $interaction; my $no_increment = 1; - my %lastrndseed; + my (%lastrndseed,%lasttype); for ($version=1;$version<=$$record{'version'};$version++) { my $timestamp = &Apache::lonlocal::locallocaltime($$record{$version.':timestamp'}); @@ -4888,12 +4864,14 @@ sub displaySubByDates { } else { $displaySub[0].=&mt('Trial: [_1]', $$record{"$where.$partid.tries"}); - if ($rndseed || $lastrndseed{$partid}) { - if ($rndseed ne $lastrndseed{$partid}) { + if (($rndseed ne '') && ($lastrndseed{$partid} ne '')) { + if (($rndseed ne $lastrndseed{$partid}) && + (($type eq 'randomizetry') || ($lasttype{$partid} eq 'randomizetry'))) { $newvariation = ' ('.&mt('New variation this try').')'; } } $lastrndseed{$partid} = $rndseed; + $lasttype{$partid} = $type; } my $responseType=($isTask ? 'Task' : $responseType->{$partid}->{$responseId}); @@ -4991,7 +4969,7 @@ sub updateGradeByPage { $iterator->next(); # skip the first BEGIN_MAP my $curRes = $iterator->next(); # for "current resource" - my ($depth,$question,$prob,$changeflag)= (1,1,1,0); + my ($depth,$question,$prob,$changeflag,$hideflag)= (1,1,1,0,0); while ($depth > 0) { if($curRes == $iterator->BEGIN_MAP) { $depth++; } if($curRes == $iterator->END_MAP) { $depth--; } @@ -5012,6 +4990,12 @@ sub updateGradeByPage { my @displayPts=(); my %aggregate = (); my $aggregateflag = 0; + if ($env{'form.HIDE'.$prob}) { + my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname); + my ($version,$parts) = split(/:/,$env{'form.HIDE'.$prob},2); + my $numchgs = &makehidden($version,$parts,\%record,$symbx,$udom,$uname,1); + $hideflag += $numchgs; + } foreach my $partid (@{$parts}) { my $newpts = $env{'form.GD_BOX'.$question.'_'.$partid}; my $oldpts = $env{'form.oldpts'.$question.'_'.$partid}; @@ -5102,8 +5086,11 @@ sub updateGradeByPage { $studentTable.=&Apache::loncommon::end_data_table(); my $grademsg=($changeflag == 0 ? &mt('No score was changed or updated.') : &mt('The scores were changed for [quant,_1,problem].', - $changeflag)); - $request->print($grademsg.$studentTable); + $changeflag).'
'); + my $hidemsg=($hideflag == 0 ? '' : + &mt('Submissions were marked "hidden" for [quant,_1,transaction].', + $hideflag).'
'); + $request->print($hidemsg.$grademsg.$studentTable); return ''; } @@ -5729,7 +5716,9 @@ sub get_scantron_config { =item username_to_idmap creates a hash keyed by student/employee ID with values of the corresponding - student username:domain. + student username:domain. If a single ID occurs for more than one student, + the status of the student is checked, and if Active, the value in the hash + will be set to the Active student. Arguments: @@ -5747,8 +5736,17 @@ sub username_to_idmap { my ($classlist)= @_; my %idmap; foreach my $student (keys(%$classlist)) { - $idmap{$classlist->{$student}->[&Apache::loncoursedata::CL_ID]}= - $student; + my $id = $classlist->{$student}->[&Apache::loncoursedata::CL_ID]; + unless ($id eq '') { + if (!exists($idmap{$id})) { + $idmap{$id} = $student; + } else { + my $status = $classlist->{$student}->[&Apache::loncoursedata::CL_STATUS]; + if ($status eq 'Active') { + $idmap{$id} = $student; + } + } + } } return %idmap; } @@ -8914,7 +8912,7 @@ sub scantron_download_scantron_data { &Apache::lonnet::allowuploaded('/adm/grades',$skipped); $r->print('

- '.&mt('[_1]Original[_2] file as uploaded by the bubblesheet office.', + '.&mt('[_1]Original[_2] file as uploaded by the bubblesheet scanning office.', '','').'