--- loncom/homework/grades.pm 2017/12/21 23:05:04 1.746
+++ loncom/homework/grades.pm 2019/02/06 05:46:51 1.758
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Grading handler
#
-# $Id: grades.pm,v 1.746 2017/12/21 23:05:04 raeburn Exp $
+# $Id: grades.pm,v 1.758 2019/02/06 05:46:51 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -46,6 +46,7 @@ use Apache::lonenc;
use Apache::lonstathelpers;
use Apache::lonquickgrades;
use Apache::bridgetask();
+use Apache::lontexconvert();
use String::Similarity;
use LONCAPA;
@@ -417,6 +418,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 = &Apache::lontexconvert::msgtexconverted($answer);
return '
'.&keywords_highlight($answer).'
';
} elsif ( $response eq 'organic') {
@@ -502,7 +504,7 @@ COMMONJSFUNCTIONS
#--- Dumps the class list with usernames,list of sections,
#--- section, ids and fullnames for each user.
sub getclasslist {
- my ($getsec,$filterlist,$getgroup) = @_;
+ my ($getsec,$filterbyaccstatus,$getgroup,$symb,$submitonly,$filterbysubmstatus) = @_;
my @getsec;
my @getgroup;
my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));
@@ -530,6 +532,13 @@ sub getclasslist {
#
my %sections;
my %fullnames;
+ my ($cdom,$cnum,$partlist);
+ if (($filterbysubmstatus) && ($submitonly ne 'all') && ($symb ne '')) {
+ $cdom = $env{"course.$env{'request.course.id'}.domain"};
+ $cnum = $env{"course.$env{'request.course.id'}.num"};
+ my $res_error;
+ ($partlist,my $handgrade,my $responseType) = &response_type($symb,\$res_error);
+ }
foreach my $student (keys(%$classlist)) {
my $end =
$classlist->{$student}->[&Apache::loncoursedata::CL_END()];
@@ -546,7 +555,7 @@ sub getclasslist {
my $group =
$classlist->{$student}->[&Apache::loncoursedata::CL_GROUP()];
# filter students according to status selected
- if ($filterlist && (!($stu_status =~ /Any/))) {
+ if ($filterbyaccstatus && (!($stu_status =~ /Any/))) {
if (!($stu_status =~ $status)) {
delete($classlist->{$student});
next;
@@ -563,13 +572,58 @@ sub getclasslist {
}
}
if (($grp eq 'none') && !$group) {
- $exclude = 0;
+ $exclude = 0;
}
}
if ($exclude) {
delete($classlist->{$student});
+ next;
}
}
+ if (($filterbysubmstatus) && ($submitonly ne 'all') && ($symb ne '')) {
+ my $udom =
+ $classlist->{$student}->[&Apache::loncoursedata::CL_SDOM()];
+ my $uname =
+ $classlist->{$student}->[&Apache::loncoursedata::CL_SNAME()];
+ if (($symb ne '') && ($udom ne '') && ($uname ne '')) {
+ if ($submitonly eq 'queued') {
+ my %queue_status =
+ &Apache::bridgetask::get_student_status($symb,$cdom,$cnum,
+ $udom,$uname);
+ if (!defined($queue_status{'gradingqueue'})) {
+ delete($classlist->{$student});
+ next;
+ }
+ } else {
+ my (%status) =&student_gradeStatus($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{$_} =~ /^ungraded/);
+ $incorrect = 1 if ($status{$_} =~ /^incorrect/);
+
+ my ($foo,$partid,$foo1) = split(/\./,$_);
+ if ($status{'resource.'.$partid.'.submitted_by'} ne '') {
+ $submitted = 0;
+ }
+ }
+ if (!$submitted && ($submitonly eq 'yes' ||
+ $submitonly eq 'incorrect' ||
+ $submitonly eq 'graded')) {
+ delete($classlist->{$student});
+ next;
+ } elsif (!$graded && ($submitonly eq 'graded')) {
+ delete($classlist->{$student});
+ next;
+ } elsif (!$incorrect && $submitonly eq 'incorrect') {
+ delete($classlist->{$student});
+ next;
+ }
+ }
+ }
+ }
$section = ($section ne '' ? $section : 'none');
if (&canview($section)) {
if (!@getsec || grep(/^\Q$section\E$/,@getsec)) {
@@ -584,7 +638,6 @@ sub getclasslist {
delete($classlist->{$student});
}
}
- my %seen = ();
my @sections = sort(keys(%sections));
return ($classlist,\@sections,\%fullnames);
}
@@ -856,7 +909,7 @@ sub verifyreceipt {
sub listStudents {
my ($request,$symb,$submitonly) = @_;
- my $is_tool = ($symb =~ /ext\.tool$/);
+ my $is_tool = ($symb =~ /ext\.tool$/);
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'};
@@ -1952,7 +2005,6 @@ sub show_problem {
sub files_exist {
my ($r, $symb) = @_;
my @students = &Apache::loncommon::get_env_multiple('form.stuinfo');
-
foreach my $student (@students) {
my ($uname,$udom,$fullname) = split(/:/,$student);
my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},
@@ -1975,7 +2027,6 @@ sub download_all_link {
$r->print(&mt('There are currently no submitted documents.'));
return;
}
-
my $all_students =
join("\n", &Apache::loncommon::get_env_multiple('form.stuinfo'));
@@ -1995,7 +2046,55 @@ sub submit_download_link {
my ($request,$symb) = @_;
if (!$symb) { return ''; }
#FIXME: Figure out which type of problem this is and provide appropriate download
- &download_all_link($request,$symb);
+ my $res_error;
+ my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error);
+ if (ref($res_error)) {
+ if ($$res_error) {
+ $request->print(&mt('An error occurred retrieving response types'));
+ return;
+ }
+ }
+ my ($numupload,$numessay) = (0,0);
+ if (ref($responseType) eq 'HASH') {
+ foreach my $part (sort(keys(%$responseType))) {
+ foreach my $id (sort(keys(%{ $responseType->{$part} }))) {
+ my $responsetype = $responseType->{$part}->{$id};
+ if ($responsetype eq 'essay') {
+ my $uploadedfiletypes =
+ &Apache::lonnet::EXT("resource.$part".'_'."$id.uploadedfiletypes",$symb);
+ if ($uploadedfiletypes) {
+ $numupload++;
+ } else {
+ $numessay++;
+ }
+ }
+ }
+ }
+ }
+ if (($numupload) || ($numessay)) {
+ my $submitonly= $env{'form.submitonly'} eq '' ? 'all' : $env{'form.submitonly'};
+ my $getsec = $env{'form.section'} eq '' ? 'all' : $env{'form.section'};
+ my $getgroup = $env{'form.group'} eq '' ? 'all' : $env{'form.group'};
+ (undef,undef,my $fullname) = &getclasslist($getsec,1,$getgroup,$symb,$submitonly,1);
+ if (ref($fullname) eq 'HASH') {
+ my @students = map { $_.':'.$fullname->{$_} } (keys(%{$fullname}));
+ if (@students) {
+ @{$env{'form.stuinfo'}} = @students;
+ if ($numupload) {
+ &download_all_link($request,$symb);
+ }
+# FIXME Need to provide a mechanism to download essays, i.e., if $numessay > 0
+# Needs to omit user's identity if resource instance is for an anonymous survey.
+ } else {
+ $request->print(&mt('No students match the criteria you selected'));
+ }
+ } else {
+ $request->print(&mt('Could not retrieve student information'));
+ }
+ } else {
+ $request->print(&mt('No essayresponse items found'));
+ }
+ return;
}
sub build_section_inputs {
@@ -2022,6 +2121,7 @@ sub submission {
my $probtitle=&Apache::lonnet::gettitle($symb);
if ($symb eq '') { $request->print("Unable to handle ambiguous references:."); return ''; }
my $is_tool = ($symb =~ /ext\.tool$/);
+ my ($essayurl,%coursedesc_by_cid);
if (!&canview($usec)) {
$request->print(
@@ -2152,11 +2252,24 @@ sub submission {
#
# Load the other essays for similarity check
#
- my (undef,undef,$essayurl) = &Apache::lonnet::decode_symb($symb);
- my ($adom,$aname,$apath)=($essayurl=~/^($LONCAPA::domain_re)\/($LONCAPA::username_re)\/(.*)$/);
- $apath=&escape($apath);
- $apath=~s/\W/\_/gs;
- &init_old_essays($symb,$apath,$adom,$aname);
+ (undef,undef,$essayurl) = &Apache::lonnet::decode_symb($symb);
+ if ($essayurl eq 'lib/templates/simpleproblem.problem') {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ if ($cdom ne '' && $cnum ne '') {
+ my ($map,$id,$res) = &Apache::lonnet::decode_symb($symb);
+ if ($map =~ m{^\Quploaded/$cdom/$cnum/\E(default(?:|_\d+)\.(?:sequence|page))$}) {
+ my $apath = $1.'_'.$id;
+ $apath=~s/\W/\_/gs;
+ &init_old_essays($symb,$apath,$cdom,$cnum);
+ }
+ }
+ } else {
+ my ($adom,$aname,$apath)=($essayurl=~/^($LONCAPA::domain_re)\/($LONCAPA::username_re)\/(.*)$/);
+ $apath=&escape($apath);
+ $apath=~s/\W/\_/gs;
+ &init_old_essays($symb,$apath,$adom,$aname);
+ }
}
}
@@ -2307,24 +2420,52 @@ sub submission {
&most_similar($uname,$udom,$symb,$subval);
if ($osim) {
$osim=int($osim*100.0);
- my %old_course_desc =
- &Apache::lonnet::coursedescription($ocrsid,
- {'one_time' => 1});
-
if ($hide eq 'anon') {
$similar=''.&mt("Essay was found to be similar to another essay submitted for this assignment.").' '.
&mt('As the current submission is for an anonymous survey, no other details are available.').'';
} else {
- $similar="
".
- &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',
- $osim,
- &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',
- $old_course_desc{'description'},
- $old_course_desc{'num'},
- $old_course_desc{'domain'}).
- '
'.
+ &mt('Essay is [_1]% similar to an essay by [_2]',
+ $osim,
+ &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').
+ '
';
+ } else {
+ my %old_course_desc;
+ if ($ocrsid ne '') {
+ if (ref($coursedesc_by_cid{$ocrsid}) eq 'HASH') {
+ %old_course_desc = %{$coursedesc_by_cid{$ocrsid}};
+ } else {
+ my $args;
+ if ($ocrsid ne $env{'request.course.id'}) {
+ $args = {'one_time' => 1};
+ }
+ %old_course_desc =
+ &Apache::lonnet::coursedescription($ocrsid,$args);
+ $coursedesc_by_cid{$ocrsid} = \%old_course_desc;
+ }
+ $similar .=
+ '
'.
+ &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',
+ $osim,
+ &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',
+ $old_course_desc{'description'},
+ $old_course_desc{'num'},
+ $old_course_desc{'domain'}).
+ '
';
+ } else {
+ $similar .=
+ '
'.
+ &mt('Essay is [_1]% similar to an essay by [_2] in an unknown course',
+ $osim,
+ &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').
+ '
';
+ }
+ }
+ $similar .= '
'.
+ &keywords_highlight($oessay).
+ '
';
}
}
}
@@ -2635,7 +2776,7 @@ sub get_last_submission {
if (!@string) {
my $msg;
if ($is_tool) {
- $msg = &mt('Nothing passed back - no attempts.');
+ $msg = &mt('No grade passed back.');
} else {
$msg = &mt('Nothing submitted - no attempts.');
}
@@ -4090,6 +4231,7 @@ sub editgrades {
$ctr++;
}
my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);
+ my $totcolspan = 0;
foreach my $partid (@partid) {
$header .= '
'.&mt('Old Score').'
'.
'
'.&mt('New Score').'
';
@@ -4106,6 +4248,7 @@ sub editgrades {
'
'.&mt('New').' '.$display.'
';
$columns{$partid}+=2;
}
+ $totcolspan += $columns{$partid};
}
foreach my $partid (@partid) {
my $display_part=&get_display_part($partid,$symb);
@@ -4121,18 +4264,18 @@ sub editgrades {
my @noupdate;
my ($updateCtr,$noupdateCtr) = (1,1);
for ($i=0; $i<$env{'form.total'}; $i++) {
- my $line;
my $user = $env{'form.ctr'.$i};
my ($uname,$udom)=split(/:/,$user);
my %newrecord;
my $updateflag = 0;
- $line .= '
';
my $usec=$classlist->{"$uname:$udom"}[5];
- if (!&canmodify($usec)) {
- my $numcols=scalar(@partid)*4+2;
+ my $canmodify = &canmodify($usec);
+ my $line = '