--- loncom/homework/grades.pm 2009/05/06 16:19:26 1.569
+++ loncom/homework/grades.pm 2009/12/09 19:41:10 1.583
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Grading handler
#
-# $Id: grades.pm,v 1.569 2009/05/06 16:19:26 bisitz Exp $
+# $Id: grades.pm,v 1.583 2009/12/09 19:41:10 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -97,9 +97,15 @@ sub ssi_print_error {
#
# --- Retrieve the parts from the metadata file.---
sub getpartlist {
- my ($symb) = @_;
+ my ($symb,$errorref) = @_;
my $navmap = Apache::lonnavmaps::navmap->new();
+ unless (ref($navmap)) {
+ if (ref($errorref)) {
+ $$errorref = 'navmap';
+ return;
+ }
+ }
my $res = $navmap->getBySymb($symb);
my $partlist = $res->parts();
my $url = $res->src();
@@ -144,9 +150,15 @@ sub nameUserString {
#--- Get the partlist and the response type for a given problem. ---
#--- Indicate if a response type is coded handgraded or not. ---
sub response_type {
- my ($symb) = shift;
+ my ($symb,$response_error) = @_;
my $navmap = Apache::lonnavmaps::navmap->new();
+ unless (ref($navmap)) {
+ if (ref($response_error)) {
+ $$response_error = 1;
+ }
+ return;
+ }
my $res = $navmap->getBySymb($symb);
my $partlist = $res->parts();
my %vPart =
@@ -183,7 +195,8 @@ sub get_display_part {
my ($partID,$symb)=@_;
my $display=&Apache::lonnet::EXT('resource.'.$partID.'.display',$symb);
if (defined($display) and $display ne '') {
- $display.= " (id $partID )";
+ $display.= ' ('
+ .&mt('Part ID: [_1]',$partID).' )';
} else {
$display=$partID;
}
@@ -193,12 +206,17 @@ sub get_display_part {
#--- Show resource title
#--- and parts and response type
sub showResourceInfo {
- my ($symb,$probTitle,$checkboxes) = @_;
+ my ($symb,$probTitle,$checkboxes,$res_error) = @_;
my $col=3;
if ($checkboxes) { $col=4; }
my $result = '
'.&mt('Current Resource').': '.$probTitle.' '."\n";
+ my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error);
+ if (ref($res_error)) {
+ if ($$res_error) {
+ return;
+ }
+ }
$result .='';
- my ($partlist,$handgrade,$responseType) = &response_type($symb);
my %resptype = ();
my $hdgrade='no';
my %partsseen;
@@ -217,9 +235,9 @@ sub showResourceInfo {
$partsseen{$partID}=1;
}
my $display_part=&get_display_part($partID,$symb);
- $result.=''.&mt('Part').': '.$display_part.
+ $result.=''.&mt('Part: [_1]',$display_part).' '.
' '.$resID.' '.
- ''.&mt('Type').': '.$responsetype.' ';
+ ''.&mt('Type: [_1]',$responsetype).' ';
# ''.&mt('Handgrade: [_1]',$handgrade).' ';
}
}
@@ -766,7 +784,13 @@ sub verifyreceipt {
if ($env{"course.$courseid.receiptalg"} eq 'receipt2' ||
$env{"course.$courseid.receiptalg"} eq 'receipt3') { $receiptparts=1; }
my $parts=['0'];
- if ($receiptparts) { ($parts)=&response_type($symb); }
+ if ($receiptparts) {
+ my $res_error;
+ ($parts)=&response_type($symb,\$res_error);
+ if ($res_error) {
+ return &navmap_errormsg();
+ }
+ }
my $header =
&Apache::loncommon::start_data_table().
@@ -1734,8 +1758,7 @@ sub gradeBox {
#&mt('Part: [_1] Points: [_2] or [_3] ',$display_part,$radio,$line);
$result .=
- ''.&mt('Part').': '.$display_part.' '.&mt('Points').': '.$radio.' '.&mt('or').' '.$line.' '.
-
+ ''.&mt('Part:').' '.$display_part.' '.&mt('Points:').' '.$radio.' '.&mt('or').' '.$line.' ';
$result.='
'."\n";
$result.=' '."\n".
' '."\n".
@@ -1745,13 +1768,17 @@ sub gradeBox {
$$record{'resource.'.$partid.'.tries'}.'" />'."\n".
' '."\n";
- $result.=&handback_box($symb,$uname,$udom,$counter,$partid,$record);
+ my $res_error;
+ $result.=&handback_box($symb,$uname,$udom,$counter,$partid,$record,\$res_error);
+ if ($res_error) {
+ return &navmap_errormsg();
+ }
return $result;
}
sub handback_box {
- my ($symb,$uname,$udom,$counter,$partid,$record) = @_;
- my ($partlist,$handgrade,$responseType) = &response_type($symb);
+ my ($symb,$uname,$udom,$counter,$partid,$record,$res_error) = @_;
+ my ($partlist,$handgrade,$responseType) = &response_type($symb,$res_error);
my (@respids);
my @part_response_id = &flatten_responseType($responseType);
foreach my $part_response_id (@part_response_id) {
@@ -2046,7 +2073,12 @@ KEYWORDS
}
my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname);
- my ($partlist,$handgrade,$responseType) = &response_type($symb);
+ my $res_error;
+ my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error);
+ if ($res_error) {
+ $request->print(&navmap_errormsg());
+ return;
+ }
# Display student info
$request->print(($counter == 0 ? '' : ' '));
@@ -2113,9 +2145,11 @@ KEYWORDS
}
my $responsetype = $responseType->{$partid}->{$respid};
if (!exists($record{"resource.$partid.$respid.submission"})) {
- $lastsubonly.="\n".'Part: '.
- $display_part.'
( ID '.$respid.
- ' ) '.
+ $lastsubonly.="\n".'
'.
+ ''.&mt('Part: [_1]',$display_part).' '.
+ ' '.
+ '('.&mt('Part ID: [_1]',$respid).')'.
+ ' '.
''.&mt('Nothing submitted - no attempts.').'
';
next;
}
@@ -2135,10 +2169,9 @@ KEYWORDS
{'one_time' => 1});
$similar="
".
- &mt('Essay is [_1]% similar to an essay by [_2] ([_3]:[_4]) in course [_5] (course id [_6]:[_7])',
+ &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',
$osim,
- &Apache::loncommon::plainname($oname,$odom),
- $oname,$odom,
+ &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',
$old_course_desc{'description'},
$old_course_desc{'num'},
$old_course_desc{'domain'}).
@@ -2152,9 +2185,11 @@ KEYWORDS
($env{'form.lastSub'} eq 'hdgrade' &&
$$handgrade{$$part[0].'_'.$$part[1]} eq 'yes')) {
my $display_part=&get_display_part($partid,$symb);
- $lastsubonly.='Part: '.
- $display_part.'
( ID '.$respid.
- ' ) ';
+ $lastsubonly.='
'.
+ '
'.&mt('Part: [_1]',$display_part).' '.
+ '
'.
+ '('.&mt('Part ID: [_1]',$respid).')'.
+ ' ';
my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record);
if (@$files) {
$lastsubonly.='
'.&mt('Like all files provided by users, this file may contain viruses').' ';
@@ -2297,7 +2332,7 @@ KEYWORDS
'
7 10 '."\n";
my $nsel = ($env{'form.NTSTU'} ne '' ? $env{'form.NTSTU'} : '1');
$ntstu =~ s/
$nsel $nsel;
- $endform.=&mt('[quant,_1,student]',$ntstu);
+ $endform.=&mt('[_1]student(s)',$ntstu);
$endform.=' '."\n".
' print(' '.&mt('Sending message to [_1]:[_2]',$uname,$udom).': '.
+ $request->print(' '.&mt('Sending message to [_1]',$uname.':'.$udom).': '.
$msgstatus);
}
if ($env{'form.collaborator'.$ctr}) {
@@ -2594,7 +2629,12 @@ sub processHandGrade {
}
$ctr = 0;
@parsedlist = reverse @parsedlist if ($button eq 'Previous');
- my ($partlist) = &response_type($symb);
+ 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);
@@ -2792,8 +2832,12 @@ sub check_and_remove_from_queue {
sub handback_files {
my ($request,$symb,$stuname,$domain,$newflg,$new_part,$newrecord) = @_;
my $portfolio_root = '/userfiles/portfolio';
- my ($partlist,$handgrade,$responseType) = &response_type($symb);
-
+ my $res_error;
+ my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error);
+ if ($res_error) {
+ $request->print(' '.&navmap_errormsg().' ');
+ return;
+ }
my @part_response_id = &flatten_responseType($responseType);
foreach my $part_response_id (@part_response_id) {
my ($part_id,$resp_id) = @{ $part_response_id };
@@ -3251,7 +3295,11 @@ sub viewgrades {
$result.= ''.$common_header.' '.&Apache::loncommon::start_data_table();
#radio buttons/text box for assigning points for a section or class.
#handles different parts of a problem
- my ($partlist,$handgrade,$responseType) = &response_type($symb);
+ my $res_error;
+ my ($partlist,$handgrade,$responseType) = &response_type($symb,\$res_error);
+ if ($res_error) {
+ return &navmap_errormsg();
+ }
my %weight = ();
my $ctsparts = 0;
my %seen = ();
@@ -3295,7 +3343,7 @@ sub viewgrades {
$result.=
&Apache::loncommon::start_data_table_row()."\n".
- ''.&mt('Part').': '.$display_part.' '.&mt('Points').': '.$radio.' '.&mt('or').' '.$line.' '.
+ ''.&mt('Part:').' '.$display_part.' '.&mt('Points:').' '.$radio.' '.&mt('or').' '.$line.' '.
&Apache::loncommon::end_data_table_row()."\n";
$ctsparts++;
}
@@ -3311,7 +3359,11 @@ sub viewgrades {
&Apache::loncommon::start_data_table_header_row().
''.&mt('No.').' '.
''.&nameUserString('header')." \n";
- my (@parts) = sort(&getpartlist($symb));
+ my $partserror;
+ my (@parts) = sort(&getpartlist($symb,\$partserror));
+ if ($partserror) {
+ return &navmap_errormsg();
+ }
my (undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
my @partids = ();
foreach my $part (@parts) {
@@ -3470,7 +3522,11 @@ sub editgrades {
my %columns = ();
my ($i,$ctr,$count,$rec_update) = (0,0,0,0);
- my (@parts) = sort(&getpartlist($symb));
+ my $partserror;
+ my (@parts) = sort(&getpartlist($symb,\$partserror));
+ if ($partserror) {
+ return &navmap_errormsg();
+ }
my $header;
while ($ctr < $env{'form.totalparts'}) {
my $partid = $env{'form.partid_'.$ctr};
@@ -3681,7 +3737,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 ID');
+ my $error1=&mt('You need to specify the username or the student/employee ID');
my $error2=&mt('You need to specify at least one grading field');
return(<print(&navmap_errormsg());
+ return;
+ }
if ($env{'form.upfile_associate'} eq 'reverse') {
&Apache::loncommon::csv_print_samples($request,\@records);
$i=&Apache::loncommon::csv_print_select_table($request,\@records,
@@ -4090,14 +4156,14 @@ sub csvuploadassign {
$countdone++;
}
}
- $request->print(''.&mt("Saved [_1] students",$countdone)." \n");
+ $request->print(' '.&Apache::lonhtmlcommon::confirm_success(&mt("Saved scores for [quant,_1,student]",$countdone),$countdone==0));
if (@skipped) {
- $request->print(''.&mt('Skipped Students').'
');
- foreach my $student (@skipped) { $request->print("$student \n"); }
+ $request->print(' '.&Apache::lonhtmlcommon::confirm_success(&mt('No scores stored for the following username(s):'),1).' ');
+ $request->print(join(', ',@skipped));
}
if (@notallowed) {
- $request->print(''.&mt('Students Not Allowed to Modify').'
');
- foreach my $student (@notallowed) { $request->print("$student \n"); }
+ $request->print(' '.&Apache::lonhtmlcommon::confirm_success(&mt('Modification of scores not allowed for the following username(s):'),1).' ');
+ $request->print(join(', ',@notallowed));
}
$request->print(" \n");
$request->print(&show_grading_menu_form($symb));
@@ -4140,7 +4206,12 @@ LISTJAVASCRIPT
&mt('Manual Grading by Page or Sequence').'';
$result.='
');
@@ -5178,7 +5279,7 @@ sub scantron_selectphase {
&Apache::loncommon::start_data_table('LC_scantron_action')."\n".
&Apache::loncommon::start_data_table_header_row()."\n".
'
- '.&mt('Review scantron data and submissions for a previously graded folder/sequence')."\n".
+ '.&mt('Review bubblesheet data and submissions for a previously graded folder/sequence')."\n".
' '."\n".
&Apache::loncommon::end_data_table_header_row()."\n".
&Apache::loncommon::start_data_table_row()."\n".
@@ -5200,7 +5301,7 @@ sub scantron_selectphase {
&Apache::loncommon::start_data_table_row()."\n".
''."\n".
' '."\n".
- ' '."\n".
+ ' '."\n".
' '."\n".
&Apache::loncommon::end_data_table_row()."\n".
&Apache::loncommon::end_data_table()."\n".
@@ -5241,7 +5342,7 @@ sub scantron_selectphase {
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 number starts
+ 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
@@ -5341,7 +5442,7 @@ sub username_to_idmap {
$whichline - line number of the passed in scanline
$field - type of change to process
(either
- 'ID' -> correct the student/employee ID number
+ 'ID' -> correct the student/employee ID
'CODE' -> correct the CODE
'answer' -> fixup the submitted answers)
@@ -6215,7 +6316,12 @@ sub scantron_validate_file {
$r->print(''.&mt('Gathering necessary information.').'
');$r->rflush();
#get the student pick code ready
$r->print(&Apache::loncommon::studentbrowser_javascript());
- my $max_bubble=&scantron_get_maxbubble();
+ my $nav_error;
+ my $max_bubble=&scantron_get_maxbubble(\$nav_error);
+ if ($nav_error) {
+ $r->print(&navmap_errormsg());
+ return '';
+ }
my $result=&scantron_form_start($max_bubble).$default_form_data;
$r->print($result);
@@ -6251,7 +6357,7 @@ sub scantron_validate_file {
' '.&mt('No').
' '.
&mt('Grading will take longer if you use verification.').' '.
- &mt("Alternatively, the 'Review scantron data' utility (see grading menu) can be used for all students after grading is complete.").' '.
+ &mt("Alternatively, the 'Review bubblesheet data' utility (see grading menu) can be used for all students after grading is complete.").' '.
' '.
' '."\n");
} else {
@@ -6627,6 +6733,10 @@ sub scantron_validate_sequence {
my ($r,$currentphase) = @_;
my $navmap=Apache::lonnavmaps::navmap->new();
+ unless (ref($navmap)) {
+ $r->print(&navmap_errormsg());
+ return (1,$currentphase);
+ }
my (undef,undef,$sequence)=
&Apache::lonnet::decode_symb($env{'form.selectpage'});
@@ -6658,8 +6768,13 @@ sub scantron_validate_ID {
#get scantron line setup
my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
my ($scanlines,$scan_data)=&scantron_getfile();
-
- &scantron_get_maxbubble(); # parse needs the bubble_lines.. array.
+
+ my $nav_error;
+ &scantron_get_maxbubble(\$nav_error); # parse needs the bubble_lines.. array.
+ if ($nav_error) {
+ $r->print(&navmap_errormsg());
+ return(1,$currentphase);
+ }
my %found=('ids'=>{},'usernames'=>{});
for (my $i=0;$i<=$scanlines->{'count'};$i++) {
@@ -7018,7 +7133,7 @@ sub prompt_for_corrections {
($responsetype_per_response{$question-1} eq 'imageresponse') ||
($responsetype_per_response{$question-1} eq 'reactionresponse') ||
($responsetype_per_response{$question-1} eq 'organicresponse')) {
- $r->print(&mt("Although this particular question type requires handgrading, the instructions for this question in the exam directed students to leave [quant,_1,line] blank on their scantron sheets.",$lines).' '.&mt('A non-zero score can be assigned to the student during scantron 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 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. ")." ");
}
@@ -7212,7 +7327,12 @@ sub scantron_validate_CODE {
my %allcodes=&get_codes();
- &scantron_get_maxbubble(); # parse needs the lines per response array.
+ my $nav_error;
+ &scantron_get_maxbubble(\$nav_error); # parse needs the lines per response array.
+ if ($nav_error) {
+ $r->print(&navmap_errormsg());
+ return(1,$currentphase);
+ }
my ($scanlines,$scan_data)=&scantron_getfile();
for (my $i=0;$i<=$scanlines->{'count'};$i++) {
@@ -7266,7 +7386,12 @@ sub scantron_validate_doublebubble {
#get scantron line setup
my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
my ($scanlines,$scan_data)=&scantron_getfile();
- &scantron_get_maxbubble(); # parse needs the bubble line array.
+ my $nav_error;
+ &scantron_get_maxbubble(\$nav_error); # parse needs the bubble line array.
+ if ($nav_error) {
+ $r->print(&navmap_errormsg());
+ return(1,$currentphase);
+ }
for (my $i=0;$i<=$scanlines->{'count'};$i++) {
my $line=&scantron_get_line($scanlines,$scan_data,$i);
@@ -7284,6 +7409,7 @@ sub scantron_validate_doublebubble {
sub scantron_get_maxbubble {
+ my ($nav_error) = @_;
if (defined($env{'form.scantron_maxbubble'}) &&
$env{'form.scantron_maxbubble'}) {
&restore_bubble_lines();
@@ -7294,6 +7420,11 @@ sub scantron_get_maxbubble {
&Apache::lonnet::decode_symb($env{'form.selectpage'});
my $navmap=Apache::lonnavmaps::navmap->new();
+ unless (ref($navmap)) {
+ if (ref($nav_error)) {
+ $$nav_error = 1;
+ }
+ }
my $map=$navmap->getResourceByUrl($sequence);
my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
@@ -7383,7 +7514,11 @@ sub scantron_validate_missingbubbles {
#get scantron line setup
my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
my ($scanlines,$scan_data)=&scantron_getfile();
- my $max_bubble=&scantron_get_maxbubble();
+ my $nav_error;
+ my $max_bubble=&scantron_get_maxbubble(\$nav_error);
+ if ($nav_error) {
+ return(1,$currentphase);
+ }
if (!$max_bubble) { $max_bubble=2**31; }
for (my $i=0;$i<=$scanlines->{'count'};$i++) {
my $line=&scantron_get_line($scanlines,$scan_data,$i);
@@ -7443,6 +7578,10 @@ sub scantron_process_students {
my $classlist=&Apache::loncoursedata::get_classlist();
my %idmap=&username_to_idmap($classlist);
my $navmap=Apache::lonnavmaps::navmap->new();
+ unless (ref($navmap)) {
+ $r->print(&navmap_errormsg());
+ return '';
+ }
my $map=$navmap->getResourceByUrl($sequence);
my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
my (%grader_partids_by_symb,%grader_randomlists_by_symb);
@@ -7475,8 +7614,8 @@ SCANTRONFORM
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,'Scantron Status',
- 'Scantron Progress',$count,
+ my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Bubblesheet Status',
+ 'Bubblesheet Progress',$count,
'inline',undef,'scantronupload');
&Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,
'Processing first student');
@@ -7485,7 +7624,12 @@ SCANTRONFORM
my $i=-1;
my $started;
- &scantron_get_maxbubble(); # Need the bubble lines array to parse.
+ my $nav_error;
+ &scantron_get_maxbubble(\$nav_error); # Need the bubble lines array to parse.
+ if ($nav_error) {
+ $r->print(&navmap_errormsg());
+ return '';
+ }
# If an ssi failed in scantron_get_maxbubble, put an error message out to
# the user and return.
@@ -7710,15 +7854,17 @@ sub scantron_upload_scantron_data {
my $syllabuslink = ''.&mt('Syllabus').' '.
(' 'x2).&mt('(shows course personnel)');
my $default_form_data=&defaultFormData(&get_symb($r,1));
+ my $nofile_alert = &mt('Please use the browse button to select a file from your local directory.');
+ 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.");
$r->print('