Added Survey meta-targets NEXT_SECTION and END_SURVEY to allow for more

convenient jumping
Improved processGotoExpression tests
This commit is contained in:
Patrick Donelan 2009-04-22 07:19:23 +00:00
parent 99855719d0
commit 6c58e1de81
3 changed files with 100 additions and 40 deletions

View file

@ -274,17 +274,20 @@ sub startTime {
Accessor. Initialized on first access via L<"initSurveyOrder">.
This data strucutre is an array (reference) of Survey addresses (see
L<WebGUI::Asset::Wobject::Survey::SurveyJSON/Address Parameter>), stored in the order
in which items are presented to the user.
This data strucutre represents the list of items that are shown to the user, in the order
that they will be shown (ignoring jumps and jump expressions).
In general, the surveyOrder data structure looks like:
Typically each item will correspond to a question, and contains enough information to look
up both the corresponding section and all contained answers (if any).
Empty sections also appear in the list.
Each element of the array is an address, similar in structure to
L<WebGUI::Asset::Wobject::Survey::SurveyJSON/Address Parameter>,
except that instead of an answerIndex in the third slot, we have a sub-array of all contained answer indicies.
[ $sectionIndex, $questionIndex, [ $answerIndex1, $answerIndex2, ....]
There is one array element for every section and address in the survey. If there are
no questions, or no addresses, those array elements will not be present.
By making use of L<WebGUI::Asset::Wobject::Survey::SurveyJSON> methods which expect address params as
arguments, you can access Section/Question/Answer items in order by iterating over surveyOrder.
@ -590,6 +593,23 @@ A variable name to match against all section and question variable names.
sub processGoto {
my $self = shift;
my ($goto) = validate_pos(@_, {type => SCALAR});
if ($goto eq 'NEXT_SECTION') {
$self->session->log->debug("NEXT_SECTION jump target encountered");
my $lastResponseSectionIndex = $self->lastResponseSectionIndex;
# Increment lastRepsonse until nextResponseSectionIndex moves
while ($self->nextResponseSectionIndex == $lastResponseSectionIndex) {
$self->lastResponse( $self->lastResponse + 1);
}
return;
}
if ($goto eq 'END_SURVEY') {
$self->session->log->debug("END_SURVEY jump target encountered");
$self->lastResponse( scalar( @{ $self->surveyOrder} ) - 1 );
return;
}
# Iterate over items in order..
my $itemIndex = 0;

View file

@ -414,16 +414,17 @@ Generates the list of valid goto targets
sub getGotoTargets {
my $self = shift;
# Valid goto targets are all of the section variable names..
my @section_vars = map {$_->{variable}} @{$self->sections};
# Valid goto targets are all of the non-empty section variable names..
my @section_vars = grep { $_ ne q{} } map {$_->{variable}} @{$self->sections};
# ..and all of the question variable names..
my @question_vars = map {$_->{variable}} @{$self->questions};
# ..and all of the non-empty question variable names..
my @question_vars = grep { $_ ne q{} } map {$_->{variable}} @{$self->questions};
# ..excluding the ones that are empty
my @grep = grep { $_ ne q{} } (@section_vars, @question_vars);
return \@grep;
#return grep { $_ ne q{} } (@section_vars, @question_vars);
# ..plus some special vars
my @special_vars = qw(NEXT_SECTION END_SURVEY);
# ..all combined
return [ @section_vars, @question_vars, @special_vars ];
}
=head2 getSectionEditVars ( $address )

View file

@ -22,7 +22,7 @@ my $session = WebGUI::Test->session;
#----------------------------------------------------------------------------
# Tests
my $tests = 75;
my $tests = 81;
plan tests => $tests + 1;
#----------------------------------------------------------------------------
@ -352,42 +352,81 @@ cmp_deeply($rJSON->responseScoresByVariableName, { s1q0 => 100, s1q1 => 200, s1
# Turn on the survey Expression Engine
WebGUI::Test->originalConfig('enableSurveyExpressionEngine');
$session->config->set('enableSurveyExpressionEngine', 1);
$rJSON->survey->section([0])->{variable} = 's0'; # our first test jump target
$rJSON->survey->section([2])->{variable} = 's2'; # our second test jump target
$rJSON->survey->question([1,0])->{variable} = 's1q0'; # a question variable to use in our expressions
$rJSON->survey->answer([1,0,0])->{recordedAnswer} = 3; # value recorded in responses hash for multi-choice answer
$rJSON->survey->section([0])->{variable} = 's0';
$rJSON->survey->question([0,0])->{variable} = 's0q0'; # surveyOrder index = 0
$rJSON->survey->question([0,1])->{variable} = 's0q1'; # surveyOrder index = 1
$rJSON->survey->question([0,2])->{variable} = 's0q2'; # surveyOrder index = 2
$rJSON->survey->section([1])->{variable} = 's1';
$rJSON->survey->question([1,0])->{variable} = 's1q0'; # surveyOrder index = 3
$rJSON->survey->question([1,1])->{variable} = 's1q1'; # surveyOrder index = 4
$rJSON->survey->section([2])->{variable} = 's2'; # empty section appears as surveyOrder index = 5
$rJSON->survey->section([3])->{variable} = 's3';
$rJSON->survey->question([3,0])->{variable} = 's3q0'; # surveyOrder index = 6
$rJSON->survey->question([3,1])->{variable} = 's3q1'; # surveyOrder index = 7
$rJSON->survey->question([3,2])->{variable} = 's3q2'; # surveyOrder index = 8
$rJSON->lastResponse(2);
$rJSON->survey->answer([0,0,0])->{recordedAnswer} = 3; # value recorded in responses hash for multi-choice answer
$rJSON->survey->answer([0,0,0])->{value} = 100; # set answer score
$rJSON->survey->answer([0,1,0])->{value} = 200; # set answer score
# Reset responses and record first answer
$rJSON->lastResponse(-1);
$rJSON->recordResponses({
'1-0comment' => 'Section 1, question 0 comment',
'1-0-0' => 'My chosen answer',
'1-0-0comment' => 'Section 1, question 0, answer 0 comment',
'0-0-0' => 'I chose the first answer to s0q0',
'0-1-0' => 'I chose the first answer to s0q1',
});
is($rJSON->lastResponse, 4, 'lastResponse at 4 before any gotoExpressions processed');
is($rJSON->nextResponse, 2, 'nextResponse at 2 (s0q1) after first response');
$rJSON->processGotoExpression('blah-dee-blah-blah {');
is($rJSON->lastResponse, 4, '..unchanged after duff expression');
is($rJSON->nextResponse, 2, '..unchanged after duff expression');
$rJSON->processGotoExpression('jump { value(s1q0) == 4} s0');
is($rJSON->lastResponse, 4, '..unchanged after false expression');
$rJSON->processGotoExpression('jump { value(s0q0) == 4} s1');
is($rJSON->nextResponse, 2, '..unchanged after false expression');
$rJSON->processGotoExpression('jump { value(s1q0) == 4} s0; jump { value(s1q0) == 5} s0;');
is($rJSON->lastResponse, 4, '..similarly for multi-statement false expression');
$rJSON->processGotoExpression('jump { value(s0q0) == 4} s0; jump { value(s1q0) == 5} s1;');
is($rJSON->nextResponse, 2, '..similarly for multi-statement false expression');
$rJSON->processGotoExpression('jump { value(s1q0) == 3} DUFF_TARGET');
is($rJSON->lastResponse, 4, '..similarly for expression with invalid target');
$rJSON->processGotoExpression('jump { value(s0q0) == 3} DUFF_TARGET');
is($rJSON->nextResponse, 2, '..similarly for expression with invalid target');
$rJSON->processGotoExpression('jump { value(s1q0) == 3} s0');
is($rJSON->lastResponse, -1, '..but updated to s0 after true expression');
$rJSON->processGotoExpression('jump { value(s0q0) == 3} s1');
is($rJSON->nextResponse, 3, 'jumps to index of first question in section');
$rJSON->processGotoExpression('jump { value(s1q0) == 4} s0; jump { value(s1q0) == 3} s2');
is($rJSON->lastResponse, 4, '..changed again for multi-statement true expression');
$rJSON->processGotoExpression('jump { value(s0q0) == 3} s2');
is($rJSON->nextResponse, 5, '..and updated to s2 with different jump target');
$rJSON->processGotoExpression('jump { score(s1q0) == 100} s0');
is($rJSON->lastResponse, -1, '..and again when score used');
$rJSON->nextResponse(2); # pretend we just finished s0q2
$rJSON->processGotoExpression('jump { value(s0q0) == 3} s3');
is($rJSON->nextResponse, 6, '..and updated to s3 with different jump target');
$rJSON->processGotoExpression('jump { score("s1") == 300} s2');
is($rJSON->lastResponse, 4, '..and again when section score total used');
$rJSON->nextResponse(2); # pretend we just finished s0q2
$rJSON->processGotoExpression('jump { value(s0q0) == 3} s3q1');
is($rJSON->nextResponse, 7, '..we can also jump to a question rather than a section');
$rJSON->nextResponse(2); # pretend we just finished s0q2
$rJSON->processGotoExpression('jump { value(s0q0) == 3} NEXT_SECTION');
is($rJSON->nextResponse, 3, '..we can also use the NEXT_SECTION target');
$rJSON->lastResponse(3); # pretend we just finished s1q0
$rJSON->processGotoExpression('jump { value(s0q0) == 3} NEXT_SECTION');
is($rJSON->nextResponse, 5, '..try that again from a different starting point');
$rJSON->nextResponse(2); # pretend we just finished s0q2
$rJSON->processGotoExpression('jump { value(s0q0) == 3} END_SURVEY');
is($rJSON->nextResponse, 9, '..we can also jump to end with END_SURVEY target');
$rJSON->nextResponse(2); # pretend we just finished s0q2
$rJSON->processGotoExpression('jump { value(s0q0) == 4} s0; jump { value(s0q0) == 3} s1');
is($rJSON->nextResponse, 3, '..first true statement wins');
$rJSON->nextResponse(2); # pretend we just finished s0q2
$rJSON->processGotoExpression('jump { score(s0q0) == 100} s1');
is($rJSON->nextResponse, 3, '..and again when score used');
$rJSON->nextResponse(2); # pretend we just finished s0q2
$rJSON->processGotoExpression('jump { score("s0") == 300} s1');
is($rJSON->nextResponse, 3, '..and again when section score total used');
$rJSON->responses({});
$rJSON->questionsAnswered(-1 * $rJSON->questionsAnswered);