');
- pDoc.write("$html_js_lt{'type'}<\\/b><\\/td> $html_js_lt{'incl'}<\\/b><\\/td> $html_js_lt{'mesa'}<\\/td><\\/tr>");
+ pDoc.write('';
- $endform.=&show_grading_menu_form($symb);
$request->print($endform);
}
return '';
@@ -2639,7 +2875,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=();
@@ -2698,15 +2934,21 @@ sub get_last_submission {
}
}
my ($partid,$foo) = split(/submission$/,$key);
- my $draft = $lasthash{$partid.'awarddetail'} eq 'DRAFT' ? 1: 0;
+ 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}) ));
}
}
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);
}
@@ -2738,11 +2980,12 @@ sub show_previous_task_version {
my ($uname,$udom) = ($env{'form.student'},$env{'form.userdom'});
my $usec = &Apache::lonnet::getsection($udom,$uname,$env{'request.course.id'});
if (!&canview($usec)) {
- $request->print(''.
- &mt('Unable to view previous version for requested student.').
- ' '.&mt('([_1] in section [_2] in course id [_3])',
- $uname.':'.$udom,$usec,$env{'request.course.id'}).
- ' ');
+ $request->print(
+ ''.
+ &mt('Unable to view previous version for requested student.').
+ ' '.&mt('([_1] in section [_2] in course id [_3])',
+ $uname.':'.$udom,$usec,$env{'request.course.id'}).
+ ' ');
return;
}
my $mode = 'both';
@@ -2907,8 +3150,7 @@ ENDJS
#--- Called from submission routine
sub processHandGrade {
- my ($request) = shift;
- my ($symb) = &get_symb($request);
+ my ($request,$symb) = @_;
my (undef,undef,$url) = &Apache::lonnet::decode_symb($symb);
my $button = $env{'form.gradeOpt'};
my $ngrade = $env{'form.NCT'};
@@ -2927,7 +3169,7 @@ sub processHandGrade {
next;
}
if ($errorflag eq 'not_allowed') {
- $request->print(
+ $request->print(
''
.&mt('Not allowed to modify grades for [_1]',"$uname:$udom")
.' ');
@@ -2958,7 +3200,7 @@ sub processHandGrade {
if ($env{'form.withgrades'.$ctr}) {
$message.="\n\nPoint".($pts > 1 ? 's':'').' awarded = '.$pts.' out of '.$wgt;
$messagetail = " for $env{'form.probTitle'} ";
+ $feedurl."?symb=$showsymb\">$restitle";
}
$msgstatus =
&Apache::lonmsg::user_normal_msg($uname,$udom,$subject,
@@ -2986,7 +3228,7 @@ sub processHandGrade {
$udom);
if ($env{'form.withgrades'.$ctr}) {
$messagetail = " for $env{'form.probTitle'} ";
+ $baseurl."?symb=$showsymb\">$restitle";
}
$msgstatus =
&Apache::lonmsg::user_normal_msg($collaborator,$udom,$subject,$message.$messagetail,undef,$baseurl,undef,undef,undef,$showsymb,$restitle);
@@ -2998,12 +3240,19 @@ sub processHandGrade {
}
}
- if ($env{'form.handgrade'} eq 'yes') {
+ my $res_error;
+ my ($partlist,$handgrade,$responseType,$numresp,$numessay) = &response_type($symb,\$res_error);
+ if ($res_error) {
+ $request->print(&navmap_errormsg());
+ return;
+ }
+
+ my %keyhash = ();
+ if ($numessay) {
# Keywords sorted in alphabatical order
my $loginuser = $env{'user.name'}.':'.$env{'user.domain'};
- my %keyhash = ();
$env{'form.keywords'} =~ s/,\s{0,}|\s+/ /g;
- $env{'form.keywords'} =~ s/^\s+|\s+$//;
+ $env{'form.keywords'} =~ s/^\s+|\s+$//g;
my (@keywords) = sort(split(/\s+/,$env{'form.keywords'}));
$env{'form.keywords'} = join(' ',@keywords);
$keyhash{$symb.'_keywords'} = $env{'form.keywords'};
@@ -3011,7 +3260,9 @@ sub processHandGrade {
$keyhash{$loginuser.'_kwclr'} = $env{'form.kwclr'};
$keyhash{$loginuser.'_kwsize'} = $env{'form.kwsize'};
$keyhash{$loginuser.'_kwstyle'} = $env{'form.kwstyle'};
+ }
+ if ($env{'form.compmsg'}) {
# message center - Order of message gets changed. Blank line is eliminated.
# New messages are saved in env for the next student.
# All messages are saved in nohist_handgrade.db
@@ -3026,17 +3277,20 @@ sub processHandGrade {
$ctr = 0;
while ($ctr < $ngrade) {
if ($env{'form.newmsg'.$ctr} ne '') {
- $keyhash{$symb.'_savemsg'.$idx} = $env{'form.newmsg'.$ctr};
- $env{'form.savemsg'.$idx} = $env{'form.newmsg'.$ctr};
- $idx++;
+ $keyhash{$symb.'_savemsg'.$idx} = $env{'form.newmsg'.$ctr};
+ $env{'form.savemsg'.$idx} = $env{'form.newmsg'.$ctr};
+ $idx++;
}
$ctr++;
}
$env{'form.savemsgN'} = --$idx;
$keyhash{$symb.'_savemsgN'} = $env{'form.savemsgN'};
- my $putresult = &Apache::lonnet::put
- ('nohist_handgrade',\%keyhash,$cdom,$cnum);
}
+ if (($numessay) || ($env{'form.compmsg'})) {
+ my $putresult = &Apache::lonnet::put
+ ('nohist_handgrade',\%keyhash,$cdom,$cnum);
+ }
+
# Called by Save & Refresh from Highlight Attribute Window
my (undef,undef,$fullname) = &getclasslist($env{'form.section'},'1');
if ($env{'form.refresh'} eq 'on') {
@@ -3051,22 +3305,12 @@ sub processHandGrade {
my $processUser = $env{'form.unamedom'.$ctr};
($env{'form.student'},$env{'form.userdom'}) = split(/:/,$processUser);
$env{'form.fullname'} = $$fullname{$processUser};
- &submission($request,$ctr,$total-1);
+ &submission($request,$ctr,$total-1,$symb);
$ctr++;
}
return '';
}
-# Go directly to grade student - from submission or link from chart page
- if ($button eq 'Grade Student') {
- (undef,undef,$env{'form.handgrade'},undef,undef) = &showResourceInfo($symb);
- my $processUser = $env{'form.unamedom'.$env{'form.studentNo'}};
- ($env{'form.student'},$env{'form.userdom'}) = split(/:/,$processUser);
- $env{'form.fullname'} = $$fullname{$processUser};
- &submission($request,0,0);
- return '';
- }
-
# Get the next/previous one or group of students
my $firststu = $env{'form.unamedom0'};
my $laststu = $env{'form.unamedom'.($ngrade-1)};
@@ -3097,12 +3341,6 @@ sub processHandGrade {
}
$ctr = 0;
@parsedlist = reverse @parsedlist if ($button eq 'Previous');
- my $res_error;
- my ($partlist) = &response_type($symb,\$res_error);
- if ($res_error) {
- $request->print(&navmap_errormsg());
- return;
- }
foreach my $student (@parsedlist) {
my $submitonly=$env{'form.submitonly'};
my ($uname,$udom) = split(/:/,$student);
@@ -3148,14 +3386,11 @@ sub processHandGrade {
$env{'form.student'} = $uname;
$env{'form.userdom'} = $udom;
$env{'form.fullname'} = $$fullname{$_};
- &submission($request,$ctr,$total);
+ &submission($request,$ctr,$total,$symb);
$ctr++;
}
if ($total < 0) {
- my $the_end = ''.&mt('LON-CAPA User Message').' '."\n";
- $the_end.=' '.&mt('[_1]Message:[_2] No more students for this section or class.','',' ').'
'."\n";
- $the_end.=&mt('Click on the button below to return to the grading menu.').' '."\n";
- $the_end.=&show_grading_menu_form($symb);
+ my $the_end.=''.&mt('[_1]Message:[_2] No more students for this section or class.','',' ').'
'."\n";
$request->print($the_end);
}
return '';
@@ -3349,19 +3584,19 @@ sub handback_files {
my $part_resp = join('_',@{ $part_response_id });
if (($env{'form.'.$newflg.'_'.$part_resp.'_countreturndoc'} =~ /^\d+$/) & ($new_part eq $part_id)) {
for (my $counter=1; $counter<=$env{'form.'.$newflg.'_'.$part_resp.'_countreturndoc'}; $counter++) {
- # if multiple files are uploaded names will be 'returndoc2','returndoc3'
- if ($env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter}) {
+ # if multiple files are uploaded names will be 'returndoc2','returndoc3'
+ if ($env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter}) {
my $fname=$env{'form.'.$newflg.'_'.$part_resp.'_returndoc'.$counter.'.filename'};
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,
@@ -3379,8 +3614,7 @@ sub handback_files {
$$newrecord{"resource.$new_part.$resp_id.handback"}.=',';
}
$$newrecord{"resource.$new_part.$resp_id.handback"} .= $save_file_name;
- $file_msg.=''.$save_file_name." ";
-
+ $file_msg.= ''.$save_file_name." ";
}
$request->print(' '.&mt('[_1] will be the uploaded filename [_2]',''.$fname.' ',''.$env{'form.'.$newflg.'_'.$part_resp.'_origdoc'.$counter}.' '));
}
@@ -3391,10 +3625,11 @@ sub handback_files {
$request->print(' ');
my @what = ($symb,$env{'request.course.id'},'handback');
&Apache::lonnet::mark_as_readonly($domain,$stuname,\@handedback,\@what);
- my $user_lh = &Apache::loncommon::user_lang($stuname,$domain,$env{'request.course.id'});
+ my $user_lh = &Apache::loncommon::user_lang($stuname,$domain,$env{'request.course.id'});
my ($subject,$message);
if (scalar(@handedback) == 1) {
$subject = &mt_user($user_lh,'File Handed Back by Instructor');
+ $message = &mt_user($user_lh,'A file has been returned that was originally submitted in response to: ');
} else {
$subject = &mt_user($user_lh,'Files Handed Back by Instructor');
$message = &mt_user($user_lh,'Files have been returned that were originally submitted in response to: ');
@@ -3510,29 +3745,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);
@@ -3541,64 +3761,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
@@ -3609,8 +3771,7 @@ sub viewgrades_js {
my $alertmsg = &mt('A number equal or greater than 0 is expected. Entered value = ');
&js_escape(\$alertmsg);
- $request->print(<
+ $request->print(&Apache::lonhtmlcommon::scripttag(<
VIEWJAVASCRIPT
}
#--- show scores for a section or whole class w/ option to change/update a score
sub viewgrades {
- my ($request) = shift;
+ my ($request,$symb) = @_;
+ my ($is_tool,$toolsymb);
+ if ($symb =~ /ext\.tool$/) {
+ $is_tool = 1;
+ $toolsymb = $symb;
+ }
&viewgrades_js($request);
- my ($symb) = &get_symb($request);
#need to make sure we have the correct data for later EXT calls,
#thus invalidate the cache
&Apache::lonnet::devalidatecourseresdata(
@@ -3789,7 +3953,6 @@ sub viewgrades {
&Apache::lonnet::clear_EXT_cache_status();
my $result=''.&mt('Manual Grading').' ';
- $result.=''.&mt('Current Resource').': '.$env{'form.probTitle'}.' '."\n";
#view individual student submission form - called using Javascript viewOneStudent
$result.=&jscriptNform($symb);
@@ -3800,9 +3963,7 @@ sub viewgrades {
' '."\n".
' '."\n".
&build_section_inputs().
- ' '."\n".
' '."\n".
- ' '."\n";
#retrieve selected groups
my (@groups,$group_display);
@@ -3826,7 +3987,7 @@ sub viewgrades {
$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');
+ $common_header = &mt('Assign Common Grade to Class');
$specific_header = &mt('Assign Grade to Specific Students in Class');
}
} elsif (grep(/^none$/,@sections)) {
@@ -3839,7 +4000,7 @@ sub viewgrades {
$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');
+ $specific_header = &mt('Assign Grade to Specific Students in no Section');
}
} else {
$section_display = join (", ",@sections);
@@ -3853,7 +4014,7 @@ sub viewgrades {
$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);
+ $specific_header = &mt('Assign Grade to Specific Students in Section(s) [_1]',$section_display);
}
}
my %submit_types = &substatus_options();
@@ -3862,7 +4023,13 @@ sub viewgrades {
if ($env{'form.submitonly'} eq 'all') {
$result.= ''.$common_header.' ';
} else {
- $result.= ''.$common_header.' '.&mt('(submission status: "[_1]")',$submission_status).' ';
+ my $text;
+ if ($is_tool) {
+ $text = &mt('(transaction status: "[_1]")',$submission_status);
+ } else {
+ $text = &mt('(submission status: "[_1]")',$submission_status);
+ }
+ $result.= ''.$common_header.' '.$text.' ';
}
$result .= &Apache::loncommon::start_data_table();
#radio buttons/text box for assigning points for a section or class.
@@ -3875,13 +4042,17 @@ 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 $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb);
$weight{$partid} = $wgt eq '' ? '1' : $wgt;
@@ -3900,10 +4071,10 @@ sub viewgrades {
$partid.'" size="4" '.'onchange="javascript:writePoint(\''.
$partid.'\','.$weight{$partid}.',\'textval\')" /> /'.
$weight{$partid}.' '.&mt('(problem weight)').' '."\n";
- $line.= ''.&mt('Grade Status').': '.
- ' '.
+ $line.= ''.&mt('Grade Status').': '.
+ ' '.
' '.
''.&mt('excused').' '.
''.&mt('reset status').' '.
@@ -3927,10 +4098,16 @@ sub viewgrades {
#table listing all the students in a section/class
#header of table
- if ($env{'form.submitonly'} eq 'all') {
+ if ($env{'form.submitonly'} eq 'all') {
$result.= ''.$specific_header.' ';
} else {
- $result.= ''.$specific_header.' '.&mt('(submission status: "[_1]")',$submission_status).' ';
+ my $text;
+ if ($is_tool) {
+ $text = &mt('(transaction status: "[_1]")',$submission_status);
+ } else {
+ $text = &mt('(submission status: "[_1]")',$submission_status);
+ }
+ $result.= ''.$specific_header.' '.$text.' ';
}
$result.= &Apache::loncommon::start_data_table().
&Apache::loncommon::start_data_table_header_row().
@@ -3944,17 +4121,20 @@ 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);
+#
+# FIXME: Looks like $display looks at English text
+#
my $display_part=&get_display_part($partid,$symb);
if ($display =~ /^Partial Credit Factor/) {
$result.=''.
- &mt('Score Part: [_1][_2](weight = [_3])',
- $display_part,' ',$weight{$partid}).' '."\n";
+ &mt('Score Part: [_1][_2](weight = [_3])',
+ $display_part,' ',$weight{$partid}).''."\n";
next;
} else {
@@ -3985,7 +4165,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";
@@ -4002,7 +4182,7 @@ sub viewgrades {
$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);
+ $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);
@@ -4055,8 +4235,8 @@ sub viewgrades {
}
} 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);
+ $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);
@@ -4065,16 +4245,15 @@ sub viewgrades {
$section_display,$group_display,$stu_status,$submission_status);
}
}
- }
+ }
$result .= ' ';
}
- $result.=&show_grading_menu_form($symb);
return $result;
}
-#--- call by previous routine to display each student who satisfies submission filter.
+#--- 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'};
@@ -4132,7 +4311,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},
@@ -4180,12 +4358,14 @@ sub viewstudentgrade {
#--- change scores for all the students in a section/class
# record does not get update if unchanged
sub editgrades {
- my ($request) = @_;
+ my ($request,$symb) = @_;
+ my $toolsymb;
+ if ($symb =~ /ext\.tool$/) {
+ $toolsymb = $symb;
+ }
- my ($symb)=&get_symb($request);
my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));
my $title=''.&mt('Current Grade Status').' ';
- $title.=''.&mt('Current Resource').': '.$env{'form.probTitle'}.' '."\n";
$title.=''.&mt('Section:').' '.$section_display.' '."\n";
my $result= &Apache::loncommon::start_data_table().
@@ -4229,7 +4409,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/;
@@ -4257,16 +4437,16 @@ sub editgrades {
my ($uname,$udom)=split(/:/,$user);
my %newrecord;
my $updateflag = 0;
- my $usec=$classlist->{"$uname:$udom"}[5];
- my $canmodify = &canmodify($usec);
- my $line = ''.
- &nameUserString(undef,$$fullname{$user},$uname,$udom).' ';
- if (!$canmodify) {
- push(@noupdate,
- $line."".
- &mt('Not allowed to modify student')." ");
- next;
- }
+ my $usec=$classlist->{"$uname:$udom"}[5];
+ my $canmodify = &canmodify($usec);
+ my $line = ''.
+ &nameUserString(undef,$$fullname{$user},$uname,$udom).' ';
+ if (!$canmodify) {
+ push(@noupdate,
+ $line."".
+ &mt('Not allowed to modify student')." ");
+ next;
+ }
my %aggregate = ();
my $aggregateflag = 0;
$user=~s/:/_/; # colon doen't work in javascript for names
@@ -4394,8 +4574,7 @@ sub editgrades {
&Apache::loncommon::end_data_table_row();
}
}
- $result .= &Apache::loncommon::end_data_table().
- &show_grading_menu_form($symb);
+ $result .= &Apache::loncommon::end_data_table();
my $msg = ''.
&mt('Number of records updated = [_1] for [quant,_2,student].',
$rec_update,$count).' '.
@@ -4423,7 +4602,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);
@@ -4432,13 +4611,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;
}
@@ -4465,7 +4646,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);
@@ -4474,13 +4655,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;
}
@@ -4512,21 +4695,14 @@ sub csvuploadmap_header {
$javascript=&csvupload_javascript_forward_associate();
}
- my ($result) = &showResourceInfo($symb,$env{'form.probTitle'});
- my $checked=(($env{'form.noFirstLine'})?' checked="checked"':'');
- my $ignore=&mt('Ignore First Line');
$symb = &Apache::lonenc::check_encrypt($symb);
+ $request->print('
'.
+ &mt('Total number of records found in file: [_1]',$distotal).' '.
+ &mt('Associate entries from the uploaded file with as many fields as you can.'));
+ my $reverse=&mt("Reverse Association");
$request->print(<
-Uploading Class Grades
-$result
-
-Identify fields
-Total number of records found in file: $distotal
-Enter as many fields as you can. The system will inform you and bring you back
-to this page if the data selected is insufficient to run your class.
-
- $ignore
+
+
@@ -4535,20 +4711,20 @@ to this page if the data selected is ins
-
-
-
ENDPICK
+ $request->print(&Apache::lonhtmlcommon::scripttag($javascript));
return '';
}
sub csvupload_fields {
my ($symb,$errorref) = @_;
+ my $toolsymb;
+ if ($symb =~ /ext\.tool$/) {
+ $toolsymb = $symb;
+ }
my (@parts) = &getpartlist($symb,$errorref);
if (ref($errorref)) {
if ($$errorref) {
@@ -4558,13 +4734,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]"]);
@@ -4589,8 +4766,7 @@ ENDPICK
sub checkforfile_js {
my $alertmsg = &mt('Please use the browse button to select a file from your local directory.');
&js_escape(\$alertmsg);
- my $result =<
+ my $result = &Apache::lonhtmlcommon::scripttag(<
CSVFORMJS
return $result;
}
sub upcsvScores_form {
- my ($request) = shift;
- my ($symb)=&get_symb($request);
+ my ($request,$symb) = @_;
if (!$symb) {return '';}
my $result=&checkforfile_js();
- $env{'form.probTitle'} = &Apache::lonnet::gettitle($symb);
- my ($table) = &showResourceInfo($symb,$env{'form.probTitle'});
- $result.=$table;
- $result.=''."\n";
- $result.=''."\n";
- $result.='
'."\n";
- $result.=&show_grading_menu_form($symb);
+ &mt("How do I create a CSV file from a spreadsheet")).
+ ' '.
+ &Apache::loncommon::end_data_table_row().
+ &Apache::loncommon::end_data_table();
return $result;
}
sub csvuploadmap {
- my ($request)= @_;
- my ($symb)=&get_symb($request);
+ my ($request,$symb) = @_;
if (!$symb) {return '';}
my $datatoken;
if (!$env{'form.datatoken'}) {
$datatoken=&Apache::loncommon::upfile_store($request);
} else {
- $datatoken=&Apache::loncommon::valid_datatoken($env{'form.datatoken'});
- if ($datatoken ne '') {
+ $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();
- if ($env{'form.noFirstLine'}) { shift(@records); }
&csvuploadmap_header($request,$symb,$datatoken,$#records+1);
my ($i,$keyfields);
if (@records) {
@@ -4685,39 +4851,27 @@ sub csvuploadmap {
}
}
&csvuploadmap_footer($request,$i,$keyfields);
- $request->print(&show_grading_menu_form($symb));
return '';
}
sub csvuploadoptions {
- my ($request)= @_;
- my ($symb)=&get_symb($request);
- my $checked=(($env{'form.noFirstLine'})?'1':'0');
- my $ignore=&mt('Ignore First Line');
+ my ($request,$symb)= @_;
+ my $overwrite=&mt('Overwrite any existing score');
$request->print(<
-Uploading Class Grade Options
-
- Overwrite any existing score
+ $overwrite
ENDPICK
my %fields=&get_fields();
if (!defined($fields{'domain'})) {
my $domform = &Apache::loncommon::select_dom_form($env{'request.role.domain'},'default_domain');
- $request->print("\n Users are in domain: ".$domform."
\n");
+ $request->print("\n".&mt('Users are in domain: [_1]',$domform)."
\n");
}
foreach my $key (sort(keys(%env))) {
if ($key !~ /^form\.(.*)$/) { next; }
@@ -4730,7 +4884,6 @@ ENDPICK
# FIXME do a check for any invalid user ids?...
$request->print('
'."\n");
- $request->print(&show_grading_menu_form($symb));
return '';
}
@@ -4752,18 +4905,15 @@ sub get_fields {
}
sub csvuploadassign {
- my ($request)= @_;
- my ($symb)=&get_symb($request);
+ my ($request,$symb) = @_;
if (!$symb) {return '';}
my $error_msg = '';
my $datatoken = &Apache::loncommon::valid_datatoken($env{'form.datatoken'});
- if ($datatoken ne '') {
+ if ($datatoken ne '') {
&Apache::loncommon::load_tmp_file($request,$datatoken);
}
my @gradedata = &Apache::loncommon::upfile_record_sep();
- if ($env{'form.noFirstLine'}) { shift(@gradedata); }
my %fields=&get_fields();
- $request->print('Assigning Grades ');
my $courseid=$env{'request.course.id'};
my ($classlist) = &getclasslist('all',0);
my @notallowed;
@@ -4784,13 +4934,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");
@@ -4818,7 +5000,7 @@ sub csvuploadassign {
my $award=($pcr == 0) ? 'incorrect_by_override'
: 'correct_by_override';
if ($pcr>1) {
- push(@warnings,&mt("[_1]: point value larger than weight","$username:$domain"));
+ push(@warnings,&mt("[_1]: point value larger than weight","$username:$domain"));
}
$grades{"resource.$part.awarded"}=$pcr;
$grades{"resource.$part.solved"}=$award;
@@ -4839,7 +5021,7 @@ sub csvuploadassign {
$grades{$store_key}=$entries{$fields{$dest}};
}
}
- if (! %grades) {
+ if (! %grades) {
push(@skipped,&mt("[_1]: no data to save","$username:$domain"));
} else {
$grades{"resource.regrader"}="$env{'user.name'}:$env{'user.domain'}";
@@ -4847,19 +5029,20 @@ sub csvuploadassign {
$env{'request.course.id'},
$domain,$username);
if ($result eq 'ok') {
+# Successfully stored
$request->print('.');
# Remove from grading queue
&Apache::bridgetask::remove_from_queue('gradingqueue',$symb,
$env{'course.'.$env{'request.course.id'}.'.domain'},
$env{'course.'.$env{'request.course.id'}.'.num'},
$domain,$username);
- } else {
+ $countdone++;
+ } else {
$request->print("".
&mt("Failed to save data for student [_1]. Message when trying to save was: [_2]",
"$username:$domain",$result)."
");
}
$request->rflush();
- $countdone++;
}
}
$request->print(' '.&Apache::lonhtmlcommon::confirm_success(&mt("Saved scores for [quant,_1,student]",$countdone),$countdone==0));
@@ -4876,7 +5059,6 @@ sub csvuploadassign {
$request->print(join(', ',@notallowed));
}
$request->print(" \n");
- $request->print(&show_grading_menu_form($symb));
return $error_msg;
}
#------------- end of section for handling csv file upload ---------
@@ -4887,12 +5069,11 @@ sub csvuploadassign {
#
#--- Select a page/sequence and a student to grade
sub pickStudentPage {
- my ($request) = shift;
+ my ($request,$symb) = @_;
my $alertmsg = &mt('Please select the student you wish to grade.');
&js_escape(\$alertmsg);
- $request->print(<
+ $request->print(&Apache::lonhtmlcommon::scripttag(<
LISTJAVASCRIPT
&commonJSfunctions($request);
- my ($symb) = &get_symb($request);
+
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'};
@@ -4927,49 +5107,68 @@ LISTJAVASCRIPT
my ($curpage) =&Apache::lonnet::decode_symb($symb);
# my ($curpage,$mapId) =&Apache::lonnet::decode_symb($symb);
# my $type=($curpage =~ /\.(page|sequence)/);
- my $select = ''."\n";
+
+ # Collection of hidden fields
my $ctr=0;
foreach (@$titles) {
- my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
- $select.=''.$showtitle.' '."\n";
- $ctr++;
+ my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
+ $result.=' '."\n";
+ $result.=' '."\n";
+ $ctr++;
}
- $select.= ' ';
- $result.=' '.&mt('Problems from').': '.$select." \n";
+ $result.=' '."\n".
+ ' '."\n";
+
+ $result.=&build_section_inputs();
+ my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));
+ $result.=' '."\n".
+ ' '."\n".
+ ' '."\n";
+ # Show grading options
+ $result.=&Apache::lonhtmlcommon::start_pick_box();
+ my $select = ''."\n";
$ctr=0;
foreach (@$titles) {
my ($minder,$showtitle) = ($_ =~ /(\d+)\.(.*)/);
- $result.=' '."\n";
- $result.=' '."\n";
+ $select.=''.$showtitle.' '."\n";
$ctr++;
}
- $result.=' '."\n".
- ' '."\n";
+ $select.= ' ';
- my $options =
- ' '.&mt('no').' '."\n".
- ' '.&mt('yes').' '." \n";
- $result.=' '.&mt('View Problem Text').': '.$options;
-
- $options =
- ' '.&mt('none').' '."\n".
- ' '.&mt('by dates and submissions').' '."\n".
- ' '.&mt('all details').' '."\n";
- $result.=' '.&mt('Submissions').': '.$options;
+ $result.=
+ &Apache::lonhtmlcommon::row_title(&mt('Problems from'))
+ .$select
+ .&Apache::lonhtmlcommon::row_closure();
+
+ $result.=
+ &Apache::lonhtmlcommon::row_title(&mt('View Problem Text'))
+ .' '.&mt('no').' '."\n"
+ .' '
+ .&mt('yes').' '."\n"
+ .&Apache::lonhtmlcommon::row_closure();
+
+ $result.=
+ &Apache::lonhtmlcommon::row_title(&mt('View Submissions'))
+ .' '
+ .&mt('none').' '."\n"
+ .' '.&mt('all submissions').' '."\n"
+ .' '
+ .&mt('all submissions with details').' '
+ .&Apache::lonhtmlcommon::row_closure();
- $result.=&build_section_inputs();
- my $stu_status = join(':',&Apache::loncommon::get_env_multiple('form.Status'));
- $result.=' '."\n".
- ' '."\n".
- ' '."\n".
- ' '." \n";
+ $result.=
+ &Apache::lonhtmlcommon::row_title(&mt('Use CODE'))
+ .' '
+ .&Apache::lonhtmlcommon::row_closure(1)
+ .&Apache::lonhtmlcommon::end_pick_box();
- $result.=' '.&mt('Use CODE').': '."\n";
-
- $result.=' '."\n";
$request->print($result);
@@ -5011,7 +5210,6 @@ LISTJAVASCRIPT
$studentTable.=' '."\n";
- $studentTable.=&show_grading_menu_form($symb);
$request->print($studentTable);
return '';
@@ -5034,7 +5232,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
@@ -5048,9 +5246,7 @@ sub getSymbMap {
#
#--- Displays a page/sequence w/wo problems, w/wo submissions
sub displayPage {
- my ($request) = shift;
-
- my ($symb) = &get_symb($request);
+ my ($request,$symb) = @_;
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'};
@@ -5067,11 +5263,11 @@ sub displayPage {
&Apache::lonnet::clear_EXT_cache_status();
if (!&canview($usec)) {
- $request->print(''.
- &mt('Unable to view requested student. ([_1])',
- $env{'form.student'}).
- ' ');
- $request->print(&show_grading_menu_form($symb));
+ $request->print(
+ ''.
+ &mt('Unable to view requested student. ([_1])',
+ $env{'form.student'}).
+ ' ');
return;
}
my $result=' '.$env{'form.title'}.' ';
@@ -5089,14 +5285,12 @@ sub displayPage {
my $navmap = Apache::lonnavmaps::navmap->new();
unless (ref($navmap)) {
$request->print(&navmap_errormsg());
- $request->print(&show_grading_menu_form($symb));
return;
}
my ($mapUrl, $id, $resUrl)=&Apache::lonnet::decode_symb($env{'form.page'});
my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps
if (!$map) {
$request->print(''.&mt('Unable to view requested sequence. ([_1])',$resUrl).' ');
- $request->print(&show_grading_menu_form($symb));
return;
}
my $iterator = $navmap->getIterator($map->map_start(),
@@ -5109,8 +5303,7 @@ sub displayPage {
' '."\n".
' '."\n".
' '."\n".
- ' '."\n".
- ' '."\n";
+ ' '."\n";
if (defined($env{'form.CODE'})) {
$studentTable.=
@@ -5124,7 +5317,7 @@ sub displayPage {
''."\n".
&Apache::loncommon::start_data_table().
&Apache::loncommon::start_data_table_header_row().
- ' Prob. '.
+ ''.&mt('Prob.').' '.
' '.($env{'form.vProb'} eq 'no' ? &mt('Title') : &mt('Problem Text')).'/'.&mt('Grade').' '.
&Apache::loncommon::end_data_table_header_row();
@@ -5136,10 +5329,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.
@@ -5150,26 +5344,34 @@ sub displayPage {
' ';
$studentTable.='';
my %form = ('CODE' => $env{'form.CODE'},);
- if ($env{'form.vProb'} eq 'yes' ) {
- $studentTable.=&show_problem($request,$symbx,$uname,$udom,1,
- undef,'both',\%form);
- } else {
- my $companswer = &Apache::loncommon::get_student_answers($symbx,$uname,$udom,$env{'request.course.id'},%form);
- $companswer =~ s|||g;
- $companswer =~ s| ||g;
-# while ($companswer =~ /()/s) { # \n");
-# }
-# $companswer =~ s|||g;
- $studentTable.=' '.$title.' '.&mt('Correct answer').': '.$companswer;
+ if ($is_tool) {
+ $studentTable.=' '.$title.' ';
+ } else {
+ if ($env{'form.vProb'} eq 'yes' ) {
+ $studentTable.=&show_problem($request,$symbx,$uname,$udom,1,
+ undef,'both',\%form);
+ } else {
+ my $companswer = &Apache::loncommon::get_student_answers($symbx,$uname,$udom,$env{'request.course.id'},%form);
+ $companswer =~ s|||g;
+ $companswer =~ s| ||g;
+# while ($companswer =~ /()/s) { # \n");
+# }
+# $companswer =~ s|||g;
+ $studentTable.=' '.$title.' '.&mt('Correct answer').': '.$companswer;
+ }
}
my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname);
if ($env{'form.lastSub'} eq 'datesub') {
if ($record{'version'} eq '') {
- $studentTable.=' '.&mt('No recorded submission for this problem.').' ';
+ my $msg = &mt('No recorded submission for this problem.');
+ if ($is_tool) {
+ $msg = &mt('No recorded transactions for this external tool');
+ }
+ $studentTable.=' '.$msg.' ';
} else {
my %responseType = ();
foreach my $partid (@{$parts}) {
@@ -5182,11 +5384,10 @@ sub displayPage {
$responseType{$partid} = \%responseIds;
}
$studentTable.= &displaySubByDates($symbx,\%record,$parts,\%responseType,$checkIcon,$uname,$udom);
-
}
} elsif ($env{'form.lastSub'} eq 'all') {
my $last = ($env{'form.lastSub'} eq 'last' ? 'last' : '');
- my $identifier = (&canmodify($usec)? $prob : '');
+ my $identifier = (&canmodify($usec)? $prob : '');
$studentTable.=&Apache::loncommon::get_previous_attempt($symbx,$uname,$udom,
$env{'request.course.id'},
'','.submission',undef,
@@ -5214,7 +5415,6 @@ sub displayPage {
' '.
''."\n";
- $studentTable.=&show_grading_menu_form($symb);
$request->print($studentTable);
return '';
@@ -5224,13 +5424,14 @@ sub displaySubByDates {
my ($symb,$record,$parts,$responseType,$checkIcon,$uname,$udom) = @_;
my $isCODE=0;
my $isTask = ($symb =~/\.task$/);
+ my $is_tool = ($symb =~/\.tool$/);
if (exists($record->{'resource.CODE'})) { $isCODE=1; }
my $studentTable=&Apache::loncommon::start_data_table().
&Apache::loncommon::start_data_table_header_row().
''.&mt('Date/Time').' '.
($isCODE?''.&mt('CODE').' ':'').
($isTask?''.&mt('Version').' ':'').
- ''.&mt('Submission').' '.
+ ''.($is_tool?&mt('Grade'):&mt('Submission')).' '.
''.&mt('Status').' '.
&Apache::loncommon::end_data_table_header_row();
my ($version);
@@ -5238,7 +5439,11 @@ sub displaySubByDates {
my %orders;
$mark{'correct_by_student'} = $checkIcon;
if (!exists($$record{'1:timestamp'})) {
- return ' '.&mt('Nothing submitted - no attempts.').' ';
+ if ($is_tool) {
+ return ' '.&mt('No grade passed back.').' ';
+ } else {
+ return ' '.&mt('Nothing submitted - no attempts.').' ';
+ }
}
my $interaction;
@@ -5271,56 +5476,64 @@ sub displaySubByDates {
if (($type eq 'anonsurvey') || ($type eq 'anonsurveycred')) {
$hidden = 1;
}
- my @matchKey = ($isTask ? sort(grep /^resource\.\d+\.\Q$partid\E\.award$/,@versionKeys)
- : sort(grep /^resource\.\Q$partid\E\..*?\.submission$/,@versionKeys));
-
+ my @matchKey;
+ if ($isTask) {
+ @matchKey = sort(grep(/^resource\.\d+\.\Q$partid\E\.award$/,@versionKeys));
+ } elsif ($is_tool) {
+ @matchKey = sort(grep(/^resource\.\Q$partid\E\.awarded$/,@versionKeys));
+ } else {
+ @matchKey = sort(grep(/^resource\.\Q$partid\E\..*?\.submission$/,@versionKeys));
+ }
# next if ($$record{"$version:resource.$partid.solved"} eq '');
my $display_part=&get_display_part($partid,$symb);
foreach my $matchKey (@matchKey) {
if (exists($$record{$version.':'.$matchKey}) &&
$$record{$version.':'.$matchKey} ne '') {
-
- my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/)
- : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/));
- $displaySub[0].='';
- $displaySub[0].=''.&mt('Part: [_1]',$display_part).' '
- .' '
- .'('.&mt('Response ID: [_1]',$responseId).')'
- .' '
- .' ';
- if ($hidden) {
- $displaySub[0].= &mt('Anonymous Survey').' ';
+ if ($is_tool) {
+ $displaySub[0].=$$record{"$version:resource.$partid.awarded"};
} else {
- my ($trial,$rndseed,$newvariation);
- if ($type eq 'randomizetry') {
- $trial = $$record{"$where.$partid.tries"};
- $rndseed = $$record{"$where.$partid.rndseed"};
- }
- if ($$record{"$where.$partid.tries"} eq '') {
- $displaySub[0].=&mt('Trial not counted');
- } else {
- $displaySub[0].=&mt('Trial: [_1]',
- $$record{"$where.$partid.tries"});
- if (($rndseed ne '') && ($lastrndseed{$partid} ne '')) {
- if (($rndseed ne $lastrndseed{$partid}) &&
- (($type eq 'randomizetry') || ($lasttype{$partid} eq 'randomizetry'))) {
- $newvariation = ' ('.&mt('New variation this try').')';
- }
+ my ($responseId)= ($isTask ? ($matchKey=~ /^resource\.(.*?)\.\Q$partid\E\.award$/)
+ : ($matchKey=~ /^resource\.\Q$partid\E\.(.*?)\.submission$/));
+ $displaySub[0].='';
+ $displaySub[0].=''.&mt('Part: [_1]',$display_part).' '
+ .' '
+ .'('.&mt('Response ID: [_1]',$responseId).')'
+ .' '
+ .' ';
+ if ($hidden) {
+ $displaySub[0].= &mt('Anonymous Survey').' ';
+ } else {
+ my ($trial,$rndseed,$newvariation);
+ if ($type eq 'randomizetry') {
+ $trial = $$record{"$where.$partid.tries"};
+ $rndseed = $$record{"$where.$partid.rndseed"};
}
- $lastrndseed{$partid} = $rndseed;
- $lasttype{$partid} = $type;
- }
- my $responseType=($isTask ? 'Task'
+ if ($$record{"$where.$partid.tries"} eq '') {
+ $displaySub[0].=&mt('Trial not counted');
+ } else {
+ $displaySub[0].=&mt('Trial: [_1]',
+ $$record{"$where.$partid.tries"});
+ 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});
- if (!exists($orders{$partid})) { $orders{$partid}={}; }
- if ((!exists($orders{$partid}->{$responseId})) || ($trial)) {
- $orders{$partid}->{$responseId}=
- &get_order($partid,$responseId,$symb,$uname,$udom,
- $no_increment,$type,$trial,$rndseed);
- }
- $displaySub[0].=''.$newvariation.' '; # /nobreak
- $displaySub[0].=' '.
- &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:",$uname,$udom,$type,$trial,$rndseed).' ';
+ if (!exists($orders{$partid})) { $orders{$partid}={}; }
+ if ((!exists($orders{$partid}->{$responseId})) || ($trial)) {
+ $orders{$partid}->{$responseId}=
+ &get_order($partid,$responseId,$symb,$uname,$udom,
+ $no_increment,$type,$trial,$rndseed);
+ }
+ $displaySub[0].=''.$newvariation.' '; # /nobreak
+ $displaySub[0].=' '.
+ &cleanRecord($$record{$version.':'.$matchKey},$responseType,$symb,$partid,$responseId,$record,$orders{$partid}->{$responseId},"$version:",$uname,$udom,$type,$trial,$rndseed).' ';
+ }
}
}
}
@@ -5335,14 +5548,22 @@ sub displaySubByDates {
lc($$record{"$where.$partid.award"}).' '.
$mark{$$record{"$where.$partid.solved"}}.
' ';
+ } elsif (($is_tool) && (exists($$record{"$version:resource.$partid.solved"}))) {
+ if ($$record{"$version:resource.$partid.solved"} =~ /^(in|)correct_by_passback$/) {
+ $displaySub[1].=&mt('Grade passed back by external tool');
+ }
}
if (exists $$record{"$where.$partid.regrader"}) {
- $displaySub[2].=$$record{"$where.$partid.regrader"}.
- ' ('.&mt('Part').': '.$display_part.')';
+ $displaySub[2].=$$record{"$where.$partid.regrader"};
+ unless ($is_tool) {
+ $displaySub[2].=' ('.&mt('Part').': '.$display_part.')';
+ }
} elsif ($$record{"$version:resource.$partid.regrader"} =~ /\S/) {
$displaySub[2].=
- $$record{"$version:resource.$partid.regrader"}.
- ' ('.&mt('Part').': '.$display_part.')';
+ $$record{"$version:resource.$partid.regrader"};
+ unless ($is_tool) {
+ $displaySub[2].=' ('.&mt('Part').': '.$display_part.')';
+ }
}
}
# needed because old essay regrader has not parts info
@@ -5361,7 +5582,7 @@ sub displaySubByDates {
}
sub updateGradeByPage {
- my ($request) = shift;
+ my ($request,$symb) = @_;
my $cdom = $env{"course.$env{'request.course.id'}.domain"};
my $cnum = $env{"course.$env{'request.course.id'}.num"};
@@ -5372,7 +5593,6 @@ sub updateGradeByPage {
my $usec=$classlist->{$env{'form.student'}}[5];
if (!&canmodify($usec)) {
$request->print(''.&mt('Unable to modify requested student ([_1])',$env{'form.student'}).' ');
- $request->print(&show_grading_menu_form($env{'form.symb'}));
return;
}
my $result=' '.$env{'form.title'}.' ';
@@ -5391,8 +5611,6 @@ sub updateGradeByPage {
my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps
if (!$map) {
$request->print(''.&mt('Unable to grade requested sequence ([_1]).',$resUrl).' ');
- my ($symb)=&get_symb($request);
- $request->print(&show_grading_menu_form($symb));
return;
}
my $iterator = $navmap->getIterator($map->map_start(),
@@ -5524,7 +5742,6 @@ sub updateGradeByPage {
}
$studentTable.=&Apache::loncommon::end_data_table();
- $studentTable.=&show_grading_menu_form($env{'form.symb'});
my $grademsg=($changeflag == 0 ? &mt('No score was changed or updated.') :
&mt('The scores were changed for [quant,_1,problem].',
$changeflag).' ');
@@ -5605,9 +5822,7 @@ the homework problem.
sub defaultFormData {
my ($symb)=@_;
- return ' '."\n".
- ' '."\n".
- ' '."\n";
+ return ' ';
}
@@ -5760,7 +5975,7 @@ sub scantron_uploads {
sub scantron_scantab {
my $result=''."\n";
$result.=' '."\n";
- my @lines = &get_scantronformat_file();
+ my @lines = &Apache::lonnet::get_scantronformat_file();
if (@lines > 0) {
foreach my $line (@lines) {
next if (($line =~ /^\#/) || ($line eq ''));
@@ -5772,62 +5987,6 @@ sub scantron_scantab {
return $result;
}
-=pod
-
-=item get_scantronformat_file
-
- Returns an array containing lines from the scantron format file for
- the domain of the course.
-
- If a url for a custom.tab file is listed in domain's configuration.db,
- lines are from this file.
-
- Otherwise, if a default.tab has been published in RES space by the
- domainconfig user, lines are from this file.
-
- Otherwise, fall back to getting lines from the legacy file on the
- local server: /home/httpd/lonTabs/default_scantronformat.tab
-
-=cut
-
-sub get_scantronformat_file {
- my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'};
- my %domconfig = &Apache::lonnet::get_dom('configuration',['scantron'],$cdom);
- my $gottab = 0;
- my @lines;
- if (ref($domconfig{'scantron'}) eq 'HASH') {
- if ($domconfig{'scantron'}{'scantronformat'} ne '') {
- my $formatfile = &Apache::lonnet::getfile($Apache::lonnet::perlvar{'lonDocRoot'}.$domconfig{'scantron'}{'scantronformat'});
- if ($formatfile ne '-1') {
- @lines = split("\n",$formatfile,-1);
- $gottab = 1;
- }
- }
- }
- if (!$gottab) {
- my $confname = $cdom.'-domainconfig';
- my $default = $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'.$cdom.'/'.$confname.'/default.tab';
- my $formatfile = &Apache::lonnet::getfile($default);
- if ($formatfile ne '-1') {
- @lines = split("\n",$formatfile,-1);
- $gottab = 1;
- }
- }
- if (!$gottab) {
- my @domains = &Apache::lonnet::current_machine_domains();
- if (grep(/^\Q$cdom\E$/,@domains)) {
- my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
- @lines = <$fh>;
- close($fh);
- } else {
- my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/default_scantronformat.tab');
- @lines = <$fh>;
- close($fh);
- }
- }
- return @lines;
-}
-
=pod
=item scantron_CODElist
@@ -5889,8 +6048,7 @@ sub scantron_CODEunique {
=cut
sub scantron_selectphase {
- my ($r,$file2grade) = @_;
- my ($symb)=&get_symb($r);
+ my ($r,$file2grade,$symb) = @_;
if (!$symb) {return '';}
my $map_error;
my $sequence_selector=&getSequenceDropDown($symb,\$map_error);
@@ -5899,7 +6057,6 @@ sub scantron_selectphase {
return;
}
my $default_form_data=&defaultFormData($symb);
- my $grading_menu_button=&show_grading_menu_form($symb);
my $file_selector=&scantron_uploads($file2grade);
my $format_selector=&scantron_scantab();
my $CODE_selector=&scantron_CODElist();
@@ -5908,54 +6065,62 @@ sub scantron_selectphase {
$ssi_error = 0;
- if (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) ||
- &Apache::lonnet::allowed('usc',$env{'request.course.id'})) {
+ if (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) || $perm{'usc'}) {
- # Chunk of form to prompt for a scantron file upload.
+ # Chunk of form to prompt for a scantron file upload.
$r->print('
-
- '.&Apache::loncommon::start_data_table('LC_scantron_action').'
- '.&Apache::loncommon::start_data_table_header_row().'
-
- '.&mt('Specify a bubblesheet data file to upload.').'
-
- '.&Apache::loncommon::end_data_table_header_row().'
- '.&Apache::loncommon::start_data_table_row().'
-
-');
- my $default_form_data=&defaultFormData(&get_symb($r,1));
+ ');
my $cdom= $env{'course.'.$env{'request.course.id'}.'.domain'};
my $cnum= $env{'course.'.$env{'request.course.id'}.'.num'};
+ my $csec= $env{'request.course.sec'};
my $alertmsg = &mt('Please use the browse button to select a file from your local directory.');
&js_escape(\$alertmsg);
- $r->print('
-
-
+ if (formname.upfile.value == "") {
+ alert("'.$alertmsg.'");
+ return false;
+ }
+ formname.submit();
+ }'."\n".$formatjs));
+ $r->print('
'.$default_form_data.'
+
- '.&mt('File to upload: [_1]',' ').'
-
-
-
-');
+ '.&Apache::loncommon::start_data_table('LC_scantron_action').'
+ '.&Apache::loncommon::start_data_table_header_row().'
+
+ '.&mt('Specify a bubblesheet data file to upload.').'
+
+ '.&Apache::loncommon::end_data_table_header_row().'
+ '.&Apache::loncommon::start_data_table_row().'
+
+ '.&mt('File to upload: [_1]',' ').' '."\n");
+ if ($formatoptions) {
+ $r->print('
+ '.&Apache::loncommon::end_data_table_row().'
+ '.&Apache::loncommon::start_data_table_row().'
+ '.$formattitle.(' 'x2).$formatoptions.'
+
+ '.&Apache::loncommon::end_data_table_row().'
+ '.&Apache::loncommon::start_data_table_row().'
+ '
+ );
+ } else {
+ $r->print(' ');
+ }
+ $r->print('
+
+ '.&Apache::loncommon::end_data_table_row().'
+ '.&Apache::loncommon::end_data_table().'
+ '
+ );
- $r->print('
-
- '.&Apache::loncommon::end_data_table_row().'
- '.&Apache::loncommon::end_data_table().'
-');
}
# Chunk of form to prompt for a file to grade and how:
@@ -6063,108 +6228,17 @@ sub scantron_selectphase {
&Apache::loncommon::end_data_table_row()."\n".
&Apache::loncommon::end_data_table()."\n".
' ');
- $r->print($grading_menu_button);
return;
}
-=pod
-
-=item get_scantron_config
-
- Parse and return the scantron configuration line selected as a
- hash of configuration file fields.
-
- Arguments:
- which - the name of the configuration to parse from the file.
-
-
- Returns:
- If the named configuration is not in the file, an empty
- hash is returned.
- a hash with the fields
- name - internal name for the this configuration setup
- description - text to display to operator that describes this config
- CODElocation - if 0 or the string 'none'
- - no CODE exists for this config
- if -1 || the string 'letter'
- - a CODE exists for this config and is
- a string of letters
- Unsupported value (but planned for future support)
- if a positive integer
- - The CODE exists as the first n items from
- the question section of the form
- if the string 'number'
- - The CODE exists for this config and is
- a string of numbers
- CODEstart - (only matter if a CODE exists) column in the line where
- the CODE starts
- CODElength - length of the CODE
- IDstart - column where the student/employee ID starts
- IDlength - length of the student/employee ID info
- Qstart - column where the information from the bubbled
- 'questions' start
- Qlength - number of columns comprising a single bubble line from
- the sheet. (usually either 1 or 10)
- Qon - either a single character representing the character used
- to signal a bubble was chosen in the positional setup, or
- the string 'letter' if the letter of the chosen bubble is
- in the final, or 'number' if a number representing the
- chosen bubble is in the file (1->A 0->J)
- Qoff - the character used to represent that a bubble was
- left blank
- PaperID - if the scanning process generates a unique number for each
- sheet scanned the column that this ID number starts in
- PaperIDlength - number of columns that comprise the unique ID number
- for the sheet of paper
- FirstName - column that the first name starts in
- FirstNameLength - number of columns that the first name spans
-
- LastName - column that the last name starts in
- LastNameLength - number of columns that the last name spans
- BubblesPerRow - number of bubbles available in each row used to
- bubble an answer. (If not specified, 10 assumed).
-
-=cut
-
-sub get_scantron_config {
- my ($which) = @_;
- my @lines = &get_scantronformat_file();
- my %config;
- #FIXME probably should move to XML it has already gotten a bit much now
- foreach my $line (@lines) {
- my ($name,$descrip)=split(/:/,$line);
- if ($name ne $which ) { next; }
- chomp($line);
- my @config=split(/:/,$line);
- $config{'name'}=$config[0];
- $config{'description'}=$config[1];
- $config{'CODElocation'}=$config[2];
- $config{'CODEstart'}=$config[3];
- $config{'CODElength'}=$config[4];
- $config{'IDstart'}=$config[5];
- $config{'IDlength'}=$config[6];
- $config{'Qstart'}=$config[7];
- $config{'Qlength'}=$config[8];
- $config{'Qoff'}=$config[9];
- $config{'Qon'}=$config[10];
- $config{'PaperID'}=$config[11];
- $config{'PaperIDlength'}=$config[12];
- $config{'FirstName'}=$config[13];
- $config{'FirstNamelength'}=$config[14];
- $config{'LastName'}=$config[15];
- $config{'LastNamelength'}=$config[16];
- $config{'BubblesPerRow'}=$config[17];
- last;
- }
- return %config;
-}
-
=pod
=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:
@@ -6204,7 +6278,7 @@ sub username_to_idmap {
Process a requested correction to a scanline.
Arguments:
- $scantron_config - hash from &get_scantron_config()
+ $scantron_config - hash from &Apache::lonnet::get_scantron_config()
$scan_data - hash of correction information
(see &scantron_getfile())
$line - existing scanline
@@ -6364,12 +6438,12 @@ sub digits_to_letters {
=item scantron_parse_scanline
- Decodes a scanline from the selected scantron file
+ Decodes a scanline from the selected bubblesheet file
Arguments:
- line - The text of the scantron file line to process
+ line - The text of the bubblesheet file line to process
whichline - Line number
- scantron_config - Hash describing the format of the scantron lines.
+ scantron_config - Hash describing the format of the bubblesheet lines.
scan_data - Hash of extra information about the scanline
(see scantron_getfile for more information)
just_header - True if should not process question answers but only
@@ -6394,7 +6468,7 @@ sub digits_to_letters {
totalref - Ref of scalar used to score total number of bubble
lines needed for responses in a scan line (used when
randompick in use.
-
+
Returns:
Hash containing the result of parsing the scanline
@@ -6487,7 +6561,7 @@ sub scantron_parse_scanline {
$partids_by_symb,$orderedforcode,
$respnumlookup,$startline);
if ($total) {
- $lastpos = $total*$$scantron_config{'Qlength'};
+ $lastpos = $total*$$scantron_config{'Qlength'};
}
if (ref($totalref)) {
$$totalref = $total;
@@ -6501,7 +6575,7 @@ sub scantron_parse_scanline {
if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) {
$answers_needed = $bubble_lines_per_response{$respnumlookup->{$questnum}};
} else {
- $answers_needed = $bubble_lines_per_response{$questnum};
+ $answers_needed = $bubble_lines_per_response{$questnum};
}
my $answer_length = ($$scantron_config{'Qlength'} * $answers_needed)
|| 1;
@@ -6562,7 +6636,7 @@ sub scantron_parse_scanline {
sub get_master_seq {
my ($resources,$master_seq,$symb_to_resource) = @_;
- return unless ((ref($resources) eq 'ARRAY') && (ref($master_seq) eq 'ARRAY') &&
+ return unless ((ref($resources) eq 'ARRAY') && (ref($master_seq) eq 'ARRAY') &&
(ref($symb_to_resource) eq 'HASH'));
my $resource_error;
foreach my $resource (@{$resources}) {
@@ -6640,7 +6714,7 @@ sub scantron_validator_lettnum {
my $occurrences = 0;
my $responsenum = $questnum-1;
if (($randompick || $randomorder) && (ref($respnumlookup) eq 'HASH')) {
- $responsenum = $respnumlookup->{$questnum-1}
+ $responsenum = $respnumlookup->{$questnum-1}
}
if (($responsetype_per_response{$responsenum} eq 'essayresponse') ||
($responsetype_per_response{$responsenum} eq 'formularesponse') ||
@@ -6887,7 +6961,7 @@ sub scantron_filter {
sub scantron_process_corrections {
my ($r) = @_;
- my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
+ my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
my ($scanlines,$scan_data)=&scantron_getfile();
my $classlist=&Apache::loncoursedata::get_classlist();
my $which=$env{'form.scantron_line'};
@@ -6936,7 +7010,7 @@ sub scantron_process_corrections {
}
}
if ($err) {
- $r->print(
+ $r->print(
''
.&mt('Unable to accept last correction, an error occurred: [_1]',
$errmsg)
@@ -7054,9 +7128,9 @@ sub check_for_error {
=cut
sub scantron_warning_screen {
- my ($button_text)=@_;
+ my ($button_text,$symb)=@_;
my $title=&Apache::lonnet::gettitle($env{'form.selectpage'});
- my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
+ my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
my $CODElist;
if ($scantron_config{'CODElocation'} &&
$scantron_config{'CODEstart'} &&
@@ -7073,7 +7147,7 @@ sub scantron_warning_screen {
'
'.&mt('Hand-graded items: points from last bubble in row').' '.
$env{'form.scantron_lastbubblepoints'}.' ';
}
- return ('
+ return '
'.&mt("Please double check the information below before clicking on '[_1]'",&mt($button_text)).'
@@ -7083,12 +7157,9 @@ sub scantron_warning_screen {
'.&mt('Data File that will be used:').' '.$env{'form.scantron_selectfile'}.'
'.$CODElist.$lastbubblepoints.'
-
- '.&mt("If this information is correct, please click on '[_1]'.",&mt($button_text)).'
- '.&mt("If something is incorrect, please click the 'Grading Menu' button to start over.").'
-
-
-');
+ '.&mt("If this information is correct, please click on '[_1]'.",&mt($button_text)).'
+'.&mt('If something is incorrect, please return to [_1]Grade/Manage/Review Bubblesheets[_2] to start over.','',' ').'
+';
}
=pod
@@ -7101,8 +7172,7 @@ sub scantron_warning_screen {
=cut
sub scantron_do_warning {
- my ($r)=@_;
- my ($symb)=&get_symb($r);
+ my ($r,$symb)=@_;
if (!$symb) {return '';}
my $default_form_data=&defaultFormData($symb);
$r->print(&scantron_form_start().$default_form_data);
@@ -7115,20 +7185,63 @@ sub scantron_do_warning {
}
if ( $env{'form.scantron_selectfile'} eq '') {
$r->print(''.&mt("You have not selected a file that contains the student's response data.").'
');
- }
+ }
if ( $env{'form.scantron_format'} eq '') {
$r->print(''.&mt("You have not selected the format of the student's response data.").'
');
- }
+ }
} else {
- my $warning=&scantron_warning_screen('Grading: Validate Records');
+ my $warning=&scantron_warning_screen('Grading: Validate Records',$symb);
+ my ($checksec,@possibles) = &gradable_sections();
+ my $gradesections;
+ if ($checksec) {
+ my $file=$env{'form.scantron_selectfile'};
+ if (&valid_file($file)) {
+ my %bysec = &scantron_get_sections();
+ my $table;
+ if ((keys(%bysec) > 1) || ((keys(%bysec) == 1) && ((keys(%bysec))[0] ne $checksec))) {
+ $gradesections = &mt('Your current role is for section [_1].',''.$checksec.' ').' ';
+ $table = &Apache::loncommon::start_data_table()."\n".
+ &Apache::loncommon::start_data_table_header_row().
+ ''.&mt('Section').' '.&mt('Number of records').' '.
+ &Apache::loncommon::end_data_table_header_row()."\n";
+ if ($bysec{'none'}) {
+ $table .= &Apache::loncommon::start_data_table_row().
+ ''.&mt('None').' '.$bysec{'none'}.' '.
+ &Apache::loncommon::end_data_table_row()."\n";
+ }
+ foreach my $sec (sort { $a <=> $b } keys(%bysec)) {
+ next if ($sec eq 'none');
+ $table .= &Apache::loncommon::start_data_table_row().
+ ''.$sec.' '.$bysec{$sec}.' '.
+ &Apache::loncommon::end_data_table_row()."\n";
+ }
+ $table .= &Apache::loncommon::end_data_table()."\n";
+ $gradesections .= &mt('Sections represented in the bubblesheet data file (based on bubbled student IDs) are as follows:').
+ ''.$table.'
';
+ if (@possibles) {
+ $gradesections .= ''.
+ &mt('You have role(s) in [quant,_1,other section,other sections] with privileges to manage grades.',
+ scalar(@possibles)).' '.
+ &mt('Check which of those section(s), in addition to section [_1], you wish to grade using this bubblesheet file:',
+ ''.$checksec.' ').' ';
+ foreach my $sec (sort {$a <=> $b } @possibles) {
+ $gradesections .= ' '.$sec.' '.(' 'x2);
+ }
+ $gradesections .= '
';
+ }
+ }
+ } else {
+ $gradesections = ''.&mt('The selected file is unavailable').'
';
+ }
+ }
my $bubbledbyhand=&hand_bubble_option();
$r->print('
-'.$warning.$bubbledbyhand.'
+'.$warning.$gradesections.$bubbledbyhand.'
');
}
- $r->print(" ".&show_grading_menu_form($symb));
+ $r->print(" ");
return '';
}
@@ -7186,8 +7299,7 @@ SCANTRONFORM
=cut
sub scantron_validate_file {
- my ($r) = @_;
- my ($symb)=&get_symb($r);
+ my ($r,$symb) = @_;
if (!$symb) {return '';}
my $default_form_data=&defaultFormData($symb);
@@ -7211,11 +7323,42 @@ sub scantron_validate_file {
if ($env{'form.scantron_corrections'}) {
&scantron_process_corrections($r);
}
- $r->print(''.&mt('Gathering necessary information.').'
');$r->rflush();
+
+ $r->print(''.&mt('Gathering necessary information.').'
');
+ my ($checksec,@gradable);
+ if ($env{'request.course.sec'}) {
+ ($checksec,my @possibles) = &gradable_sections();
+ if ($checksec) {
+ if (@possibles) {
+ my @chosensecs = &Apache::loncommon::get_env_multiple('form.scantron_othersections');
+ if (@chosensecs) {
+ foreach my $sec (@chosensecs) {
+ if (grep(/^\Q$sec\E$/,@possibles)) {
+ unless (grep(/^\Q$sec\E$/,@gradable)) {
+ push(@gradable,$sec);
+ }
+ }
+ }
+ }
+ }
+ $r->print('
');
+ if (@gradable) {
+ my @showsections = sort { $a <=> $b } (@gradable,$checksec);
+ $r->print(
+ ''.&mt('Sections to be Graded:').' '.join(', ',@showsections).' ');
+ } else {
+ $r->print(
+ ''.&mt('Section to be Graded:').' '.$checksec.' ');
+ }
+ $r->print('
');
+ }
+ }
+ $r->rflush();
+
#get the student pick code ready
$r->print(&Apache::loncommon::studentbrowser_javascript());
my $nav_error;
- my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
+ my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config);
if ($nav_error) {
$r->print(&navmap_errormsg());
@@ -7236,23 +7379,39 @@ sub scantron_validate_file {
$env{'form.validatepass'} = 0;
}
my $currentphase=$env{'form.validatepass'};
-
+ my %skipbysec=();
my $stop=0;
while (!$stop && $currentphase < scalar(@validate_phases)) {
$r->print(&mt('Validating '.$validate_phases[$currentphase]).' ');
$r->rflush();
-
+
my $which="scantron_validate_".$validate_phases[$currentphase];
{
no strict 'refs';
- ($stop,$currentphase)=&$which($r,$currentphase);
+ my @extras=();
+ if ($validate_phases[$currentphase] eq 'ID') {
+ @extras = (\%skipbysec,$checksec,@gradable);
+ }
+ ($stop,$currentphase)=&$which($r,$currentphase,@extras);
}
}
if (!$stop) {
- my $warning=&scantron_warning_screen('Start Grading');
+ my $warning=&scantron_warning_screen('Start Grading',$symb);
+ my $secinfo;
+ if (keys(%skipbysec) > 0) {
+ my $seclist = '';
+ foreach my $sec (sort { $a <=> $b } keys(%skipbysec)) {
+ $seclist .= ''.&mt('section [_1]: [_2]',$sec,$skipbysec{$sec}).' ';
+ }
+ $seclist .= ' ';
+ $secinfo = ''.
+ &mt('Numbers of records for students in sections not being graded [_1]',
+ $seclist).
+ '
';
+ }
$r->print(&mt('Validation process complete.').' '.
- $warning.
+ $secinfo.$warning.
&mt('Perform verification for each student after storage of submissions?').
' '.
' '.&mt('Yes').' '.
@@ -7260,7 +7419,7 @@ sub scantron_validate_file {
' '.&mt('No').
' '.
&mt('Grading will take longer if you use verification.').' '.
- &mt("Alternatively, the 'Review bubblesheet data' utility (see grading menu) can be used for all students after grading is complete.").' '.
+ &mt('Otherwise, Grade/Manage/Review Bubblesheets [_1] Review bubblesheet data can be used once grading is complete.','»').' '.
' '.
' '."\n");
} else {
@@ -7272,7 +7431,7 @@ sub scantron_validate_file {
$r->print(' ');
$r->print(' '.&mt('this error').' ');
- $r->print(" ".&mt("Or click the 'Grading Menu' button to start over.")."
");
+ $r->print(''.&mt('Or return to [_1]Grade/Manage/Review Bubblesheets[_2] to start over.','',' ').'
');
} else {
if ($validate_phases[$currentphase] eq 'doublebubble' || $validate_phases[$currentphase] eq 'missingbubbles') {
$r->print(' ');
@@ -7284,7 +7443,7 @@ sub scantron_validate_file {
$r->print(" ".&mt("this scanline saving it for later."));
}
}
- $r->print(" ".&show_grading_menu_form($symb));
+ $r->print(" ");
return '';
}
@@ -7651,9 +7810,10 @@ sub scantron_validate_sequence {
my @resources=
$navmap->retrieveResources($map,\&scantron_filter_not_exam,1,0);
if (@resources) {
- $r->print(''
+ $r->print(
+ '
'
.&mt('Some resources in the sequence currently are not set to'
- .' exam mode. Grading these resources currently may not'
+ .' bubblesheet exam mode. Grading these resources currently may not'
.' work correctly.')
.'
'
);
@@ -7667,14 +7827,15 @@ sub scantron_validate_sequence {
sub scantron_validate_ID {
- my ($r,$currentphase) = @_;
+ my ($r,$currentphase,$skipbysec,$checksec,@gradable) = @_;
#get student info
my $classlist=&Apache::loncoursedata::get_classlist();
my %idmap=&username_to_idmap($classlist);
+ my $secidx = &Apache::loncoursedata::CL_SECTION();
#get scantron line setup
- my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
+ my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
my ($scanlines,$scan_data)=&scantron_getfile();
my $nav_error;
@@ -7685,6 +7846,7 @@ sub scantron_validate_ID {
}
my %found=('ids'=>{},'usernames'=>{});
+ my $unsavedskips = 0;
for (my $i=0;$i<=$scanlines->{'count'};$i++) {
my $line=&scantron_get_line($scanlines,$scan_data,$i);
if ($line=~/^[\s\cz]*$/) { next; }
@@ -7697,13 +7859,41 @@ sub scantron_validate_ID {
}
if ($found) {
my $username=$idmap{$found};
+ if ($checksec) {
+ if (ref($classlist->{$username}) eq 'ARRAY') {
+ my $stusec = $classlist->{$username}->[$secidx];
+ if ($stusec ne $checksec) {
+ unless ((@gradable > 0) && (grep(/^\Q$stusec\E$/,@gradable))) {
+ my $skip=1;
+ &scantron_put_line($scanlines,$scan_data,$i,$line,$skip);
+ if (ref($skipbysec) eq 'HASH') {
+ if ($stusec eq '') {
+ $skipbysec->{'none'} ++;
+ } else {
+ $skipbysec->{$stusec} ++;
+ }
+ }
+ $unsavedskips ++;
+ next;
+ }
+ }
+ }
+ }
if ($found{'ids'}{$found}) {
&scantron_get_correction($r,$i,$scan_record,\%scantron_config,
$line,'duplicateID',$found);
+ if ($unsavedskips) {
+ &scantron_putfile($scanlines,$scan_data);
+ $unsavedskips = 0;
+ }
return(1,$currentphase);
} elsif ($found{'usernames'}{$username}) {
&scantron_get_correction($r,$i,$scan_record,\%scantron_config,
$line,'duplicateID',$username);
+ if ($unsavedskips) {
+ &scantron_putfile($scanlines,$scan_data);
+ $unsavedskips = 0;
+ }
return(1,$currentphase);
}
#FIXME store away line we previously saw the ID on to use above
@@ -7712,29 +7902,95 @@ sub scantron_validate_ID {
} else {
if ($id =~ /^\s*$/) {
my $username=&scan_data($scan_data,"$i.user");
- if (defined($username) && $found{'usernames'}{$username}) {
+ if (($checksec && $username ne '')) {
+ if (ref($classlist->{$username}) eq 'ARRAY') {
+ my $stusec = $classlist->{$username}->[$secidx];
+ if ($stusec ne $checksec) {
+ unless ((@gradable > 0) && (grep(/^\Q$stusec\E$/,@gradable))) {
+ my $skip=1;
+ &scantron_put_line($scanlines,$scan_data,$i,$line,$skip);
+ if (ref($skipbysec) eq 'HASH') {
+ if ($stusec eq '') {
+ $skipbysec->{'none'} ++;
+ } else {
+ $skipbysec->{$stusec} ++;
+ }
+ }
+ $unsavedskips ++;
+ next;
+ }
+ }
+ }
+ } elsif (defined($username) && $found{'usernames'}{$username}) {
&scantron_get_correction($r,$i,$scan_record,
\%scantron_config,
$line,'duplicateID',$username);
+ if ($unsavedskips) {
+ &scantron_putfile($scanlines,$scan_data);
+ $unsavedskips = 0;
+ }
return(1,$currentphase);
} elsif (!defined($username)) {
&scantron_get_correction($r,$i,$scan_record,
\%scantron_config,
$line,'incorrectID');
+ if ($unsavedskips) {
+ &scantron_putfile($scanlines,$scan_data);
+ $unsavedskips = 0;
+ }
return(1,$currentphase);
}
$found{'usernames'}{$username}++;
} else {
&scantron_get_correction($r,$i,$scan_record,\%scantron_config,
$line,'incorrectID');
+ if ($unsavedskips) {
+ &scantron_putfile($scanlines,$scan_data);
+ $unsavedskips = 0;
+ }
return(1,$currentphase);
}
}
}
-
+ if ($unsavedskips) {
+ &scantron_putfile($scanlines,$scan_data);
+ $unsavedskips = 0;
+ }
return (0,$currentphase+1);
}
+sub scantron_get_sections {
+ my %bysec;
+ if ($env{'form.scantron_format'} ne '') {
+ my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
+ my ($scanlines,$scan_data)=&scantron_getfile();
+ my $classlist=&Apache::loncoursedata::get_classlist();
+ my %idmap=&username_to_idmap($classlist);
+ foreach my $key (keys(%idmap)) {
+ my $lckey = lc($key);
+ $idmap{$lckey} = $idmap{$key};
+ }
+ my $secidx = &Apache::loncoursedata::CL_SECTION();
+ for (my $i=0;$i<=$scanlines->{'count'};$i++) {
+ my $line=&scantron_get_line($scanlines,$scan_data,$i);
+ if ($line=~/^[\s\cz]*$/) { next; }
+ my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,
+ $scan_data);
+ my $id=lc($$scan_record{'scantron.ID'});
+ if (exists($idmap{$id})) {
+ if (ref($classlist->{$idmap{$id}}) eq 'ARRAY') {
+ my $stusec = $classlist->{$idmap{$id}}->[$secidx];
+ if ($stusec eq '') {
+ $bysec{'none'} ++;
+ } else {
+ $bysec{$stusec} ++;
+ }
+ }
+ }
+ }
+ }
+ return %bysec;
+}
sub scantron_get_correction {
my ($r,$i,$scan_record,$scan_config,$line,$error,$arg,
@@ -7775,10 +8031,10 @@ sub scantron_get_correction {
if ($error =~ /ID$/) {
if ($error eq 'incorrectID') {
- $r->print(''.&mt("The encoded ID is not in the classlist").
+ $r->print('
'.&mt("The encoded ID is not in the classlist").
"
\n");
} elsif ($error eq 'duplicateID') {
- $r->print(''.&mt("The encoded ID has also been used by a previous paper [_1]",$arg)."
\n");
+ $r->print(''.&mt("The encoded ID has also been used by a previous paper [_1]",$arg)."
\n");
}
$r->print($message);
$r->print("".&mt("How should I handle this?")." \n");
@@ -7798,8 +8054,8 @@ sub scantron_get_correction {
} elsif ($error eq 'duplicateCODE') {
$r->print('
'.&mt("The encoded CODE has also been used by a previous paper [_1], and CODEs are supposed to be unique.",join(', ',@{$arg}))."
\n");
}
- $r->print("".&mt('The CODE on the form is [_1]',
- "'$$scan_record{'scantron.CODE'}' ")
+ $r->print("
".&mt('The CODE on the form is [_1]',
+ "'$$scan_record{'scantron.CODE'}' ")
."
\n");
$r->print($message);
$r->print("".&mt("How should I handle this?")."
\n");
@@ -7835,8 +8091,7 @@ sub scantron_get_correction {
$r->print("\n ");
}
- $r->print(<
+ $r->print(&Apache::lonhtmlcommon::scripttag(<
ENDSCRIPT
my $href="/adm/pickcode?".
"form=".&escape("scantronupload").
@@ -7898,7 +8152,7 @@ ENDSCRIPT
# The form field scantron_questions is actually a list of line numbers not
# a list of question numbers. Therefore:
#
-
+
my $line_list = &questions_to_line_list($arg,$randomorder,$randompick,
$respnumlookup,$startline);
@@ -7923,8 +8177,7 @@ sub verify_bubbles_checked {
my $ansnumstr = join('","',@ansnums);
my $warning = &mt("A bubble or 'No bubble' selection has not been made for one or more lines.");
&js_escape(\$warning);
- my $output = (<
+ my $output = &Apache::lonhtmlcommon::scripttag(<
ENDSCRIPT
return $output;
}
@@ -8010,7 +8262,7 @@ sub questions_to_line_list {
} else {
$first = $first_bubble_line{$responsenum} + 1;
}
- $count = $bubble_lines_per_response{$responsenum};
+ $count = $bubble_lines_per_response{$responsenum};
}
$last = $first+$count-1;
push(@lines, ($first..$last));
@@ -8041,6 +8293,7 @@ for multi and missing bubble cases).
and value is number of first bubble line for current student
or code-based randompick and/or randomorder.
+
Implicit inputs:
%bubble_lines_per_response - Starting line numbers for each question.
Numbered from 0 (but question numbers are from
@@ -8093,7 +8346,7 @@ sub prompt_for_corrections {
} else {
if (($randomorder || $randompick) && (ref($respnumlookup) eq 'HASH')) {
$responsenum = $respnumlookup->{$question-1};
- if (ref($startline) eq 'HASH') {
+ if (ref($startline) eq 'HASH') {
$first = $startline->{$question-1};
}
} else {
@@ -8111,7 +8364,16 @@ sub prompt_for_corrections {
($responsetype_per_response{$responsenum} eq 'imageresponse') ||
($responsetype_per_response{$responsenum} eq 'reactionresponse') ||
($responsetype_per_response{$responsenum} eq 'organicresponse')) {
- $r->print(&mt("Although this particular question type requires handgrading, the instructions for this question in the bubblesheet exam directed students to leave [quant,_1,line] blank on their bubblesheets.",$lines).' '.&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.').' '.&mt('The score for this question will be a sum of the numeric values for the selected bubbles from each line, where A=1 point, B=2 points etc.').' '.&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.").' ');
+ $r->print(
+ &mt("Although this particular question type requires handgrading, the instructions for this question in the bubblesheet exam directed students to leave [quant,_1,line] blank on their bubblesheets.",$lines)
+ .' '
+ .&mt('A non-zero score can be assigned to the student during bubblesheet grading by selecting a bubble in at least one line.')
+ .' '
+ .&mt('The score for this question will be a sum of the numeric values for the selected bubbles from each line, where A=1 point, B=2 points etc.')
+ .' '
+ .&mt("To assign a score of zero for this question, mark all lines as 'No bubble'.")
+ .' '
+ );
} else {
$r->print(&mt("Select at most one bubble in a single line and select 'No Bubble' in all the other lines. ")." ");
}
@@ -8138,7 +8400,7 @@ sub prompt_for_corrections {
Arguments:
$r - Apache request object
- $scan_config - hash from &get_scantron_config()
+ $scan_config - hash from &Apache::lonnet::get_scantron_config()
$line - Number of the line being displayed.
$questionnum - Question number (may include subquestion)
$error - Type of error.
@@ -8151,7 +8413,7 @@ sub scantron_bubble_selector {
my $max=$$scan_config{'Qlength'};
my $scmode=$$scan_config{'Qon'};
- if ($scmode eq 'number' || $scmode eq 'letter') {
+ if ($scmode eq 'number' || $scmode eq 'letter') {
if (($$scan_config{'BubblesPerRow'} =~ /^\d+$/) &&
($$scan_config{'BubblesPerRow'} > 0)) {
$max=$$scan_config{'BubblesPerRow'};
@@ -8302,7 +8564,7 @@ sub get_codes {
sub scantron_validate_CODE {
my ($r,$currentphase) = @_;
- my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
+ my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
if ($scantron_config{'CODElocation'} &&
$scantron_config{'CODEstart'} &&
$scantron_config{'CODElength'}) {
@@ -8376,7 +8638,7 @@ sub scantron_validate_doublebubble {
&Apache::lonnet::decode_symb($env{'form.selectpage'});
#get scantron line setup
- my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
+ my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
my ($scanlines,$scan_data)=&scantron_getfile();
my $navmap = Apache::lonnavmaps::navmap->new();
@@ -8470,7 +8732,7 @@ sub scantron_get_maxbubble {
my $response_number = 0;
my $bubble_line = 0;
foreach my $resource (@resources) {
- my $resid = $resource->id();
+ my $resid = $resource->id();
my ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname,
$udom,undef,$bubbles_per_row);
if ((ref($analysis) eq 'HASH') && (ref($parts) eq 'ARRAY')) {
@@ -8521,7 +8783,7 @@ sub scantron_get_maxbubble {
$bubble_lines_per_response{$response_number} = $lines;
$responsetype_per_response{$response_number} =
$analysis->{$part_id.'.type'};
- $masterseq_id_responsenum{$resid.'_'.$part_id} = $response_number;
+ $masterseq_id_responsenum{$resid.'_'.$part_id} = $response_number;
$response_number++;
$bubble_line += $lines;
@@ -8558,7 +8820,7 @@ sub scantron_validate_missingbubbles {
&Apache::lonnet::decode_symb($env{'form.selectpage'});
#get scantron line setup
- my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
+ my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
my ($scanlines,$scan_data)=&scantron_getfile();
my $navmap = Apache::lonnavmaps::navmap->new();
@@ -8602,9 +8864,9 @@ sub scantron_validate_missingbubbles {
for (my $i=0;$i<=$scanlines->{'count'};$i++) {
my $line=&scantron_get_line($scanlines,$scan_data,$i);
if ($line=~/^[\s\cz]*$/) { next; }
- my $scan_record =
+ my $scan_record =
&scantron_parse_scanline($line,$i,\%scantron_config,$scan_data,undef,\%idmap,
- $randomorder,$randompick,$sequence,\@master_seq,
+ $randomorder,$randompick,$sequence,\@master_seq,
\%symb_to_resource,\%grader_partids_by_symb,
\%orderedforcode,\%respnumlookup,\%startline);
if (!defined($$scan_record{'scantron.missingerror'})) { next; }
@@ -8615,36 +8877,36 @@ sub scantron_validate_missingbubbles {
foreach my $missing (@{$$scan_record{'scantron.missingerror'}}) {
my $lastbubble;
if ($missing =~ /^(\d+)\.(\d+)$/) {
- my $question = $1;
- my $subquestion = $2;
- my ($first,$responsenum);
- if ($randomorder || $randompick) {
- $responsenum = $respnumlookup{$question-1};
- $first = $startline{$question-1};
- } else {
- $responsenum = $question-1;
- $first = $first_bubble_line{$responsenum};
- }
- if (!defined($first)) { next; }
- my @subans = split(/,/,$subdivided_bubble_lines{$responsenum});
- my $subcount = 1;
- while ($subcount<$subquestion) {
- $first += $subans[$subcount-1];
- $subcount ++;
- }
- my $count = $subans[$subquestion-1];
- $lastbubble = $first + $count;
+ my $question = $1;
+ my $subquestion = $2;
+ my ($first,$responsenum);
+ if ($randomorder || $randompick) {
+ $responsenum = $respnumlookup{$question-1};
+ $first = $startline{$question-1};
+ } else {
+ $responsenum = $question-1;
+ $first = $first_bubble_line{$responsenum};
+ }
+ if (!defined($first)) { next; }
+ my @subans = split(/,/,$subdivided_bubble_lines{$responsenum});
+ my $subcount = 1;
+ while ($subcount<$subquestion) {
+ $first += $subans[$subcount-1];
+ $subcount ++;
+ }
+ my $count = $subans[$subquestion-1];
+ $lastbubble = $first + $count;
} else {
- my ($first,$responsenum);
- if ($randomorder || $randompick) {
- $responsenum = $respnumlookup{$missing-1};
- $first = $startline{$missing-1};
- } else {
- $responsenum = $missing-1;
- $first = $first_bubble_line{$responsenum};
- }
- if (!defined($first)) { next; }
- $lastbubble = $first + $bubble_lines_per_response{$responsenum};
+ my ($first,$responsenum);
+ if ($randomorder || $randompick) {
+ $responsenum = $respnumlookup{$missing-1};
+ $first = $startline{$missing-1};
+ } else {
+ $responsenum = $missing-1;
+ $first = $first_bubble_line{$responsenum};
+ }
+ if (!defined($first)) { next; }
+ $lastbubble = $first + $bubble_lines_per_response{$responsenum};
}
if ($lastbubble > $max_bubble) { next; }
push(@to_correct,$missing);
@@ -8687,7 +8949,7 @@ sub hand_bubble_option {
}
}
if ($needs_hand_bubbles) {
- my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
+ my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config);
return &mt('The sequence to be graded contains response types which are handgraded.').''.
&mt('If you have already graded these by bubbling sheets to indicate points awarded, [_1]what point value is assigned to a filled last bubble in each row?',' ').
@@ -8698,17 +8960,16 @@ sub hand_bubble_option {
}
sub scantron_process_students {
- my ($r) = @_;
+ my ($r,$symb) = @_;
my (undef,undef,$sequence)=&Apache::lonnet::decode_symb($env{'form.selectpage'});
- my ($symb)=&get_symb($r);
if (!$symb) {
return '';
}
my $default_form_data=&defaultFormData($symb);
- my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
- my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config);
+ my %scantron_config=&Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
+ my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config);
my ($scanlines,$scan_data)=&scantron_getfile();
my $classlist=&Apache::loncoursedata::get_classlist();
my %idmap=&username_to_idmap($classlist);
@@ -8747,14 +9008,14 @@ sub scantron_process_students {
SCANTRONFORM
$r->print($result);
+ my ($checksec,@possibles)=&gradable_sections();
my @delayqueue;
my (%completedstudents,%scandata);
-
+
my $lock=&Apache::lonnet::set_lock(&mt('Grading bubblesheet exam'));
my $count=&get_todo_count($scanlines,$scan_data);
my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,$count);
- &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,
- 'Processing first student');
+ &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,'Processing first student');
$r->print(' ');
my $start=&Time::HiRes::time();
my $i=-1;
@@ -8772,12 +9033,11 @@ SCANTRONFORM
if ($ssi_error) {
$r->print("");
&ssi_print_error($r);
- $r->print(&show_grading_menu_form($symb));
&Apache::lonnet::remove_lock($lock);
return ''; # Dunno why the other returns return '' rather than just returning.
}
- my %lettdig = &letter_to_digits();
+ my %lettdig = &Apache::lonnet::letter_to_digits();
my $numletts = scalar(keys(%lettdig));
my %orderedforcode;
@@ -8787,15 +9047,14 @@ SCANTRONFORM
my $line=&scantron_get_line($scanlines,$scan_data,$i);
if ($line=~/^[\s\cz]*$/) { next; }
if ($started) {
- &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
- 'last student');
+ &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last student');
}
$started=1;
my %respnumlookup = ();
my %startline = ();
my $total;
my $scan_record=&scantron_parse_scanline($line,$i,\%scantron_config,
- $scan_data,undef,\%idmap,$randomorder,
+ $scan_data,undef,\%idmap,$randomorder,
$randompick,$sequence,\@master_seq,
\%symb_to_resource,\%grader_partids_by_symb,
\%orderedforcode,\%respnumlookup,\%startline,
@@ -8812,6 +9071,13 @@ SCANTRONFORM
next;
}
my $usec = $classlist->{$uname}->[&Apache::loncoursedata::CL_SECTION];
+ if (($checksec ne '') && ($checksec ne $usec)) {
+ unless (grep(/^\Q$usec\E$/,@possibles)) {
+ &scantron_add_delay(\@delayqueue,$line,
+ "No role with manage grades privilege in student's section ($usec)",3);
+ next;
+ }
+ }
my $user = $uname.':'.$usec;
($uname,$udom)=split(/:/,$uname);
@@ -8825,7 +9091,7 @@ SCANTRONFORM
my @mapresources = @resources;
if ($randomorder || $randompick) {
- @mapresources =
+ @mapresources =
&users_order($user,$scancode,$sequence,\@master_seq,\%symb_to_resource,
\%orderedforcode);
}
@@ -8875,7 +9141,6 @@ SCANTRONFORM
$ssi_error = 0; # So end of handler error message does not trigger.
$r->print("");
&ssi_print_error($r);
- $r->print(&show_grading_menu_form($symb));
&Apache::lonnet::remove_lock($lock);
return ''; # Why return ''? Beats me.
}
@@ -8915,12 +9180,11 @@ SCANTRONFORM
if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,
\@mapresources,\%partids_by_symb,
$bubbles_per_row,$randomorder,$randompick,
- \%respnumlookup,\%startline)
+ \%respnumlookup,\%startline)
eq 'ssi_error') {
$ssi_error = 0; # So end of handler error message does not trigger.
$r->print("");
&ssi_print_error($r);
- $r->print(&show_grading_menu_form($symb));
&Apache::lonnet::remove_lock($lock);
delete($completedstudents{$uname});
return '';
@@ -8978,7 +9242,6 @@ SCANTRONFORM
# $r->print("
took $lasttime
");
$r->print("");
- $r->print(&show_grading_menu_form($symb));
return '';
}
@@ -9010,7 +9273,7 @@ sub graders_resources_pass {
=item users_order
Returns array of resources in current map, ordered based on either CODE,
- if this is a CODEd exam, or based on student's identity if this is a
+ if this is a CODEd exam, or based on student's identity if this is a
"NAMEd" exam.
Should be used when randomorder and/or randompick applied when the
@@ -9037,7 +9300,7 @@ sub users_order {
if (ref($actual_seq) eq 'ARRAY') {
@mapresources = map { $symb_to_resource->{$_}; } @{$actual_seq};
if (ref($orderedforcode) eq 'HASH') {
- if (@mapresources > 0) {
+ if (@mapresources > 0) {
$orderedforcode->{$scancode} = \@mapresources;
}
}
@@ -9050,7 +9313,7 @@ sub users_order {
$master_seq,
$user,undef,1);
if (ref($actual_seq) eq 'ARRAY') {
- @mapresources =
+ @mapresources =
map { $symb_to_resource->{$_}; } @{$actual_seq};
}
}
@@ -9106,23 +9369,22 @@ sub grade_student_bubbles {
}
sub scantron_upload_scantron_data {
- my ($r)=@_;
+ my ($r,$symb) = @_;
my $dom = $env{'request.role.domain'};
+ my ($formatoptions,$formattitle,$formatjs) = &scantron_upload_dataformat($dom);
my $domdesc = &Apache::lonnet::domain($dom,'description');
$r->print(&Apache::loncommon::coursebrowser_javascript($dom));
my $select_link=&Apache::loncommon::selectcourse_link('rules','courseid',
'domainid',
'coursename',$dom);
my $syllabuslink = ''.&mt('Syllabus').' '.
- (' 'x2).&mt('(shows course personnel)');
- my ($symb) = &get_symb($r,1);
+ (' 'x2).&mt('(shows course personnel)');
my $default_form_data=&defaultFormData($symb);
my $nofile_alert = &mt('Please use the browse button to select a file from your local directory.');
&js_escape(\$nofile_alert);
my $nocourseid_alert = &mt("Please use the 'Select Course' link to open a separate window where you can search for a course to which a file can be uploaded.");
&js_escape(\$nocourseid_alert);
- $r->print('
-
-
+ '.$formatjs.'
+'));
+ $r->print('
'.&mt('Send bubblesheet data to a course').'
@@ -9164,7 +9427,12 @@ sub scantron_upload_scantron_data {
&Apache::lonhtmlcommon::row_closure().
&Apache::lonhtmlcommon::row_title(&mt('Domain')).
' '.$domdesc.
- &Apache::lonhtmlcommon::row_closure().
+ &Apache::lonhtmlcommon::row_closure());
+ if ($formatoptions) {
+ $r->print(&Apache::lonhtmlcommon::row_title($formattitle).$formatoptions.
+ &Apache::lonhtmlcommon::row_closure());
+ }
+ $r->print(
&Apache::lonhtmlcommon::row_title(&mt('File to upload')).
' '.
&Apache::lonhtmlcommon::row_closure(1).
@@ -9177,10 +9445,87 @@ sub scantron_upload_scantron_data {
return '';
}
+sub scantron_upload_dataformat {
+ my ($dom) = @_;
+ my ($formatoptions,$formattitle,$formatjs);
+ $formatjs = <<'END';
+function toggleScantab(form) {
+ return;
+}
+END
+ my %domconfig = &Apache::lonnet::get_dom('configuration',['scantron'],$dom);
+ if (ref($domconfig{'scantron'}) eq 'HASH') {
+ if (ref($domconfig{'scantron'}{'config'}) eq 'HASH') {
+ if (keys(%{$domconfig{'scantron'}{'config'}}) > 1) {
+ if (($domconfig{'scantron'}{'config'}{'dat'}) &&
+ (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH')) {
+ if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
+ if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}})) {
+ my ($onclick,$formatextra,$singleline);
+ my @lines = &Apache::lonnet::get_scantronformat_file();
+ my $count = 0;
+ foreach my $line (@lines) {
+ next if ($line =~ /^#/);
+ $singleline = $line;
+ $count ++;
+ }
+ if ($count > 1) {
+ $formatextra = ''.
+ ''.
+ &mt('Bubblesheet type').': '.
+ &scantron_scantab().'
';
+ $onclick = ' onclick="toggleScantab(this.form);"';
+ $formatjs = <<"END";
+function toggleScantab(form) {
+ var divid = 'bubbletype';
+ if (document.getElementById(divid)) {
+ var radioname = 'fileformat';
+ var num = form.elements[radioname].length;
+ if (num) {
+ for (var i=0; i ';
+ }
+ $formattitle = &mt('File format');
+ $formatoptions = ' '.
+ &mt('Plain Text (no delimiters)').
+ ' '.(' 'x2).
+ ' '.
+ &mt('Comma separated values').' '.$formatextra;
+ }
+ }
+ }
+ } elsif (keys(%{$domconfig{'scantron'}{'config'}}) == 1) {
+ if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
+ if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}})) {
+ $formattitle = &mt('Bubblesheet type');
+ $formatoptions = &scantron_scantab();
+ }
+ }
+ }
+ }
+ }
+ return ($formatoptions,$formattitle,$formatjs);
+}
sub scantron_upload_scantron_data_save {
- my($r)=@_;
- my ($symb)=&get_symb($r,1);
+ my ($r,$symb) = @_;
my $doanotherupload=
' '."\n".
' '."\n".
@@ -9188,37 +9533,76 @@ sub scantron_upload_scantron_data_save {
' '."\n";
if (!&Apache::lonnet::allowed('usc',$env{'form.domainid'}) &&
!&Apache::lonnet::allowed('usc',
- $env{'form.domainid'}.'_'.$env{'form.courseid'})) {
+ $env{'form.domainid'}.'_'.$env{'form.courseid'}) &&
+ !&Apache::lonnet::allowed('usc',
+ $env{'form.domainid'}.'_'.$env{'form.courseid'}.'/'.$env{'form.coursesec'})) {
$r->print(&mt("You are not allowed to upload bubblesheet data to the requested course.")." ");
- if ($symb) {
- $r->print(&show_grading_menu_form($symb));
- } else {
+ unless ($symb) {
$r->print($doanotherupload);
}
return '';
}
my %coursedata=&Apache::lonnet::coursedescription($env{'form.domainid'}.'_'.$env{'form.courseid'});
my $uploadedfile;
- $r->print(''.&mt("Uploading file to [_1]",$coursedata{'description'}).'
');
+ $r->print(''.&mt('Uploading file to [_1]','"'.$coursedata{'description'}.'"').'
');
if (length($env{'form.upfile'}) < 2) {
$r->print(
&Apache::lonhtmlcommon::confirm_success(
&mt('The file: [_1] you attempted to upload contained no information. Please check that you entered the correct filename.',
''.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').' '),1));
} else {
- my $result =
- &Apache::lonnet::userfileupload('upfile','','scantron','','','',
+ my %domconfig = &Apache::lonnet::get_dom('configuration',['scantron'],$env{'form.domainid'});
+ my $parser;
+ if (ref($domconfig{'scantron'}) eq 'HASH') {
+ if (ref($domconfig{'scantron'}{'config'}) eq 'HASH') {
+ my $is_csv;
+ my @possibles = keys(%{$domconfig{'scantron'}{'config'}});
+ if (@possibles > 1) {
+ if ($env{'form.fileformat'} eq 'csv') {
+ if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {
+ if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
+ if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}}) > 1) {
+ $is_csv = 1;
+ }
+ }
+ }
+ }
+ } elsif (@possibles == 1) {
+ if (ref($domconfig{'scantron'}{'config'}{'csv'}) eq 'HASH') {
+ if (ref($domconfig{'scantron'}{'config'}{'csv'}{'fields'}) eq 'HASH') {
+ if (keys(%{$domconfig{'scantron'}{'config'}{'csv'}{'fields'}}) > 1) {
+ $is_csv = 1;
+ }
+ }
+ }
+ }
+ if ($is_csv) {
+ $parser = $domconfig{'scantron'}{'config'}{'csv'};
+ }
+ }
+ }
+ my $result =
+ &Apache::lonnet::userfileupload('upfile','scantron','scantron',$parser,'','',
$env{'form.courseid'},$env{'form.domainid'});
- if ($result =~ m{^/uploaded/}) {
+ if ($result =~ m{^/uploaded/}) {
$r->print(
&Apache::lonhtmlcommon::confirm_success(&mt('Upload successful')).' '.
&mt('Uploaded [_1] bytes of data into location: [_2]',
(length($env{'form.upfile'})-1),
''.$result.' '));
($uploadedfile) = ($result =~ m{/([^/]+)$});
+ if ($uploadedfile =~ /^scantron_orig_/) {
+ my $logname = $uploadedfile;
+ $logname =~ s/^scantron_orig_//;
+ if ($logname ne '') {
+ my $now = time;
+ my %info = ($logname => { $now => $env{'user.name'}.':'.$env{'user.domain'} });
+ &Apache::lonnet::put('scantronupload',\%info,$env{'form.domainid'},$env{'form.courseid'});
+ }
+ }
$r->print(&validate_uploaded_scantron_file($env{'form.domainid'},
- $env{'form.courseid'},$uploadedfile));
- } else {
+ $env{'form.courseid'},$symb,$uploadedfile));
+ } else {
$r->print(
&Apache::lonhtmlcommon::confirm_success(&mt('Upload failed'),1).' '.
&mt('An error ([_1]) occurred when attempting to upload the file: [_2]',
@@ -9227,7 +9611,7 @@ sub scantron_upload_scantron_data_save {
}
}
if ($symb) {
- $r->print(&scantron_selectphase($r,$uploadedfile));
+ $r->print(&scantron_selectphase($r,$uploadedfile,$symb));
} else {
$r->print($doanotherupload);
}
@@ -9235,13 +9619,34 @@ sub scantron_upload_scantron_data_save {
}
sub validate_uploaded_scantron_file {
- my ($cdom,$cname,$fname) = @_;
+ my ($cdom,$cname,$symb,$fname,$context,$countsref) = @_;
+
my $scanlines=&Apache::lonnet::getfile('/uploaded/'.$cdom.'/'.$cname.'/'.$fname);
my @lines;
if ($scanlines ne '-1') {
@lines=split("\n",$scanlines,-1);
}
- my $output;
+ my ($output,$secidx,$checksec,$priv,%crsroleshash,@possibles);
+ $secidx = &Apache::loncoursedata::CL_SECTION();
+ if ($context eq 'download') {
+ $priv = 'mgr';
+ } else {
+ $priv = 'usc';
+ }
+ unless ((&Apache::lonnet::allowed($priv,$env{'request.role.domain'})) ||
+ (($env{'request.course.id'}) &&
+ (&Apache::lonnet::allowed($priv,$env{'request.course.id'})))) {
+ if ($env{'request.course.sec'} ne '') {
+ unless (&Apache::lonnet::allowed($priv,
+ "$env{'request.course.id'}/$env{'request.course.sec'}")) {
+ unless ($context eq 'download') {
+ $output = ''.&mt('You do not have permission to upload bubblesheet data').'
';
+ }
+ return $output;
+ }
+ ($checksec,@possibles)=&gradable_sections();
+ }
+ }
if (@lines) {
my (%counts,$max_match_format);
my ($found_match_count,$max_match_count,$max_match_pct) = (0,0,0);
@@ -9252,7 +9657,7 @@ sub validate_uploaded_scantron_file {
$idmap{$lckey} = $idmap{$key};
}
my %unique_formats;
- my @formatlines = &get_scantronformat_file();
+ my @formatlines = &Apache::lonnet::get_scantronformat_file();
foreach my $line (@formatlines) {
chomp($line);
my @config = split(/:/,$line);
@@ -9271,6 +9676,8 @@ sub validate_uploaded_scantron_file {
%{$counts{$key}} = (
'found' => 0,
'total' => 0,
+ 'totalanysec' => 0,
+ 'othersec' => 0,
);
foreach my $line (@lines) {
next if ($line =~ /^#/);
@@ -9278,6 +9685,23 @@ sub validate_uploaded_scantron_file {
my $id = substr($line,$idstart-1,$idlength);
$id = lc($id);
if (exists($idmap{$id})) {
+ if ($checksec ne '') {
+ $counts{$key}{'totalanysec'} ++;
+ if (ref($classlist->{$idmap{$id}}) eq 'ARRAY') {
+ my $stusec = $classlist->{$idmap{$id}}->[$secidx];
+ if ($stusec ne $checksec) {
+ if (@possibles) {
+ unless (grep(/^\Q$stusec\E$/,@possibles)) {
+ $counts{$key}{'othersec'} ++;
+ next;
+ }
+ } else {
+ $counts{$key}{'othersec'} ++;
+ next;
+ }
+ }
+ }
+ }
$counts{$key}{'found'} ++;
}
$counts{$key}{'total'} ++;
@@ -9292,7 +9716,7 @@ sub validate_uploaded_scantron_file {
}
}
}
- if (ref($unique_formats{$max_match_format}) eq 'ARRAY') {
+ if ((ref($unique_formats{$max_match_format}) eq 'ARRAY') && ($context ne 'download')) {
my $format_descs;
my $numwithformat = @{$unique_formats{$max_match_format}};
for (my $i=0; $i<$numwithformat; $i++) {
@@ -9337,13 +9761,179 @@ sub validate_uploaded_scantron_file {
''.&mt('The course roster is not up to date.').' '.
'';
}
+ if (($checksec ne '') && (ref($counts{$max_match_format}) eq 'HASH')) {
+ if ($counts{$max_match_format}{'othersec'}) {
+ my $percent_nongrade = (100*$counts{$max_match_format}{'othersec'})/($counts{$max_match_format}{'totalanysec'});
+ my $showpct = sprintf("%.0f",$percent_nongrade).'%';
+ my $confirmdel = &mt('Are you sure you want to permanently delete this file?');
+ &js_escape(\$confirmdel);
+ $output .= ''.
+ &mt('Comparison of student IDs in the uploaded file with the course roster found [_1][quant,_2,match,matches][_3] for students in section(s) for which none of your role(s) have privileges to modify grades',
+ '',$counts{$max_match_format}{'othersec'},' ').
+ ' '.
+ &mt('Unless you are assigned role(s) which allow modification of grades in additional sections, [_1] of the records in this file will be automatically excluded when you perform bubblesheet grading.',''.$showpct.' ').
+ '
'.
+ &mt('If you prefer to delete the file now, use: [_1]').
+ '
'.
+ ' '.
+ ' '.
+ ' '.
+ ' '.
+ ' '.
+ ' '.
+ ' '.
+ ' ';
+ }
+ }
}
- } else {
+ if (($context eq 'download') && ($checksec ne '')) {
+ if ((ref($countsref) eq 'HASH') && (ref($counts{$max_match_format}) eq 'HASH')) {
+ $countsref->{'totalanysec'} = $counts{$max_match_format}{'totalanysec'};
+ $countsref->{'othersec'} = $counts{$max_match_format}{'othersec'};
+ }
+ }
+ } elsif ($context ne 'download') {
$output = ''.&mt('Uploaded file contained no data').'
';
}
return $output;
}
+sub gradable_sections {
+ my $checksec = $env{'request.course.sec'};
+ my @oksecs;
+ if ($checksec) {
+ my %availablesecs = §ions_grade_privs();
+ if (ref($availablesecs{'mgr'}) eq 'ARRAY') {
+ foreach my $sec (@{$availablesecs{'mgr'}}) {
+ unless (grep(/^\Q$sec\E$/,@oksecs)) {
+ push(@oksecs,$sec);
+ }
+ }
+ if (grep(/^all$/,@oksecs)) {
+ undef($checksec);
+ }
+ }
+ }
+ return($checksec,@oksecs);
+}
+
+sub sections_grade_privs {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my %availablesecs = (
+ mgr => [],
+ vgr => [],
+ usc => [],
+ );
+ my $ccrole = 'cc';
+ if ($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Community') {
+ $ccrole = 'co';
+ }
+ my %crsroleshash = &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},
+ 'userroles',['active'],
+ [$ccrole,'in','cr'],$cdom,1);
+ my $crsid = $cnum.':'.$cdom;
+ foreach my $item (keys(%crsroleshash)) {
+ next unless ($item =~ /^$crsid\:/);
+ my ($crsnum,$crsdom,$role,$sec) = split(/\:/,$item);
+ my $suffix = "/$cdom/$cnum./$cdom/$cnum";
+ if ($sec ne '') {
+ $suffix = "/$cdom/$cnum/$sec./$cdom/$cnum/$sec";
+ }
+ if (($role eq $ccrole) || ($role eq 'in')) {
+ foreach my $priv ('mgr','vgr','usc') {
+ unless (grep(/^all$/,@{$availablesecs{$priv}})) {
+ if ($sec eq '') {
+ $availablesecs{$priv} = ['all'];
+ } elsif ($sec ne $env{'request.course.sec'}) {
+ unless (grep(/^\Q$sec\E$/,@{$availablesecs{$priv}})) {
+ push(@{$availablesecs{$priv}},$sec);
+ }
+ }
+ }
+ }
+ } elsif ($role =~ m{^cr/}) {
+ foreach my $priv ('mgr','vgr','usc') {
+ unless (grep(/^all$/,@{$availablesecs{$priv}})) {
+ if ($env{"user.priv.$role.$suffix"} =~ /:$priv&/) {
+ if ($sec eq '') {
+ $availablesecs{$priv} = ['all'];
+ } elsif ($sec ne $env{'request.course.sec'}) {
+ unless (grep(/^\Q$sec\E$/,@{$availablesecs{$priv}})) {
+ push(@{$availablesecs{$priv}},$sec);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return %availablesecs;
+}
+
+sub scantron_upload_delete {
+ my ($r,$symb) = @_;
+ my $filename = $env{'form.uploadedfile'};
+ if ($filename =~ /^scantron_orig_/) {
+ if (&Apache::lonnet::allowed('usc',$env{'form.domainid'}) ||
+ &Apache::lonnet::allowed('usc',
+ $env{'form.domainid'}.'_'.$env{'form.courseid'}) ||
+ &Apache::lonnet::allowed('usc',
+ $env{'form.domainid'}.'_'.$env{'form.courseid'}.'/'.$env{'form.coursesec'})) {
+ my $uploadurl = '/uploaded/'.$env{'form.domainid'}.'/'.$env{'form.courseid'}.'/'.$env{'form.uploadedfile'};
+ my $retrieval = &Apache::lonnet::getfile($uploadurl);
+ if ($retrieval eq '-1') {
+ $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('File deletion failed'),1).' '.
+ &mt('File requested for deletion not found.'));
+ } else {
+ $filename =~ s/^scantron_orig_//;
+ if ($filename ne '') {
+ my ($is_valid,$numleft);
+ my %info = &Apache::lonnet::get('scantronupload',[$filename],$env{'form.domainid'},$env{'form.courseid'});
+ if (keys(%info)) {
+ if (ref($info{$filename}) eq 'HASH') {
+ foreach my $timestamp (sort(keys(%{$info{$filename}}))) {
+ if ($info{$filename}{$timestamp} eq $env{'user.name'}.':'.$env{'user.domain'}) {
+ $is_valid = 1;
+ delete($info{$filename}{$timestamp});
+ }
+ }
+ $numleft = scalar(keys(%{$info{$filename}}));
+ }
+ }
+ if ($is_valid) {
+ my $result = &Apache::lonnet::removeuploadedurl($uploadurl);
+ if ($result eq 'ok') {
+ $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('File deletion successful')).' ');
+ if ($numleft) {
+ &Apache::lonnet::put('scantronupload',\%info,$env{'form.domainid'},$env{'form.courseid'});
+ } else {
+ &Apache::lonnet::del('scantronupload',[$filename],$env{'form.domainid'},$env{'form.courseid'});
+ }
+ } else {
+ $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('File deletion failed'),1).' '.
+ &mt('Result was [_1]',$result));
+ }
+ } else {
+ $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('File deletion failed'),1).' '.
+ &mt('File requested for deletion was uploaded by a different user.'));
+ }
+ } else {
+ $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('File deletion failed'),1).' '.
+ &mt('Filename of bubblesheet data file requested for deletion is invalid.'));
+ }
+ }
+ } else {
+ $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('File deletion failed'),1).' '.
+ &mt('You are not permitted to delete bubblesheet data files from the requested course.'));
+ }
+ } else {
+ $r->print(&Apache::lonhtmlcommon::confirm_success(&mt('File deletion failed'),1).' '.
+ &mt('Filename of bubblesheet data file requested for deletion is invalid.'));
+ }
+ return;
+}
+
sub valid_file {
my ($requested_file)=@_;
foreach my $filename (sort(&scantron_filenames())) {
@@ -9353,8 +9943,7 @@ sub valid_file {
}
sub scantron_download_scantron_data {
- my ($r)=@_;
- my ($symb) = &get_symb($r,1);
+ my ($r,$symb) = @_;
my $default_form_data=&defaultFormData($symb);
my $cname=$env{'course.'.$env{'request.course.id'}.'.num'};
my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'};
@@ -9365,9 +9954,31 @@ sub scantron_download_scantron_data {
'.&mt('The requested filename was invalid.').'
');
- $r->print(&show_grading_menu_form($symb));
return;
}
+ my (%uploader,$is_owner,%counts,$percent);
+ my %uploader = &Apache::lonnet::get('scantronupload',[$file],$cdom,$cname);
+ if (ref($uploader{$file}) eq 'HASH') {
+ foreach my $timestamp (sort { $a <=> $b } keys(%{$uploader{$file}})) {
+ if ($uploader{$file}{$timestamp} eq $env{'user.name'}.':'.$env{'user.domain'}) {
+ $is_owner = 1;
+ last;
+ }
+ }
+ }
+ unless ($is_owner) {
+ &validate_uploaded_scantron_file($cdom,$cname,$symb,'scantron_orig_'.$file,'download',\%counts);
+ if ($counts{'totalanysec'}) {
+ my $percent_othersec = (100*$counts{'othersec'})/($counts{'totalanysec'});
+ if ($percent_othersec >= 10) {
+ my $showpct = sprintf("%.0f",$percent_othersec).'%';
+ $r->print(''.
+ &mt('The original uploaded file includes [_1] or more of records for students for which none of your roles have rights to modify grades, so files are unavailable for download.',$showpct).
+ '
');
+ return;
+ }
+ }
+ }
my $orig='/uploaded/'.$cdom.'/'.$cname.'/scantron_orig_'.$file;
my $corrected='/uploaded/'.$cdom.'/'.$cname.'/scantron_corrected_'.$file;
my $skipped='/uploaded/'.$cdom.'/'.$cname.'/scantron_skipped_'.$file;
@@ -9376,7 +9987,7 @@ sub scantron_download_scantron_data {
&Apache::lonnet::allowuploaded('/adm/grades',$skipped);
$r->print('
- '.&mt('[_1]Original[_2] file as uploaded by bubblesheet scanning office.',
+ '.&mt('[_1]Original[_2] file as uploaded by the bubblesheet scanning office.',
'',' ').'
@@ -9388,26 +9999,23 @@ sub scantron_download_scantron_data {
'',' ').'
');
- $r->print(&show_grading_menu_form($symb));
return '';
}
sub checkscantron_results {
- my ($r) = @_;
- my ($symb)=&get_symb($r);
+ my ($r,$symb) = @_;
if (!$symb) {return '';}
- my $grading_menu_button=&show_grading_menu_form($symb);
my $cid = $env{'request.course.id'};
- my %lettdig = &letter_to_digits();
+ my %lettdig = &Apache::lonnet::letter_to_digits();
my $numletts = scalar(keys(%lettdig));
my $cnum = $env{'course.'.$cid.'.num'};
my $cdom = $env{'course.'.$cid.'.domain'};
my (undef, undef, $sequence) = &Apache::lonnet::decode_symb($env{'form.selectpage'});
my %record;
my %scantron_config =
- &Apache::grades::get_scantron_config($env{'form.scantron_format'});
+ &Apache::lonnet::get_scantron_config($env{'form.scantron_format'});
my $bubbles_per_row = &bubblesheet_bubbles_per_row(\%scantron_config);
- my ($scanlines,$scan_data)=&Apache::grades::scantron_getfile();
+ my ($scanlines,$scan_data)=&scantron_getfile();
my $classlist=&Apache::loncoursedata::get_classlist();
my %idmap=&Apache::grades::username_to_idmap($classlist);
my $navmap=Apache::lonnavmaps::navmap->new();
@@ -9418,7 +10026,7 @@ sub checkscantron_results {
my $map=$navmap->getResourceByUrl($sequence);
my ($randomorder,$randompick,@master_seq,%symb_to_resource,%grader_partids_by_symb,
%grader_randomlists_by_symb,%orderedforcode);
- if (ref($map)) {
+ if (ref($map)) {
$randomorder=$map->randomorder();
$randompick=$map->randompick();
}
@@ -9447,8 +10055,7 @@ sub checkscantron_results {
return '';
}
- &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,
- 'Processing first student');
+ &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,'Processing first student');
my $start=&Time::HiRes::time();
my $i=-1;
@@ -9458,8 +10065,7 @@ sub checkscantron_results {
my $line=&Apache::grades::scantron_get_line($scanlines,$scan_data,$i);
if ($line=~/^[\s\cz]*$/) { next; }
if ($started) {
- &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
- 'last student');
+ &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last student');
}
$started=1;
my $scan_record=
@@ -9571,19 +10177,21 @@ sub checkscantron_results {
}
}
}
- $r->print(''.
- &mt('Comparison of bubblesheet data (including corrections) with corresponding submission records (most recent submission) for [_1][quant,_2,student][_3] ([quant,_4,bubblesheet line] per student).',
- '',
- $numstudents,
- ' ',
- $env{'form.scantron_maxbubble'}).
- '
'
+ $r->print(
+ ''
+ .&mt('Comparison of bubblesheet data (including corrections) with corresponding submission records (most recent submission) for [_1][quant,_2,student][_3] ([quant,_4,bubblesheet line] per student).',
+ '',
+ $numstudents,
+ ' ',
+ $env{'form.scantron_maxbubble'})
+ .'
'
);
$r->print(''
.&mt('Exact matches for [_1][quant,_2,student][_3].','',$passed,' ')
.' '
.&mt('Discrepancies detected for [_1][quant,_2,student][_3].','',$failed,' ')
- .'
');
+ .''
+ );
if ($passed) {
$r->print(&mt('Students with exact correspondence between bubblesheet data and submissions are as follows:').' ');
$r->print(&Apache::loncommon::start_data_table()."\n".
@@ -9603,7 +10211,7 @@ sub checkscantron_results {
&Apache::loncommon::end_data_table()).' '.
&mt('Differences can occur if submissions were modified using manual grading after a bubblesheet grading pass.').' '.&mt('If unexpected discrepancies were detected, it is recommended that you inspect the original bubblesheets.');
}
- $r->print(' '.$grading_menu_button);
+ $r->print(' ');
return;
}
@@ -9729,53 +10337,12 @@ sub verify_scantron_grading {
return ($counter,$record);
}
-sub letter_to_digits {
- my %lettdig = (
- A => 1,
- B => 2,
- C => 3,
- D => 4,
- E => 5,
- F => 6,
- G => 7,
- H => 8,
- I => 9,
- J => 0,
- );
- return %lettdig;
-}
-
-
#-------- end of section for handling grading scantron forms -------
#
#-------------------------------------------------------------------
#-------------------------- Menu interface -------------------------
#
-#--- Show a Grading Menu button - Calls the next routine ---
-sub show_grading_menu_form {
- my ($symb)=@_;
- my $result.=''."\n".
- ' '."\n".
- ' '."\n".
- ' '."\n".
- ' '."\n".
- ' '."\n";
- return $result;
-}
-
-# -- Retrieve choices for grading form
-sub savedState {
- my %savedState = ();
- if ($env{'form.saveState'}) {
- foreach (split(/:/,$env{'form.saveState'})) {
- my ($key,$value) = split(/=/,$_,2);
- $savedState{$key} = $value;
- }
- }
- return \%savedState;
-}
-
#--- Href with symb and command ---
sub href_symb_cmd {
@@ -9784,23 +10351,26 @@ sub href_symb_cmd {
}
sub grading_menu {
- my ($request) = @_;
- my ($symb)=&get_symb($request);
+ my ($request,$symb) = @_;
if (!$symb) {return '';}
- my $probTitle = &Apache::lonnet::gettitle($symb);
- my ($table,undef,$hdgrade) = &showResourceInfo($symb,$probTitle);
- $request->print($table);
my %fields = ('symb'=>&Apache::lonenc::check_encrypt($symb),
- 'handgrade'=>$hdgrade,
- 'probTitle'=>$probTitle,
- 'command'=>'submit_options',
- 'saveState'=>"",
- 'gradingMenu'=>1,
- 'showgrading'=>"yes");
-
- my $url1 = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
+ 'command'=>'individual');
+ my $url1a = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
+
+ $fields{'command'}='ungraded';
+ my $url1b=&Apache::lonhtmlcommon::build_url('grades/',\%fields);
+
+ $fields{'command'}='table';
+ my $url1c=&Apache::lonhtmlcommon::build_url('grades/',\%fields);
+
+ $fields{'command'}='all_for_one';
+ my $url1d=&Apache::lonhtmlcommon::build_url('grades/',\%fields);
+
+ $fields{'command'}='downloadfilesselect';
+ my $url1e=&Apache::lonhtmlcommon::build_url('grades/',\%fields);
+
$fields{'command'} = 'csvform';
my $url2 = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
@@ -9809,15 +10379,46 @@ sub grading_menu {
$fields{'command'} = 'scantron_selectphase';
my $url4 = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
+
+ $fields{'command'} = 'initialverifyreceipt';
+ my $url5 = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
- my @menu = ({ categorytitle=>'Course Grading',
+ my @menu = ({ categorytitle=>'Hand Grading',
items =>[
- { linktext => 'Manual Grading/View Submissions',
- url => $url1,
+ { linktext => 'Select individual students to grade',
+ url => $url1a,
permission => 'F',
- icon => 'edit-find-replace.png',
- linktitle => 'Start the process of hand grading submissions.'
+ icon => 'grade_students.png',
+ linktitle => 'Grade current resource for a selection of students.'
+ },
+ { linktext => 'Grade ungraded submissions',
+ url => $url1b,
+ permission => 'F',
+ icon => 'ungrade_sub.png',
+ linktitle => 'Grade all submissions that have not been graded yet.'
+ },
+
+ { linktext => 'Grading table',
+ url => $url1c,
+ permission => 'F',
+ icon => 'grading_table.png',
+ linktitle => 'Grade current resource for all students.'
},
+ { linktext => 'Grade page/folder for one student',
+ url => $url1d,
+ permission => 'F',
+ icon => 'grade_PageFolder.png',
+ linktitle => 'Grade all resources in current page/sequence/folder for one student.'
+ },
+ { linktext => 'Download submissions',
+ url => $url1e,
+ permission => 'F',
+ icon => 'download_sub.png',
+ linktitle => 'Download all students submissions.'
+ }]},
+ { categorytitle=>'Automated Grading',
+ items =>[
+
{ linktext => 'Upload Scores',
url => $url2,
permission => 'F',
@@ -9833,168 +10434,153 @@ sub grading_menu {
{ linktext => 'Grade/Manage/Review Bubblesheets',
url => $url4,
permission => 'F',
- icon => 'stat.png',
+ icon => 'bubblesheet.png',
linktitle => 'Grade bubblesheet exams, upload/download bubblesheet data files, and review previously graded bubblesheet exams.'
- }
+ },
+ { linktext => 'Verify Receipt Number',
+ url => $url5,
+ permission => 'F',
+ icon => 'receipt_number.png',
+ linktitle => 'Verify a system-generated receipt number for correct problem solution.'
+ }
+
]
});
- #$fields{'command'} = 'verify';
- #$url = &Apache::lonhtmlcommon::build_url('grades/',\%fields);
- #
# Create the menu
my $Str;
- # $Str .= ''.&mt('Please select a grading task').' ';
$Str .= '';
$Str .= ' '.
- ' '."\n".
- ' '."\n".
- ' '."\n".
- ' '."\n".
- ' '."\n".
- ' '."\n";
-
- $Str .= Apache::lonhtmlcommon::generate_menu(@menu);
- #$menudata->{'jscript'}
- $Str .=' '.
- &Apache::lonnet::recprefix($env{'request.course.id'}).
- '- ';
-
- $Str .=" \n";
- my $receiptalert = &mt("Please enter a receipt number given by a student in the receipt box.");
- $request->print(<
- function checkChoice(formname,val,cmdx) {
- if (val <= 2) {
- var cmd = radioSelection(formname.radioChoice);
- var cmdsave = cmd;
- } else {
- cmd = cmdx;
- cmdsave = 'submission';
- }
- formname.command.value = cmd;
- if (val < 5) formname.submit();
- if (val == 5) {
- if (!checkReceiptNo(formname,'notOK')) {
- return false;
- } else {
- formname.submit();
- }
- }
- }
+ ' '."\n";
- function checkReceiptNo(formname,nospace) {
- var receiptNo = formname.receipt.value;
- var checkOpt = false;
- if (nospace == "OK" && isNaN(receiptNo)) {checkOpt = true;}
- if (nospace == "notOK" && (isNaN(receiptNo) || receiptNo == "")) {checkOpt = true;}
- if (checkOpt) {
- alert("$receiptalert");
- formname.receipt.value = "";
- formname.receipt.focus();
- return false;
- }
- return true;
- }
-
-GRADINGMENUJS
- &commonJSfunctions($request);
+ $Str .= &Apache::lonhtmlcommon::generate_menu(@menu);
return $Str;
}
+sub ungraded {
+ my ($request)=@_;
+ &submit_options($request);
+}
-#--- Displays the submissions first page -------
-sub submit_options {
- my ($request) = @_;
- my ($symb)=&get_symb($request);
+sub submit_options_sequence {
+ my ($request,$symb) = @_;
if (!$symb) {return '';}
- my $probTitle = &Apache::lonnet::gettitle($symb);
+ &commonJSfunctions($request);
+ my $result;
- my $receiptalert = &mt("Please enter a receipt number given by a student in the receipt box.");
- $request->print(<
- function checkChoice(formname,val,cmdx) {
- if (val <= 2) {
- var cmd = radioSelection(formname.radioChoice);
- var cmdsave = cmd;
- } else {
- cmd = cmdx;
- cmdsave = 'submission';
- }
- formname.command.value = cmd;
- formname.saveState.value = "saveCmd="+cmdsave+":saveSec="+pullDownSelection(formname.section)+
- ":saveSub="+pullDownSelection(formname.submitonly)+":saveStatus="+pullDownSelection(formname.Status);
- if (val < 5) formname.submit();
- if (val == 5) {
- if (!checkReceiptNo(formname,'notOK')) { return false;}
- formname.submit();
- }
- if (val < 7) formname.submit();
- }
-
- function checkReceiptNo(formname,nospace) {
- var receiptNo = formname.receipt.value;
- var checkOpt = false;
- if (nospace == "OK" && isNaN(receiptNo)) {checkOpt = true;}
- if (nospace == "notOK" && (isNaN(receiptNo) || receiptNo == "")) {checkOpt = true;}
- if (checkOpt) {
- alert("$receiptalert");
- formname.receipt.value = "";
- formname.receipt.focus();
- return false;
- }
- return true;
- }
-
-GRADINGMENUJS
+ $result.=''."\n".
+ ' '."\n";
+ $result.=&selectfield(0).
+ '
+
+
+
+
+ ';
+ return $result;
+}
+
+sub submit_options_table {
+ my ($request,$symb) = @_;
+ if (!$symb) {return '';}
&commonJSfunctions($request);
- my ($table,undef,$hdgrade) = &showResourceInfo($symb,$probTitle);
+ my $is_tool = ($symb =~ /ext\.tool$/);
my $result;
- my (undef,$sections) = &getclasslist('all','0');
- my $savedState = &savedState();
- my $saveCmd = ($$savedState{'saveCmd'} eq '' ? 'submission' : $$savedState{'saveCmd'});
- my $saveSec = ($$savedState{'saveSec'} eq '' ? 'all' : $$savedState{'saveSec'});
- my $saveSub = ($$savedState{'saveSub'} eq '' ? 'all' : $$savedState{'saveSub'});
- my $saveStatus = ($$savedState{'saveStatus'} eq '' ? 'Active' : $$savedState{'saveStatus'});
-
- # Preselect sections
- my $selsec="";
- if (ref($sections)) {
- foreach my $section (sort(@$sections)) {
- $selsec.=''.$section.' '."\n";
+
+ $result.=''."\n".
+ ' '."\n";
+
+ $result.=&selectfield(1,$is_tool).
+ '
+
+
+
+
+ ';
+ return $result;
+}
+
+sub submit_options_download {
+ my ($request,$symb) = @_;
+ if (!$symb) {return '';}
+
+ my $res_error;
+ my ($partlist,$handgrade,$responseType,$numresp,$numessay,$numdropbox) =
+ &response_type($symb,\$res_error);
+ if ($res_error) {
+ $request->print(&mt('An error occurred retrieving response types'));
+ return;
+ }
+ unless ($numessay) {
+ $request->print(&mt('No essayresponse items found'));
+ return;
+ }
+ my $table;
+ if (ref($partlist) eq 'ARRAY') {
+ if (scalar(@$partlist) > 1 ) {
+ $table = &showResourceInfo($symb,$partlist,$responseType,'gradingMenu',1,1);
}
}
- $result.=''."\n".
- ' '."\n".
- ' '."\n".
- ' '."\n".
- ' '."\n".
- ' '."\n".
- ' '."\n".
- ' '."\n";
+ my $is_tool = ($symb =~ /ext\.tool$/);
+ &commonJSfunctions($request);
+ my $result=' '."\n".
+ $table."\n".
+ ' '."\n";
$result.='
- '.&mt('Grade Current Resource').'
-
-
- '.$table.'
-
+ '.&mt('Select Students for whom to Download Submissions').'
+'.&selectfield(1,$is_tool).'
+
+
+
+
+
+
+ ';
+ return $result;
+}
+
+#--- Displays the submissions first page -------
+sub submit_options {
+ my ($request,$symb) = @_;
+ if (!$symb) {return '';}
+
+ my $is_tool = ($symb =~ /ext\.tool$/);
+ &commonJSfunctions($request);
+ my $result;
+
+ $result.=''."\n".
+ ' '."\n";
+ $result.=&selectfield(1,$is_tool).'
+
+
+
+
+ ';
+ return $result;
+}
-
+sub selectfield {
+ my ($full,$is_tool)=@_;
+ my %options;
+ if ($is_tool) {
+ %options =
+ (&transtatus_options,
+ 'select_form_order' => ['yes','incorrect','all']);
+ } else {
+ %options =
+ (&substatus_options,
+ 'select_form_order' => ['yes','queued','graded','incorrect','all']);
+ }
+ my $result='
'.&mt('Sections').'
- '."\n";
- $result.= $selsec;
- $result.= 'all ';
- $result.='
+ '.&Apache::lonstatistics::SectionSelect('section','multiple',5).'
@@ -10008,63 +10594,22 @@ GRADINGMENUJS
'.&mt('Access Status').'
- '.&Apache::lonhtmlcommon::StatusOptions($saveStatus,undef,5,undef,'mult').'
-
-
+ '.&Apache::lonhtmlcommon::StatusOptions(undef,undef,5,undef,'mult').'
+ ';
+ if ($full) {
+ my $heading = &mt('Submission Status');
+ if ($is_tool) {
+ $heading = &mt('Transaction Status');
+ }
+ $result.='
- '.&mt('Submission Status').'
-
-
- '.&mt('with submissions').'
- '.&mt('in grading queue').'
- '.&mt('with ungraded submissions').'
- '.&mt('with incorrect submissions').'
- '.&mt('with any status').'
-
-
-
-
-
-
-
-
-
-
- '.&mt('Grade Complete Folder for One Student').'
-
-
- ';
- $result .= &show_grading_menu_form($symb);
+ '.$heading.'
+ '.
+ &Apache::loncommon::select_form('all','submitonly',\%options).
+ '';
+ }
+ $result.='
';
return $result;
}
@@ -10078,13 +10623,21 @@ sub substatus_options {
);
}
+sub transtatus_options {
+ return &Apache::lonlocal::texthash(
+ 'yes' => 'with score transactions',
+ 'incorrect' => 'with less than full credit',
+ 'all' => 'with any status',
+ );
+}
+
sub reset_perm {
undef(%perm);
}
sub init_perm {
&reset_perm();
- foreach my $test_perm ('vgr','mgr','opa') {
+ foreach my $test_perm ('vgr','mgr','opa','usc') {
my $scope = $env{'request.course.id'};
if (!($perm{$test_perm}=&Apache::lonnet::allowed($test_perm,$scope))) {
@@ -10177,18 +10730,14 @@ sub clicker_grading_parameters {
}
sub process_clicker {
- my ($r)=@_;
- my ($symb)=&get_symb($r);
+ my ($r,$symb)=@_;
if (!$symb) {return '';}
my $result=&checkforfile_js();
- $env{'form.probTitle'} = &Apache::lonnet::gettitle($symb);
- my ($table) = &showResourceInfo($symb,$env{'form.probTitle'});
- $result.=$table;
- $result.=''."\n";
- $result.=''."\n";
- $result.=' '.&mt('Specify a file containing the clicker information for this resource.').
- ' '."\n";
- $result.=''."\n";
+ $result.=&Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_header_row().
+ ' '.&mt('Specify a file containing clicker information and set grading options.').' '.
+ &Apache::loncommon::end_data_table_header_row().
+ &Apache::loncommon::start_data_table_row()."\n";
# Attempt to restore parameters from last session, set defaults if not present
my %Saveable_Parameters=&clicker_grading_parameters();
&Apache::loncommon::restore_course_settings('grades_clicker',
@@ -10205,7 +10754,7 @@ sub process_clicker {
}
}
- my $upload=&mt("Upload File");
+ my $upload=&mt("Evaluate File");
my $type=&mt("Type");
my $attendance=&mt("Award points just for participation");
my $personnel=&mt("Correctness determined from response by course personnel");
@@ -10215,12 +10764,11 @@ sub process_clicker {
my $pcorrect=&mt("Percentage points for correct solution");
my $pincorrect=&mt("Percentage points for incorrect solution");
my $selectform=&Apache::loncommon::select_form($env{'form.upfiletype'},'upfiletype',
- {'iclicker' => 'i>clicker',
+ {'iclicker' => 'i>clicker',
'interwrite' => 'interwrite PRS',
'turning' => 'Turning Technologies'});
$symb = &Apache::lonenc::check_encrypt($symb);
- $result.=<
+ $result.= &Apache::lonhtmlcommon::scripttag(<
+ENDUPFORM
+ $result.= <
-
-
$type: $selectform
- $attendance
+ENDUPFORM
+ $result.=' '.&Apache::loncommon::end_data_table_row().
+ &Apache::loncommon::start_data_table_row().''.(< $attendance
$personnel
$specific
@@ -10274,34 +10824,35 @@ function sanitycheck() {
-$pcorrect:
+ENDGRADINGFORM
+ $result.=' '.&Apache::loncommon::end_data_table_row().
+ &Apache::loncommon::start_data_table_row().''.(<$pcorrect:
$pincorrect:
-ENDUPFORM
- $result.='
'."\n".
- '
'."\n";
- $result.=&show_grading_menu_form($symb);
+ENDPERCFORM
+ $result.=''.
+ &Apache::loncommon::end_data_table_row().
+ &Apache::loncommon::end_data_table();
return $result;
}
sub process_clicker_file {
- my ($r)=@_;
- my ($symb)=&get_symb($r);
+ my ($r,$symb) = @_;
if (!$symb) {return '';}
my %Saveable_Parameters=&clicker_grading_parameters();
&Apache::loncommon::store_course_settings('grades_clicker',
\%Saveable_Parameters);
-
- my ($result) = &showResourceInfo($symb,$env{'form.probTitle'});
+ my $result='';
if (($env{'form.gradingmechanism'} eq 'specific') && ($env{'form.specificid'}!~/\w/)) {
$result.=''.&mt('You need to specify a clicker ID for the correct answer').' ';
- return $result.&show_grading_menu_form($symb);
+ return $result;
}
if (($env{'form.gradingmechanism'} eq 'given') && ($env{'form.givenanswer'}!~/\S/)) {
$result.=''.&mt('You need to specify the correct answer').' ';
- return $result.&show_grading_menu_form($symb);
+ return $result;
}
my $foundgiven=0;
if ($env{'form.gradingmechanism'} eq 'given') {
@@ -10350,7 +10901,7 @@ sub process_clicker_file {
$result .=
&Apache::lonhtmlcommon::confirm_success(
&mt('No IDs found to determine correct answer'),1);
- return $result.&show_grading_menu_form($symb);
+ return $result;
}
}
if (length($env{'form.upfile'}) < 2) {
@@ -10358,7 +10909,7 @@ sub process_clicker_file {
&Apache::lonhtmlcommon::confirm_success(
&mt('The file: [_1] you attempted to upload contained no information. Please check that you entered the correct filename.',
''.&HTML::Entities::encode($env{'form.upfile.filename'},'<>&"').' '),1);
- return $result.&show_grading_menu_form($symb);
+ return $result;
}
my $mimetype;
if ($env{'form.upfiletype'} eq 'iclicker') {
@@ -10368,29 +10919,28 @@ sub process_clicker_file {
$result.= ''.
&Apache::lonhtmlcommon::confirm_success(
&mt('File format is neither csv (iclicker 6) nor xml (iclicker 7)'),1).'
';
- return $result.&show_grading_menu_form($symb);
+ return $result;
}
} elsif (($env{'form.upfiletype'} ne 'interwrite') && ($env{'form.upfiletype'} ne 'turning')) {
$result .= ''.
&Apache::lonhtmlcommon::confirm_success(
&mt('Invalid clicker type: choose one of: i>clicker, Interwrite PRS, or Turning Technologies.'),1).'
';
- return $result.&show_grading_menu_form($symb);
+ return $result;
}
# Were able to get all the info needed, now analyze the file
$result.=&Apache::loncommon::studentbrowser_javascript();
$symb = &Apache::lonenc::check_encrypt($symb);
- my $heading=&mt('Scanning clicker file');
- $result.=(<
-
-$heading
+ $result.=&Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_header_row().
+ ' '.&mt('Evaluate clicker file').' '.
+ &Apache::loncommon::end_data_table_header_row().
+ &Apache::loncommon::start_data_table_row().(<
-
-
@@ -10420,7 +10970,7 @@ ENDHEADER
' ';
if (($env{'form.gradingmechanism'} eq 'given') && ($number!=$foundgiven)) {
$result.=''.&mt('Number of given answers does not agree with number of questions in file.').' ';
- return $result.&show_grading_menu_form($symb);
+ return $result;
}
# Remember Question Titles
# FIXME: Possibly need delimiter other than ":"
@@ -10440,7 +10990,9 @@ ENDHEADER
} elsif ($clicker_ids{$id}) {
if ($clicker_ids{$id}=~/\,/) {
# More than one user with the same clicker!
- $result.="\n ".&mt('Clicker registered more than once').": ".$id." ";
+ $result.="".&Apache::loncommon::end_data_table_row().
+ &Apache::loncommon::start_data_table_row()."".
+ &mt('Clicker registered more than once').": ".$id." ";
$result.="\n".' '.
"";
foreach my $reguser (sort(split(/\,/,$clicker_ids{$id}))) {
@@ -10454,12 +11006,14 @@ ENDHEADER
$student_count++;
}
} else {
- $result.="\n ".&mt('Unregistered Clicker')." ".$id." ";
+ $result.=" ".&Apache::loncommon::end_data_table_row().
+ &Apache::loncommon::start_data_table_row()."".
+ &mt('Unregistered Clicker')." ".$id." ";
$result.="\n".' '.
"\n".&mt("Username").": ".
"\n".&mt("Domain").": ".
&Apache::loncommon::select_dom_form($env{'course.'.$env{'request.course.id'}.'.domain'},'udom'.$id).' '.
- &Apache::loncommon::selectstudent_link('clickeranalysis','uname'.$id,'udom'.$id,0,$id);
+ &Apache::loncommon::selectstudent_link('clickeranalysis','uname'.$id,'udom'.$id,'',$id);
$unknown_count++;
}
}
@@ -10480,9 +11034,10 @@ ENDHEADER
} else {
$result.=' ';
}
- $result.='
'."\n".
- '
'."\n";
- return $result.&show_grading_menu_form($symb);
+ $result.=''.
+ &Apache::loncommon::end_data_table_row().
+ &Apache::loncommon::end_data_table();
+ return $result;
}
sub iclicker_eval {
@@ -10612,9 +11167,9 @@ sub turning_eval {
return ($errormsg,$number);
}
+
sub assign_clicker_grades {
- my ($r)=@_;
- my ($symb)=&get_symb($r);
+ my ($r,$symb) = @_;
if (!$symb) {return '';}
# See which part we are saving to
my $res_error;
@@ -10625,15 +11180,11 @@ sub assign_clicker_grades {
# FIXME: This should probably look for the first handgradeable part
my $part=$$partlist[0];
# Start screen output
- my ($result) = &showResourceInfo($symb,$env{'form.probTitle'});
-
- $result .= ' '.
- &Apache::loncommon::start_data_table().
- &Apache::loncommon::start_data_table_header_row().
- ''.&mt('Assigning grades based on clicker file').' '.
- &Apache::loncommon::end_data_table_header_row().
- &Apache::loncommon::start_data_table_row().'';
-
+ my $result = &Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_header_row().
+ ' '.&mt('Assigning grades based on clicker file').' '.
+ &Apache::loncommon::end_data_table_header_row().
+ &Apache::loncommon::start_data_table_row().'';
# Get correct result
# FIXME: Possibly need delimiter other than ":"
my @correct=();
@@ -10688,14 +11239,14 @@ sub assign_clicker_grades {
&mt('More than one entry found for [_1]!',''.$user.' ').
' ';
}
- $users{$user}=1;
+ $users{$user}=1;
my @answer=split(/\,/,$env{$key});
my $sum=0;
my $realnumber=$number;
for (my $i=0;$i<$number;$i++) {
if ($correct[$i] eq '-') {
$realnumber--;
- } elsif ($answer[$i]) {
+ } elsif (($answer[$i]) || ($answer[$i]=~/^[0\.]+$/)) {
if ($gradingmechanism eq 'attendance') {
$sum+=$pcorrect;
} elsif ($correct[$i] eq '*') {
@@ -10742,8 +11293,8 @@ sub assign_clicker_grades {
$result.=' '.&mt('Successfully stored grades for [quant,_1,student].',$storecount).
' '.
&Apache::loncommon::end_data_table_row().
- &Apache::loncommon::end_data_table()." \n";
- return $result.&show_grading_menu_form($symb);
+ &Apache::loncommon::end_data_table();
+ return $result;
}
sub navmap_errormsg {
@@ -10754,18 +11305,93 @@ sub navmap_errormsg {
}
sub startpage {
- my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$js) = @_;
+ my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$head_extra,$onload,$divforres) = @_;
+ my %args;
+ if ($onload) {
+ my %loaditems = (
+ 'onload' => $onload,
+ );
+ $args{'add_entries'} = \%loaditems;
+ }
if ($nomenu) {
- $r->print(&Apache::loncommon::start_page("Student's Version",$js,{'only_body' => '1'}));
+ $args{'only_body'} = 1;
+ $r->print(&Apache::loncommon::start_page("Student's Version",$head_extra,\%args));
} else {
- $r->print(&Apache::loncommon::start_page('Grading',$js,
- {'bread_crumbs' => $crumbs}));
+ unshift(@$crumbs,{href=>&href_symb_cmd($symb,'gradingmenu'),text=>"Grading"});
+ $args{'bread_crumbs'} = $crumbs;
+ $r->print(&Apache::loncommon::start_page('Grading',$head_extra,\%args));
+ if ($env{'request.course.id'}) {
+ &Apache::lonquickgrades::startGradeScreen($r,($env{'form.symb'}?'probgrading':'grading'));
+ }
}
unless ($nodisplayflag) {
- $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp));
+ $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp,$divforres));
}
}
+sub select_problem {
+ my ($r)=@_;
+ $r->print(''.&mt('Select the problem or one of the problems you want to grade').' ');
+ $r->print(&Apache::lonstathelpers::problem_selector('.',undef,1,undef,undef,1,1));
+ $r->print(' ');
+ $r->print(' ');
+}
+
+sub css_links {
+ my ($currsymb,$level) = @_;
+ my ($links,@symbs,%cssrefs,%httpref);
+ if ($level eq 'map') {
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (ref($navmap)) {
+ my ($map,undef,$url)=&Apache::lonnet::decode_symb($currsymb);
+ my @resources = $navmap->retrieveResources($map,sub { $_[0]->is_problem() },0,0);
+ foreach my $res (@resources) {
+ if (ref($res)) {
+ if ($res->symb()) {
+ push(@symbs,$res->symb());
+ }
+ }
+ }
+ }
+ } else {
+ @symbs = ($currsymb);
+ }
+ foreach my $symb (@symbs) {
+ my $css_href = &Apache::lonnet::EXT('resource.0.cssfile',$symb);
+ if ($css_href =~ /\S/) {
+ unless ($css_href =~ m{https?://}) {
+ my ($map,undef,$url)=&Apache::lonnet::decode_symb($symb);
+ my $proburl = &Apache::lonnet::clutter($url);
+ my ($probdir) = ($proburl =~ m{(.+)/[^/]+$});
+ unless ($css_href =~ m{^/}) {
+ $css_href = &Apache::lonnet::hreflocation($probdir,$css_href);
+ }
+ if ($css_href =~ m{^/(res|uploaded)/}) {
+ unless (($httpref{'httpref.'.$css_href}) |
+ (&Apache::lonnet::is_on_map($css_href))) {
+ my $thisurl = $proburl;
+ if ($env{'httpref.'.$proburl}) {
+ $thisurl = $env{'httpref.'.$proburl};
+ }
+ $httpref{'httpref.'.$css_href} = $thisurl;
+ }
+ }
+ }
+ $cssrefs{$css_href} = 1;
+ }
+ }
+ if (keys(%httpref)) {
+ &Apache::lonnet::appenv(\%httpref);
+ }
+ if (keys(%cssrefs)) {
+ foreach my $css_href (keys(%cssrefs)) {
+ next unless ($css_href =~ m{^(/res/|/uploaded/|https?://)});
+ $links .= ' '."\n";
+ }
+ }
+ return $links;
+}
+
sub handler {
my $request=$_[0];
&reset_caches();
@@ -10776,172 +11402,241 @@ sub handler {
}
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'});
- my $symb=&get_symb($request,1);
+# see what command we need to execute
+
my @commands=&Apache::loncommon::get_env_multiple('form.command');
my $command=$commands[0];
+ &init_perm();
+ if (!$env{'request.course.id'}) {
+ unless ((&Apache::lonnet::allowed('usc',$env{'request.role.domain'})) &&
+ ($command =~ /^scantronupload/)) {
+ # Not in a course.
+ $env{'user.error.msg'}="/adm/grades::vgr:0:0:Cannot display grades page outside course context";
+ return HTTP_NOT_ACCEPTABLE;
+ }
+ } elsif (!%perm) {
+ $request->internal_redirect('/adm/quickgrades');
+ return OK;
+ }
+ &Apache::loncommon::content_type($request,'text/html');
+ $request->send_http_header;
+
if ($#commands > 0) {
&Apache::lonnet::logthis("grades got multiple commands ".join(':',@commands));
}
+# see what the symb is
+
+ my $symb=$env{'form.symb'};
+ unless ($symb) {
+ (my $url=$env{'form.url'}) =~ s-^https*://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
+ $symb=&Apache::lonnet::symbread($url);
+ }
+ &Apache::lonenc::check_decrypt(\$symb);
+
$ssi_error = 0;
- my $brcrum = [{href=>"/adm/grades",text=>"Grading"}];
- my $start_page = &Apache::loncommon::start_page('Grading',undef,
- {'bread_crumbs' => $brcrum});
- if ($symb eq '' && $command eq '') {
- if ($env{'user.adv'}) {
- &Apache::loncommon::content_type($request,'text/html');
- $request->send_http_header;
- $request->print($start_page);
- if (($env{'form.codeone'}) && ($env{'form.codetwo'}) &&
- ($env{'form.codethree'})) {
- my $token=$env{'form.codeone'}.'*'.$env{'form.codetwo'}.'*'.
- $env{'form.codethree'};
- my ($tsymb,$tuname,$tudom,$tcrsid)=
- &Apache::lonnet::checkin($token);
- if ($tsymb) {
- my ($map,$id,$url)=&Apache::lonnet::decode_symb($tsymb);
- if (&Apache::lonnet::allowed('mgr',$tcrsid)) {
- $request->print(&ssi_with_retries('/res/'.$url, $ssi_retries,
- ('grade_username' => $tuname,
- 'grade_domain' => $tudom,
- 'grade_courseid' => $tcrsid,
- 'grade_symb' => $tsymb)));
- } else {
- $request->print('Not authorized: '.$token.' ');
- }
- } else {
- $request->print('Not a valid DocID: '.$token.' ');
- }
- } else {
- $request->print(&Apache::lonxml::tokeninputfield());
- }
- } elsif ($env{'request.course.id'}) {
- &init_perm();
- if (!%perm) {
- $request->internal_redirect('/adm/quickgrades');
- return OK;
- } else {
- &Apache::loncommon::content_type($request,'text/html');
- $request->send_http_header;
- $request->print($start_page);
- }
- }
+ if (($symb eq '' || $command eq '') && ($env{'request.course.id'})) {
+#
+# Not called from a resource, but inside a course
+#
+ &startpage($request,undef,[],1,1);
+ &select_problem($request);
} else {
- &init_perm();
- if (!$env{'request.course.id'}) {
- unless ((&Apache::lonnet::allowed('usc',$env{'request.role.domain'})) &&
- ($command =~ /^scantronupload/)) {
- # Not in a course.
- $env{'user.error.msg'}="/adm/grades::vgr:0:0:Cannot display grades page outside course context";
- return HTTP_NOT_ACCEPTABLE;
- }
- } elsif (!%perm) {
- $request->internal_redirect('/adm/quickgrades');
- }
- &Apache::loncommon::content_type($request,'text/html');
- $request->send_http_header;
- unless ((($command eq 'submission' || $command eq 'versionsub')) && ($perm{'vgr'})) {
- $request->print($start_page);
- }
if ($command eq 'submission' && $perm{'vgr'}) {
- my ($stuvcurrent,$stuvdisp,$versionform,$js);
+ my ($stuvcurrent,$stuvdisp,$versionform,$js,$onload);
if (($env{'form.student'} ne '') && ($env{'form.userdom'} ne '')) {
($stuvcurrent,$stuvdisp,$versionform,$js) =
&choose_task_version_form($symb,$env{'form.student'},
$env{'form.userdom'});
}
- &startpage($request,$symb,[{href=>"", text=>"Student Submissions"}],undef,undef,$stuvcurrent,$stuvdisp,undef,$js);
+ my $divforres;
+ if ($env{'form.student'} eq '') {
+ $js .= &part_selector_js();
+ $onload = "toggleParts('gradesub');";
+ } else {
+ $divforres = 1;
+ }
+ my $csslinks = &css_links($symb);
+ my $head_extra = $js."\n".$csslinks;
+ &startpage($request,$symb,[{href=>"", text=>"Student Submissions"}],undef,undef,
+ $stuvcurrent,$stuvdisp,undef,$head_extra,$onload,$divforres);
if ($versionform) {
+ if ($divforres) {
+ $request->print('
');
+ }
$request->print($versionform);
}
- $request->print(' ');
- ($env{'form.student'} eq '' ? &listStudents($request) : &submission($request,0,0));
+ ($env{'form.student'} eq '' ? &listStudents($request,$symb,'',$divforres) : &submission($request,0,0,$symb,$divforres,$command));
} elsif ($command eq 'versionsub' && $perm{'vgr'}) {
my ($stuvcurrent,$stuvdisp,$versionform,$js) =
&choose_task_version_form($symb,$env{'form.student'},
$env{'form.userdom'},
$env{'form.inhibitmenu'});
- &startpage($request,$symb,[{href=>"", text=>"Previous Student Version"}],undef,undef,$stuvcurrent,$stuvdisp,$env{'form.inhibitmenu'},$js);
+ my $csslinks = &css_links($symb);
+ my $head_extra = $js."\n".$csslinks;
+ &startpage($request,$symb,[{href=>"", text=>"Previous Student Version"}],undef,undef,
+ $stuvcurrent,$stuvdisp,$env{'form.inhibitmenu'},$head_extra);
if ($versionform) {
$request->print($versionform);
}
$request->print(' ');
$request->print(&show_previous_task_version($request,$symb));
} elsif ($command eq 'pickStudentPage' && $perm{'vgr'}) {
- &pickStudentPage($request);
+ &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},
+ {href=>'',text=>'Select student'}],1,1);
+ &pickStudentPage($request,$symb);
} elsif ($command eq 'displayPage' && $perm{'vgr'}) {
- &displayPage($request);
+ my $csslinks = &css_links($symb,'map');
+ &startpage($request,$symb,
+ [{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},
+ {href=>'',text=>'Select student'},
+ {href=>'',text=>'Grade student'}],1,1,undef,undef,undef,$csslinks);
+ &displayPage($request,$symb);
} elsif ($command eq 'gradeByPage' && $perm{'mgr'}) {
- &updateGradeByPage($request);
+ &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'},
+ {href=>'',text=>'Select student'},
+ {href=>'',text=>'Grade student'},
+ {href=>'',text=>'Store grades'}],1,1);
+ &updateGradeByPage($request,$symb);
} elsif ($command eq 'processGroup' && $perm{'vgr'}) {
- &processGroup($request);
+ my $csslinks = &css_links($symb);
+ &startpage($request,$symb,[{href=>'',text=>'...'},
+ {href=>'',text=>'Modify grades'}],undef,undef,undef,undef,undef,$csslinks,undef,1);
+ &processGroup($request,$symb);
} elsif ($command eq 'gradingmenu' && $perm{'vgr'}) {
- $request->print(&grading_menu($request));
- } elsif ($command eq 'submit_options' && $perm{'vgr'}) {
- $request->print(&submit_options($request));
+ &startpage($request,$symb);
+ $request->print(&grading_menu($request,$symb));
+ } elsif ($command eq 'individual' && $perm{'vgr'}) {
+ &startpage($request,$symb,[{href=>'',text=>'Select individual students to grade'}]);
+ $request->print(&submit_options($request,$symb));
+ } elsif ($command eq 'ungraded' && $perm{'vgr'}) {
+ my $js = &part_selector_js();
+ my $onload = "toggleParts('gradesub');";
+ &startpage($request,$symb,[{href=>'',text=>'Grade ungraded submissions'}],
+ undef,undef,undef,undef,undef,$js,$onload);
+ $request->print(&listStudents($request,$symb,'graded'));
+ } elsif ($command eq 'table' && $perm{'vgr'}) {
+ &startpage($request,$symb,[{href=>"", text=>"Grading table"}]);
+ $request->print(&submit_options_table($request,$symb));
+ } elsif ($command eq 'all_for_one' && $perm{'vgr'}) {
+ &startpage($request,$symb,[{href=>'',text=>'Grade page/folder for one student'}],1,1);
+ $request->print(&submit_options_sequence($request,$symb));
} elsif ($command eq 'viewgrades' && $perm{'vgr'}) {
- $request->print(&viewgrades($request));
+ &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},{href=>'', text=>"Modify grades"}]);
+ $request->print(&viewgrades($request,$symb));
} elsif ($command eq 'handgrade' && $perm{'mgr'}) {
- $request->print(&processHandGrade($request));
+ &startpage($request,$symb,[{href=>'',text=>'...'},
+ {href=>'',text=>'Store grades'}]);
+ $request->print(&processHandGrade($request,$symb));
} elsif ($command eq 'editgrades' && $perm{'mgr'}) {
- $request->print(&editgrades($request));
+ &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"table"), text=>"Grading table"},
+ {href=>&href_symb_cmd($symb,'viewgrades').'&group=all§ion=all&Status=Active',
+ text=>"Modify grades"},
+ {href=>'', text=>"Store grades"}]);
+ $request->print(&editgrades($request,$symb));
+ } elsif ($command eq 'initialverifyreceipt' && $perm{'vgr'}) {
+ &startpage($request,$symb,[{href=>'',text=>'Verify Receipt Number'}]);
+ $request->print(&initialverifyreceipt($request,$symb));
} elsif ($command eq 'verify' && $perm{'vgr'}) {
- $request->print(&verifyreceipt($request));
+ &startpage($request,$symb,[{href=>&href_symb_cmd($symb,"initialverifyreceipt"),text=>'Verify Receipt Number'},
+ {href=>'',text=>'Verification Result'}]);
+ $request->print(&verifyreceipt($request,$symb));
} elsif ($command eq 'processclicker' && $perm{'mgr'}) {
- $request->print(&process_clicker($request));
+ &startpage($request,$symb,[{href=>'', text=>'Process clicker'}]);
+ $request->print(&process_clicker($request,$symb));
} elsif ($command eq 'processclickerfile' && $perm{'mgr'}) {
- $request->print(&process_clicker_file($request));
+ &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'processclicker'), text=>'Process clicker'},
+ {href=>'', text=>'Process clicker file'}]);
+ $request->print(&process_clicker_file($request,$symb));
} elsif ($command eq 'assignclickergrades' && $perm{'mgr'}) {
- $request->print(&assign_clicker_grades($request));
+ &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'processclicker'), text=>'Process clicker'},
+ {href=>'', text=>'Process clicker file'},
+ {href=>'', text=>'Store grades'}]);
+ $request->print(&assign_clicker_grades($request,$symb));
} elsif ($command eq 'csvform' && $perm{'mgr'}) {
- $request->print(&upcsvScores_form($request));
+ &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
+ $request->print(&upcsvScores_form($request,$symb));
} elsif ($command eq 'csvupload' && $perm{'mgr'}) {
- $request->print(&csvupload($request));
+ &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
+ $request->print(&csvupload($request,$symb));
} elsif ($command eq 'csvuploadmap' && $perm{'mgr'} ) {
- $request->print(&csvuploadmap($request));
+ &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
+ $request->print(&csvuploadmap($request,$symb));
} elsif ($command eq 'csvuploadoptions' && $perm{'mgr'}) {
if ($env{'form.associate'} ne 'Reverse Association') {
- $request->print(&csvuploadoptions($request));
+ &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
+ $request->print(&csvuploadoptions($request,$symb));
} else {
if ( $env{'form.upfile_associate'} ne 'reverse' ) {
$env{'form.upfile_associate'} = 'reverse';
} else {
$env{'form.upfile_associate'} = 'forward';
}
- $request->print(&csvuploadmap($request));
+ &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
+ $request->print(&csvuploadmap($request,$symb));
}
} elsif ($command eq 'csvuploadassign' && $perm{'mgr'} ) {
- $request->print(&csvuploadassign($request));
+ &startpage($request,$symb,[{href=>'', text=>'Upload Scores'}],1,1);
+ $request->print(&csvuploadassign($request,$symb));
} elsif ($command eq 'scantron_selectphase' && $perm{'mgr'}) {
- $request->print(&scantron_selectphase($request));
+ &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1,
+ undef,undef,undef,undef,'toggleScantab(document.rules);');
+ $request->print(&scantron_selectphase($request,undef,$symb));
} elsif ($command eq 'scantron_warning' && $perm{'mgr'}) {
- $request->print(&scantron_do_warning($request));
+ &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
+ $request->print(&scantron_do_warning($request,$symb));
} elsif ($command eq 'scantron_validate' && $perm{'mgr'}) {
- $request->print(&scantron_validate_file($request));
+ &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
+ $request->print(&scantron_validate_file($request,$symb));
} elsif ($command eq 'scantron_process' && $perm{'mgr'}) {
- $request->print(&scantron_process_students($request));
+ &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
+ $request->print(&scantron_process_students($request,$symb));
} elsif ($command eq 'scantronupload' &&
- (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})||
- &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) {
- $request->print(&scantron_upload_scantron_data($request));
+ (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) || $perm{'usc'})) {
+ &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1,
+ undef,undef,undef,undef,'toggleScantab(document.rules);');
+ $request->print(&scantron_upload_scantron_data($request,$symb));
} elsif ($command eq 'scantronupload_save' &&
- (&Apache::lonnet::allowed('usc',$env{'request.role.domain'})||
- &Apache::lonnet::allowed('usc',$env{'request.course.id'}))) {
- $request->print(&scantron_upload_scantron_data_save($request));
- } elsif ($command eq 'scantron_download' &&
- &Apache::lonnet::allowed('usc',$env{'request.course.id'})) {
- $request->print(&scantron_download_scantron_data($request));
+ (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) || $perm{'usc'})) {
+ &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
+ $request->print(&scantron_upload_scantron_data_save($request,$symb));
+ } elsif ($command eq 'scantron_download' && ($perm{'usc'} || $perm{'mgr'})) {
+ &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
+ $request->print(&scantron_download_scantron_data($request,$symb));
+ } elsif ($command eq 'scantronupload_delete' &&
+ (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) || $perm{'usc'})) {
+ &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
+ &scantron_upload_delete($request,$symb);
} elsif ($command eq 'checksubmissions' && $perm{'vgr'}) {
- $request->print(&checkscantron_results($request));
+ &startpage($request,$symb,[{href=>'', text=>'Grade/Manage/Review Bubblesheets'}],1,1);
+ $request->print(&checkscantron_results($request,$symb));
+ } elsif ($command eq 'downloadfilesselect' && $perm{'vgr'}) {
+ my $js = &part_selector_js();
+ my $onload = "toggleParts('gradingMenu');";
+ &startpage($request,$symb,[{href=>'', text=>'Select which submissions to download'}],
+ undef,undef,undef,undef,undef,$js,$onload);
+ $request->print(&submit_options_download($request,$symb));
+ } elsif ($command eq 'downloadfileslink' && $perm{'vgr'}) {
+ &startpage($request,$symb,
+ [{href=>&href_symb_cmd($symb,'downloadfilesselect'), text=>'Select which submissions to download'},
+ {href=>'', text=>'Download submitted files'}],
+ undef,undef,undef,undef,undef,undef,undef,1);
+ $request->print('
');
+ &submit_download_link($request,$symb);
} elsif ($command) {
+ &startpage($request,$symb,[{href=>'', text=>'Access denied'}]);
$request->print(''.&mt('Access Denied ([_1])',$command).'
');
}
}
if ($ssi_error) {
&ssi_print_error($request);
}
- $request->print(&Apache::loncommon::end_page());
+ if ($env{'form.inhibitmenu'}) {
+ $request->print(&Apache::loncommon::end_page());
+ } elsif ($env{'request.course.id'}) {
+ &Apache::lonquickgrades::endGradeScreen($request);
+ }
&reset_caches();
return OK;
}
@@ -10965,7 +11660,7 @@ described at http://www.lon-capa.org.
=head1 OVERVIEW
Do an ssi with retries:
-While I'd love to factor out this with the vesrion in lonprintout,
+While I'd love to factor out this with the version in lonprintout,
that would either require a data coupling between modules, which I refuse to perpetuate (there's quite enough of that already), or would require the invention of another infrastructure
I'm not quite ready to invent (e.g. an ssi_with_retry object).
@@ -11012,6 +11707,75 @@ ssi_with_retries()
=over
+=head1 Routines to display previous version of a Task for a specific student
+
+Tasks are graded pass/fail. Students who have yet to pass a particular Task
+can receive another opportunity. Access to tasks is slot-based. If a slot
+requires a proctor to check-in the student, a new version of the Task will
+be created when the student is checked in to the new opportunity.
+
+If a particular student has tried two or more versions of a particular task,
+the submission screen provides a user with vgr privileges (e.g., a Course
+Coordinator) the ability to display a previous version worked on by the
+student. By default, the current version is displayed. If a previous version
+has been selected for display, submission data are only shown that pertain
+to that particular version, and the interface to submit grades is not shown.
+
+=over 4
+
+=item show_previous_task_version()
+
+Displays a specified version of a student's Task, as the student sees it.
+
+Inputs: 2
+ request - request object
+ symb - unique symb for current instance of resource
+
+Output: None.
+
+Side Effects: calls &show_problem() to print version of Task, with
+ version contained in form item: $env{'form.previousversion'}
+
+=item choose_task_version_form()
+
+Displays a web form used to select which version of a student's view of a
+Task should be displayed. Either launches a pop-up window, or replaces
+content in existing pop-up, or replaces page in main window.
+
+Inputs: 4
+ symb - unique symb for current instance of resource
+ uname - username of student
+ udom - domain of student
+ nomenu - 1 if display is in a pop-up window, and hence no menu
+ breadcrumbs etc., are displayed
+
+Output: 4
+ current - student's current version
+ displayed - student's version being displayed
+ result - scalar containing HTML for web form used to switch to
+ a different version (or a link to close window, if pop-up).
+ js - javascript for processing selection in versions web form
+
+Side Effects: None.
+
+=item previous_display_javascript()
+
+Inputs: 2
+ nomenu - 1 if display is in a pop-up window, and hence no menu
+ breadcrumbs etc., are displayed.
+ current - student's current version number.
+
+Output: 1
+ js - javascript for processing selection in versions web form.
+
+Side Effects: None.
+
+=back
+
+=head1 Routines to process bubblesheet data.
+
+=over 4
+
=item scantron_get_correction() :
Builds the interface screen to interact with the operator to fix a
@@ -11021,7 +11785,7 @@ ssi_with_retries()
$r - Apache request object
$i - number of the current scanline
$scan_record - hash ref as returned from &scantron_parse_scanline()
- $scan_config - hash ref as returned from &get_scantron_config()
+ $scan_config - hash ref as returned from &Apache::lonnet::get_scantron_config()
$line - full contents of the current scanline
$error - error condition, valid values are
'incorrectCODE', 'duplicateCODE',
@@ -11048,6 +11812,7 @@ ssi_with_retries()
or code-based randompick and/or randomorder.
+
=item scantron_get_maxbubble() :
Arguments:
@@ -11107,7 +11872,12 @@ ssi_with_retries()
=item scantron_upload_scantron_data_save() :
Adds a provided bubble information data file to the course if user
- has the correct privileges to do so.
+ has the correct privileges to do so.
+
+= item scantron_upload_delete() :
+
+ Deletes a previously uploaded bubble information data file, if user
+ was the one who uploaded the file, and has the privileges to do so.
=item valid_file() :
@@ -11127,7 +11897,9 @@ ssi_with_retries()
=item navmap_errormsg() :
Returns HTML mark-up inside a
with a link to re-initialize the course.
- Should be called whenever the request to instantiate a navmap object fails.
+ Should be called whenever the request to instantiate a navmap object fails.
+
+=back
=back