Started working on Survey Multiple Choice bundle management.

This commit is contained in:
Patrick Donelan 2009-02-16 00:13:58 +00:00
parent bc9c66c2fd
commit 50091e8e3a
3 changed files with 139 additions and 167 deletions

View file

@ -461,56 +461,12 @@ sub recordResponses {
my $self = shift;
my ($responses) = validate_pos( @_, { type => HASHREF } );
my %mcTypes = (
'Agree/Disagree' => 1,
Certainty => 1,
Concern => 1,
Confidence => 1,
Education => 1,
Effectiveness => 1,
Gender => 1,
Ideology => 1,
Importance => 1,
Likelihood => 1,
Party => 1,
'Multiple Choice' => 1,
'Oppose/Support' => 1,
Race => 1,
Risk => 1,
Satisfaction => 1,
Scale => 1,
Security => 1,
Threat => 1,
'True/False' => 1,
'Yes/No' => 1,
);
my %sliderTypes = (
'Dual Slider - Range' => 1,
'Multi Slider - Allocate' => 1,
Slider => 1,
);
my %textTypes = (
Currency => 1,
Email => 1,
'Phone Number' => 1,
Text => 1,
'Text Date' => 1,
'TextArea' => 1,
);
my %fileTypes = (
'File Upload' => 1,
);
my %dateTypes = (
Date => 1,
'Date Range' => 1,
);
my %hiddenTypes = (
Hidden => 1,
);
# Build a lookup table of non-multiple choice question types
my %knownTypes = map {$_ => 1} $self->survey->specialQuestionTypes;
# We want to record responses against the "next" response section and questions, since these are
# the items that have just been displayed to the user.
my $section = $self->nextResponseSection();
my $section = $self->nextResponseSection();
my @questions = $self->nextQuestions();
# Handle terminal Section..
@ -554,11 +510,12 @@ sub recordResponses {
# Proceed if we're satisfied that response is valid..
if ( defined $answerValue && $answerValue =~ /\S/ ) {
$aAnswered = 1;
if ( exists $mcTypes{ $question->{questionType} } ) {
$self->responses->{ $answer->{id} }->{value} = $answer->{recordedAnswer};
}
else {
if ($knownTypes{$question->{questionType}}) {
$self->responses->{ $answer->{id} }->{value} = $answerValue;
} else {
# Unknown type, must be a multi-choice bundle
# For Multi-choice, use recordedAnswer instead of answerValue
$self->responses->{ $answer->{id} }->{value} = $answer->{recordedAnswer};
}
$self->responses->{ $answer->{id} }->{time} = time;
$self->responses->{ $answer->{id} }->{comment} = $answerComment;

View file

@ -59,6 +59,69 @@ use Storable qw/dclone/;
# The maximum value of questionsPerPage is currently hardcoded here
my $MAX_QUESTIONS_PER_PAGE = 20;
my %MULTI_CHOICE_BUNDLES = (
'Agree/Disagree' => [ 'Strongly disagree', (q{}) x 5, 'Strongly agree' ],
Certainty => [ 'Not at all certain', (q{}) x 9, 'Extremely certain' ],
Concern => [ 'Not at all concerned', (q{}) x 9, 'Extremely concerned' ],
Confidence => [ 'Not at all confident', (q{}) x 9, 'Extremely confident' ],
Education => [
'Elementary or some high school',
'High school/GED',
'Some college/vocational school',
'College graduate',
'Some graduate work',
'Master\'s degree',
'Doctorate (of any type)',
'Other degree (verbatim)',
],
Effectiveness => [ 'Not at all effective', (q{}) x 9, 'Extremely effective' ],
Gender => [qw( Male Female )],
Ideology => [
'Strongly liberal',
'Liberal',
'Somewhat liberal',
'Middle of the road',
'Slightly conservative',
'Conservative',
'Strongly conservative'
],
Importance => [ 'Not at all important', (q{}) x 9, 'Extremely important' ],
Likelihood => [ 'Not at all likely', (q{}) x 9, 'Extremely likely' ],
'Oppose/Support' => [ 'Strongly oppose', (q{}) x 5, 'Strongly support' ],
Party =>
[ 'Democratic party', 'Republican party (or GOP)', 'Independant party', 'Other party (verbatim)' ],
Race =>
[ 'American Indian', 'Asian', 'Black', 'Hispanic', 'White non-Hispanic', 'Something else (verbatim)' ],
Risk => [ 'No risk', (q{}) x 9, 'Extreme risk' ],
Satisfaction => [ 'Not at all satisfied', (q{}) x 9, 'Extremely satisfied' ],
Security => [ 'Not at all secure', (q{}) x 9, 'Extremely secure' ],
Threat => [ 'No threat', (q{}) x 9, 'Extreme threat' ],
'True/False' => [qw( True False )],
'Yes/No' => [qw( Yes No )],
Scale => [q{}],
'Multiple Choice' => [q{}],
);
my @SPECIAL_QUESTION_TYPES = (
'Dual Slider - Range',
'Multi Slider - Allocate',
'Slider',
'Currency',
'Email',
'Phone Number',
'Text',
'Text Date',
'TextArea',
'File Upload',
'Date',
'Date Range',
'Hidden',
);
sub specialQuestionTypes {
return @SPECIAL_QUESTION_TYPES;
}
=head2 new ( $session, json )
Object constructor.
@ -461,24 +524,12 @@ sub getQuestionEditVars {
=head2 getValidQuestionTypes
A convenience method. Returns a list of question types. If you add a question
type to the Survey, you must handle it in the following places: here, updateQuestionAnswers,
recordResponses (ResponseJSON) and administersurvey.js
A convenience method. Returns a list of question types.
=cut
sub getValidQuestionTypes {
return (
'Agree/Disagree', 'Certainty', 'Concern', 'Confidence',
'Currency', 'Date', 'Date Range', 'Dual Slider - Range',
'Education', 'Effectiveness', 'Email', 'File Upload',
'Gender', 'Hidden', 'Ideology', 'Importance',
'Likelihood', 'Multi Slider - Allocate', 'Multiple Choice', 'Oppose/Support',
'Party', 'Phone Number', 'Race', 'Risk',
'Satisfaction', 'Scale', 'Security', 'Slider',
'Text', 'TextArea', 'Text Date', 'Threat',
'True/False', 'Yes/No'
);
return sort (@SPECIAL_QUESTION_TYPES, keys %MULTI_CHOICE_BUNDLES);
}
=head2 getAnswerEditVars ( $address )
@ -888,9 +939,6 @@ sub updateQuestionAnswers {
# Add the default set of answers. The question type determines both the number
# of answers added and the answer text to use. When updating answer text
# first update $address_copy to point to the answer
# TODO: Rather than being hard-coded, these question type/answer bundles should
# be loaded dynamically and customizable by the user (see also getValidQuestionTypes)
if ( $type eq 'Date Range'
or $type eq 'Multi Slider - Allocate'
@ -919,108 +967,41 @@ sub updateQuestionAnswers {
$address_copy[2] = 0;
$self->update( \@address_copy, { 'text', 'Email:' } );
}
elsif ( $type eq 'Education' ) {
my @ans = (
'Elementary or some high school',
'High school/GED',
'Some college/vocational school',
'College graduate',
'Some graduate work',
'Master\'s degree',
'Doctorate (of any type)',
'Other degree (verbatim)',
);
$self->addAnswersToQuestion( \@address_copy, \@ans, { 7, 1 } );
}
elsif ( $type eq 'Party' ) {
my @ans
= ( 'Democratic party', 'Republican party (or GOP)', 'Independant party', 'Other party (verbatim)' );
$self->addAnswersToQuestion( \@address_copy, \@ans, { 3, 1 } );
}
elsif ( $type eq 'Race' ) {
my @ans = ( 'American Indian', 'Asian', 'Black', 'Hispanic', 'White non-Hispanic',
'Something else (verbatim)', );
$self->addAnswersToQuestion( \@address_copy, \@ans, { 5, 1 } );
}
elsif ( $type eq 'Ideology' ) {
my @ans = (
'Strongly liberal',
'Liberal',
'Somewhat liberal',
'Middle of the road',
'Slightly conservative',
'Conservative',
'Strongly conservative',
);
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Security' ) {
my @ans = ( 'Not at all secure', (q{}) x 9, 'Extremely secure', );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Threat' ) {
my @ans = ( 'No threat', (q{}) x 9, 'Extreme threat', );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Risk' ) {
my @ans = ( 'No risk', (q{}) x 9, 'Extreme risk' );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Concern' ) {
my @ans = ( 'Not at all concerned', (q{}) x 9, 'Extremely concerned' );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Effectiveness' ) {
my @ans = ( 'Not at all effective', (q{}) x 9, 'Extremely effective' );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Confidence' ) {
my @ans = ( 'Not at all confident', (q{}) x 9, 'Extremely confident' );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Satisfaction' ) {
my @ans = ( 'Not at all satisfied', (q{}) x 9, 'Extremely satisfied' );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Certainty' ) {
my @ans = ( 'Not at all certain', (q{}) x 9, 'Extremely certain' );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Likelihood' ) {
my @ans = ( 'Not at all likely', (q{}) x 9, 'Extremely likely' );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Importance' ) {
my @ans = ( 'Not at all important', (q{}) x 9, 'Extremely important' );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Oppose/Support' ) {
my @ans = ( 'Strongly oppose', (q{}) x 5, 'Strongly support' );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Agree/Disagree' ) {
my @ans = ( 'Strongly disagree', (q{}) x 5, 'Strongly agree' );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'True/False' ) {
my @ans = qw( True False );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Yes/No' ) {
my @ans = qw( Yes No );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
elsif ( $type eq 'Gender' ) {
my @ans = qw( Male Female );
$self->addAnswersToQuestion( \@address_copy, \@ans, {} );
}
else {
elsif ( my $answerBundle = $self->getMultiChoiceBundle($type) ) {
# We found a known multi-choice bundle.
# Mark any answer containing the string "verbatim" as verbatim
my $verbatims = {};
for my $answerIndex (0 .. $#$answerBundle) {
if ($answerBundle->[$answerIndex] =~ /\(verbatim\)/) {
$verbatims->{$answerIndex} = 1;
}
}
# Add the bundle of multi-choice answers, along with the verbatims hash
$self->addAnswersToQuestion( \@address_copy, $answerBundle, $verbatims );
} else {
# Default action is to add a single, default answer to the question
push @{ $question->{answers} }, $self->newAnswer();
}
return;
}
=head2 getMultiChoiceBundle
Returns a list of answers for each multi-choice bundle.
Currently these are hard-coded but soon they will live in the database.
=cut
sub getMultiChoiceBundle {
my $self = shift;
my ($type) = validate_pos( @_, { type => SCALAR | UNDEF } );
return $MULTI_CHOICE_BUNDLES{$type};
}
=head2 addAnswersToQuestion ($address, $answers, $verbatims)
Helper routine for updateQuestionAnswers. Adds an array of answers to a question.