--- loncom/homework/grades.pm 2015/06/09 21:22:48 1.736
+++ loncom/homework/grades.pm 2018/10/08 19:04:06 1.751
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Grading handler
#
-# $Id: grades.pm,v 1.736 2015/06/09 21:22:48 damieng Exp $
+# $Id: grades.pm,v 1.751 2018/10/08 19:04:06 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -116,7 +116,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 }) {
@@ -293,7 +297,7 @@ sub reset_caches {
}
sub scantron_partids_tograde {
- my ($resource,$cid,$uname,$udom,$check_for_randomlist,$bubbles_per_row) = @_;
+ my ($resource,$cid,$uname,$udom,$check_for_randomlist,$bubbles_per_row,$scancode) = @_;
my (%analysis,@parts);
if (ref($resource)) {
my $symb = $resource->symb();
@@ -301,6 +305,13 @@ sub reset_caches {
if ($check_for_randomlist) {
$add_to_form = { 'check_parts_withrandomlist' => 1,};
}
+ if ($scancode) {
+ if (ref($add_to_form) eq 'HASH') {
+ $add_to_form->{'code_for_randomlist'} = $scancode;
+ } else {
+ $add_to_form = { 'code_for_randomlist' => $scancode,};
+ }
+ }
my $analyze =
&get_analyze($symb,$uname,$udom,undef,$add_to_form,
undef,undef,undef,$bubbles_per_row);
@@ -406,6 +417,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') {
@@ -491,7 +503,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 +531,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()];
@@ -535,7 +554,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 +571,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 +637,6 @@ sub getclasslist {
delete($classlist->{$student});
}
}
- my %seen = ();
my @sections = sort(keys(%sections));
return ($classlist,\@sections,\%fullnames);
}
@@ -845,6 +908,7 @@ sub verifyreceipt {
sub listStudents {
my ($request,$symb,$submitonly) = @_;
+ 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'};
@@ -900,38 +964,66 @@ LISTJAVASCRIPT
"\n";
$gradeTable .= &Apache::lonhtmlcommon::start_pick_box();
- $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Problem Text'))
- .''."\n"
- .''."\n"
- .' '."\n"
- .&Apache::lonhtmlcommon::row_closure();
- $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Answer'))
- .''."\n"
- .''."\n"
- .' '."\n"
- .&Apache::lonhtmlcommon::row_closure();
+ unless ($is_tool) {
+ $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Problem Text'))
+ .''."\n"
+ .''."\n"
+ .' '."\n"
+ .&Apache::lonhtmlcommon::row_closure();
+ $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Answer'))
+ .''."\n"
+ .''."\n"
+ .' '."\n"
+ .&Apache::lonhtmlcommon::row_closure();
+ }
my $submission_options;
my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));
my $saveStatus = $stu_status eq '' ? 'Active' : $stu_status;
$env{'form.Status'} = $saveStatus;
+ my %optiontext;
+ if ($is_tool) {
+ %optiontext = &Apache::lonlocal::texthash (
+ lastonly => 'last transaction',
+ last => 'last transaction with details',
+ datesub => 'all transactions',
+ all => 'all transactions with details',
+ );
+ } else {
+ %optiontext = &Apache::lonlocal::texthash (
+ lastonly => 'last submission',
+ last => 'last submission with details',
+ datesub => 'all submissions',
+ all => 'all submissions with details',
+ );
+ }
$submission_options.=
''.
''."\n".
+ $optiontext{'lastonly'}.' '."\n".
''.
''."\n".
+ $optiontext{'last'}.' '."\n".
''.
''."\n".
+ $optiontext{'datesub'}.''."\n".
''.
'';
- $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('View Submissions'))
+ $optiontext{'all'}.'';
+ my $viewtitle;
+ if ($is_tool) {
+ $viewtitle = &mt('View Transactions');
+ } else {
+ $viewtitle = &mt('View Submissions');
+ }
+ $gradeTable .= &Apache::lonhtmlcommon::row_title($viewtitle)
.$submission_options
.&Apache::lonhtmlcommon::row_closure();
+ my $closure;
+ if (($is_tool) && (exists($env{'form.Status'}))) {
+ $closure = 1;
+ }
$gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Grading Increments'))
.''
- .&Apache::lonhtmlcommon::row_closure();
+ .&Apache::lonhtmlcommon::row_closure($closure);
$gradeTable .=
&build_section_inputs().
@@ -950,19 +1042,30 @@ LISTJAVASCRIPT
if (exists($env{'form.Status'})) {
$gradeTable .= ''."\n";
} else {
+ if ($is_tool) {
+ $closure = 1;
+ }
$gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Student Status'))
.&Apache::lonhtmlcommon::StatusOptions(
$saveStatus,undef,1,'javascript:reLoadList(this.form);')
- .&Apache::lonhtmlcommon::row_closure();
+ .&Apache::lonhtmlcommon::row_closure($closure);
}
- $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Check For Plagiarism'))
- .''
- .&Apache::lonhtmlcommon::row_closure(1)
- .&Apache::lonhtmlcommon::end_pick_box();
-
+ unless ($is_tool) {
+ $closure = 1;
+ $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Check For Plagiarism'))
+ .''
+ .&Apache::lonhtmlcommon::row_closure($closure);
+ }
+ $gradeTable .= &Apache::lonhtmlcommon::end_pick_box();
+ my $regrademsg;
+ if ($is_tool) {
+ $regrademsg =&mt("To view/grade/regrade, click on the check box(es) next to the student's name(s). Then click on the Next button.");
+ } else {
+ $regrademsg = &mt("To view/grade/regrade a submission or a group of submissions, click on the check box(es) next to the student's name(s). Then click on the Next button.");
+ }
$gradeTable .= '
'
- .&mt("To view/grade/regrade a submission or a group of submissions, click on the check box(es) next to the student's name(s). Then click on the Next button.")."\n"
+ .$regrademsg."\n"
.''
.'
';
@@ -1901,7 +2004,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'},
@@ -1924,7 +2026,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'));
@@ -1944,7 +2045,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 {
@@ -1970,6 +2119,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$/);
if (!&canview($usec)) {
$request->print(
@@ -1982,8 +2132,10 @@ sub submission {
}
if (!$env{'form.lastSub'}) { $env{'form.lastSub'} = 'datesub'; }
- if (!$env{'form.vProb'}) { $env{'form.vProb'} = 'yes'; }
- if (!$env{'form.vAns'}) { $env{'form.vAns'} = 'yes'; }
+ unless ($is_tool) {
+ if (!$env{'form.vProb'}) { $env{'form.vProb'} = 'yes'; }
+ if (!$env{'form.vAns'}) { $env{'form.vAns'} = 'yes'; }
+ }
my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : '');
my $checkIcon = ''
- .'
'.&mt('Submissions').'
';
+ .'
'.$boxtitle.'
';
$result.=''."\n";
# if ($env{'form.handgrade'} eq 'no') {
- if (1) {
+ unless ($is_tool) {
$result.='
'
.&mt('Part(s) graded correct by the computer is marked with a [_1] symbol.',$checkIcon)
."
\n";
@@ -2171,7 +2327,7 @@ sub submission {
my $fullname;
my $col_fullnames = [];
# if ($env{'form.handgrade'} eq 'yes') {
- if (1) {
+ unless ($is_tool) {
(my $sub_result,$fullname,$col_fullnames)=
&check_collaborators($symb,$uname,$udom,\%record,$handgrade,
$counter);
@@ -2186,12 +2342,16 @@ sub submission {
# (3) Last submission plus the parts info
# (4) The whole record for this student
- my ($string,$timestamp)= &get_last_submission(\%record);
+ my ($string,$timestamp)= &get_last_submission(\%record,$is_tool);
my $lastsubonly;
if ($$timestamp eq '') {
$lastsubonly.='
'
@@ -2374,7 +2534,12 @@ sub submission {
my %seen = ();
my @partlist;
my @gradePartRespid;
- my @part_response_id = &flatten_responseType($responseType);
+ my @part_response_id;
+ if ($is_tool) {
+ @part_response_id = ([0,'']);
+ } else {
+ @part_response_id = &flatten_responseType($responseType);
+ }
$request->print(
'
'
.'
'.&mt('Assign Grades').'
'
@@ -2500,7 +2665,7 @@ sub check_collaborators {
#--- Retrieve the last submission for all the parts
sub get_last_submission {
- my ($returnhash)=@_;
+ my ($returnhash,$is_tool)=@_;
my (@string,$timestamp,%lasthidden);
if ($$returnhash{'version'}) {
my %lasthash=();
@@ -2566,8 +2731,14 @@ sub get_last_submission {
}
}
if (!@string) {
+ my $msg;
+ if ($is_tool) {
+ $msg = &mt('No grade passed back.');
+ } else {
+ $msg = &mt('Nothing submitted - no attempts.');
+ }
$string[0] =
- ''.&mt('Nothing submitted - no attempts.').'';
+ ''.$msg.'';
}
return (\@string,\$timestamp);
}
@@ -3554,6 +3725,11 @@ VIEWJAVASCRIPT
#--- show scores for a section or whole class w/ option to change/update a score
sub viewgrades {
my ($request,$symb) = @_;
+ my ($is_tool,$toolsymb);
+ if ($symb =~ /ext\.tool$/) {
+ $is_tool = 1;
+ $toolsymb = $symb;
+ }
&viewgrades_js($request);
#need to make sure we have the correct data for later EXT calls,
@@ -3576,19 +3752,73 @@ sub viewgrades {
&build_section_inputs().
''."\n".
- my ($common_header,$specific_header);
- if ($env{'form.section'} eq 'all') {
- $common_header = &mt('Assign Common Grade to Class');
- $specific_header = &mt('Assign Grade to Specific Students in Class');
- } elsif ($env{'form.section'} eq 'none') {
- $common_header = &mt('Assign Common Grade to Students in no Section');
- $specific_header = &mt('Assign Grade to Specific Students in no Section');
- } else {
- my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));
- $common_header = &mt('Assign Common Grade to Students in Section(s) [_1]',$section_display);
- $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1]',$section_display);
+ #retrieve selected groups
+ my (@groups,$group_display);
+ @groups = &Apache::loncommon::get_env_multiple('form.group');
+ if (grep(/^all$/,@groups)) {
+ @groups = ('all');
+ } elsif (grep(/^none$/,@groups)) {
+ @groups = ('none');
+ } elsif (@groups > 0) {
+ $group_display = join(', ',@groups);
+ }
+
+ my ($common_header,$specific_header,@sections,$section_display);
+ @sections = &Apache::loncommon::get_env_multiple('form.section');
+ if (grep(/^all$/,@sections)) {
+ @sections = ('all');
+ if ($group_display) {
+ $common_header = &mt('Assign Common Grade to Students in Group(s) [_1]',$group_display);
+ $specific_header = &mt('Assign Grade to Specific Students in Group(s) [_1]',$group_display);
+ } elsif (grep(/^none$/,@groups)) {
+ $common_header = &mt('Assign Common Grade to Students not assigned to any groups');
+ $specific_header = &mt('Assign Grade to Specific Students not assigned to any groups');
+ } else {
+ $common_header = &mt('Assign Common Grade to Class');
+ $specific_header = &mt('Assign Grade to Specific Students in Class');
+ }
+ } elsif (grep(/^none$/,@sections)) {
+ @sections = ('none');
+ if ($group_display) {
+ $common_header = &mt('Assign Common Grade to Students in no Section and in Group(s) [_1]',$group_display);
+ $specific_header = &mt('Assign Grade to Specific Students in no Section and in Group(s)',$group_display);
+ } elsif (grep(/^none$/,@groups)) {
+ $common_header = &mt('Assign Common Grade to Students in no Section and in no Group');
+ $specific_header = &mt('Assign Grade to Specific Students in no Section and in no Group');
+ } else {
+ $common_header = &mt('Assign Common Grade to Students in no Section');
+ $specific_header = &mt('Assign Grade to Specific Students in no Section');
+ }
+ } else {
+ $section_display = join (", ",@sections);
+ if ($group_display) {
+ $common_header = &mt('Assign Common Grade to Students in Section(s) [_1], and in Group(s) [_2]',
+ $section_display,$group_display);
+ $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1], and in Group(s) [_2]',
+ $section_display,$group_display);
+ } elsif (grep(/^none$/,@groups)) {
+ $common_header = &mt('Assign Common Grade to Students in Section(s) [_1] and no Group',$section_display);
+ $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1] and no Group',$section_display);
+ } else {
+ $common_header = &mt('Assign Common Grade to Students in Section(s) [_1]',$section_display);
+ $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1]',$section_display);
+ }
}
- $result.= '
'.$common_header.'
'.&Apache::loncommon::start_data_table();
+ my %submit_types = &substatus_options();
+ my $submission_status = $submit_types{$env{'form.submitonly'}};
+
+ if ($env{'form.submitonly'} eq 'all') {
+ $result.= '
';
+ }
+ $result .= &Apache::loncommon::start_data_table();
#radio buttons/text box for assigning points for a section or class.
#handles different parts of a problem
my $res_error;
@@ -3599,13 +3829,18 @@ sub viewgrades {
my %weight = ();
my $ctsparts = 0;
my %seen = ();
- my @part_response_id = &flatten_responseType($responseType);
+ my @part_response_id;
+ if ($is_tool) {
+ @part_response_id = ([0,'']);
+ } else {
+ @part_response_id = &flatten_responseType($responseType);
+ }
foreach my $part_response_id (@part_response_id) {
my ($partid,$respid) = @{ $part_response_id };
my $part_resp = join('_',@{ $part_response_id });
next if $seen{$partid};
$seen{$partid}++;
- my $handgrade=$$handgrade{$part_resp};
+# my $handgrade=$$handgrade{$part_resp};
my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb);
$weight{$partid} = $wgt eq '' ? '1' : $wgt;
@@ -3651,8 +3886,18 @@ sub viewgrades {
#table listing all the students in a section/class
#header of table
- $result.= '
\n";
@@ -3664,10 +3909,10 @@ sub viewgrades {
my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
my @partids = ();
foreach my $part (@parts) {
- my $display=&Apache::lonnet::metadata($url,$part.'.display');
+ my $display=&Apache::lonnet::metadata($url,$part.'.display',$toolsymb);
my $narrowtext = &mt('Tries');
$display =~ s|^Number of Attempts|$narrowtext |; # makes the column narrower
- if (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name'); }
+ if (!$display) { $display = &Apache::lonnet::metadata($url,$part.'.name',$toolsymb); }
my ($partid) = &split_part_type($part);
push(@partids,$partid);
#
@@ -3698,7 +3943,7 @@ sub viewgrades {
#get info for each student
#list all the students - with points and grade status
- my (undef,undef,$fullname) = &getclasslist($env{'form.section'},'1');
+ my (undef,undef,$fullname) = &getclasslist(\@sections,'1',\@groups);
my $ctr = 0;
foreach (sort
{
@@ -3707,35 +3952,142 @@ sub viewgrades {
}
return $a cmp $b;
} (keys(%$fullname))) {
- $ctr++;
$result.=&viewstudentgrade($symb,$env{'request.course.id'},
- $_,$$fullname{$_},\@parts,\%weight,$ctr,\%last_resets);
+ $_,$$fullname{$_},\@parts,\%weight,\$ctr,\%last_resets,$is_tool);
}
$result.=&Apache::loncommon::end_data_table();
$result.=''."\n";
$result.=''."\n";
- if (scalar(%$fullname) eq 0) {
- my $colspan=3+scalar(@parts);
- my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));
+ if ($ctr == 0) {
my $stu_status = join(' or ',&Apache::loncommon::get_env_multiple('form.Status'));
- $result=''.
- &mt('There are no students in section(s) [_1] with enrollment status [_2] to modify or grade.',
- $section_display, $stu_status).
- '';
+ $result='
'.&mt('Manual Grading').'
'.
+ '';
+ if ($env{'form.submitonly'} eq 'all') {
+ if (grep(/^all$/,@sections)) {
+ if (grep(/^all$/,@groups)) {
+ $result .= &mt('There are no students with enrollment status [_1] to modify or grade.',
+ $stu_status);
+ } elsif (grep(/^none$/,@groups)) {
+ $result .= &mt('There are no students with no group assigned and with enrollment status [_1] to modify or grade.',
+ $stu_status);
+ } else {
+ $result .= &mt('There are no students in group(s) [_1] with enrollment status [_2] to modify or grade.',
+ $group_display,$stu_status);
+ }
+ } elsif (grep(/^none$/,@sections)) {
+ if (grep(/^all$/,@groups)) {
+ $result .= &mt('There are no students in no section with enrollment status [_1] to modify or grade.',
+ $stu_status);
+ } elsif (grep(/^none$/,@groups)) {
+ $result .= &mt('There are no students in no section and no group with enrollment status [_1] to modify or grade.',
+ $stu_status);
+ } else {
+ $result .= &mt('There are no students in no section in group(s) [_1] with enrollment status [_2] to modify or grade.',
+ $group_display,$stu_status);
+ }
+ } else {
+ if (grep(/^all$/,@groups)) {
+ $result .= &mt('There are no students in section(s) [_1] with enrollment status [_2] to modify or grade.',
+ $section_display,$stu_status);
+ } elsif (grep(/^none$/,@groups)) {
+ $result .= &mt('There are no students in section(s) [_1] and no group with enrollment status [_2] to modify or grade.',
+ $section_display,$stu_status);
+ } else {
+ $result .= &mt('There are no students in section(s) [_1] and group(s) [_2] with enrollment status [_3] to modify or grade.',
+ $section_display,$group_display,$stu_status);
+ }
+ }
+ } else {
+ if (grep(/^all$/,@sections)) {
+ if (grep(/^all$/,@groups)) {
+ $result .= &mt('There are no students with enrollment status [_1] and submission status "[_2]" to modify or grade.',
+ $stu_status,$submission_status);
+ } elsif (grep(/^none$/,@groups)) {
+ $result .= &mt('There are no students with no group assigned with enrollment status [_1] and submission status "[_2]" to modify or grade.',
+ $stu_status,$submission_status);
+ } else {
+ $result .= &mt('There are no students in group(s) [_1] with enrollment status [_2] and submission status "[_3]" to modify or grade.',
+ $group_display,$stu_status,$submission_status);
+ }
+ } elsif (grep(/^none$/,@sections)) {
+ if (grep(/^all$/,@groups)) {
+ $result .= &mt('There are no students in no section with enrollment status [_1] and submission status "[_2]" to modify or grade.',
+ $stu_status,$submission_status);
+ } elsif (grep(/^none$/,@groups)) {
+ $result .= &mt('There are no students in no section and no group with enrollment status [_1] and submission status "[_2]" to modify or grade.',
+ $stu_status,$submission_status);
+ } else {
+ $result .= &mt('There are no students in no section in group(s) [_1] with enrollment status [_2] and submission status "[_3]" to modify or grade.',
+ $group_display,$stu_status,$submission_status);
+ }
+ } else {
+ if (grep(/^all$/,@groups)) {
+ $result .= &mt('There are no students in section(s) [_1] with enrollment status [_2] and submission status "[_3]" to modify or grade.',
+ $section_display,$stu_status,$submission_status);
+ } elsif (grep(/^none$/,@groups)) {
+ $result .= &mt('There are no students in section(s) [_1] and no group with enrollment status [_2] and submission status "[_3]" to modify or grade.',
+ $section_display,$stu_status,$submission_status);
+ } else {
+ $result .= &mt('There are no students in section(s) [_1] and group(s) [_2] with enrollment status [_3] and submission status "[_4]" to modify or grade.',
+ $section_display,$group_display,$stu_status,$submission_status);
+ }
+ }
+ }
+ $result .= ' ';
}
return $result;
}
-#--- call by previous routine to display each student
+#--- call by previous routine to display each student who satisfies submission filter.
sub viewstudentgrade {
- my ($symb,$courseid,$student,$fullname,$parts,$weight,$ctr,$last_resets) = @_;
+ my ($symb,$courseid,$student,$fullname,$parts,$weight,$ctr,$last_resets,$is_tool) = @_;
my ($uname,$udom) = split(/:/,$student);
my %record=&Apache::lonnet::restore($symb,$courseid,$udom,$uname);
- my %aggregates = ();
+ my $submitonly = $env{'form.submitonly'};
+ unless (($submitonly eq 'all') || ($submitonly eq 'queued')) {
+ my %partstatus = ();
+ if (ref($parts) eq 'ARRAY') {
+ foreach my $apart (@{$parts}) {
+ my ($part,$type) = &split_part_type($apart);
+ my ($status,undef) = split(/_/,$record{"resource.$part.solved"},2);
+ $status = 'nothing' if ($status eq '');
+ $partstatus{$part} = $status;
+ my $subkey = "resource.$part.submitted_by";
+ $partstatus{$subkey} = $record{$subkey} if ($record{$subkey} ne '');
+ }
+ my $submitted = 0;
+ my $graded = 0;
+ my $incorrect = 0;
+ foreach my $key (keys(%partstatus)) {
+ $submitted = 1 if ($partstatus{$key} ne 'nothing');
+ $graded = 1 if ($partstatus{$key} =~ /^ungraded/);
+ $incorrect = 1 if ($partstatus{$key} =~ /^incorrect/);
+
+ my $partid = (split(/\./,$key))[1];
+ if ($partstatus{'resource.'.$partid.'.'.$key.'.submitted_by'} ne '') {
+ $submitted = 0;
+ }
+ }
+ return if (!$submitted && ($submitonly eq 'yes' ||
+ $submitonly eq 'incorrect' ||
+ $submitonly eq 'graded'));
+ return if (!$graded && ($submitonly eq 'graded'));
+ return if (!$incorrect && $submitonly eq 'incorrect');
+ }
+ }
+ if ($submitonly eq 'queued') {
+ my ($cdom,$cnum) = split(/_/,$courseid);
+ my %queue_status =
+ &Apache::bridgetask::get_student_status($symb,$cdom,$cnum,
+ $udom,$uname);
+ return if (!defined($queue_status{'gradingqueue'}));
+ }
+ $$ctr++;
+ my %aggregates = ();
my $result=&Apache::loncommon::start_data_table_row().'
'."\n";
@@ -3747,7 +4099,6 @@ sub viewstudentgrade {
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},
@@ -3796,6 +4147,10 @@ sub viewstudentgrade {
# record does not get update if unchanged
sub editgrades {
my ($request,$symb) = @_;
+ my $toolsymb;
+ if ($symb =~ /ext\.tool$/) {
+ $toolsymb = $symb;
+ }
my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));
my $title='
'.&mt('Current Grade Status').'
';
@@ -3833,6 +4188,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').'
';
@@ -3841,7 +4197,7 @@ sub editgrades {
my ($part,$type) = &split_part_type($stores);
if ($part !~ m/^\Q$partid\E/) { next;}
if ($type eq 'awarded' || $type eq 'solved') { next; }
- my $display=&Apache::lonnet::metadata($url,$stores.'.display');
+ my $display=&Apache::lonnet::metadata($url,$stores.'.display',$toolsymb);
$display =~ s/\[Part: \Q$part\E\]//;
my $narrowtext = &mt('Tries');
$display =~ s/Number of Attempts/$narrowtext/;
@@ -3849,6 +4205,7 @@ sub editgrades {
'
'.&mt('New').' '.$display.'
';
$columns{$partid}+=2;
}
+ $totcolspan += $columns{$partid};
}
foreach my $partid (@partid) {
my $display_part=&get_display_part($partid,$symb);
@@ -3864,18 +4221,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 = '
");
next;
}
my %aggregate = ();
@@ -3992,8 +4349,7 @@ sub editgrades {
}
}
if (@noupdate) {
-# my $numcols=(scalar(@partid)*(scalar(@parts)-1)*2)+3;
- my $numcols=scalar(@partid)*4+2;
+ my $numcols=$totcolspan+2;
$result .= &Apache::loncommon::start_data_table_row('LC_empty_row').
'
'.
&mt('No Changes Occurred For the Students Below').
@@ -4034,7 +4390,7 @@ sub split_part_type {
#
#--- Javascript to handle csv upload
sub csvupload_javascript_reverse_associate {
- my $error1=&mt('You need to specify the username or the student/employee ID');
+ my $error1=&mt('You need to specify the username, the student/employee ID, or the clicker ID');
my $error2=&mt('You need to specify at least one grading field');
&js_escape(\$error1);
&js_escape(\$error2);
@@ -4043,13 +4399,15 @@ sub csvupload_javascript_reverse_associa
var foundsomething=0;
var founduname=0;
var foundID=0;
+ var foundclicker=0;
for (i=0;i<=vf.nfields.value;i++) {
tw=eval('vf.f'+i+'.selectedIndex');
if (i==0 && tw!=0) { foundID=1; }
if (i==1 && tw!=0) { founduname=1; }
- if (i!=0 && i!=1 && i!=2 && tw!=0) { foundsomething=1; }
+ if (i==2 && tw!=0) { foundclicker=1; }
+ if (i!=0 && i!=1 && i!=2 && i!=3 && tw!=0) { foundsomething=1; }
}
- if (founduname==0 && foundID==0) {
+ if (founduname==0 && foundID==0 && foundclicker==0) {
alert('$error1');
return;
}
@@ -4076,7 +4434,7 @@ ENDPICK
}
sub csvupload_javascript_forward_associate {
- my $error1=&mt('You need to specify the username or the student/employee ID');
+ my $error1=&mt('You need to specify the username, the student/employee ID, or the clicker ID');
my $error2=&mt('You need to specify at least one grading field');
&js_escape(\$error1);
&js_escape(\$error2);
@@ -4085,13 +4443,15 @@ sub csvupload_javascript_forward_associa
var foundsomething=0;
var founduname=0;
var foundID=0;
+ var foundclicker=0;
for (i=0;i<=vf.nfields.value;i++) {
tw=eval('vf.f'+i+'.selectedIndex');
if (tw==1) { foundID=1; }
if (tw==2) { founduname=1; }
- if (tw>3) { foundsomething=1; }
+ if (tw==3) { foundclicker=1; }
+ if (tw>4) { foundsomething=1; }
}
- if (founduname==0 && foundID==0) {
+ if (founduname==0 && foundID==0 && Ć’oundclicker==0) {
alert('$error1');
return;
}
@@ -4149,6 +4509,10 @@ ENDPICK
sub csvupload_fields {
my ($symb,$errorref) = @_;
+ my $toolsymb;
+ if ($symb =~ /ext\.tool$/) {
+ $toolsymb = $symb;
+ }
my (@parts) = &getpartlist($symb,$errorref);
if (ref($errorref)) {
if ($$errorref) {
@@ -4158,13 +4522,14 @@ sub csvupload_fields {
my @fields=(['ID','Student/Employee ID'],
['username','Student Username'],
+ ['clicker','Clicker ID'],
['domain','Student Domain']);
my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);
foreach my $part (sort(@parts)) {
my @datum;
- my $display=&Apache::lonnet::metadata($url,$part.'.display');
+ my $display=&Apache::lonnet::metadata($url,$part.'.display',$toolsymb);
my $name=$part;
- if (!$display) { $display = $name; }
+ if (!$display) { $display = $name; }
@datum=($name,$display);
if ($name=~/^stores_(.*)_awarded/) {
push(@fields,['stores_'.$1.'_points',"Points [Part: $1]"]);
@@ -4239,8 +4604,10 @@ sub csvuploadmap {
if (!$env{'form.datatoken'}) {
$datatoken=&Apache::loncommon::upfile_store($request);
} else {
- $datatoken=$env{'form.datatoken'};
- &Apache::loncommon::load_tmp_file($request);
+ $datatoken=&Apache::loncommon::valid_datatoken($env{'form.datatoken'});
+ if ($datatoken ne '') {
+ &Apache::loncommon::load_tmp_file($request,$datatoken);
+ }
}
my @records=&Apache::loncommon::upfile_record_sep();
&csvuploadmap_header($request,$symb,$datatoken,$#records+1);
@@ -4329,7 +4696,10 @@ sub csvuploadassign {
my ($request,$symb)= @_;
if (!$symb) {return '';}
my $error_msg = '';
- &Apache::loncommon::load_tmp_file($request);
+ my $datatoken = &Apache::loncommon::valid_datatoken($env{'form.datatoken'});
+ if ($datatoken ne '') {
+ &Apache::loncommon::load_tmp_file($request,$datatoken);
+ }
my @gradedata = &Apache::loncommon::upfile_record_sep();
my %fields=&get_fields();
my $courseid=$env{'request.course.id'};
@@ -4352,13 +4722,45 @@ sub csvuploadassign {
if (!$username) {
my $id=$entries{$fields{'ID'}};
$id=~s/\s//g;
- my %ids=&Apache::lonnet::idget($domain,$id);
- $username=$ids{$id};
+ if ($id ne '') {
+ my %ids=&Apache::lonnet::idget($domain,[$id]);
+ $username=$ids{$id};
+ } else {
+ if ($entries{$fields{'clicker'}}) {
+ my $clicker = $entries{$fields{'clicker'}};
+ $clicker=~s/\s//g;
+ if ($clicker ne '') {
+ my %clickers = &Apache::lonnet::idget($domain,[$clicker],'clickers');
+ if ($clickers{$clicker} ne '') {
+ my $match = 0;
+ my @inclass;
+ foreach my $poss (split(/,/,$clickers{$clicker})) {
+ if (exists($$classlist{"$poss:$domain"})) {
+ $username = $poss;
+ push(@inclass,$poss);
+ $match ++;
+
+ }
+ }
+ if ($match > 1) {
+ undef($username);
+ $request->print('
'.
+ &mt('Score not saved for clicker: [_1] (matched multiple usernames: [_2])',
+ $clicker,join(', ',@inclass)).'
');
+ }
+ }
+ }
+ }
+ }
}
if (!exists($$classlist{"$username:$domain"})) {
my $id=$entries{$fields{'ID'}};
$id=~s/\s//g;
- if ($id) {
+ my $clicker = $entries{$fields{'clicker'}};
+ $clicker=~s/\s//g;
+ if ($clicker) {
+ push(@skipped,"$clicker:$domain");
+ } elsif ($id) {
push(@skipped,"$id:$domain");
} else {
push(@skipped,"$username:$domain");
@@ -4617,7 +5019,7 @@ sub getSymbMap {
my @sequences = $navmap->retrieveResources(undef, sub { shift->is_map(); },
1,0,1);
for my $sequence ($navmap->getById('0.0'), @sequences) {
- if ($navmap->hasResource($sequence, sub { shift->is_problem(); }, 0) ) {
+ if ($navmap->hasResource($sequence, sub { shift->is_gradable(); }, 0) ) {
my $title = $minder.'.'.
&HTML::Entities::encode($sequence->compTitle(),'"\'&');
push(@titles, $title); # minder in case two titles are identical
@@ -4714,10 +5116,11 @@ sub displayPage {
if($curRes == $iterator->BEGIN_MAP) { $depth++; }
if($curRes == $iterator->END_MAP) { $depth--; }
- if (ref($curRes) && $curRes->is_problem()) {
+ if (ref($curRes) && $curRes->is_gradable()) {
my $parts = $curRes->parts();
my $title = $curRes->compTitle();
my $symbx = $curRes->symb();
+ my $is_tool = ($symbx =~ /ext\.tool$/);
$studentTable.=
&Apache::loncommon::start_data_table_row().
'
'.$prob.
@@ -4728,26 +5131,34 @@ sub displayPage {
'