--- loncom/homework/grades.pm 2016/10/14 16:47:25 1.738
+++ loncom/homework/grades.pm 2017/12/31 13:29:53 1.748
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Grading handler
#
-# $Id: grades.pm,v 1.738 2016/10/14 16:47:25 raeburn Exp $
+# $Id: grades.pm,v 1.748 2017/12/31 13:29:53 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);
@@ -845,6 +856,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 +912,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 +990,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"
.''
.'
';
@@ -1970,6 +2021,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 +2034,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 +2229,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 +2244,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 +2436,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 +2567,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 +2633,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 +3627,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,
@@ -3634,7 +3712,13 @@ sub viewgrades {
if ($env{'form.submitonly'} eq 'all') {
$result.= '
';
}
$result.= &Apache::loncommon::start_data_table().
&Apache::loncommon::start_data_table_header_row().
@@ -3716,10 +3811,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);
#
@@ -3760,7 +3855,7 @@ sub viewgrades {
return $a cmp $b;
} (keys(%$fullname))) {
$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";
@@ -3798,7 +3893,7 @@ sub viewgrades {
$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] nd no group with enrollment status [_2] to modify or grade.',
+ $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.',
@@ -3848,7 +3943,7 @@ sub viewgrades {
#--- 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 $submitonly = $env{'form.submitonly'};
@@ -3954,6 +4049,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').'
';
@@ -3991,6 +4090,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').'
';
@@ -3999,7 +4099,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/;
@@ -4007,6 +4107,7 @@ sub editgrades {
'
'.&mt('New').' '.$display.'
';
$columns{$partid}+=2;
}
+ $totcolspan += $columns{$partid};
}
foreach my $partid (@partid) {
my $display_part=&get_display_part($partid,$symb);
@@ -4022,18 +4123,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 = ();
@@ -4150,8 +4251,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').
@@ -4192,7 +4292,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);
@@ -4201,13 +4301,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;
}
@@ -4234,7 +4336,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);
@@ -4243,13 +4345,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;
}
@@ -4307,6 +4411,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) {
@@ -4315,15 +4423,15 @@ sub csvupload_fields {
}
my @fields=(['ID','Student/Employee ID'],
- ['clicker','Clicker 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]"]);
@@ -4398,8 +4506,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);
@@ -4488,7 +4598,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'};
@@ -4808,7 +4921,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
@@ -4905,10 +5018,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.
@@ -4919,26 +5033,32 @@ sub displayPage {
'