[LON-CAPA-cvs] cvs: loncom /homework grades.pm matchresponse.pm optionresponse.pm radiobuttonresponse.pm rankresponse.pm response.pm /interface lonprintout.pm
raeburn
raeburn at source.lon-capa.org
Tue Sep 13 17:43:03 EDT 2011
raeburn Tue Sep 13 21:43:03 2011 EDT
Modified files:
/loncom/homework grades.pm radiobuttonresponse.pm rankresponse.pm
optionresponse.pm matchresponse.pm response.pm
/loncom/interface lonprintout.pm
Log:
- Additional (eighteenth field) BubblesPerRow in Bubblesheet Format file.
- specify bubbles available for each question row (default is 10).
- Support case where question (or subquestion for optionresponse,
matchresponse, or rankresponse) requires more bubbles than in one line.
- Students prompted to bubble once in multiple lines.
- Numbering recognizes multiple lines per question.
- Also supports: imageresponse, stringresponse, formularesponse where
students leave link(s) blank if weight assigned is greater than
bubbles per line -- multiple lines also supported in this case.
For example:
- 15-bubble MSU Art History exams now supported on standard 10-bubble
bubblesheets used at MSU.
-------------- next part --------------
Index: loncom/homework/grades.pm
diff -u loncom/homework/grades.pm:1.648 loncom/homework/grades.pm:1.649
--- loncom/homework/grades.pm:1.648 Fri May 27 14:39:50 2011
+++ loncom/homework/grades.pm Tue Sep 13 21:42:58 2011
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Grading handler
#
-# $Id: grades.pm,v 1.648 2011/05/27 14:39:50 bisitz Exp $
+# $Id: grades.pm,v 1.649 2011/09/13 21:42:58 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -213,7 +213,7 @@
}
sub get_analyze {
- my ($symb,$uname,$udom,$no_increment,$add_to_hash,$type,$trial,$rndseed)=@_;
+ my ($symb,$uname,$udom,$no_increment,$add_to_hash,$type,$trial,$rndseed,$bubbles_per_row)=@_;
my $key = "$symb\0$uname\0$udom";
if ($type eq 'randomizetry') {
if ($trial ne '') {
@@ -247,6 +247,9 @@
'grade_courseid' => $env{'request.course.id'},
'grade_username' => $uname,
'grade_noincrement' => $no_increment);
+ if ($bubbles_per_row ne '') {
+ $form{'bubbles_per_row'} = $bubbles_per_row;
+ }
if ($type eq 'randomizetry') {
$form{'grade_questiontype'} = $type;
if ($rndseed ne '') {
@@ -287,7 +290,7 @@
}
sub scantron_partids_tograde {
- my ($resource,$cid,$uname,$udom,$check_for_randomlist) = @_;
+ my ($resource,$cid,$uname,$udom,$check_for_randomlist,$bubbles_per_row) = @_;
my (%analysis, at parts);
if (ref($resource)) {
my $symb = $resource->symb();
@@ -295,7 +298,9 @@
if ($check_for_randomlist) {
$add_to_form = { 'check_parts_withrandomlist' => 1,};
}
- my $analyze = &get_analyze($symb,$uname,$udom,undef,$add_to_form);
+ my $analyze =
+ &get_analyze($symb,$uname,$udom,undef,$add_to_form,
+ undef,undef,undef,$bubbles_per_row);
if (ref($analyze) eq 'HASH') {
%analysis = %{$analyze};
}
@@ -5350,7 +5355,8 @@
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 {
@@ -5380,6 +5386,7 @@
$config{'FirstNamelength'}=$config[14];
$config{'LastName'}=$config[15];
$config{'LastNamelength'}=$config[16];
+ $config{'BubblesPerRow'}=$config[17];
last;
}
return %config;
@@ -6301,7 +6308,8 @@
#get the student pick code ready
$r->print(&Apache::loncommon::studentbrowser_javascript());
my $nav_error;
- my $max_bubble=&scantron_get_maxbubble(\$nav_error);
+ my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
+ my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config);
if ($nav_error) {
$r->print(&navmap_errormsg());
return '';
@@ -6754,7 +6762,7 @@
my ($scanlines,$scan_data)=&scantron_getfile();
my $nav_error;
- &scantron_get_maxbubble(\$nav_error); # parse needs the bubble_lines.. array.
+ &scantron_get_maxbubble(\$nav_error,\%scantron_config); # parse needs the bubble_lines.. array.
if ($nav_error) {
$r->print(&navmap_errormsg());
return(1,$currentphase);
@@ -7153,7 +7161,19 @@
my $max=$$scan_config{'Qlength'};
my $scmode=$$scan_config{'Qon'};
- if ($scmode eq 'number' || $scmode eq 'letter') { $max=10; }
+ if ($scmode eq 'number' || $scmode eq 'letter') {
+ if (($$scan_config{'BubblesPerRow'} =~ /^\d+$/) &&
+ ($$scan_config{'BubblesPerRow'} > 0)) {
+ $max=$$scan_config{'BubblesPerRow'};
+ if (($scmode eq 'number') && ($max > 10)) {
+ $max = 10;
+ } elsif (($scmode eq 'letter') && $max > 26) {
+ $max = 26;
+ }
+ } else {
+ $max = 10;
+ }
+ }
my @alphabet=('A'..'Z');
$r->print(&Apache::loncommon::start_data_table().
@@ -7308,7 +7328,7 @@
my %allcodes=&get_codes();
my $nav_error;
- &scantron_get_maxbubble(\$nav_error); # parse needs the lines per response array.
+ &scantron_get_maxbubble(\$nav_error,\%scantron_config); # parse needs the lines per response array.
if ($nav_error) {
$r->print(&navmap_errormsg());
return(1,$currentphase);
@@ -7367,7 +7387,7 @@
my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
my ($scanlines,$scan_data)=&scantron_getfile();
my $nav_error;
- &scantron_get_maxbubble(\$nav_error); # parse needs the bubble line array.
+ &scantron_get_maxbubble(\$nav_error,\%scantron_config); # parse needs the bubble line array.
if ($nav_error) {
$r->print(&navmap_errormsg());
return(1,$currentphase);
@@ -7389,7 +7409,7 @@
sub scantron_get_maxbubble {
- my ($nav_error) = @_;
+ my ($nav_error,$scantron_config) = @_;
if (defined($env{'form.scantron_maxbubble'}) &&
$env{'form.scantron_maxbubble'}) {
&restore_bubble_lines();
@@ -7408,6 +7428,7 @@
}
my $map=$navmap->getResourceByUrl($sequence);
my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
+ my $bubbles_per_row = &bubblesheet_bubbles_per_row($scantron_config);
&Apache::lonxml::clear_problem_counter();
@@ -7423,7 +7444,7 @@
my $response_number = 0;
my $bubble_line = 0;
foreach my $resource (@resources) {
- my ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname,$udom);
+ my ($analysis,$parts) = &scantron_partids_tograde($resource,$cid,$uname,$udom,undef,$bubbles_per_row);
if ((ref($analysis) eq 'HASH') && (ref($parts) eq 'ARRAY')) {
foreach my $part_id (@{$parts}) {
my $lines;
@@ -7452,9 +7473,10 @@
if (ref($analysis->{$part_id.'.shown'}) eq 'ARRAY') {
$numshown = scalar(@{$analysis->{$part_id.'.shown'}});
}
- my $bubbles_per_line = 10;
- my $inner_bubble_lines = int($numbub/$bubbles_per_line);
- if (($numbub % $bubbles_per_line) != 0) {
+ my $bubbles_per_row =
+ &bubblesheet_bubbles_per_row($scantron_config);
+ my $inner_bubble_lines = int($numbub/$bubbles_per_row);
+ if (($numbub % $bubbles_per_row) != 0) {
$inner_bubble_lines++;
}
for (my $i=0; $i<$numshown; $i++) {
@@ -7465,7 +7487,7 @@
$lines = $numshown * $inner_bubble_lines;
} else {
$lines = $analysis->{"$part_id.bubble_lines"};
- }
+ }
$first_bubble_line{$response_number} = $bubble_line;
$bubble_lines_per_response{$response_number} = $lines;
@@ -7486,6 +7508,18 @@
return $env{'form.scantron_maxbubble'};
}
+sub bubblesheet_bubbles_per_row {
+ my ($scantron_config) = @_;
+ my $bubbles_per_row;
+ if (ref($scantron_config) eq 'HASH') {
+ $bubbles_per_row = $scantron_config->{'BubblesPerRow'};
+ }
+ if ((!$bubbles_per_row) || ($bubbles_per_row < 1)) {
+ $bubbles_per_row = 10;
+ }
+ return $bubbles_per_row;
+}
+
sub scantron_validate_missingbubbles {
my ($r,$currentphase) = @_;
#get student info
@@ -7496,7 +7530,7 @@
my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
my ($scanlines,$scan_data)=&scantron_getfile();
my $nav_error;
- my $max_bubble=&scantron_get_maxbubble(\$nav_error);
+ my $max_bubble=&scantron_get_maxbubble(\$nav_error,\%scantron_config);
if ($nav_error) {
return(1,$currentphase);
}
@@ -7554,6 +7588,8 @@
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 ($scanlines,$scan_data)=&scantron_getfile();
my $classlist=&Apache::loncoursedata::get_classlist();
my %idmap=&username_to_idmap($classlist);
@@ -7566,7 +7602,7 @@
my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0);
my (%grader_partids_by_symb,%grader_randomlists_by_symb);
&graders_resources_pass(\@resources,\%grader_partids_by_symb,
- \%grader_randomlists_by_symb);
+ \%grader_randomlists_by_symb,$bubbles_per_row);
my $resource_error;
foreach my $resource (@resources) {
my $ressymb;
@@ -7578,7 +7614,7 @@
}
my ($analysis,$parts) =
&scantron_partids_tograde($resource,$env{'request.course.id'},
- $env{'user.name'},$env{'user.domain'},1);
+ $env{'user.name'},$env{'user.domain'},1,$bubbles_per_row);
$grader_partids_by_symb{$ressymb} = $parts;
if (ref($analysis) eq 'HASH') {
if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') {
@@ -7616,7 +7652,7 @@
my $started;
my $nav_error;
- &scantron_get_maxbubble(\$nav_error); # Need the bubble lines array to parse.
+ &scantron_get_maxbubble(\$nav_error,\%scantron_config); # Need the bubble lines array to parse.
if ($nav_error) {
$r->print(&navmap_errormsg());
return '';
@@ -7672,7 +7708,7 @@
if ((exists($grader_randomlists_by_symb{$ressymb})) ||
(ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {
my ($analysis,$parts) =
- &scantron_partids_tograde($resource,$env{'request.course.id'},$uname,$udom);
+ &scantron_partids_tograde($resource,$env{'request.course.id'},$uname,$udom,undef,$bubbles_per_row);
$partids_by_symb{$ressymb} = $parts;
} else {
$partids_by_symb{$ressymb} = $grader_partids_by_symb{$ressymb};
@@ -7701,7 +7737,8 @@
}
if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,
- \@resources,\%partids_by_symb) eq 'ssi_error') {
+ \@resources,\%partids_by_symb,
+ $bubbles_per_row) eq 'ssi_error') {
$ssi_error = 0; # So end of handler error message does not trigger.
$r->print("</form>");
&ssi_print_error($r);
@@ -7728,7 +7765,8 @@
if ($studentrecord ne $studentdata) {
&Apache::lonxml::clear_problem_counter();
if (&grade_student_bubbles($r,$uname,$udom,$scan_record,$scancode,
- \@resources,\%partids_by_symb) eq 'ssi_error') {
+ \@resources,\%partids_by_symb,
+ $bubbles_per_row) eq 'ssi_error') {
$ssi_error = 0; # So end of handler error message does not trigger.
$r->print("</form>");
&ssi_print_error($r);
@@ -7791,14 +7829,15 @@
}
sub graders_resources_pass {
- my ($resources,$grader_partids_by_symb,$grader_randomlists_by_symb) = @_;
+ my ($resources,$grader_partids_by_symb,$grader_randomlists_by_symb,
+ $bubbles_per_row) = @_;
if ((ref($resources) eq 'ARRAY') && (ref($grader_partids_by_symb)) &&
(ref($grader_randomlists_by_symb) eq 'HASH')) {
foreach my $resource (@{$resources}) {
my $ressymb = $resource->symb();
my ($analysis,$parts) =
&scantron_partids_tograde($resource,$env{'request.course.id'},
- $env{'user.name'},$env{'user.domain'},1);
+ $env{'user.name'},$env{'user.domain'},1,$bubbles_per_row);
$grader_partids_by_symb->{$ressymb} = $parts;
if (ref($analysis) eq 'HASH') {
if (ref($analysis->{'parts_withrandomlist'}) eq 'ARRAY') {
@@ -7812,7 +7851,8 @@
}
sub grade_student_bubbles {
- my ($r,$uname,$udom,$scan_record,$scancode,$resources,$parts) = @_;
+ my ($r,$uname,$udom,$scan_record,$scancode,$resources,$parts,$bubbles_per_row) = @_;
+# Walk folder as student here to get resources in order student sees.
if (ref($resources) eq 'ARRAY') {
my $count = 0;
foreach my $resource (@{$resources}) {
@@ -7825,6 +7865,9 @@
'grade_symb' => $ressymb,
'CODE' => $scancode
);
+ if ($bubbles_per_row ne '') {
+ $form{'bubbles_per_row'} = $bubbles_per_row;
+ }
if (ref($parts) eq 'HASH') {
if (ref($parts->{$ressymb}) eq 'ARRAY') {
foreach my $part (@{$parts->{$ressymb}}) {
@@ -8100,6 +8143,7 @@
my %record;
my %scantron_config =
&Apache::grades::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 $classlist=&Apache::loncoursedata::get_classlist();
my %idmap=&Apache::grades::username_to_idmap($classlist);
@@ -8127,7 +8171,7 @@
'inline',undef,'checkscantron');
my ($username,$domain,$started);
my $nav_error;
- &scantron_get_maxbubble(\$nav_error); # Need the bubble lines array to parse.
+ &scantron_get_maxbubble(\$nav_error,\%scantron_config); # Need the bubble lines array to parse.
if ($nav_error) {
$r->print(&navmap_errormsg());
return '';
@@ -8177,7 +8221,7 @@
if ((exists($grader_randomlists_by_symb{$ressymb})) ||
(ref($grader_partids_by_symb{$ressymb}) ne 'ARRAY')) {
(my $analysis,$parts) =
- &scantron_partids_tograde($resource,$env{'request.course.id'},$username,$domain);
+ &scantron_partids_tograde($resource,$env{'request.course.id'},$username,$domain,undef,$bubbles_per_row);
} else {
$parts = $grader_partids_by_symb{$ressymb};
}
@@ -9517,6 +9561,8 @@
calling routine should trap the error condition and display the warning
found in &navmap_errormsg().
+ $scantron_config - Reference to bubblesheet format configuration hash.
+
Returns the maximum number of bubble lines that are expected to
occur. Does this by walking the selected sequence rendering the
resource and then checking &Apache::lonxml::get_problem_counter()
Index: loncom/homework/radiobuttonresponse.pm
diff -u loncom/homework/radiobuttonresponse.pm:1.150 loncom/homework/radiobuttonresponse.pm:1.151
--- loncom/homework/radiobuttonresponse.pm:1.150 Fri Aug 26 22:40:17 2011
+++ loncom/homework/radiobuttonresponse.pm Tue Sep 13 21:42:58 2011
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# mutliple choice style responses
#
-# $Id: radiobuttonresponse.pm,v 1.150 2011/08/26 22:40:17 raeburn Exp $
+# $Id: radiobuttonresponse.pm,v 1.151 2011/09/13 21:42:58 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -138,14 +138,10 @@
%Apache::response::foilgroup=();
sub start_foilgroup {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
- my $result;
%Apache::response::foilgroup=();
$Apache::radiobuttonresponse::conceptgroup=0;
&Apache::response::pushrandomnumber(undef,$target);
- if ($target eq 'tex' && $Apache::lonhomework::type eq 'exam') {
- $result.='\item[\textbf{'.$Apache::lonxml::counter.'}.]';
- }
- return $result;
+ return;
}
sub storesurvey {
@@ -222,15 +218,10 @@
my $result;
my $bubble_lines;
- my $bubbles_per_line;
my $answer_count;
my $id = $Apache::inputtags::response['-1'];
my $part = $Apache::inputtags::part;
- $bubbles_per_line =
- &Apache::response::get_response_param($Apache::inputtags::part."_$id",
- 'numbubbles',
- $default_bubbles_per_line);
-
+ my $bubbles_per_line = &getbubblesnum($part,$id);
if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' ||
$target eq 'tex' || $target eq 'analyze') {
@@ -260,7 +251,7 @@
$answer_count = scalar(@shown);
if ($target eq 'web' || $target eq 'tex') {
- $result=&displayfoils($target,
+ $result=&displayfoils($target,
$answer, \@shown,
$direction,
$bubbles_per_line);
@@ -295,6 +286,20 @@
return $result;
}
+sub getbubblesnum {
+ my ($part,$id) = @_;
+ my $bubbles_per_line;
+ my $default_numbubbles = $default_bubbles_per_line;
+ if (($env{'form.bubbles_per_row'} =~ /^\d+$/) &&
+ ($env{'form.bubbles_per_row'} > 0)) {
+ $default_numbubbles = $env{'form.bubbles_per_row'};
+ }
+ $bubbles_per_line =
+ &Apache::response::get_response_param($part."_$id",'numbubbles',
+ $default_numbubbles);
+ return $bubbles_per_line;
+}
+
sub getfoilcounts {
my @names;
my $truecnt=0;
@@ -648,6 +653,30 @@
if ($target ne 'tex' && $direction eq 'horizontal') {
$result.="<table><tr>";
}
+ my $numlines;
+ if (($target eq 'tex') && ($Apache::lonhomework::type eq 'exam')) {
+ my $numitems = scalar(@{ $whichfoils });
+ $numlines = int($numitems/$bubbles_per_line);
+ if (($numitems % $bubbles_per_line) != 0) {
+ $numlines ++;
+ }
+ if ($numlines < 1) {
+ $numlines = 1;
+ }
+ if ($numlines > 1) {
+ my $linetext;
+ for (my $i=0; $i<$numlines; $i++) {
+ $linetext .= $Apache::lonxml::counter+$i.', ';
+ }
+ $linetext =~ s/,\s$//;
+ $result .= '\item[\small {\textbf{'.$linetext.'}}]'.
+ ' {\footnotesize '.
+ &mt('(Bubble once in [_1] lines)',$numlines).
+ '} \hspace*{\fill} \\\\';
+ } else {
+ $result .= '\item[\textbf{'.$Apache::lonxml::counter.'}.]';
+ }
+ }
foreach my $name (@{ $whichfoils }) {
if ($target ne 'tex') {
if ($direction eq 'horizontal') {
@@ -671,9 +700,12 @@
$line++;
$i = 0;
$bubble_number = 0;
- $result.='\item[\textbf{'.($Apache::lonxml::counter+$line).'}.]';
}
- $result .= '{\small \textbf{'.$alphabet[$i].'}}$\bigcirc$'.$Apache::response::foilgroup{$name.'.text'}.'\\\\'; #' stupid emacs
+ my $identifier;
+ if ($numlines > 1) {
+ $identifier = $Apache::lonxml::counter+$line;
+ }
+ $result .= '{\small \textbf{'.$identifier.$alphabet[$i].'}}$\bigcirc$'.$Apache::response::foilgroup{$name.'.text'}.'\\\\'; #' stupid emacs
$i++;
$bubble_number++;
} else {
@@ -852,6 +884,7 @@
<endouttext />
</foil>';
}
+
1;
__END__
Index: loncom/homework/rankresponse.pm
diff -u loncom/homework/rankresponse.pm:1.65 loncom/homework/rankresponse.pm:1.66
--- loncom/homework/rankresponse.pm:1.65 Tue Jun 7 17:27:37 2011
+++ loncom/homework/rankresponse.pm Tue Sep 13 21:42:58 2011
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# rank style response
#
-# $Id: rankresponse.pm,v 1.65 2011/06/07 17:27:37 www Exp $
+# $Id: rankresponse.pm,v 1.66 2011/09/13 21:42:58 raeburn Exp $
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
@@ -127,8 +127,17 @@
}
my $part = $Apache::inputtags::part;
my $id = $Apache::inputtags::response[-1];
- &Apache::lonxml::increment_counter(&getfoilcounts($max),
- "$part.$id");
+ my ($numrows,$bubbles_per_row);
+ if (($target eq 'tex') && ($Apache::lonhomework::type eq 'exam')) {
+ my (@whichfoils)=&whichfoils($max,$randomize);
+ ($numrows,$bubbles_per_row) =
+ &Apache::optionresponse::getnumrows(scalar(@whichfoils));
+ }
+ if ($numrows < 1) {
+ $numrows = 1;
+ }
+ my $increment = &getfoilcounts($max) * $numrows;
+ &Apache::lonxml::increment_counter($increment,"$part.$id");
if ($target eq 'analyze') {
&Apache::lonhomework::set_bubble_lines();
}
@@ -227,8 +236,34 @@
my %grade;
my ($temp,$right,$wrong,$ignored)=(1,0,0,0);
my @correctorder=&get_correct_order($tol, at whichfoils);
+ my ($numrows,$bubbles_per_row);
+ if ($Apache::lonhomework::scantronmode) {
+ my $numitems = scalar(@whichfoils);
+ ($numrows,$bubbles_per_row) =
+ &Apache::optionresponse::getnumrows($numitems);
+ }
+ if ($numrows < 1) {
+ $numrows = 1;
+ }
+
foreach my $name (@whichfoils) {
- my $response = &Apache::response::getresponse($temp,'A is 1');
+ my $response;
+ if ($numrows > 1) {
+ my $num = $temp;
+ my $totalnum;
+ for (my $i=0; $i<$numrows; $i++) {
+ my $item = &Apache::response::getresponse($num,'A is 1');
+ if ($item =~ /^\d+$/) {
+ $totalnum = $i*$bubbles_per_row + $item;
+ }
+ $num ++;
+ }
+ $response = $totalnum;
+ $temp += $numrows;
+ } else {
+ $response = &Apache::response::getresponse($temp,'A is 1');
+ $temp ++;
+ }
my $value=shift(@correctorder);
if ( $response =~ /[^\s]/) {
$responsehash{$name}=$response;
@@ -241,7 +276,6 @@
} else {
$ignored++;
}
- $temp++;
}
my $malformed=&check_response_order(%responsehash);
my $part=$Apache::inputtags::part;
@@ -346,6 +380,13 @@
my %lastresponse=&Apache::lonnet::str2hash($lastresponse);
my @alp = splice @alphabet, 0, $#whichopt + 1;
my $internal_counter=$Apache::lonxml::counter;
+ my ($numrows,$bubbles_per_row);
+ if (($target eq 'tex') && ($Apache::lonhomework::type eq 'exam')) {
+ ($numrows,$bubbles_per_row) =
+ &Apache::optionresponse::getnumrows(scalar(@alp));
+ } else {
+ $numrows = 1;
+ }
if($target eq 'tex' && $env{'form.pdfFormFields'} eq 'yes') {
$result .= '\strut \\\\ \strut \\\\' ;
}
@@ -398,12 +439,26 @@
}
} else {
if ($Apache::lonhomework::type eq 'exam') {
+ my $itemlabel;
+ if ($numrows == 1) {
+ $itemlabel = '\item[\textbf{'.$internal_counter.'}]';
+ } else {
+ my $linetext;
+ for (my $i=0; $i<$numrows; $i++) {
+ $linetext .= $internal_counter+$i.', ';
+ }
+ $linetext =~ s/,\s$//;
+ $itemlabel = '\item[\small {\textbf{'.$linetext.'}}]'.
+ ' {\footnotesize '.
+ &mt('(Bubble once in [_1] lines)',$numrows).
+ '} \hspace*{\fill} \\\\';
+ }
$result .= '\vskip 0 mm '.$text.' \vskip 0 mm '."\n";
$result .= '\vskip -1 mm';
- $result .= '\begin{enumerate}\item[\textbf{'.$internal_counter.'}.]';
- $result .= &Apache::optionresponse::bubbles(\@alp,\@whichopt,'rankresponse');
- $result .= '\end{enumerate} \vskip -8 mm \strut ';
- $internal_counter++;
+ $result .= '\begin{enumerate}'.$itemlabel;
+ $result .= &Apache::optionresponse::bubbles(\@alp,\@whichopt,'rankresponse',undef,$numrows,$bubbles_per_row,$internal_counter);
+ $result .= '\end{enumerate} \vskip -8 mm \strut ';
+ $internal_counter += $numrows;
} else {
if($env{'form.pdfFormFields'} ne 'yes') {
$result.=' \vskip 0mm \framebox[5 mm][s]{\tiny\strut} '.$text."\n";
Index: loncom/homework/optionresponse.pm
diff -u loncom/homework/optionresponse.pm:1.176 loncom/homework/optionresponse.pm:1.177
--- loncom/homework/optionresponse.pm:1.176 Tue Jun 7 17:27:37 2011
+++ loncom/homework/optionresponse.pm Tue Sep 13 21:42:58 2011
@@ -1,7 +1,7 @@
# LearningOnline Network with CAPA
# option list style responses
#
-# $Id: optionresponse.pm,v 1.176 2011/06/07 17:27:37 www Exp $
+# $Id: optionresponse.pm,v 1.177 2011/09/13 21:42:58 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -252,11 +252,41 @@
my $right=0;
my $wrong=0;
my $ignored=0;
+ my ($numrows,$bubbles_per_row);
+ if ($Apache::lonhomework::scantronmode) {
+ my $numitems = scalar(@opt);
+ ($numrows,$bubbles_per_row) =
+ &Apache::optionresponse::getnumrows($numitems);
+ }
+ if ($numrows < 1) {
+ $numrows = 1;
+ }
foreach $name (@whichopt) {
- my $response=&Apache::response::getresponse($temp);
- if ($env{'form.submitted'} eq 'scantron' && $response=~/\S/) {
- $response = $opt[$response];
- }
+ my $response;
+ if ($env{'form.submitted'} eq 'scantron') {
+ if ($numrows > 1) {
+ my $num = $temp;
+ my $totalnum;
+ for (my $i=0; $i<$numrows; $i++) {
+ my $item = &Apache::response::getresponse($num);
+ if ($item =~ /^\d+$/) {
+ $totalnum = $i*$bubbles_per_row + $item;
+ }
+ $num ++;
+ }
+ if ($totalnum =~ /^\d+$/) {
+ $response = $opt[$totalnum];
+ }
+ $temp += $numrows;
+ } else {
+ if ($response=~/\S/) {
+ $response = $opt[$response];
+ }
+ $temp ++;
+ }
+ } else {
+ $temp ++;
+ }
if ( $response =~ /[^\s]/) {
$responsehash{$name}=$response;
my $value=$Apache::response::foilgroup{$name.'.value'};
@@ -269,7 +299,6 @@
} else {
$ignored++;
}
- $temp++;
}
my $part=$Apache::inputtags::part;
my $id = $Apache::inputtags::response['-1'];
@@ -347,8 +376,16 @@
}
my $part_id = $Apache::inputtags::part;
my $response_id = $Apache::inputtags::response[-1];
- &Apache::lonxml::increment_counter(&getfoilcounts($max),
- "$part_id.$response_id");
+ my ($numrows,$bubbles_per_row);
+ if (($target eq 'tex') && ($Apache::lonhomework::type eq 'exam')) {
+ ($numrows,$bubbles_per_row) =
+ &Apache::optionresponse::getnumrows(scalar(@opt));
+ }
+ if ($numrows < 1) {
+ $numrows = 1;
+ }
+ my $increment = &getfoilcounts($max) * $numrows;
+ &Apache::lonxml::increment_counter($increment,"$part_id.$response_id");
if ($target eq 'analyze') {
&Apache::lonhomework::set_bubble_lines();
}
@@ -631,9 +668,24 @@
}
if ($Apache::lonhomework::type eq 'exam') {
$result.='\vskip -1 mm\noindent';
- $result.= '\textbf{'. $internal_counter.'}. \vskip -3mm'.&bubbles(\@alphabet,\@opt).
- ' \strut ';
- $internal_counter++;
+ my ($numrows,$bubbles_per_row) = &getnumrows(scalar(@opt));
+ if ($numrows == 1) {
+ $result .= '\textbf{'.$internal_counter.'}. \vskip -3mm';
+ } else {
+ my $linetext;
+ for (my $i=0; $i<$numrows; $i++) {
+ $linetext .= $internal_counter+$i.', ';
+ }
+ $linetext =~ s/,\s$//;
+ $result .= '\small {\textbf{'.$linetext.'}} '.
+ '\hskip 2 mm {\footnotesize '.
+ &mt('(Bubble once in [_1] lines)',$numrows).
+ '} \vskip 1 mm';
+ }
+ $result.= &bubbles(\@alphabet,\@opt,undef,undef,$numrows,
+ $bubbles_per_row,$internal_counter).
+ ' \strut ';
+ $internal_counter += $numrows;
}
if ($target eq 'tex' && $env{'form.pdfFormFields'} eq 'yes'
&& $Apache::inputtags::status[-1] eq 'CAN_ANSWER'
@@ -714,7 +766,8 @@
sub bubbles {
- my ($ralphabet,$ropt,$response, $max_width) = @_;
+ my ($ralphabet,$ropt,$response,$max_width,$numrows,$bubbles_per_row,
+ $internal_counter) = @_;
my @alphabet = @$ralphabet;
my @opt = @$ropt;
my ($result,$head,$line) =('','','');
@@ -735,28 +788,37 @@
}
&Apache::lonxml::debug("Final maxwidth: $textwidth");
for (my $ind=0;$ind<=$number_of_bubbles;$ind++) {
+ my $item;
+ if ($numrows > 1) {
+ my $num = $internal_counter+int($ind/$bubbles_per_row);
+ my $idx = int($ind % $bubbles_per_row);
+ $item = $num.$alphabet[$idx];
+ } else {
+ $item = $alphabet[$ind];
+ }
my $leftmargin;
$opt[$ind]=&Apache::lonxml::latex_special_symbols($opt[$ind]);
if ($response eq 'rankresponse') {$opt[$ind]='Rank '.$opt[$ind];}
if ($ind==0) {$leftmargin=6;} else {$leftmargin=10;}
- $current_length += (length($opt[$ind])+length($alphabet[$ind])+4)*2;
+ $current_length += (length($opt[$ind])+length($item)+4)*2;
+
if ($current_length<($textwidth-$leftmargin) and $ind!=$number_of_bubbles) {
- $line.='\hskip 4 mm {\small \textbf{'.$alphabet[$ind].'}}$\bigcirc$\hskip -1 mm & \hskip -3 mm {\small '.$opt[$ind].'} & ';
+
+ $line.='\hskip 4 mm {\small \textbf{'.$item.'}}$\bigcirc$\hskip -1 mm & \hskip -3 mm {\small '.$opt[$ind].'} & ';
$head.='lr';
} else {
$line=~s/\&\s*$//;
$result.='\vskip -1 mm\noindent\setlength{\tabcolsep}{2 mm}\renewcommand{\arraystretch}{1.25}\begin{tabular}{'.$head.'}'.$line.'\\\\\end{tabular}\vskip 0 mm';
- $line = '\hskip 4 mm {\small \textbf{'.$alphabet[$ind].'}}$\bigcirc$\hskip -1 mm & \hskip -3 mm {\small '.$opt[$ind].'} & ';;
+ $line = '\hskip 4 mm {\small \textbf{'.$item.'}}$\bigcirc$\hskip -1 mm & \hskip -3 mm {\small '.$opt[$ind].'} & ';
$head ='lr';
- $current_length = (length($opt[$ind])+length($alphabet[$ind]))*2;
+ $current_length = (length($opt[$ind])+length($item))*2;
}
}
return $result;
}
-
sub start_conceptgroup {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
$Apache::optionresponse::conceptgroup=1;
@@ -904,6 +966,24 @@
sub insert_drawoptionlist {
return '<drawoptionlist />';
}
+
+sub getnumrows {
+ my ($numitems) = @_;
+ my $bubbles_per_row;
+ my $default_numbubbles = 10;
+ if (($env{'form.bubbles_per_row'} =~ /^\d+$/) &&
+ ($env{'form.bubbles_per_row'} > 0)) {
+ $bubbles_per_row = $env{'form.bubbles_per_row'};
+ } else {
+ $bubbles_per_row = $default_numbubbles;
+ }
+ my $numrows = int ($numitems/$bubbles_per_row);
+ if (($numitems % $bubbles_per_row) != 0) {
+ $numrows ++;
+ }
+ return ($numrows,$bubbles_per_row);
+}
+
1;
__END__
Index: loncom/homework/matchresponse.pm
diff -u loncom/homework/matchresponse.pm:1.81 loncom/homework/matchresponse.pm:1.82
--- loncom/homework/matchresponse.pm:1.81 Sun Dec 19 00:54:20 2010
+++ loncom/homework/matchresponse.pm Tue Sep 13 21:42:58 2011
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Full matching style response
#
-# $Id: matchresponse.pm,v 1.81 2010/12/19 00:54:20 raeburn Exp $
+# $Id: matchresponse.pm,v 1.82 2011/09/13 21:42:58 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -173,9 +173,31 @@
} elsif ($target eq 'tex') {
my $table=' \begin{description}\setlength{\leftmargin}{2em}\setlength{\labelwidth}{1em}\setlength{\itemsep}{0.5pt plus1pt minus2pt}\setlength{\listparindent}{0em} ';
my $i=0;
+ my ($numrows,$bubbles_per_row);
+ if ($Apache::lonhomework::type eq 'exam') {
+ ($numrows,$bubbles_per_row) =
+ &Apache::optionresponse::getnumrows(scalar(@names));
+ } else {
+ $numrows = 1;
+ }
foreach my $name (@names) {
# $Apache::response::itemgroup{$name.'.text'}=~s/\$\$/\$/g;
- $table.='\item['.$alphabet[$i].'] '.
+ my $item;
+ if (($numrows > 1) && ($bubbles_per_row > 0)) {
+ my $num = 1+int($i/$bubbles_per_row);
+ my $idx = int($i % $bubbles_per_row);
+ if ($idx == 0) {
+ if ($num == 1) {
+ $table .= '\item[\footnotesize {'.&mt('(first line)').'}]';
+ } else {
+ $table .= '\item[\footnotesize {'.&mt('(next line)').'}]';
+ }
+ }
+ $item = $alphabet[$idx];
+ } else {
+ $item = $alphabet[$i];
+ }
+ $table.='\item['.$item.'] '.
$Apache::response::itemgroup{$name.'.text'};
$i++;
}
@@ -288,8 +310,20 @@
['text','value','location']);
#FIXME need to store options in some way
}
- &Apache::lonxml::increment_counter(&getfoilcounts($max),
- "$part.$response_id");
+ my ($numrows,$bubbles_per_row);
+ if (($target eq 'tex') && ($Apache::lonhomework::type eq 'exam')) {
+ my $numitems;
+ if (ref($Apache::response::itemgroup{'names'}) eq 'ARRAY') {
+ $numitems = scalar(@{ $Apache::response::itemgroup{'names'} });
+ ($numrows,$bubbles_per_row) =
+ &Apache::optionresponse::getnumrows($numitems);
+ }
+ }
+ if ($numrows < 1) {
+ $numrows = 1;
+ }
+ my $increment = &getfoilcounts($max) * $numrows;
+ &Apache::lonxml::increment_counter($increment,"$part.$response_id");
if ($target eq 'analyze') {
&Apache::lonhomework::set_bubble_lines();
}
@@ -362,8 +396,41 @@
%{ $Apache::response::itemgroup{'letter_name_map'} };
}
my @items;
+ my $numitems = scalar(@{ $Apache::response::itemgroup{'names'} });
+ my ($numrows,$bubbles_per_row);
+ if ($Apache::lonhomework::scantronmode) {
+ my $numitems = scalar(@{ $Apache::response::itemgroup{'names'} });
+ ($numrows,$bubbles_per_row) =
+ &Apache::optionresponse::getnumrows($numitems);
+ }
+ if ($numrows < 1) {
+ $numrows = 1;
+ }
+ my @alphabet=('A'..'Z');
+ my %nums_from_letters;
+ for (my $i=0; $i<@alphabet; $i++) {
+ $nums_from_letters{$alphabet[$i]} = $i;
+ }
foreach my $name (@whichfoils) {
- my $response = &Apache::response::getresponse($temp,'letter');
+ my $response;
+ if ($numrows > 1) {
+ my $num = $temp;
+ my $totalnum;
+ for (my $i=0; $i<$numrows; $i++) {
+ my $item = &Apache::response::getresponse($num,'letter');
+ if ($item =~ /^\w$/) {
+ $totalnum = $i*$bubbles_per_row + $nums_from_letters{$item};
+ }
+ $num ++;
+ }
+ if ($totalnum =~ /^\d+$/) {
+ $response = $alphabet[$totalnum];
+ }
+ $temp += $numrows;
+ } else {
+ $response = &Apache::response::getresponse($temp,'letter');
+ $temp ++;
+ }
push(@items,$response);
my $responsename = $letter_name_map{$response};
my $value=$Apache::response::foilgroup{$name.'.value'};
@@ -381,7 +448,6 @@
} else {
$ignored++;
}
- $temp++;
}
my $part=$Apache::inputtags::part;
my $id = $Apache::inputtags::response['-1'];
@@ -535,6 +601,13 @@
my @alphabet=('A'..'Z');
my @used_letters=sort(keys(%letter_name_map));
my $internal_counter=$Apache::lonxml::counter;
+ my ($numrows,$bubbles_per_row);
+ if (($target eq 'tex') && ($Apache::lonhomework::type eq 'exam')) {
+ ($numrows,$bubbles_per_row) =
+ &Apache::optionresponse::getnumrows(scalar(@used_letters));
+ } else {
+ $numrows = 1;
+ }
foreach my $name (@whichfoils) {
my $lastopt=$lastresponse{$name};
my $last_letter=$name_letter_map{$lastopt};
@@ -618,15 +691,27 @@
my @emptyItems = ();
for (my $i=0;$i<=$#used_letters;$i++) {push @emptyItems, ' ';}
$question.='\vskip -1 mm\noindent\begin{list}{}{\setlength{\listparindent}{0mm}\setlength{\leftmargin}{2mm}}'
- .'\item \hskip -3mm \textbf{'.$internal_counter.'}';
+ .'\item \hskip -3mm ';
+ if ($numrows == 1) {
+ $question .= '\textbf{'.$internal_counter.'}';
+ } else {
+ my $linetext;
+ for (my $i=0; $i<$numrows; $i++) {
+ $linetext .= $internal_counter+$i.', ';
+ }
+ $linetext =~ s/,\s$//;
+ $question .= '\small {\textbf{'.$linetext.'}} '.
+ '\hskip 2 mm {\footnotesize '.
+ &mt('(Bubble once in [_1] lines)',$numrows).
+ '} \vskip 3 mm';
+ }
+ my $max_width;
if (&itemdisplay('left') || &itemdisplay('right')) {
- $question .= '\vskip -4 mm' . &Apache::optionresponse::bubbles(\@used_letters,\@emptyItems, "", $righttabsize);
- }
- else {
- $question .= '\vskip -4 mm' . &Apache::optionresponse::bubbles(\@used_letters,\@emptyItems);
- }
+ $max_width = $righttabsize;
+ }
+ $question .= '\vskip -4 mm' . &Apache::optionresponse::bubbles(\@used_letters,\@emptyItems,'',$max_width,$numrows,$bubbles_per_row,$internal_counter);
$question .= '\end{list} \vskip -8 mm \strut ';
- $internal_counter++;
+ $internal_counter += $numrows;
} else {
if($env{'form.pdfFormFields'} eq 'yes'
&& $Apache::inputtags::status['-1'] eq 'CAN_ANSWER') {
@@ -823,5 +908,6 @@
<endouttext />
</foil>';
}
+
1;
__END__
Index: loncom/homework/response.pm
diff -u loncom/homework/response.pm:1.225 loncom/homework/response.pm:1.226
--- loncom/homework/response.pm:1.225 Thu Sep 8 01:18:15 2011
+++ loncom/homework/response.pm Tue Sep 13 21:42:58 2011
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# various response type definitons response definition
#
-# $Id: response.pm,v 1.225 2011/09/08 01:18:15 raeburn Exp $
+# $Id: response.pm,v 1.226 2011/09/13 21:42:58 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -1003,16 +1003,18 @@
$Apache::lonhomework::results{"resource.$part.$id.scantron"}.=
$response;
if ($resulttype ne 'letter') {
- if ($resulttype eq 'A is 1') {
- $response = $let_to_num{$response}+1;
- } else {
- $response = $let_to_num{$response};
+ $response = $let_to_num{$response};
+ if ($resulttype eq 'A is 1') {
+ if ($response ne "") {
+ $response = $response+1;
+ }
}
if ($response ne "") {
$response += $line * $bubbles_per_line;
}
} else {
if ($response ne "") {
+ my $raw = $response;
$response = chr(ord($response) + $line * $bubbles_per_line);
}
}
@@ -1033,7 +1035,10 @@
=item &repetition();
Returns the number of lines that are required to encode the weight.
-(Currently expects that there are 10 bubbles per line)
+(Default is for 10 bubbles per bubblesheet item; other (integer)
+values can be specified by using a custom Bubblesheet format file
+with an eighteenth entry (BubblesPerRow) set to the integer
+appropriate for the bubblesheets which will be used to assign weights.
=cut
@@ -1041,8 +1046,15 @@
my $id = $Apache::inputtags::part;
my $weight = &Apache::lonnet::EXT("resource.$id.weight");
if (!defined($weight) || ($weight eq '')) { $weight=1; }
- my $repetition = int($weight/10);
- if ($weight % 10 != 0) { $repetition++; }
+ my $bubbles_per_row;
+ if (($env{'form.bubbles_per_row'} =~ /^\d+$/) &&
+ ($env{'form.bubbles_per_row'} > 0)) {
+ $bubbles_per_row = $env{'form.bubbles_per_row'};
+ } else {
+ $bubbles_per_row = 10;
+ }
+ my $repetition = int($weight/$bubbles_per_row);
+ if ($weight % $bubbles_per_row != 0) { $repetition++; }
return $repetition;
}
Index: loncom/interface/lonprintout.pm
diff -u loncom/interface/lonprintout.pm:1.595 loncom/interface/lonprintout.pm:1.596
--- loncom/interface/lonprintout.pm:1.595 Wed Jun 22 11:00:47 2011
+++ loncom/interface/lonprintout.pm Tue Sep 13 21:43:03 2011
@@ -2,7 +2,7 @@
# The LearningOnline Network
# Printout
#
-# $Id: lonprintout.pm,v 1.595 2011/06/22 11:00:47 foxr Exp $
+# $Id: lonprintout.pm,v 1.596 2011/09/13 21:43:03 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -2928,17 +2928,24 @@
my $code_option=$helper->{'VARS'}->{'CODE_OPTION'};
my @lines = &Apache::grades::get_scantronformat_file();
- my ($code_type,$code_length)=('letter',6);
+ my ($code_type,$code_length,$bubbles_per_row)=('letter',6,10);
foreach my $line (@lines) {
- my ($name,$type,$length) = (split(/:/,$line))[0,2,4];
+ chomp($line);
+ my ($name,$type,$length,$bubbles_per_item) =
+ (split(/:/,$line))[0,2,4,17];
if ($name eq $code_option) {
$code_length=$length;
if ($type eq 'number') { $code_type = 'number'; }
+ chomp($bubbles_per_item);
+ if (($bubbles_per_item ne '') && ($bubbles_per_item > 0)) {
+ $bubbles_per_row = $bubbles_per_item;
+ }
}
}
my %moreenv = ('textwidth' => &get_textwidth($helper,$LaTeXwidth));
$moreenv{'problem_split'} = $parmhash{'problem_stream_switch'};
$moreenv{'instructor_comments'}='hide';
+ $moreenv{'bubbles_per_row'} = $bubbles_per_row;
my $seed=time+($$<<16)+($$);
my @allcodes;
if ($old_name) {
@@ -3265,7 +3272,7 @@
($print_type eq 'incomplete_problems_selpeople_course')) {
$print_incomplete = 1;
}
- if ($person =~ 'anon') {
+ if ($person eq 'anonymous') {
$namepostfix .="Name: ";
$fullname = "CODE - ".$moreenv->{'CODE'};
}
More information about the LON-CAPA-cvs
mailing list