--- loncom/homework/radiobuttonresponse.pm 2002/09/23 19:09:52 1.48
+++ loncom/homework/radiobuttonresponse.pm 2003/01/07 22:13:07 1.63
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# mutliple choice style responses
#
-# $Id: radiobuttonresponse.pm,v 1.48 2002/09/23 19:09:52 albertel Exp $
+# $Id: radiobuttonresponse.pm,v 1.63 2003/01/07 22:13:07 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -42,6 +42,7 @@ sub start_radiobuttonresponse {
&Apache::lonxml::register('Apache::radiobuttonresponse',('foilgroup','foil','conceptgroup'));
push (@Apache::lonxml::namespace,'radiobuttonresponse');
my $id = &Apache::response::start_response($parstack,$safeeval);
+ %Apache::hint::radiobutton=();
if ($target eq 'meta') {
$result=&Apache::response::meta_package_write('radiobuttonresponse');
} elsif ($target eq 'edit' ) {
@@ -79,10 +80,16 @@ sub end_radiobuttonresponse {
%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::setrandomnumber();
- return '';
+ if ($target eq 'tex' && $Apache::lonhomework::type eq 'exam') {
+ $result.='\item[\textbf{'.$Apache::lonxml::counter.'}.]';
+ &Apache::lonxml::increment_counter();
+ }
+ return $result;
}
sub storesurvey {
@@ -101,13 +108,14 @@ sub storesurvey {
}
sub grade_response {
- my ($max,$answer,$randomize)=@_;
+ my ($max,$randomize)=@_;
+ #keep the random numbers the same must always call this
+ my ($answer,@whichfoils)=&whichfoils($max,$randomize);
if (!defined($ENV{'form.submitted'})) { return; }
my $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 @whichfoils=&whichfoils($max,$answer,$randomize);
my %responsehash;
$responsehash{$whichfoils[$response]}=$response;
my $responsestr=&Apache::lonnet::hash2str(%responsehash);
@@ -140,20 +148,15 @@ sub end_foilgroup {
}
} else {
my $name;
- my ($truecnt,$falsecnt,$max) = &getfoilcounts($parstack,$safeeval);
- my $count=0;
- # we will add in 1 of the true statements
- if (($falsecnt+1)>$max) { $count=$max } else { $count=$falsecnt+1; }
- my $answer = int(rand ($count));
- &Apache::lonxml::debug("Answer is $answer, $count from $max, $falsecnt");
+ my $max = &Apache::lonxml::get_param('max',$parstack,$safeeval,'-2');
my $randomize = &Apache::lonxml::get_param('randomize',$parstack,
$safeeval,'-2');
if ($target eq 'web' || $target eq 'tex') {
- $result=&displayfoils($target,$max,$answer,$randomize);
+ $result=&displayfoils($target,$max,$randomize);
} elsif ($target eq 'answer' ) {
- $result=&displayanswers($max,$answer,$randomize);
+ $result=&displayanswers($max,$randomize);
} elsif ( $target eq 'grade') {
- &grade_response($max,$answer,$randomize);
+ &grade_response($max,$randomize);
}
}
}
@@ -161,8 +164,6 @@ sub end_foilgroup {
}
sub getfoilcounts {
- my ($parstack,$safeeval)=@_;
- my $max = &Apache::lonxml::get_param('max',$parstack,$safeeval,'-2');
my @names;
my $truecnt=0;
my $falsecnt=0;
@@ -177,7 +178,7 @@ sub getfoilcounts {
$falsecnt++;
}
}
- return ($truecnt,$falsecnt,$max);
+ return ($truecnt,$falsecnt);
}
sub displayallfoils {
@@ -216,24 +217,31 @@ sub displayallfoils {
}
sub whichfoils {
- my ($max,$answer,$randomize)=@_;
+ my ($max,$randomize)=@_;
my @truelist;
my @falselist;
my @whichfalse =();
-
+ my ($truecnt,$falsecnt) = &getfoilcounts();
+ my $count=0;
+ # we will add in 1 of the true statements
+ if (($falsecnt+1)>$max) { $count=$max } else { $count=$falsecnt+1; }
+ my $answer=int(&Math::Random::random_uniform() * ($count));
+ &Apache::lonxml::debug("Count is $count, $answer is $answer");
my @names;
if ( $Apache::response::foilgroup{'names'} ) {
- @names= @{ $Apache::response::foilgroup{'names'} };
+ @names= @{ $Apache::response::foilgroup{'names'} };
}
if (&Apache::response::showallfoils()) {
- @whichfalse=@names;
+ @whichfalse=@names;
} elsif ($randomize eq 'no') {
&Apache::lonxml::debug("No randomization");
my $havetrue=0;
foreach my $name (@names) {
if ($Apache::response::foilgroup{$name.'.value'} eq 'true') {
- if (!$havetrue ) { push(@whichfalse,$name); $havetrue++; }
+ if (!$havetrue ) {
+ push(@whichfalse,$name); $havetrue++; $answer=$#whichfalse;
+ }
} elsif ($Apache::response::foilgroup{$name.'.value'} eq 'false') {
push (@whichfalse,$name);
} elsif ($Apache::response::foilgroup{$name.'.value'} eq 'unused') {
@@ -242,47 +250,113 @@ sub whichfoils {
}
}
} else {
+ my $current=0;
+ &Apache::lonhomework::showhash(%Apache::response::foilgroup);
+ my (%top,%bottom);
+ #first find out where everyone wants to be
foreach my $name (@names) {
- #result.="
$name is $Apache::response::foilgroup{$name.'.value'} ";
- if ($Apache::response::foilgroup{$name.'.value'} eq 'true') {
- push (@truelist,$name);
- } elsif ($Apache::response::foilgroup{$name.'.value'} eq 'false') {
- push (@falselist,$name);
- } elsif ($Apache::response::foilgroup{$name.'.value'} eq 'unused') {
- } else {
- &Apache::lonxml::error(&HTML::Entities::encode("No valid value assigned ($Apache::response::foilgroup{$name.'.value'}) for foil $name in "));
- }
+ $current++;
+ if ($Apache::response::foilgroup{$name.'.value'} eq 'true') {
+ push (@truelist,$name);
+ if ($Apache::response::foilgroup{$name.'.location'} eq 'top') {
+ $top{$name}=$current;
+ } elsif ($Apache::response::foilgroup{$name.'.location'} eq 'bottom') {
+ $bottom{$name}=$current;
+ }
+ } elsif ($Apache::response::foilgroup{$name.'.value'} eq 'false') {
+ push (@falselist,$name);
+ if ($Apache::response::foilgroup{$name.'.location'} eq 'top') {
+ $top{$name}=$current;
+ } elsif ($Apache::response::foilgroup{$name.'.location'} eq 'bottom') {
+ $bottom{$name}=$current;
+ }
+ } elsif ($Apache::response::foilgroup{$name.'.value'} eq 'unused') {
+ } else {
+ &Apache::lonxml::error(&HTML::Entities::encode("No valid value assigned ($Apache::response::foilgroup{$name.'.value'}) for foil $name in "));
+ }
}
- my $whichtrue = int(rand($#truelist+1));
+ #pick a true statement
+ my $whichtrue = int(&Math::Random::random_uniform() * ($#truelist+1));
&Apache::lonxml::debug("Max is $max, From $#truelist elms, picking $whichtrue");
- while ((($#whichfalse+1) < $max-1) && ($#falselist > -1)) {
- &Apache::lonxml::debug("Have $#whichfalse max is $max");
- my $afalse=int(rand($#falselist+1));
- &Apache::lonxml::debug("From $#falselist elms, picking $afalse");
- $afalse=splice(@falselist,$afalse,1);
- &Apache::lonxml::debug("Picked $afalse");
- push (@whichfalse,$afalse);
+ my (@toplist, @bottomlist);
+ my $topcount=0;
+ # assign everyone to either toplist/bottomlist or whichfalse
+ # which false is randomized, toplist bottomlist are in order
+ while ((($#whichfalse) < $max-2) && ($#falselist > -1)) {
+ &Apache::lonxml::debug("Have $#whichfalse max is $max");
+ my $afalse=int(&Math::Random::random_uniform() * ($#falselist+1));
+ &Apache::lonxml::debug("From $#falselist elms, picking $afalse");
+ $afalse=splice(@falselist,$afalse,1);
+ &Apache::lonxml::debug("Picked $afalse");
+ &Apache::lonhomework::showhash(('names'=>\@names));
+ &Apache::lonhomework::showhash(%top);
+ if ($top{$afalse}) {
+ $toplist[$top{$afalse}]=$afalse;
+ $topcount++;
+ } elsif ($bottom{$afalse}) {
+ $bottomlist[$bottom{$afalse}]=$afalse;
+ } else {
+ push (@whichfalse,$afalse);
+ }
}
- splice(@whichfalse,$answer,0,$truelist[$whichtrue]);
- &Apache::lonxml::debug("the true statement is $answer");
+ my $truename=$truelist[$whichtrue];
+ my $dosplice=1;
+ #insert the true statement, keeping track of where it wants to be
+ if ($Apache::response::foilgroup{$truename.'.location'} eq 'top' ) {
+ $toplist[$top{$truename}]=$truename;
+ $answer=-1;
+ foreach my $top (reverse(@toplist)) {
+ if ($top) { $answer++;}
+ if ($top eq $truename) { last; }
+ }
+ $dosplice=0;
+ } elsif ($Apache::response::foilgroup{$truename.'.location'} eq 'bottom') {
+ $bottomlist[$bottom{$truename}]=$truename;
+ $answer=-1;
+ foreach my $bot (@bottomlist) {
+ if ($bot) { $answer++;}
+ if ($bot eq $truename) { last; }
+ }
+ $answer+=$topcount+$#whichfalse+1;
+ $dosplice=0;
+ } else {
+ if ($topcount>0) {
+ $answer = int(&Math::Random::random_uniform() * ($#whichfalse+1))
+ + $topcount;
+ }
+ }
+ #add the top items to the top, bottom items to the bottom
+ for (my $i=0;$i<=$#toplist;$i++) {
+ if ($toplist[$i]) { unshift(@whichfalse,$toplist[$i]) }
+ }
+ for (my $i=0;$i<=$#bottomlist;$i++) {
+ if ($bottomlist[$i]) { push(@whichfalse,$bottomlist[$i]) }
+ }
+ #if the true statement is randomized insert it into the list
+ if ($dosplice) { splice(@whichfalse,$answer,0,$truelist[$whichtrue]); }
}
- return @whichfalse;
+ &Apache::lonxml::debug("Answer is $answer");
+ return ($answer,@whichfalse);
}
sub displayfoils {
- my ($target,$max,$answer,$randomize)=@_;
+ my ($target,$max,$randomize)=@_;
my $result;
- my @whichfoils=&whichfoils($max,$answer,$randomize);
- if ($Apache::lonhomework::history{"resource.$Apache::inputtags::part.solved"} =~ /^correct/ || ($Apache::inputtags::status[-1] eq 'SHOW_ANSWER')) {
+ my ($answer,@whichfoils)=&whichfoils($max,$randomize);
+ my $part=$Apache::inputtags::part;
+ my $solved=$Apache::lonhomework::history{"resource.$part.solved"};
+ my $status=$Apache::inputtags::status[-1];
+ if ( ($target ne 'tex') &&
+ (($solved =~ /^correct/) || ($status eq 'SHOW_ANSWER')) ) {
foreach my $name (@whichfoils) {
if ($target ne 'tex') {
$result.="
";
} else {
- $result.='\vskip 0 mm \item ';
+ $result.='\item \vskip -2 mm ';
}
if ($Apache::response::foilgroup{$name.'.value'} eq 'true') {
- if ($target ne 'tex') { $result.='Correct:'; } else { $result.='Correct: ';}
+ if ($target ne 'tex') { $result.='Correct:'; } else { $result.='Correct: \textbf{';}
} else {
$result.='Incorrect:';
}
@@ -292,11 +366,13 @@ sub displayfoils {
$result.=$Apache::response::foilgroup{$name.'.text'};
}
if ($Apache::response::foilgroup{$name.'.value'} eq 'true') {
- if ($target ne 'tex') { $result.='';}
+ if ($target ne 'tex') { $result.='';} else {$result.='}';}
}
}
} else {
- my $temp=0;
+ my @alphabet = ('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
+ my $i = 0;
+ my $temp=0;
my $id=$Apache::inputtags::response['-1'];
my $part=$Apache::inputtags::part;
my $lastresponse=$Apache::lonhomework::history{"resource.$part.$id.submission"};
@@ -306,8 +382,16 @@ sub displayfoils {
$result.="
\n";
+ if ($Apache::lonhomework::type eq 'exam') {
+ $result .= '';
+ }
} else {
- $result .= '\item '.$Apache::response::foilgroup{$name.'.text'};
+ if ($Apache::lonhomework::type eq 'exam') {
+ $result .= '{\small \textbf{'.$alphabet[$i].'}}$\bigcirc$'.$Apache::response::foilgroup{$name.'.text'}.'\\\\'; #' stupid emacs
+ $i++;
+ } else {
+ $result .= '\vspace*{-2 mm}\item '.$Apache::response::foilgroup{$name.'.text'};
+ }
}
$temp++;
}
@@ -317,8 +401,8 @@ sub displayfoils {
}
sub displayanswers {
- my ($max,$answer,$randomize)=@_;
- my @whichopt = &whichfoils($max,$answer,$randomize);
+ my ($max,$randomize)=@_;
+ my ($answer,@whichopt) = &whichfoils($max,$randomize);
my $result=&Apache::response::answer_header('radiobuttonresponse');
foreach my $name (@whichopt) {
$result.=&Apache::response::answer_part('radiobuttonresponse',
@@ -352,14 +436,19 @@ sub end_conceptgroup {
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || $target eq 'tex') {
if (defined(@{ $Apache::response::conceptgroup{'names'} })) {
my @names = @{ $Apache::response::conceptgroup{'names'} };
- my $pick=int(rand($#names+1));
+ my $pick=int(&Math::Random::random_uniform() * ($#names+1));
my $name=$names[$pick];
push @{ $Apache::response::foilgroup{'names'} }, $name;
$Apache::response::foilgroup{"$name.text"} = $Apache::response::conceptgroup{"$name.text"};
$Apache::response::foilgroup{"$name.value"} = $Apache::response::conceptgroup{"$name.value"};
+ $Apache::response::foilgroup{"$name.location"} = $Apache::response::conceptgroup{"$name.location"};
my $concept = &Apache::lonxml::get_param('concept',$parstack,$safeeval);
$Apache::response::foilgroup{"$name.concept"} = $concept;
&Apache::lonxml::debug("Selecting $name in $concept");
+ my $part_id="$Apache::inputtags::part.$Apache::inputtags::response[-1]";
+ push(@{ $Apache::hint::radiobutton{"$part_id.concepts"} },$concept);
+ $Apache::hint::radiobutton{"$part_id.concept.$concept"}=
+ $Apache::response::conceptgroup{'names'};
}
} elsif ($target eq 'edit') {
$result=&Apache::edit::end_table();
@@ -382,8 +471,12 @@ sub start_foil {
$result.=&Apache::edit::text_arg('Name:','name',$token);
$result.=&Apache::edit::select_or_text_arg('Correct Option:','value',
['unused','true','false'],$token);
- $result.=&Apache::edit::select_or_text_arg('Location:','location',
- ['random','bottom','top'],$token);
+ my $randomize=&Apache::lonxml::get_param('randomize',$parstack,
+ $safeeval,'-3');
+ if ($randomize ne 'no') {
+ $result.=&Apache::edit::select_arg('Location:','location',
+ ['random','top','bottom'],$token);
+ }
$result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
} elsif ($target eq 'modified') {
my $constructtag=&Apache::edit::get_new_args($token,$parstack,$safeeval,