From: Sam H. v. a. <we...@ma...> - 2008-05-12 21:05:29
|
Log Message: ----------- added the ability to specify an order for the choices or push some choices to the top or bottom. Modified Files: -------------- pg/macros: parserRadioButtons.pl Revision Data ------------- Index: parserRadioButtons.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/parserRadioButtons.pl,v retrieving revision 1.10 retrieving revision 1.11 diff -Lmacros/parserRadioButtons.pl -Lmacros/parserRadioButtons.pl -u -r1.10 -r1.11 --- macros/parserRadioButtons.pl +++ macros/parserRadioButtons.pl @@ -33,6 +33,22 @@ =over +=item C<S<< order => [choice,...] >>> + +Specifies the order in which choices should be presented. All choices must be +listed. If this option is specified, the C<first> and C<last> options are +ignored. + +=item C<S<< first => [choice,...] >>> + +Specifies choices which should appear first, in the order specified, in the list +of choices. Ignored if the C<order> option is specified. + +=item C<S<< last => [choice,...] >>> + +Specifies choices which should appear last, in the order specified, in the list +of choices. Ignored if the C<order> option is specified. + =item C<S<< labels => [label1,...] >>> Specifies the text to be used @@ -129,6 +145,9 @@ checked => undef, maxLabelSize => 25, uncheckable => 0, + first => undef, + last => undef, + order => undef, @_, ); $options{labels} = [1..scalar(@$choices)] if $options{labels} eq "123"; @@ -147,12 +166,11 @@ return $self; } -# -# Locate the label of the correct answer -# The answer can be given as an index, as the full answer -# or as the label itself. -# -sub correctChoice { +# +# Given a choice, a label, or an index into the choices array, +# return the label. +# +sub findChoice { my $self = shift; my $value = shift; my $index = $self->Index($value); foreach my $i (0..scalar(@{$self->{choices}})-1) { @@ -160,6 +178,17 @@ $label = $self->makeLabel($choice) unless defined $label; return $label if $label eq $value || $index == $i || $choice eq $value; } +} + +# +# Locate the label of the correct answer +# The answer can be given as an index, as the full answer +# or as the label itself. +# +sub correctChoice { + my $self = shift; my $value = shift; + my $choice = $self->findChoice($value); + return $choice if defined $choice; Value::Error("The correct answer should be one of the button choices"); } @@ -246,18 +275,81 @@ return @radio; } +# +# Determine the order the choices should be in. +# +sub orderedChoices { + my $self = shift; + my %choiceHash = $self->choiceHash; + my @labels = keys %choiceHash; + + my @order = @{$self->{order}}; + my @first = @{$self->{first}}; + my @last = @{$self->{last}}; + + my @orderLabels; + + if (@order) { + my %remainingChoices = %choiceHash; + Value::Error("When using the 'order' option, you must list all possible choices.") + unless @order == @labels; + foreach my $i (0..$#order) { + my $label = $self->findChoice($order[$i]); + Value::Error("Item $i of the 'order' option is not a choice.") + if not defined $label; + Value::Error("Item $i of the 'order' option was already specified.") + if not exists $remainingChoices{$label}; + push @orderLabels, $label; + delete $remainingChoices{$label}; + } + } elsif (@first or @last) { + my @firstLabels; + my @lastLabels; + my %remainingChoices = %choiceHash; + + foreach my $i (0..$#first) { + my $label = $self->findChoice($first[$i]); + Value::Error("Item $i of the 'first' option is not a choice.") + if not defined $label; + Value::Error("Item $i of the 'first' option was already specified.") + if not exists $remainingChoices{$label}; + push @firstLabels, $label; + delete $remainingChoices{$label}; + } + + foreach my $i (0..$#last) { + my $label = $self->findChoice($last[$i]); + Value::Error("Item $i of the 'last' option is not a choice.") + if not defined $label; + Value::Error("Item $i of the 'last' option was already specified.") + if not exists $remainingChoices{$label}; + push @lastLabels, $label; + delete $remainingChoices{$label}; + } + + @orderLabels = (@firstLabels, keys %remainingChoices, @lastLabels); + } else { + # use the order of elements in the hash + # this is the current behavior + # might we want to explicitly randomize these? + @orderLabels = @labels; + } + + return map { $_ => $choiceHash{$_} } @orderLabels; +} + # # Create the radio-buttons text # sub buttons { my $self = shift; - my @radio = main::ans_radio_buttons($self->choiceHash); + my @radio = main::ans_radio_buttons($self->orderedChoices); @radio = $self->makeUncheckable(@radio) if $self->{uncheckable}; (wantarray) ? @radio : join($self->{separator}, @radio); } sub named_buttons { my $self = shift; my $name = shift; - my @radio = NAMED_ANS_RADIO_BUTTONS($name,$self->choiceHash); + my @radio = NAMED_ANS_RADIO_BUTTONS($name,$self->orderedChoices); @radio = $self->makeUncheckable(@radio) if $self->{uncheckable}; # # Taken from PGbasicmacros.pl |