--- loncom/homework/grades.pm 2014/11/21 17:59:11 1.727
+++ loncom/homework/grades.pm 2023/02/12 21:01:30 1.792
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Grading handler
#
-# $Id: grades.pm,v 1.727 2014/11/21 17:59:11 raeburn Exp $
+# $Id: grades.pm,v 1.792 2023/02/12 21:01:30 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -46,7 +46,10 @@ use Apache::lonenc;
use Apache::lonstathelpers;
use Apache::lonquickgrades;
use Apache::bridgetask();
+use Apache::lontexconvert();
use String::Similarity;
+use HTML::Parser();
+use File::MMagic;
use LONCAPA;
use POSIX qw(floor);
@@ -116,7 +119,11 @@ sub getpartlist {
my $res = $navmap->getBySymb($symb);
my $partlist = $res->parts();
my $url = $res->src();
- my @metakeys = split(/,/,&Apache::lonnet::metadata($url,'keys'));
+ my $toolsymb;
+ if ($url =~ /ext\.tool$/) {
+ $toolsymb = $symb;
+ }
+ my @metakeys = split(/,/,&Apache::lonnet::metadata($url,'keys',$toolsymb));
my @stores;
foreach my $part (@{ $partlist }) {
@@ -140,7 +147,7 @@ sub nameUserString {
}
#--- Get the partlist and the response type for a given problem. ---
-#--- Indicate if a response type is coded handgraded or not. ---
+#--- Count responseIDs, essayresponse items, and dropbox items ---
#--- Sets response_error pointer to "1" if navmaps object broken ---
sub response_type {
my ($symb,$response_error) = @_;
@@ -158,6 +165,7 @@ sub response_type {
return;
}
my $partlist = $res->parts();
+ my ($numresp,$numessay,$numdropbox) = (0,0,0);
my %vPart =
map { $_ => 1 } (&Apache::loncommon::get_env_multiple('form.vPart'));
my (%response_types,%handgrade);
@@ -167,13 +175,20 @@ sub response_type {
my @types = $res->responseType($part);
my @ids = $res->responseIds($part);
for (my $i=0; $i < scalar(@ids); $i++) {
+ $numresp ++;
$response_types{$part}{$ids[$i]} = $types[$i];
+ if ($types[$i] eq 'essay') {
+ $numessay ++;
+ if (&Apache::lonnet::EXT("resource.$part".'_'.$ids[$i].".uploadedfiletypes",$symb)) {
+ $numdropbox ++;
+ }
+ }
$handgrade{$part.'_'.$ids[$i]} =
&Apache::lonnet::EXT('resource.'.$part.'_'.$ids[$i].
'.handgrade',$symb);
}
}
- return ($partlist,\%handgrade,\%response_types);
+ return ($partlist,\%handgrade,\%response_types,$numresp,$numessay,$numdropbox);
}
sub flatten_responseType {
@@ -200,6 +215,129 @@ sub get_display_part {
return $display;
}
+#--- Show parts and response type
+sub showResourceInfo {
+ my ($symb,$partlist,$responseType,$formname,$checkboxes,$uploads) = @_;
+ unless ((ref($partlist) eq 'ARRAY') && (ref($responseType) eq 'HASH')) {
+ return '
';
+ }
+ my $coltitle = &mt('Problem Part Shown');
+ if ($checkboxes) {
+ $coltitle = &mt('Problem Part');
+ } else {
+ my $checkedparts = 0;
+ foreach my $partid (&Apache::loncommon::get_env_multiple('form.vPart')) {
+ if (grep(/^\Q$partid\E$/,@{$partlist})) {
+ $checkedparts ++;
+ }
+ }
+ if ($checkedparts == scalar(@{$partlist})) {
+ return '
';
+ }
+ if ($uploads) {
+ $coltitle = &mt('Problem Part Selected');
+ }
+ }
+ my $result = '
'. + &mt('No dropbox items or essayresponse items with uploadedfiletypes set.'). + '
'; + } else { + return ''.&keywords_highlight(&HTML::Entities::encode($answer, '"<>&')).''; - + $answer = &Apache::lontexconvert::msgtexconverted($answer); + return '
'.&keywords_highlight($answer).''; } elsif ( $response eq 'organic') { my $result=&mt('Smile representation: [_1]', '"'.&HTML::Entities::encode($answer, '"<>&').'"'); @@ -491,7 +636,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')); @@ -519,6 +664,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) = &response_type($symb,\$res_error); + } foreach my $student (keys(%$classlist)) { my $end = $classlist->{$student}->[&Apache::loncoursedata::CL_END()]; @@ -535,7 +687,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; @@ -552,13 +704,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)) { @@ -573,7 +770,6 @@ sub getclasslist { delete($classlist->{$student}); } } - my %seen = (); my @sections = sort(keys(%sections)); return ($classlist,\@sections,\%fullnames); } @@ -589,7 +785,7 @@ sub canmodify { #can modify the requested section return 1; } else { - # can't modify the request section + # can't modify the requested section return 0; } } @@ -602,19 +798,19 @@ sub canview { my ($sec)=@_; if ($perm{'vgr'}) { if (!defined($perm{'vgr_section'})) { - # can modify whole class + # can view whole class return 1; } else { if ($sec eq $perm{'vgr_section'}) { - #can modify the requested section + #can view the requested section return 1; } else { - # can't modify the request section + # can't view the requested section return 0; } } } - #can't modify + #can't view return 0; } @@ -755,14 +951,14 @@ sub initialverifyreceipt { #--- Check whether a receipt number is valid.--- sub verifyreceipt { - my ($request,$symb) = @_; + my ($request,$symb) = @_; my $courseid = $env{'request.course.id'}; my $receipt = &Apache::lonnet::recprefix($courseid).'-'. $env{'form.receipt'}; $receipt =~ s/[^\-\d]//g; - my $title.= + my $title = '