Fixed Survey's handling of multi-answer questions (e.g. maxAnswers != 1)

Now stores all supplied answers to multi-answer question as arrayref
Variable [[var]] text replacement converts to comma-separated list
Expression Engine's value() returns appropriate value depending on context
Expression Engine's score() does sum of multi-answers, as you would expect
Updated related i18n & hover-help, and tests
Cleaned up survey js somewhat
This commit is contained in:
Patrick Donelan 2009-05-08 08:00:04 +00:00
parent 88d6a0d067
commit cf98c81461
6 changed files with 220 additions and 203 deletions

View file

@ -45,8 +45,19 @@ Returns the recorded response value for the answer to question_variable
sub value {
my $key = shift;
my $value = $tags->{$key} || $values->{$key};
$session->log->debug("value($key) resolves to [$value]");
return $value; # scalar variable, so no need to clone
if (ref $value eq 'ARRAY') {
my $joined = join ', ', @$value;
if (wantarray) {
$session->log->debug("value($key) in list context resolves to ($joined)");
return @$value;
} else {
$session->log->debug("value($key) in scalar|void context resolves to \"$joined\"");
return $joined;
}
} else {
$session->log->debug("value($key) resolves to [$value]");
return $value;
}
}
=head2 valueX
@ -64,8 +75,19 @@ sub valueX {
if (my $other_instance = $otherInstances->{$asset_spec}) {
my $values = $other_instance->{values};
my $value = $values->{$key};
$session->log->debug("valueX($asset_spec, $key) resolves to [$value]");
return $value;
if (ref $value eq 'ARRAY') {
my $joined = join ', ', @$value;
if (wantarray) {
$session->log->debug("valueX($asset_spec, $key) in list context resolves to ($joined)");
return @$value;
} else {
$session->log->debug("valueX($asset_spec, $key) in scalar|void context resolves to \"$joined\"");
return $joined;
}
} else {
$session->log->debug("valueX($asset_spec, $key) resolves to [$value]");
return $value;
}
} else {
# Throw an exception, triggering run() to resolve the external reference and re-run
die( { other_instance => $asset_spec } );

View file

@ -815,8 +815,13 @@ sub responseValuesByVariableName {
my %options = validate(@_, { useText => 0 });
my %lookup;
while (my ($address, $response) = each %{$self->responses}) {
next if (!$response || !$address);
# Process responses in id order (so that questions with maxAnswers != 1 stringify according
# to natural ordering of answers (e.g. answer 0, answer 1, etc..
for my $address (sort keys %{$self->responses}) {
next if !$address;
my $response = $self->responses->{$address};
next if !$response;
# Turn responses s-q-a string into an address array
my @address = split /-/, $address;
@ -846,7 +851,11 @@ sub responseValuesByVariableName {
}
# Add variable => value to our hash
$lookup{$question->{variable}} = $value;
if (!$question->{maxAnswers} || $question->{maxAnswers} > 1) {
push @{$lookup{$question->{variable}}}, $value;
} else {
$lookup{$question->{variable}} = $value;
}
}
return \%lookup;
}
@ -866,8 +875,11 @@ sub responseScoresByVariableName {
my $self = shift;
my %lookup;
while (my ($address, $response) = each %{$self->responses}) {
next if (!$response || !$address);
# Process responses in id order, just to be consistent with responseValuesByVariableName
for my $address (sort keys %{$self->responses}) {
next if !$address;
my $response = $self->responses->{$address};
next if !$response;
# Turn responses s-q-a string into an address array
my @address = split /-/, $address;
@ -887,8 +899,8 @@ sub responseScoresByVariableName {
# Use question score if answer score undefined
my $score = (exists $answer->{value} && length $answer->{value} > 0) ? $answer->{value} : $question->{value};
# Add variable => score to our hash
$lookup{$question->{variable}} = $score;
# Add variable => score to our hash (or add to existing score for multi-answer questions, e.g. maxAnswers != 1)
$lookup{$question->{variable}} += $score;
}
# Add section score totals
@ -933,6 +945,11 @@ A hash reference. Each matching key in the string will be replaced with its asso
sub getTemplatedText {
my $self = shift;
my ($text, $params) = validate_pos(@_, { type => SCALAR }, { type => HASHREF });
# Turn multi-valued answers into comma-separated text
for my $value (values %$params) {
$value = join(',', @$value) if ref $value eq 'ARRAY';
}
# Replace all instances of [[var]] with the value from the $params hash reference
$text =~ s/\[\[([^\%]*?)\]\]/$params->{$1}/eg;

View file

@ -285,10 +285,10 @@ our $I18N = {
context => q|Description of the 'cols' field, used as hoverhelp in the edit question dialog.|,
lastUpdated => 1241588599
},
'comment rows' => {
message => q|Comment Rows:|,
lastUpdated => 1224686319
},
'comment rows' => {
message => q|Comment Rows:|,
lastUpdated => 1224686319
},
'rows description' => {
message => q|The number of rows used for the input field (for TextArea question types).|,
context => q|Description of the 'rows' field, used as hoverhelp in the edit question dialog.|,
@ -299,68 +299,68 @@ our $I18N = {
lastUpdated => 1224686319
},
'maximum number of answers description' => {
message => q|Enter the maximum number of answers.|,
message => q|For multi-choice questions, how many answers the user can select. <br>0 = unlimited.<br>1 = radio group style.<br>2 and above = checkbox style.|,
context => q|Description of the 'maximum number of answers' field, used as hoverhelp in the edit question dialog.|,
lastUpdated => 0
lastUpdated => 1241764603,
},
'required label' => {
message => q|Required|,
lastUpdated => 1224686319
},
'required label' => {
message => q|Required|,
lastUpdated => 1224686319
},
'required description' => {
message => q|Is this a required question?|,
context => q|Description of the 'required' field, used as hoverhelp in the edit question dialog.|,
lastUpdated => 0
},
'question score' => {
message => q|Question score:|,
lastUpdated => 1224686319
},
'question score' => {
message => q|Question score:|,
lastUpdated => 1224686319
},
'question score description' => {
message => q|Default score to use for answers in this question that don't have an answer score value set.|,
context => q|Description of the 'question value' field, used as hoverhelp in the edit question dialog.|,
lastUpdated => 1239255403
},
'please enter answer information' => {
message => q|Please enter answer information:|,
context => q|Title of the edit answer dialog.|,
lastUpdated => 1224686319
},
'answer number' => {
message => q|Answer number:|,
lastUpdated => 1224686319
},
'please enter answer information' => {
message => q|Please enter answer information:|,
context => q|Title of the edit answer dialog.|,
lastUpdated => 1224686319
},
'answer number' => {
message => q|Answer number:|,
lastUpdated => 1224686319
},
'answer number description' => {
message => q|The number of this answer|,
context => q|Description of the 'answer number' field, used as hoverhelp in the edit answer dialog.|,
lastUpdated => 0
},
'answer text' => {
message => q|Answer text:|,
lastUpdated => 1224686319
},
'answer text' => {
message => q|Answer text:|,
lastUpdated => 1224686319
},
'answer text description' => {
message => q|Enter a text for this answer. For multiple choice questions this answer will be displayed above the buttons.|,
context => q|Description of the 'answer text' field, used as hoverhelp in the edit answer dialog.|,
lastUpdated => 0
},
'recorded answer' => {
message => q|Recorded Answer:|,
lastUpdated => 1224686319
},
'recorded answer' => {
message => q|Recorded Answer:|,
lastUpdated => 1224686319
},
'recorded answer description' => {
message => q|Determines what gets recorded as the response value if this answer is selected. Allows you to 'recode' recorded responses, e.g. 'Yes' could be recorded as '1' and 'No' as '0'. Relevant only for Multiple Choice questions (other question types record the input actually entered by the user: free text, selected date, etc..).|,
context => q|Description of the 'recorded answer' field, used as hoverhelp in the edit answer dialog.|,
lastUpdated => 1239251436
},
'jump to' => {
message => q|Jump to:|,
lastUpdated => 1224686319
},
'jump expression' => {
message => q|Jump expression:|,
lastUpdated => 1229318805
},
'jump to' => {
message => q|Jump to:|,
lastUpdated => 1224686319
},
'jump expression' => {
message => q|Jump expression:|,
lastUpdated => 1229318805
},
'jump to description' => {
message => q|The section or question with this variable name will be the next to be displayed after this answer.|,
context => q|Description of the 'jump to' field, used as hoverhelp in the edit answer dialog.|,