I'm glad you found that previous post, but that solution has some weaker performance and less flexibility than similar code I have written since then. The latest version of this code is the "Multi-Select Quota" within the Community Question Library:
https://sawtoothsoftware.com/resources/question-library/multi-select-quota
SSI Web doesn't have the ability to import questions from the Community Question Library, but we should be able to recreate it in SSI Web for you.
Start by adding two numeric pass-in fields to your study, with names like "MultiSelectQuotaHelper1" and "MultiSelectQuotaHelper2".
Next we should add two quota questions to our survey, split by a page break. They should be named something like "MultiSelectQuota1" and "MultiSelectQuota2". Both quota questions should have ten quota cells each, all with a cell limit like 99999. The question that respondents skip to if they don't qualify can be set to whatever - it shouldn't actually happen with our limits so large.
The first quota cell of the first quota question should be given this qualification logic:
Begin Unverified Perl
# ****************************************************************************************************
# Parameters
# ****************************************************************************************************
my $quotaBaseName = 'MultiSelectQuota';
my $passInBaseName = 'MultiSelectQuotaHelper';
my $numberOfQuotas = 2; # the number of quota questions, and the maximum number of choices to make for any respondent
my $numberOfQuotaCells = 10; # the number of cells per quota question, and the number of options to choose from
my $numberOfChoices = 2; # the number of choices to make for this respondent, between 0 and $numberOfQuotas
my $membershipOrder = 2; # 1 - sequentially, 2 - least fill, 3 - randomize
my %qualifications = ( # whether the current respondent should qualify for a given cell; by default, all cells are qualified
);
# ****************************************************************************************************
# Run
# ****************************************************************************************************
my @options = ();
# Membership is sequential
if ($membershipOrder == 1) {
@options = (1 .. $numberOfQuotaCells);
}
# Membership is least fill
elsif ($membershipOrder == 2) {
# Calculate the score of each cell
my $leastFill;
for (my $cell = 1; $cell <= $numberOfQuotaCells; $cell++) {
my $completes = 0;
my $limit = 0;
for (my $quota = 1; $quota <= $numberOfQuotas; $quota++) {
$completes += QUOTACELLCOMPLETES($quotaBaseName . $quota, $cell);
$limit += QUOTACELLLIMIT($quotaBaseName . $quota, $cell);
}
my $score = $completes / $limit;
if (exists $leastFill->{$score}) {
push(@{$leastFill->{$score}}, $cell);
}
else {
$leastFill->{$score} = [$cell];
}
}
# Record cells ordered by score, randomizing on ties
foreach my $score (sort {$a <=> $b} (keys(%{$leastFill}))) {
my @cells = @{$leastFill->{$score}};
for (my $i = scalar(@cells); --$i; ) {
my $j = int(rand($i + 1));
next if $i == $j;
@cells[$i, $j] = @cells[$j, $i];
}
foreach my $cell (@cells) {
push (@options, $cell);
}
};
}
# Membership is randomize
else {
@options = (1 .. $numberOfQuotaCells);
for (my $i = $numberOfQuotaCells; --$i; ) {
my $j = int(rand($i + 1));
next if $i == $j;
@options[$i, $j] = @options[$j, $i];
}
}
# Check qualification logic and save to pass-in fields
my $nextChoice = 1;
for (my $i = 0; $i < $numberOfQuotaCells && $nextChoice <= $numberOfChoices; $i++) {
my $cell = $options[$i];
if (!(exists $qualifications{$cell}) || $qualifications{$cell}->()) {
SETVALUE($passInBaseName . $nextChoice++, $cell);
}
}
# Check this cell
return GETVALUE($passInBaseName . 1) == 1;
End Unverified
Lines 5-6 should be updated with the "base name" that you gave the quota questions and pass-in fields.
Lines 14-16 should be updated with the logic that determines whether respondents should qualify for each attribute. If I'm understanding your grid question correctly, it should look like this:
my %qualifications = ( # whether the current respondent should qualify for a given cell; by default, all cells are qualified
1 => sub { my $value = GETVALUE('GridQ_r1'); return $value == 4 || $value == 5; },
2 => sub { my $value = GETVALUE('GridQ_r2'); return $value == 4 || $value == 5; },
3 => sub { my $value = GETVALUE('GridQ_r3'); return $value == 4 || $value == 5; },
4 => sub { my $value = GETVALUE('GridQ_r4'); return $value == 4 || $value == 5; },
5 => sub { my $value = GETVALUE('GridQ_r5'); return $value == 4 || $value == 5; },
6 => sub { my $value = GETVALUE('GridQ_r6'); return $value == 4 || $value == 5; },
7 => sub { my $value = GETVALUE('GridQ_r7'); return $value == 4 || $value == 5; },
8 => sub { my $value = GETVALUE('GridQ_r8'); return $value == 4 || $value == 5; },
9 => sub { my $value = GETVALUE('GridQ_r9'); return $value == 4 || $value == 5; },
10 => sub { my $value = GETVALUE('GridQ_r10'); return $value == 4 || $value == 5; }
);
("GridQ" being the name of your grid question.)
All other quota cells' qualification logic should just be "[PASS-IN HELPER BASE NAME][QUOTA NUMBER] = [QUOTA CELL NUMBER]". So the second cell of the first quota question will look like "MultiSelectQuotaHelper1 = 2" and the third cell of the second quota question will look like "MultiSelectQuotaHelper2 = 3".
Does that all make sense? I know it's a lot.