qf
The function qf is used to check if a quota is full.
Note: This function is not supported by CAPI.
qf(quotaName)qf will check if the quota quotaName is full with the current respondent's answers on the questions the quota is based on, and will return true if it is full and false if it is not.
If the respondent qualifies for several quotas within quotaName, qf returns true if one of these is full, and false if none of them are full. If Optimistic Quota is enabled on quotaName then the In Progress counts are considered by the qf() function.
Note: The use of redirects, quotas, status-screened or other solutions with the principle purpose of avoiding the survey "complete" status being reached by a respondent having offered a reasonable amount of responses, is prohibited and will be regarded as an attempt to avoid transaction fee obligations to Forsta.
If a quota genderQuota is based on a question gender, and the quota is full for males and not full for females,
qf("genderQuota")will return true if the respondent has answered Male on the gender question, and false if the respondent has answered Female on the gender question.
Figure 1 - genderQuota check example
Presetting a Quota Question to Check Several Quotas
Note: This example has been superseded by the GetLeastFilledQuotaCodes() function. You should consider using this function instead of the example given here as it is more efficient.
Sometimes you have quotas based on a brand list, where the respondent may qualify for several of the quotas, but you want to pick only one of the brands the respondent has chosen and ask a set of questions for that brand only. Out of the brands the respondent has chosen, there should be picked a brand where the quota is not full yet. To check this, we have to try to set the quota question and use qf to check the quota until we find a brand where the quota is not full.
Let us say there is a multi question brands, and from this question one of the brands answered should be picked, if the quota is not full for that brand. We set up a hidden single question chosen_brand that should hold this brand. The quotas will be set up based on this question in the quota brandsquota.
The script will try to set chosen_brand to a brand chosen in brands, check the quota and continue to next brand if the quota is full. If the quota is not full, the current brand will be used.
JScript example:
var answers = f("brands").categories(); //codes of all brands selected
for(var i : int = 0;i<answers.length;i++) //iterate through the codes
{
var code = answers[i]; //current code
f("chosen_brand").set(code); //try to preset this code
if(!qf("brandsquota")) //check if quota is not full for this code
{
break; //if quota is not full, keep this brand
}
}
JavaScript example:
var answers = f("brands").categories(); //codes of all brands selected
for(var i = 0;i<answers.length;i++) //iterate through the codes
{
var code = answers[i]; //current code
f("chosen_brand").item(code).set(1); //try to preset this code
if(!qf("brandsquota")) //check if quota is not full for this code
{
break; //if quota is not full, keep this brand
}
}
After this script chosen_brand will either be set to a brand where the quota is not full, or if the quota is full for all the brands chosen_brand will be set to the last one. Typically the interview should terminate if the quotas are full for all the brands answered, so after the script there should be a normal quota check in a condition, and then an info and a stop node with quotafull status in the then-branch. The expression in the condition should be like this:
qf("brandsquota")
qc and qt
The function qt is used to retrieve the target set for a particular quota, and qc is used to retrieve the current count.
Note: These functions are not supported by CAPI.
qt(quotaName)qc(quotaName)qt and qc both return an integer. They will return target and count for the quota cell in the quota quotaName corresponding with the current respondent's answers on the questions the quota is based on.
If the respondent qualifies for several quotas within quotaName, qt and qc will return -1.
Note: Quota functions require a database, so will not work in Quick Test / External Quick Test.
Allocate a Respondent to the Lowest Current Quota Cell
This example is superseded by the GetLeastFilledQuotasCodes() function.
Assume for example that you are performing a survey to evaluate respondents’ feelings about five different web page layouts, but you want each respondent to only evaluate one of the layouts. You also want the respondents to be evenly distributed across the five layouts. You could use the following script to select which layout a respondent is shown:
JScript example:
var form = f('q1')
var codes = form.domainValues();
var count = 2000; //a value higher than your highest quota target
var code;
var lowestCode;
/*Loops through all the alternatives in q1 and checks whether the quota count is lowest with that answer*/
for(var i: int=0; i<codes.length; i++) {
var code = codes[i];
form.set(code);
if( qc("quota1") < count ) {
count = qc("quota1");
lowestCode = code;
}
}
form.set(lowerstCode);
Here q1 is the question id for the question with an answer per web page layout tested (should normally be a hidden question). quota1 is the quota id for the quota used in the survey. Now you can create skip logic in the survey based on q1.
JavaScript example:
var form = f('q1')
var codes = form.domainValues();
var count = 2000; //a value higher than your highest quota target
var code;
var lowestCode;
/*Loops through all the alternatives in q1 and checks whether the quota count is lowest with that answer*/
for(var i=0; i<codes.length; i++) {
var code = codes[i];
form.set(code);
if( qc("quota1") < count ) {
count = qc("quota1");
lowestCode = code;
}
}
form.set(lowestCode);
Note: It is important that the quota quota1 does not have any quota cells set to Any for this example. If that is the case then the respondent will qualify for several quota cells, and the qc() function will then return -1 which will stop the script working as required.
If the Total rows or columns of the quota have been changed manually in quota Grid View, then an Any row may be added to the table automatically. The respondent will then always qualify for both one of the answer choices AND the Any cell, hence resulting in -1 being returned by these functions.
GetLeastFilledQuotaCodes
The function GetLeastFilledQuotaCodes is used to retrieve an ordered array of codes for the least filled quota cells for a specific quota.
Note: This function is not supported by CAPI.
GetLeastFilledQuotaCodes(quotaName, N, [code mask])where
quotaName is the name of the quota to be evaluated.N is the number of quota cell codes to be returned if available.[code mask] is an optional array that can be applied as a mask when considering the quota cells.
The array returned is the codes of the quota cells ordered by least filled first, in percentage terms. If the percentage filled values are equal, then the equal cells are ordered randomly. The function can be used with a quota which is based on one question only, the question can be either a single or multi choice question, but there cannot be more than one question used in the quota. If the quota is based on more than 1 question an empty array is returned.
Note: In quick test mode, external test mode and through RDG, this function returns an empty array. See below.
For testing purposes you can create your script so that the GetLeastFilledQuotaCodes() function is only called when in production mode, and script another way to select quota cells for any of the test modes. For example:
if(IsInProductionMode())
{
f("top_5_cars").set(new Array(GetLeastFilledQuotaCodes('quota1', 5,f("cars_driven").categories())));
}
else
{
SetRandomCategories(5,"top_5_cars"); //test mode so select 5 random quota cells
}
For a quota based on multi choice question, answers code(s) without the prefix questionName_ are returned. Quota cells that are already full or that have a target value of 0 are not returned. For a quota based on a single choice question, [Any] cells are not considered and are not retuned by the function. For a quota based on a multi choice question all answers should be [Any] except one which should be [Chosen]; only cells with this structure are considered by the function.
In this example:
Figure 2 - Quota cell example
There is an interactive multi choice question “cars_driven”, a hidden single choice question “car” and a hidden multi choice question “top_5_cars” has the same answer list. Of the cars selected in “cars_driven” the quota cell that is least filled is assigned to the question “car”, and the top five least filled quota cells are assigned to the question “top_5_cars”. This is achieved using the “assignValues” script node, the contents of this is:
//Find the least filled quota cell and assign it
f("car").set(GetLeastFilledQuotaCodes('quota1',
1,f("cars_driven").categories()).toString());//Find the top 5 least filled quota cells and assign them
f("top_5_cars").set(new Array(GetLeastFilledQuotaCodes('quota1', 5,
f("cars_driven").categories())));
The loop “l1” is then masked based on the value assigned to the question “car”, meaning that only the chosen car (least filled quota) will have the loops questions asked.
Note that the ...(new Array()... is required because Forsta Plus returns a standard .NET array type but "Array" in JScript.NET is different; this then eliminates any possible incompatibility.
Other examples of using this function include:
- Display the least filled code:
^GetLeastFilledQuotaCodes('quota1', 1).toString()^- Display the length of the array:
^GetLeastFilledQuotaCodes('quota1', 6).Length^- Display the top 3 filtered by a hard-coded array:
^GetLeastFilledQuotaCodes('quota1', 3, ['1', '2', '3', '4', '5', '6']).toString()^Note: The GetLeastFilledQuotaCodes() function is calculated every time the function is called, therefore if it is executed several times in the same interview, the values returned could be different due to either the state of the quotas changing or due to the random selection of cells that are equally full in percentage terms.
Note: This function does not take into account the Optimistic Quota setting. I.e. in an Optimistic Quota the returned array is ordered based on the percentage of Counter/Target and does not include the In Progress or Optimistic Total Limit.
If Optimistic Quota is enabled on a quota that is used with GetLeastFilledQuotaCodes(), then potentially the function could return quota cell codes where interviews are In Progress and therefore quota cells could overachieve their targets if the In Progress interviews complete. By using qf() and GetLeastFilledQuotaCodes() it is possible to check if the least filled cells are already optimistically full. Below is an example script:
var qtaId = "aQuotaId"; //a quota that has Optimistic Quota enabled (there is no additional advantage in using this script unless Optimistic Quota is enabled)
var qid = "qtaQuestion"; //the question on which the quota is based
var n = 99; //this should be the number of cells defined in the quota
var openCells = GetLeastFilledQuotaCodes(qtaId,n);
var leastFilled;
var stop = false;
if(openCells.length>0)
{
var leastFilled = openCells[0];
for(var i=0; !stop && i<openCells.length; i++)
{
var currCell = openCells[i];
f(qid).set(currCell);
if(qf(qtaId))
{
//optimistically, In Progress interviews might fill this cell soon, discount it
f(qid).set(null);
}
else
{
//this cell is included in Least Fill and also isn't optimistically full, let's use it and stop the for() loop:
stop = true
}
}
if(!f(qid).toBoolean())
{
//all quota cells are OPTIMISTICALLY full, maybe redirect the interview to some quota full handling call block?
}
}
else
{
//all quota cells have achieved targets, redirect the interview to some quota full handling call block
}