--- loncom/homework/radiobuttonresponse.pm 2007/03/27 19:20:49 1.113 +++ loncom/homework/radiobuttonresponse.pm 2007/10/08 09:22:50 1.128 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # mutliple choice style responses # -# $Id: radiobuttonresponse.pm,v 1.113 2007/03/27 19:20:49 albertel Exp $ +# $Id: radiobuttonresponse.pm,v 1.128 2007/10/08 09:22:50 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -31,18 +31,36 @@ use strict; use HTML::Entities(); use Apache::lonlocal; use Apache::lonnet; +use Apache::response; + +my $default_bubbles_per_line = 10; + BEGIN { &Apache::lonxml::register('Apache::radiobuttonresponse',('radiobuttonresponse')); } +sub bubble_line_count { + my ($numfoils, $bubbles_per_line) = @_; + my $bubble_lines; + $bubble_lines = int($numfoils / $bubbles_per_line); + if (($numfoils % $bubbles_per_line) != 0) { + $bubble_lines++; + } + return $bubble_lines; + +} + + sub start_radiobuttonresponse { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result; + #when in a radiobutton response use these &Apache::lonxml::register('Apache::radiobuttonresponse',('foilgroup','foil','conceptgroup')); push (@Apache::lonxml::namespace,'radiobuttonresponse'); my $id = &Apache::response::start_response($parstack,$safeeval); + %Apache::hint::radiobutton=(); undef(%Apache::response::foilnames); if ($target eq 'meta') { @@ -136,22 +154,29 @@ sub storesurvey { return ''; } + sub grade_response { - my ($max,$randomize)=@_; - #keep the random numbers the same must always call this - my ($answer,@whichfoils)=&whichfoils($max,$randomize); + my ($answer, $whichfoils, $bubbles_per_line)=@_; + if ( !&Apache::response::submitted() ) { return; } my $response; + if ($env{'form.submitted'} eq 'scantron') { - $response=&Apache::response::getresponse(); + $response = &Apache::response::getresponse(1,undef, + &bubble_line_count(scalar(@{ $whichfoils}), + $bubbles_per_line), + $bubbles_per_line); + } else { $response = $env{'form.HWVAL_'.$Apache::inputtags::response['-1']}; } + + if ( $response !~ /[0-9]+/) { return; } my $part=$Apache::inputtags::part; my $id = $Apache::inputtags::response['-1']; my %responsehash; - $responsehash{$whichfoils[$response]}=$response; + $responsehash{$whichfoils->[$response]}=$response; my $responsestr=&Apache::lonnet::hash2str(%responsehash); my %previous=&Apache::response::check_for_previous($responsestr, $part,$id); @@ -172,6 +197,16 @@ sub end_foilgroup { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result; + my $bubble_lines; + my $bubbles_per_line; + my $answer_count; + my $id = $Apache::inputtags::response['-1']; + $bubbles_per_line = + &Apache::response::get_response_param($Apache::inputtags::part."_$id", + 'numbubbles', + $default_bubbles_per_line); + + if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' || $target eq 'tex' || $target eq 'analyze') { my $style = $Apache::lonhomework::type; @@ -180,42 +215,57 @@ sub end_foilgroup { if ( $style eq 'survey' && $target ne 'analyze') { if ($target eq 'web' || $target eq 'tex') { $result=&displayallfoils($direction, $target); - if ($target eq 'web') { - &setup_prior_tries_hash(); - } } elsif ( $target eq 'answer' ) { $result=&displayallanswers(); } elsif ( $target eq 'grade' ) { $result=&storesurvey(); } + $answer_count = scalar(@{$Apache::response::foilgroup{'names'}}); + } else { + my $name; my $max = &Apache::lonxml::get_param('max',$parstack,$safeeval, '-2'); my $randomize = &Apache::lonxml::get_param('randomize',$parstack, $safeeval,'-2'); + my ($answer, @shown) = &whichfoils($max, $randomize); + $answer_count = scalar(@shown); + if ($target eq 'web' || $target eq 'tex') { - $result=&displayfoils($target,$max,$randomize,$direction); - if ($target eq 'web') { - &setup_prior_tries_hash(); - } + $result=&displayfoils($target, + $answer, \@shown, + $direction, + $bubbles_per_line); } elsif ($target eq 'answer' ) { - $result=&displayanswers($max,$randomize); + $result=&displayanswers($answer, \@shown, $bubbles_per_line); } elsif ( $target eq 'grade') { - &grade_response($max,$randomize); + &grade_response($answer, \@shown, $bubbles_per_line); } elsif ( $target eq 'analyze') { - my @shown = &whichfoils($max,$randomize); + my $bubble_lines = &bubble_line_count($answer_count, + $bubbles_per_line); &Apache::response::analyze_store_foilgroup(\@shown, ['text','value','location']); my $part_id="$Apache::inputtags::part.$Apache::inputtags::response[-1]"; push (@{ $Apache::lonhomework::analyze{"$part_id.options"} }, ('true','false')); + push (@{ $Apache::lonhomework::analyze{"$part_id.bubble_lines"} }, + $bubble_lines); } } $Apache::lonxml::post_evaluate=0; } + if ($target eq 'web') { + &Apache::response::setup_prior_tries_hash(\&format_prior_answer, + [\%Apache::response::foilgroup]); + } &Apache::response::poprandomnumber(); - &Apache::lonxml::increment_counter(); + $bubble_lines = &bubble_line_count($answer_count, $bubbles_per_line); + &Apache::lonxml::increment_counter($bubble_lines, + $id); + if ($target eq 'analyze') { + &Apache::lonhomework::set_bubble_lines(); + } return $result; } @@ -237,18 +287,14 @@ sub getfoilcounts { return ($truecnt,$falsecnt); } -sub setup_prior_tries_hash { - my $part=$Apache::inputtags::part; - my $id=$Apache::inputtags::response[-1]; - foreach my $i (1..$Apache::lonhomework::history{'version'}) { - my $key = "$i:resource.$part.$id.submission"; - next if (!exists($Apache::lonhomework::history{"$key"})); - my %response = - &Apache::lonnet::str2hash($Apache::lonhomework::history{$key}); - my ($name) = keys(%response); - $Apache::inputtags::submission_display{$key} = - $Apache::response::foilgroup{$name.'.text'} - } +sub format_prior_answer { + my ($mode,$answer,$other_data) = @_; + my $foil_data = $other_data->[0]; + my %response = &Apache::lonnet::str2hash($answer); + my ($name) = keys(%response); + return ''. + $foil_data->{$name.'.text'}.''; + } sub displayallfoils { @@ -259,6 +305,7 @@ sub displayallfoils { if ( $Apache::response::foilgroup{'names'} ) { @names= @{ $Apache::response::foilgroup{'names'} }; } + my $temp=0; my $i =0; my $id=$Apache::inputtags::response['-1']; @@ -328,10 +375,39 @@ sub displayallfoils { } } } + if (($direction eq 'horizontal') && ($target ne 'tex')) { $result.=''; } return $result; } +=pod + +=item &whichfoils($max,$randomize) + +Randomizes the list of foils. +Respects + - each foils desire to be randomized + - the existance of Concept groups of foils (select 1 foil from each) + - and selects a single correct statement from all possilble true statments + - and limits it to a toal of $max foils + +WARNING: this routine uses the random number generator, it should only +be called once per target, otherwise it can cause randomness changes in +homework problems. + +Arguments + $max - maximum number of foils to select (including the true one) + (so a max of 5 is: 1 true, 4 false) + + $randomize - whether to randomize the listing of foils, by default + will randomize, only if randomize is 'no' will it not + +Returns + $answer - location in the array of the correct answer + @foils - array of foil names in to display order + +=cut + sub whichfoils { my ($max,$randomize)=@_; @@ -469,10 +545,9 @@ sub whichfoils { } sub displayfoils { - my ($target,$max,$randomize,$direction)=@_; + my ($target,$answer,$whichfoils,$direction, $bubbles_per_line)=@_; my $result; - my ($answer,@whichfoils)=&whichfoils($max,$randomize); my $part=$Apache::inputtags::part; my $solved=$Apache::lonhomework::history{"resource.$part.solved"}; if ( ($target ne 'tex') && @@ -482,7 +557,7 @@ sub displayfoils { $result.=''; } } - foreach my $name (@whichfoils) { + foreach my $name (@{ $whichfoils }) { if ($direction eq 'horizontal') { if ($target ne 'tex') { $result.='
'; } } @@ -514,6 +589,8 @@ sub displayfoils { } else { my @alphabet = ('A'..'Z'); my $i = 0; + my $bubble_number = 0; + my $line = 0; my $temp=0; my $id=$Apache::inputtags::response['-1']; my $part=$Apache::inputtags::part; @@ -522,7 +599,7 @@ sub displayfoils { if ($target ne 'tex' && $direction eq 'horizontal') { $result.=""; } - foreach my $name (@whichfoils) { + foreach my $name (@{ $whichfoils }) { if ($target ne 'tex') { if ($direction eq 'horizontal') { $result.="
"; @@ -541,8 +618,15 @@ sub displayfoils { $result .= ' />'.$Apache::response::foilgroup{$name.'.text'}.""; } else { if ($Apache::lonhomework::type eq 'exam') { + if($bubble_number >= $bubbles_per_line) { + $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 $i++; + $bubble_number++; } else { $result .= '\vspace*{-2 mm}\item '.$Apache::response::foilgroup{$name.'.text'}; } @@ -565,7 +649,6 @@ sub displayallanswers { if ( $Apache::response::foilgroup{'names'} ) { @names= @{ $Apache::response::foilgroup{'names'} }; } - my $result=&Apache::response::answer_header('radiobuttonresponse'); foreach my $name (@names) { $result.=&Apache::response::answer_part('radiobuttonresponse', @@ -576,15 +659,20 @@ sub displayallanswers { } sub displayanswers { - my ($max,$randomize)=@_; - my ($answer,@whichopt) = &whichfoils($max,$randomize); - my $result=&Apache::response::answer_header('radiobuttonresponse'); + my ($answer, $whichopt, $bubbles_per_line)=@_; + my $result; + if ($Apache::lonhomework::type eq 'exam') { - my $correct = ('A'..'Z')[$answer]; - $result.=&Apache::response::answer_part('radiobuttonresponse', - $correct); + my $line = int($answer/$bubbles_per_line); + my $correct = ('A'..'Z')[$answer%$bubbles_per_line]; + $result .= &Apache::response::answer_header('radiobuttonresponse', + $line); + $result .= &Apache::response::answer_part('radiobuttonresponse', + $correct); + } else { + $result .= &Apache::response::answer_header('radiobuttonresponse'); } - foreach my $name (@whichopt) { + foreach my $name (@{ $whichopt }) { $result.=&Apache::response::answer_part('radiobuttonresponse', $Apache::response::foilgroup{$name.'.value'}); }