Unverified Perl can be used for additional flexibility in Sawtooth Scripting.
Sawtooth Script has been implemented using the Perl Programming Language. When [% Q1 + 3 %] is specified in Lighthouse Studio, the server side Perl scripts actually receive that as [% GETVALUE("Q1") + 3; %] which is valid Perl source code. The Perl scripts evaluate this code and return the result. If additional power and flexibility are needed in your Sawtooth Script, you can enter straight Perl code to accomplish the task. This is definitely an advanced area. Lighthouse Studio does not check your Unverified Perl for errors. You must thoroughly test your Perl logic.
Perl Programming Language Basics
• | Unverified Perl can be entered by using the key words "Begin Unverified Perl" and "End Unverified". For example: |
[%
Begin Unverified Perl
GETVALUE("Q1") + 3;
End Unverified
%]
Your Unverified Perl code is not checked for errors.
• | Unverified Perl is executed on the server before the web page is sent down to the browser. So in order to execute this: |
[%
Begin Unverified Perl
GETVALUE("Q1") + 3;
End Unverified
%](
Q1 must have been answered on a previous page. You cannot refer to the answer to a question if the question is being asked on the same page.
• | Each statement must end with a semicolon. For example: |
[%
Begin Unverified Perl
my $intVar = GETVALUE("Q1") + 3;
$intVar = $intVar + (GETVALUE("Q3") / 3);
return $intVar;
End Unverified
%]
Notice the semicolons at the end of each line.
• | The last statement of the Unverified Perl is evaluated and the result returned. For example: |
[%
Begin Unverified Perl
my $intVar = GETVALUE("Q1") + 3;
$intVar = $intVar + (GETVALUE("Q3") / 3);
End Unverified
%]
returns $intVar after all the math is completed. You can also return explicitly using the "return" keyword. For example:
[%
Begin Unverified Perl
my $intVar = GETVALUE("Q1") + 3;
$intVar = $intVar + (GETVALUE("Q3") / 3);
return $intVar;
End Unverified
%]
• | To compare two values, use == for numbers and eq for text. (!= means not equal for numbers and ne means not equal for text.) For example: |
Begin Unverified Perl
if(GETVALUE("Q1") == 5)
{
AIC("Q3");
}
if(GETVALUE("QName") eq "Sally")
{
ADD("ColorList", 4);
}
End Unverified
• | Functions must be in upper case. (There are a few exceptions to this rule. Please see Unverified Perl Functions for details). For example, while creating a constructed list you can specify: |
Begin Unverified Perl
if(GETVALUE("Q1") > 5)
{
AIC("Q3");
}
End Unverified
Notice the functions GETVALUE and AIC are upper case.
• | Question names and list names are case-sensitive and must be enclosed in double quotes when used as function parameters. For example: |
Begin Unverified Perl
ADD("ColorsList");
AIC("q1");
End Unverified
The list ColorsList is enclosed in double quotes. "colorslist" is not valid, because the case does not match the case of the name of the defined list. Question names are similar.
•Avoid using single quotes in unverified Perl. If you need to use a single quote, you can do so in a separate Perl script file that you include.
List Functions:
Sawtooth Script: |
"Unverified" Perl: |
Description: |
•ADD (ListName) •ADD (ListName, Member#) •ADD (ListName, StartMember#, EndMember#) |
•ADD ("ListName") •ADD ("ListName", Member#) •ADD ("ListName", StartMember#, EndMember#) |
Adds members from a specified list to the end of the constructed list. More info.
|
AddSorted (QuestionName) AddSorted (QuestionName, intDirection)
|
ADDSORTED ("QuestionName") ADDSORTED ("QuestionName", intDirection)
|
Adds members rated/ranked within a multi-part radio/rank/numeric question to a constructed list, in ascending or descending order. Specify a 0 for intDirection to indicate descending order; specify 1 for ascending order. |
•AIC (QuestionName) •AIC (QuestionName, Member#) •AIC (QuestionName, StartMember#, EndMember#)
|
•AIC ("QuestionName") •AIC ("QuestionName", Member#) •AIC ("QuestionName", StartMember#, EndMember#)
|
Add If Chosen: Adds members chosen in a select-type question onto a new constructed list. More info.
|
AIE (QuestionName, Value) |
AIE ("QuestionName", Value) |
Add If Equal: Adds members in a grid numeric, grid constant sum, grid ranking, grid with all radio buttons, constant sum, or ranking question that were given answers equal to a specific value. More info. (See also Loop functions.) |
AIG (QuestionName, Value) |
AIG ("QuestionName", Value) |
Add If Greater: Adds members in a grid numeric, grid constant sum, grid ranking, grid with all radio buttons, constant sum, or ranking question that were given answers greater than a specific value. More info. (See also Loop functions.) |
AIL (QuestionName, Value) |
AIL ("QuestionName", Value) |
Add If Less: Adds members in a grid numeric, grid constant sum, grid ranking, grid with all radio buttons, constant sum, or ranking question that were given answers less than a specific value. More info. (See also Loop functions.) |
ANC (QuestionName) ANC (QuestionName, Member#) ANC (QuestionName, StartMember#, EndMember#)
|
ANC ("QuestionName") |
Add if Not Chosen: Adds members not chosen in a select-type question onto a new constructed list. More info. |
ANE (QuestionName, Value) |
ANE ("QuestionName", Value) |
Add if Not Equal: Adds members in a grid numeric, grid constant sum, grid ranking, grid with all radio buttons, constant sum, or ranking question that were given answers not equal to a specific value. More info. (See also Loop functions.) |
BanditMaxDiff(MaxDiffExerciseName, Items) |
BanditMaxDiff("MaxDiffExerciseName", Items) |
Uses Thompson Sampling to select items from a parent list to add to the constructed list to be shown to a respondent within an adaptive bandit MaxDiff exercise. More info. |
DisplayListLabels (ListName, SeparatorText", "FinalSeparatorText")
|
DISPLAYLISTLABELS ("ListName", "SeparatorText", "FinalSeparatorText") |
Returns a string with every list item separated by "SeparatorText" with "FinalSeparatorText" prior to the last list item. For example: DisplayListLabels (fruitlist, "," , "and") returns: grape, peach, and cherry. |
•INSERT (TargetPosition#, ListName) •INSERT (TargetPosition#, ListName, Member#) •INSERT (TargetPosition#, ListName, StartMember#, EndMember#) |
•INSERT (TargetPosition#, "ListName") •INSERT (TargetPosition#, "ListName", Member#) •INSERT (TargetPosition#, "ListName", StartMember#, EndMember#) |
Inserts members from a specified list to an exact position within a constructed list. More info.
|
FormatListLabels (ListName, "BeforeText", AfterText") |
FORMATLISTLABELS ("ListName", "BeforeText", AfterText") |
Returns a string with all list items joined together with "BeforeText" before each item and "AfterText" after each item. For example "<li>" and "</li>" as BeforeText and AfterText returns a bulleted list. |
ListHasParentMember (ListName, ParentMember#)
|
LISTHASPARENTMEMBER ("ListName", ParentMember#) |
Is true if the specified parent member exists in the specified list. More info |
ListLabel (ListName, Member#) |
LISTLABEL ("ListName", Member#) |
Returns the label of a specified member number in a list. |
ListLabelsArray (ListName) |
LISTLABELSARRAY ("ListName") |
Returns a comma-separated list of member labels enclosed in quotes. |
ListLength (ListName) |
LISTLENGTH ("ListName") |
Returns the number of members in the list. |
ListMax (Value) |
LISTMAX (Value) |
Controls the maximum length of a list. |
ListMin (Value) |
LISTMIN (Value) |
Controls the minimum length of a list.
|
ListValue (ListName, Member#) |
LISTVALUE ("ListName", Member#) |
Returns the value of the specified member number in a list. |
ListValuesArray (ListName) |
LISTVALUESARRAY ("ListName") |
Returns a list of list values (example: [1, 4, 6]). |
Mirror (ListName) Mirror (ListName, Offset) |
MIRROR ("ListName") MIRROR ("ListName", Offset) |
Adds list members from the parent list that correspond to the list values in ListName. |
ParentListName() |
PARENTLISTNAME() |
Returns the parent list name of the current constructed list. This is useful to use as input for "ListName" in other list functions. For example: ADD(ParentListName()) |
•Randomize () •Randomize (SeedValue) •Randomize (StartMember#, EndMember#) •Randomize (SeedValue, StartMember#, EndMember#) |
•RANDOMIZE () •RANDOMIZE (SeedValue) •RANDOMIZE (StartMember#, EndMember#) •RANDOMIZE (SeedValue, StartMember#, EndMember#) |
Randomizes the members of a constructed list. |
•Remove (ListName) •Remove (ListName, Member#) •Remove (ListName, StartMember#, EndMember#)
|
•REMOVE ("ListName") •REMOVE ("ListName", Member#) •REMOVE ("ListName", StartMember#, EndMember#) |
Removes the members in the specified list from the constructed list. |
Reverse () |
REVERSE () |
Reverses the members in a list. For example, list members A, B, C, D when reversed become D, C, B, A. |
RIC (QuestionName) RIC (QuestionName, Member#) RIC (QuestionName, StartMember#, EndMember#) |
RIC ("QuestionName") RIC ("QuestionName", Member#) RIC ("QuestionName", StartMember#, EndMember#) |
Remove If Chosen. Removes all items from the list chosen in QuestionName. |
SetListLength (Value) |
SETLISTLENGTH (Value) |
Controls the length of a list. |
SortByLabel () |
SORTBYLABEL () |
Sorts a list based on list labels. Numbers are sorted below letters. |
SortByValue () |
SORTBYVALUE ()
|
Sorts the members in a constructed list with respect to their natural order (lowest to highest value) from their parent predefined list. For example, list members with values 5, 3, 2, 7 would be sorted as 2, 3, 5, 7. |
System Functions:
Sawtooth Script: |
"Unverified" Perl: |
Description: |
Answered(QuestionName) |
ANSWERED("QuestionName") |
Is true if the question was answered by the respondent, false otherwise. |
BlockPosition() |
BLOCKPOSITION() |
Returns the current block number when used within a Randomized Block sequence. |
Browser() |
BROWSER() |
Returns information on respondent's browser. |
CheckSelect (QuestionName, Value) |
CHECKSELECT ("QuestionName", Value) |
For use within Free Format questions. Returns the HTML for a checkbox, including the specific HTML compatible with Graphical Select buttons. More info. |
Debug() |
DEBUG() |
Returns debug information that assists you when testing the questionnaire. |
DisplayTotal (FirstQuestionName, LastQuestionName, Width) |
DISPLAYTOTAL ("FirstQuestionName", "LastQuestionName", Width) |
Returns a grayed out box displaying the total of all questions on the same page beginning with FirstQuestionName and ending with LastQuestionName. |
EncodeForURL(QuestionName) |
ENCODEFORURL("QuestionName") |
Converts characters that are not valid for use in URLs to URL-supported strings. |
GetValue(QuestionName) |
GETVALUE("QuestionName") |
Returns value from data record for the given variable name. See also SetValue(). More info. |
IPAddress() |
IPADDRESS() |
Returns respondent's IP Address. |
GraphicsPath() |
GRAPHICSPATH() |
Returns the system graphics path. |
JavaScript() |
JAVASCRIPT() |
Is true if they have JavaScript, false otherwise. |
Label(QuestionName) |
LABEL("QuestionName") |
Returns the label that is associated with the answer to a single select response type question. |
LinkButton("URL") |
LINKBUTTON("URL") |
Returns an HTML "submit" button (this helps in linking surveys). |
NumChecked(QuestionName) |
NUMCHECKED("QuestionName") |
Returns number of response options checked. QuestionName can be a select checkbox (i.e. Q1), a row or column of checkboxes (i.e. Q1_r1 or Q1_c1), or a Free Format question (i.e. Q1_checked). |
OperatingSystem() |
OPERATINGSYSTEM() |
Returns information on respondent's operating system. |
PageNumber() |
PAGENUMBER() |
Returns current page number. |
PageTime(StartPage) PageTime(StartPage, EndPage) |
PAGETIME(StartPage) PAGETIME(StartPage, EndPage) |
Returns the time (in seconds) between StartPage and EndPage (integer values). |
PopUp("LinkText", "File.htm", Width, Height) |
POPUP("LinkText", "File.htm", Width, Height) |
Returns the HTML for a JavaScript pop-up. File.htm is assumed to be in the graphics folder. Or, File.htm can be elsewhere if referenced with full http:// path. More info |
ProgressBar() |
PROGRESSBAR() |
Returns the progress bar to the screen. Typically placed in the Global Header or Global Footer. |
ProgressBarOff() |
PROGRESSBAROFF() |
Turns off the progress bar on the page where it is placed. |
ProgressBarSet(Value) |
PROGRESSBARSET(Value) |
Sets the Progress Bar to the Value. |
RemovePrevious() |
REMOVEPREVIOUS() |
Removes the Previous button from the page where it is placed. |
QuestionName() |
QUESTIONNAME() |
Returns the name of the current question. May be used in Header 1, etc. sections, and also in skip patterns. |
RadioSelect (QuestionName, Value) |
RADIOSELECT ("QuestionName", Value) |
For use within Free Format questions. Returns the HTML for a radio button, including the specific HTML compatible with Graphical Select buttons. More info. |
RandNum(Seed) RandNum(Seed, Min#, Max#)
|
RANDNUM(Seed) RANDNUM(Seed, Min#, Max#) |
Returns a random number. If one parameter is given, returns a uniform random decimal value between 0 and 1. If three parameters are given, returns a random integer value from Min# to Max#. Seed must be an integer. If Seed is 0, the system clock is used to seed the random number generator. |
RespNum() |
RESPNUM() |
Returns the internal respondent number, a unique number that identifies the respondent. |
ScreenWidth() |
SCREENWIDTH() |
Returns the width of the respondent's browser screen (in pixels). This can be used to detect if the respondent is on a mobile device. |
SetValue(QuestionName, Value) |
SETVALUE ("QuestionName", Value) |
Stores to the data record the value for the given QuestionName. Warning: will overwrite existing data in the target QuestionName. More info. |
Shown(QuestionName) |
SHOWN("QuestionName") |
Is true if the question has been seen by the respondent, or false if the question was not seen by the respondent |
Studyname() |
STUDYNAME() |
Returns the name of the study. |
SysRand() SysRand(Min#, Max#)
|
SYSRAND() SYSRAND(Min#, Max#) |
Returns a random number seeded by the system clock (different seed every time instruction is encountered). |
SystemTime() |
time() |
Returns a number representing the current time (number of non-leap seconds since January 1, 1970). |
ToolTip("LinkText","HelpText") ToolTip("LinkText","HelpText", ToolTip("LinkText","HelpText", Width, Height) |
TOOLTIP("LinkText","HelpText") TOOLTIP("LinkText","HelpText", TOOLTIP("LinkText","HelpText", Width, Height) |
Used for creating a tooltip help upon mouseover. More info. |
TotalPages() |
TOTALPAGES() |
Returns the total number of pages in the study. |
UserAgent() |
USERAGENT() |
Returns respondent's User Agent. |
WriteLog("Message") |
WRITELOG("Message") |
Writes a message to the Survey Log. Type (optional) is a number representing the type of log entry. For Type enter 1 for an "error", 2 for a "warning", and 3 for a "notice". |
Quota Control Functions:
Sawtooth Script: |
"Unverified" Perl: |
Description: |
GetValue(QuestionName) |
GETVALUE("QuestionName") |
Returns the quota cell value to which the respondent has been assigned for the quota question referred to by QuestionName.
An empty string (nothing) is returned if unassigned. A "-1" is returned if the respondent did not qualify due to logic or they qualified for a cell that already had its limit met. A "-2" is returned if all of the quota cell limits for the quota were met and the respondent could not get in. A "-3" is returned if the respondent qualified for a quota cell but then left the survey. While they were gone all of the quota cell limits were met. |
QuotaCellName (QuestionName) |
QUOTACELLNAME ("QuestionName") |
Returns the quota cell name to which the respondent has been assigned; returns empty string (nothing) if unassigned |
IsQuotaCellOpen (QuestionName, QUOTA_CELL_NAME) IsQuotaCellOpen (QuestionName, QUOTA_CELL_VALUE) |
ISQUOTACELLOPEN ("QuestionName", QUOTA_CELL_VALUE) |
Returns true (1) if the cell is open, false (0) if the cell is closed |
QuotaCellRemaining (QuestionName, QUOTA_CELL_NAME) QuotaCellRemaining (QuestionName, QUOTA_CELL_VALUE) |
QUOTACELLREMAINING ("QuestionName", QUOTA_CELL_VALUE)
|
Returns number of completes left to fill the quota cell. Returns 0 if quota cell is full. |
QuotaCellLimit (QuestionName, QUOTA_CELL_NAME) QuotaCellLimit (QuestionName, QUOTA_CELL_VALUE) |
QUOTACELLLIMIT ("QuestionName", QUOTA_CELL_VALUE) |
Return the quota cell limit |
QuotaCellCompletes (QuestionName, QUOTA_CELL_NAME) QuotaCellCompletes (QuestionName, QUOTA_CELL_VALUE) |
QUOTACELLCOMPLETES ("QuestionName", QUOTA_CELL_VALUE) |
Returns number of completes in the quota cell |
AreAllQuotasClosed()
|
AREALLQUOTASCLOSED() |
Returns true if all cells have been closed. This might be useful if you don't want to show a "survey closed" message but would like to skip the respondent to a different survey. |
AreAllQuotaCellsClosed (QuestionName) |
AREALLQUOTACELLSCLOSED ("QuestionName") |
Returns true if all cells have been closed for the specified quota. |
AreAnyQuotasClosed()
|
AREANYQUOTASCLOSED()
|
Returns true if all cells have been closed for any quota.
|
Math Functions:
Sawtooth Script: |
"Unverified" Perl: |
Description: |
Abs (*NUMBER) |
abs (NUMBER) |
Returns the absolute value of NUMBER. |
Ceiling (NUMBER) |
CEILING (NUMBER) |
Rounds the NUMBER up to the closest integer. |
Exp (NUMBER) |
exp (NUMBER)
|
Returns e (2.71828183) raised to the power of NUMBER |
Floor (NUMBER) |
int (NUMBER) |
Rounds the NUMBER down to the closest integer. |
FORMATNUMBER (NUMBER, "ThousandsSeparator", "DecimalSeparator", NumDecimalPlaces) |
FORMATNUMBER (NUMBER, "ThousandsSeparator", "DecimalSeparator", NumDecimalPlaces) |
Formats a number with commas and decimal places. More Information. |
Log10 (NUMBER) |
LOG10 (NUMBER) |
Returns the log (base 10) of NUMBER. |
Ln (NUMBER) |
log (NUMBER) |
Returns the natural log of NUMBER. |
POWER (NUMBER1, NUMBER2) |
POWER (NUMBER1, NUMBER2) |
Returns NUMBER1 raised to the NUMBER2 power. |
ROUND (NUMBER) ROUND (NUMBER, #DECIMALS) |
ROUND (NUMBER, 0) ROUND (NUMBER, #DECIMALS) |
Rounds NUMBER to the #DECIMALS places. If no decimal places are specified, rounds to nearest integer. |
ROUNDTONUMBER (NUMBER, ROUNDTO) ROUNDTONUMBER (NUMBER, ROUNDTO, #DECIMALS) |
ROUNDTONUMBER (NUMBER, ROUNDTO) ROUNDTONUMBER (NUMBER, ROUNDTO, #DECIMALS) |
Rounds NUMBER to the nearest ROUNDTO value, such as to the nearest 10, 25, 50, 100, 250, 500, 1000, 5000, 10000, etc. |
Sqrt (NUMBER) |
sqrt (NUMBER) |
Returns the square root of NUMBER. |
*For all math functions, NUMBER can be any QuestionName that contains a numeric value or any numeric expression (including functions and mathematical operators) that returns a numeric value. |
Loop Functions:
Sawtooth Script: |
"Unverified" Perl: |
Description: |
AIELoopList (Loop_Name, Question_Name, Value) |
AIELOOPLIST ("Loop_Name", "Question_Name", Value) |
Similar to the AIE list function. Adds the list item from the loop list to the constructed list if the answer to the question is equal to Value. |
AIGLoopList (Loop_Name, Question_Name, Value) |
AIGLOOPLIST ("Loop_Name", "Question_Name", Value) |
Similar to the AIG list function. Adds the list item from the loop list to the constructed list if the answer to the question is greater than the Value. |
AILLoopList (Loop_Name, Question_Name, Value) |
AILLOOPLIST ("Loop_Name", "Question_Name", Value) |
Similar to the AIL list function. Adds the list item from the loop list to the constructed list if the answer to the question is less than the Value. |
ANELoopList (Loop_Name, Question_Name, Value) |
ANELOOPLIST ("Loop_Name", "Question_Name", Value) |
Similar to the ANE list function. Adds the list item from the loop list to the constructed list if the answer to the question is not equal to the Value. |
LOOPITERATION ( ) LOOPITERATION (Loop_Name) |
LOOPITERATION ( ) LOOPITERATION ("Loop_Name") |
Returns the current iteration count for the list item for the current loop. Loop Name is used in case more than one loop applies (e.g. nested loops). |
LOOPLABEL ( ) LOOPLABEL (Loop_Name) |
LOOPLABEL ( ) LOOPLABEL ("Loop_Name") |
Returns the label for the list item for the current loop. Loop Name is used in case more than one loop applies (e.g. nested loops). |
LOOPVALUE ( ) LOOPVALUE (Loop_Name) |
LOOPVALUE ( ) LOOPVALUE ("Loop_Name") |
Returns the parent list item number for the list item for the current loop. Loop Name is used in case more than one loop applies (e.g. nested loops). |
String Functions:
Sawtooth Script: |
"Unverified" Perl: |
Description: |
IsNumber (QuestionName) |
ISNUMBER ( GETVALUE("QuestionName")) |
Is true if the entire string is all digits, false otherwise. |
Length (QuestionName) |
length ( GETVALUE("QuestionName")) |
Returns the number of characters contained in the response. |
Mid (QuestionName, BeginPosition, Length) |
MID (GETVALUE("QuestionName"), BeginPosition, Length)
|
Extracts a substring of a string given by QuestionName. The substring is extracted starting at the character number specified in BeginPosition (1-based counting) with length specified in Length. |
TextExists (QuestionName, "TextToLookFor") |
TEXTEXISTS (GETVALUE( "QuestionName"), "TextToLookFor") |
Searches for "TextToLookFor" in the answer of QuestionName. If found, a 1 is returned; if not found, a 0 is returned. |
ToLower (QuestionName) |
lc (GETVALUE("QuestionName")) |
Returns a lowercased version of the response. |
ToUpper (QuestionName) |
uc (GETVALUE("QuestionName")) |
Returns an uppercased version of the response. |
Error Functions:
Sawtooth Script: |
"Unverified" Perl: |
Description: |
ErrCursum () |
ERRCURSUM () |
Returns the current sum of the constant sum question. |
ErrField () |
ERRFIELD () |
Returns the question number on the page. |
ErrMax () |
ERRMAX () |
Returns the maximum value allowed for the question. |
ErrMin () |
ERRMIN ()
|
Returns the minimum value allowed for the question. |
ErrQName () |
ERRQNAME () |
Returns the question name. |
ErrText () |
ERRTEXT () |
Returns the question-specific error message that is optionally specified at the question level, under the Advanced... button.
|
ErrTotal () |
ERRTOTAL () |
Returns the total amount that the responses to the constant sum question should add to. |
CBC Functions:
Sawtooth Script: |
"Unverified" Perl: |
Description: |
CBCAttributeLabel (ExerciseName_CBCQuestionName, AttributePosition#) |
CBCATTRIBUTELABEL ("ExerciseName_CBCQuestionName", AttributePosition#) |
Returns the attribute label for the given attribute row position. Useful if the attribute position is randomized in the design. |
CBCAttributeValue (ExerciseName_CBCQuestionName, ConceptPosition#, LevelTextPosition#) |
CBCATTRIBUTEVALUE ("ExerciseName_CBCQuestionName", ConceptPosition#, LevelTextPosition#) |
Returns the attribute value for the given attribute concept position and level position. Useful if the attribute position is randomized in the design. |
CBCColumnWidth |
CBCCOLUMNWIDTH |
Returns the CSS needed to define the column widths for the CBC task. |
CBCDesignLevelText (ExerciseName_CBCQuestionName, ConceptPosition#, LevelTextPosition#) |
CBCDESIGNLEVELTEXT ("ExerciseName_CBCQuestionName", ConceptPosition#, LevelTextPosition#) |
Returns the level text for the specified CBC question for the specified concept position and level text position. This function is used when researchers want to customize the format of their CBC questions. |
CBCDesignLevelValue (ExerciseName_CBCQuestionName, ConceptPosition#, LevelTextPosition#) |
CBCDESIGNLEVELVALUE ("ExerciseName_CBCQuestionName", ConceptPosition#, LevelTextPosition#) |
Returns the level value for the specified CBC question in the specified concept position and level position within the task. Useful if the attribute position is randomized in the design. |
CBCDesignConceptValue (CBCQuestionName, ConceptPosition#)
|
CBCDESIGNCONCEPTVALUE ("CBCQuestionName", ConceptPosition#) |
Returns the actual concept number from the design that is being displayed to the screen in ConceptPosition#. Position numbers will only differ if concept sorting is in place. This function is used when researchers want to customize the format of their CBC questions. |
CBCNone () |
CBCNONE () |
Returns the "None" text for the CBC question (traditional "None" option only) and is only used in Shelf Facing Display CBC questions. |
CBCVersion () |
CBCVERSION () |
Returns the design version number and question name. This function is useful when creating paper-and-pencil interviews. (Example: D-1, T-CBCRAN1) |
CBCCurrentTask() |
CBCCURRENTTASK() |
Returns the index number for the ith CBC task in the exercise. For the first task it will return a 1, the second one a 2, etc. Must be used inside of the CBC question. |
CBCTotalTasks() |
CBCTOTALTASKS() |
Returns the total number of CBC tasks in the current exercise. Must be used inside of a CBC question. |
ACA Functions:
Sawtooth Script: |
"Unverified" Perl: |
Description: |
ACAAttribute () |
ACAATTRIBUTE () |
Returns the text for the attribute label within the ACARating or ACAImportance questions. |
ACABest () |
ACABEST () |
Within the ACAImportance question, returns the level text for the "best" level rated from the previous ACARating question. |
ACABestLevelLabel (Attribute#, Rank#) |
ACABESTLEVELLABEL (Attribute#, Rank#) |
Returns label for best attribute level of Attribute #. Rank# optional. Rank# of 2 returns second-best attribute level. |
ACABestLevelValue (Attribute#, Rank#) |
ACABESTLEVELVALUE (Attribute#, Rank#) |
Returns level number for best attribute level of Attribute #. Rank# optional. Rank# of 2 returns second-best attribute level number. |
ACAImportance (Attribute#) |
ACAIMPORTANCE (Attribute#) |
Returns the importance score for the attribute, as specified by Attribute#. May be used after the ACAImportance question section. (See also ACAStrictImportance.) |
ACALeastImpAttLabel (Rank#) |
ACALEASTIMPATTLABEL (Rank#) |
Returns label for the least important attribute. Rank# optional. Rank# of 2 returns second-least important attribute. |
ACALeastImpAttValue (Rank#) |
ACALEASTIMPATTVALUE (Rank#) |
Returns attribute number of the least important attribute. Rank# optional. Rank# of 2 returns second-least important attribute number. |
ACAMostImpAttLabel (Rank#) |
ACAMOSTIMPATTLABEL (Rank#) |
Returns label for the most important attribute. Rank# optional. Rank# of 2 returns second-most important attribute. |
ACAMostImpAttValue (Rank#) |
ACAMOSTIMPATTVALUE (Rank#) |
Returns attribute number of the most important attribute. Rank# optional. Rank# of 2 returns second-most important attribute number. |
ACAPriorsBestLevelLabel (Attribute#) |
ACAPRIORSBESTLEVELLABEL (Attribute#) |
Returns the best level text for attribute#, based only on Priors information. |
ACAPriorsBestLevelValue (Attribute#) |
ACAPRIORSBESTLEVELVALUE (Attribute#) |
Returns the best level number for attribute#, based only on Priors information. |
ACAPriorsWorstLevelLabel (Attribute#) |
ACAPRIORSWORSTLEVELLABEL (Attribute#) |
Returns the worst level text for attribute#, based only on Priors information. |
ACAPriorsWorstLevelValue (Attribute#) |
ACAPRIORSWORSTLEVELVALUE (Attribute#) |
Returns the worst level number for attribute#, based only on Priors information. |
ACAStrictImportance (Attribute#) |
ACASTRICTIMPORTANCE (Attribute#) |
Returns the strict importance score for the attribute, as specified by Attribute#. May be used after the ACAImportance question section. |
ACAUtility (Attribute#, Level#) |
ACAUTILITY (Attribute#, Level#)
|
Returns the part-worth utility for the attribute and level, as specified by Attribute# and Level#. May be used after the ACAImportance question section. |
ACAWorst () |
ACAWORST () |
Within the ACAImportance question, returns the level text for the "worst" level rated from the previous ACARating question. |
ACAWorstLevelLabel (Attribute#, Rank#) |
ACAWORSTLEVELLABEL (Attribute#, Rank#) |
Returns label for worst attribute level of Attribute #. Rank# optional. Rank# of 2 returns second-worst attribute level. |
ACAWorstLevelValue (Attribute#, Rank#) |
ACAWORSTLEVELVALUE (Attribute#, Rank#) |
Returns level number for worst attribute level of Attribute #. Rank# optional. Rank# of 2 returns second-worst attribute level number.
|
CVA Functions:
Sawtooth Script: |
"Unverified" Perl: |
Description: |
CVAVersion () |
CVAVERSION () |
Returns the design version number and question name. This function is useful when creating paper-and-pencil interviews with multiple versions. (Example: D-1, T-CVA_1) |
MaxDiff Functions:
Sawtooth Script: |
"Unverified" Perl: |
Description: |
BanditMaxDiff (MaxDiffExerciseName, Items, NumThompsonItems) |
BANDITMAXDIFF ("MaxDiffExerciseName", Items, NumThompsonItems) |
List function for bandit MaxDiff. More info. |
MaxDiffDesignLabel (ExerciseName_ Question#, Position#) |
MAXDIFFDESIGNLABEL ("ExerciseName_ Question#", Position#) |
Returns the item text for the specified MaxDiff question for the specified Position#. This function is used when researchers want to customize the format of their CBC questions. |
MaxDiffDesignValue (ExerciseName_ Question#, Position#) |
MAXDIFFDESIGNVALUE ("ExerciseName_ Question#", Position#) |
Returns the item value for the specified MaxDiff question for the specified Position#. This function is used when researchers want to customize the format of their CBC questions. |
MaxDiffRankAttLabel (ExerciseName, Rank#) |
MAXDIFFRANKATTLABEL ("ExerciseName", Rank#)
|
Returns the list item label for the item with the rank specified. So a rank of 1 would return the list item label with the highest maxdiff logit score. More info. |
MaxDiffRankAttValue (ExerciseName, Rank#) |
MAXDIFFRANKATTVALUE ("ExerciseName", Rank#) |
Returns the list item value for the item with the rank specified. So a rank of 1 would return the list item value with the highest maxdiff logit score. More info. |
MaxDiffRLH(ExerciseName) |
MAXDIFFRLH("ExerciseName") |
Returns the RLH (Root Likelihood) fit statistic for the logit estimation. More info. |
MaxDiffRSQ(ExerciseName) |
MAXDIFFRSQ("ExerciseName") |
Returns the RSQ (Pseudo R-Squared) fit statistic for the logit estimation. More info. |
MaxDiffScore (ExerciseName, ItemIndex) |
MAXDIFFSCORE ("ExerciseName", ItemIndex) |
Returns the maxdiff logit score for the ItemIndex of the list associated with ExerciseName. More info. |
MaxDiffCurrentSet() |
MAXDIFFCURRENTSET() |
Returns the index number for the ith MaxDiff set (question) in the exercise. For the first set it will return a 1, the second one a 2, etc. Must be used inside of the MaxDiff question.
|
MaxDiffTotalSets() |
MAXDIFFTOTALSETS() |
Returns the total number of MaxDiff sets (questions) in the current exercise. Must be used inside of a MaxDiff question.
|
MaxDiffVersion() |
MAXDIFFVERSION() |
Returns the design version number and question name. This function is useful when creating paper-and-pencil interviews involving multiple versions. (Example: D-1, T-MXDIFF_1). Only available within a MaxDiff task. |
ACBC Functions:
Sawtooth Script: |
"Unverified" Perl: |
Description: |
ACBCBYOLabel (ExerciseName, Attribute#) |
ACBCBYOLABEL ("ExerciseName", Attribute#) |
Returns the level label selected in the BYO question for the indicated attribute#. |
ACBCBYOValue (ExerciseName, Attribute#) |
ACBCBYOVALUE ("ExerciseName", Attribute#) |
Returns the level value selected in the BYO question for the indicated attribute#. |
ACBCCurrentCalibration() |
ACBCCURRENTCALIBRATION() |
Returns the index of the current Calibration Concept. Needs to be used inside of an ACBC Calibration. |
ACBCCurrentChoiceTask()
|
ACBCCURRENTCHOICETASK() |
Returns the index of the current Choice Task. Needs to be used inside of an ACBC ChoiceTask. |
ACBCCurrentScreener() |
ACBCCURRENTSCREENER() |
Returns the index of the current Screening Task. Needs to be used inside of an ACBC Screener. |
ACBCIsMustHave (ExerciseName, Attribute#, Level#) |
ACBCISMUSTHAVE ("ExerciseName", Attribute#, Level#) |
Returns True if the attribute and level specified has been declared a "Must Have".
|
ACBCIsUnacceptable (ExerciseName, Attribute#, Level#)
|
ACBCISUNACCEPTABLE ("ExerciseName", Attribute#, Level#)
|
Returns True if the attribute and level specified has been declared "Unacceptable". If referencing a Summed Price attribute, specify a price value rather than the Level#. |
ACBCNumCalibrations() |
ACBCNUMCALIBRATIONS() |
Returns the total number of Calibration Concepts. Can use this inside of a ACBCCalibration. If used outside of an ACBCCalibration needs to have the ACBCExerciseName passed as a parameter. |
ACBCNumChoiceTasks() |
ACBCNUMCHOICETASKS() |
Returns the total number of Choice Tasks. Can use this inside of a ACBCChoiceTask. If used outside of an ACBCChoiceTask needs to have the ACBCExerciseName passed as a parameter. |
ACBCNumScreenedInConcepts (ExerciseName) |
ACBCNUMSCREENEDINCONCEPTS ("ExerciseName") |
Returns the total number of Product Concepts marked "a possibility" by the respondent. NOTE: Does not include the BYO if it is included in the tournament. |
ACBCNumScreeners() |
ACBCNUMSCREENERS() |
Returns the total number of Screening Tasks. Can use this inside of a ACBCScreener. If used outside of an ACBCScreener needs to have the ACBCExerciseName passed as a parameter. |
ACBCWinnerLabel (ExerciseName, Attribute#) |
ACBCWINNERLABEL ("ExerciseName", Attribute#) |
Returns the level label for the choice tournament winner for the indicated attribute# (if no tournament exists, returns nothing). Hint: use ACBCNumScreenedInConcepts to determine if you should skip a question in which you might show the tournament winner. |
ACBCWinnerValue (ExerciseName, Attribute#) |
ACBCWINNERVALUE ("ExerciseName", Attribute#) |
Returns the level value for the choice tournament winner for the indicated attribute# (if no tournament exists, returns nothing). Hint: use ACBCNumScreenedInConcepts to determine if you should skip a question in which you might show the tournament winner. |
BYOCondText(ExerciseName, CondText#)
BYOCondText(ExerciseName, CondText#, XPos, YPos) |
BYOCONDTEXT ("ExerciseName", CondText#)
BYOCONDTEXT ("ExerciseName", CondText#, XPos, YPos) |
Within a BYO question, returns the conditional text/graphic element for the CondText# relationship from the conditional relationship table. If XPos and YPos (values expressed in Pixels) are given, then the conditional element is shown at that fixed position on the screen (hovering graphic). |
Perl Programming Language Basics
There are many books and web sites devoted to teaching Perl. An introductory Perl tutorial can be found at: http://perldoc.perl.org/perlintro.html.
• | Scalars – Scalars can hold single values such as an integer, real number, or text. Scalar names must always begin with a $ sign. All variables in Unverified Perl must be declared using the word "my". For example: |
my $numDays = 12;
my $numTotalSeconds = 0;
my $txtMessage = "The total number of seconds is:";
$numTotalSeconds = $numDays * 24 * 60 * 60;
return $txtMessage . $numTotalSeconds;
Notice that before you can use $numDays, it needs to be declared using my $numDays. The first line declares $numDays as a scalar variable and then assigns it to contain the value 12. When run, the above script returns:
The total number of seconds is: 1036800
(The "." in $txtMessage . $numTotalSeconds concatenates two values.)
• | Arrays – Arrays are variables that hold a collection of items. Array names must begin with an @ sign. For example: |
my @Scores = (55, 22, 4, 17);
my $FirstScore = 0;
$FirstScore = $Scores[0];
The first line above creates an array named Scores. It then initializes @Scores to a list of scores: 55, 22, 4, and 17. To extract the elements of the array, you must replace the @ with a $ and reference the element using [ NUMBER ] where NUMBER is the ith list item, zero based. So [0] returns the 1st item, [1] the 2nd and so on.
• | Hashes – Hashes are variables that hold a collection of items that consist of key value pairs. The values are accessed by referring to their key. Hash names begin with a % sign. For example: |
my %ScoresLookup = ();
%ScoresLookup = (
'Bob' => 55,
'Sally' => 22,
'Frank' => 4,
'Pam' => 17
);
return "Sally has a score of: " . $ScoresLookup{'Sally'};
The above code declares a hash named ScoresLookup. It assigns a set of key value pairs to ScoresLookup. Finally it returns the sentence:
Sally has a score of: 22
Notice that to access an item's value, we replace the % in the hash name with $ and use {'KEY'} where KEY is the key that is associated with a certain value.
• | The "if" statement can be used to conditionally execute code. For example: |
if(GETVALUE("Q1") > 5)
{
AIC("Q3");
}
The AIC("Q3") function is only executed if the answer to Q1 is greater than 5. The following statement is also valid:
if(GETVALUE("Q1") > 5)
{
AIC("Q3");
}
elsif(GETVALUE("Q1") < 5)
{
AIC("Q2");
}
else
{
AIC("Q5");
}
If the answer to Q1 is greater than 5, then AIC("Q3") is executed. If it is less than 5, then AIC("Q2") is executed. If it is equal to 5, the first two tests fail and AIC("Q5") is executed.
When writing many "if" statements be sure to write efficient code. See: Efficient Code section below.
In conditional logic, use the following symbols:
•"&&" for "And"
•"||" for "Or"
•"==" for "="
For example:
if (GETVALUE("Q1") == 3 && (GETVALUE("Q2") > 4 || GETVALUE("Q2") < 100))
{
AIC("Q5");
}
• | The "for" loop allows you to execute a section of code over and over again. For example: |
my @Scores = (55, 22, 4, 17);
my $TotalOfScores = 0;
my $i = 0;
my $FirstScore=0;
for($i = 1; $i <= 4; $i++)
{
$TotalOfScores = $TotalOfScores + $Scores[$i – 1];
}
$FirstScore = $Scores[0];
Another way that you could do this is with a "foreach." For example:
my @Scores = (55, 22, 4, 17);
my $TotalOfScores = 0;
my $SingleScore = 0;
foreach $SingleScore (@Scores)
{
$TotalOfScores = $TotalOfScores + $SingleScore;
}
The "foreach" fills $SingleScore with each value inside @Scores one at a time until it reaches the end of @Scores.
You can create your own Perl functions by using the "sub" keyword. For example:
sub AddTwoNumbers
{
my($NumOne, $NumTwo) = @_;
my $TheSum = $NumOne + $NumTwo;
return $TheSum;
}
The above code creates a new function named "AddTwoNumbers". The line:
my($NumOne, $NumTwo) = @_;
is the syntax required to pass two parameters to the function. To use this new function, use:
my $Result = 0;
$Result = AddTwoNumbers(5, 6);
Result would then be assigned the number 11. When "AddTwoNumbers" is called, 5 is assigned to $NumOne and 6 to $NumTwo. The "return" keyword passes the result from the function back to the caller.
• | Conditional List Logic – In constructed list logic, you might conditionally call a function. For example: |
Begin Unverified Perl
AIC("q1");
if(LISTHASPARENTMEMBER("ListA", 5))
{
ADD("ParentList", 7);
}
End Unverified
This example begins by adding all of the items that were chosen from "q1". An Unverified Perl "if" statement is then used to add list item #7 if list item #5 is in the list.
• | Dynamic Text - This example shows how to use Unverified Perl to show dynamic text to the screen. It also shows how to concatenate . |
[%
Begin Unverified Perl
if(GETVALUE("q1") > 1)
{
return "Tell us about each of your " . GETVALUE("q1") . " cars";
}
else
{
return "Tell us about your car";
}
End Unverified
%]
If the answer to "q1" is greater than 1 (say 5), the question header is in the plural form:
Tell us about each of your 5 cars
If "q1" is 1, the singular form is used:
Tell us about your car
Notice the line:
return "Tell us about each of your " . GETVALUE("q1") . " cars";
The period concatenates values together.
• | Working with Variables and Saving them to the Database – First, create a Free Format question with a variable of type "hidden." Then, include the following text in the HTML section of the Free Format question: |
<input type="hidden" name="ff_income" value="
[%
Begin Unverified Perl
my $TakeHome = 0;
$TakeHome = GETVALUE("QIncomeVar") * .85;
return $TakeHome;
End Unverified
%]
">
The text above defines an HTML hidden input field. The name of the input field is "ff_income" and the value is computed by Sawtooth Script. In the Sawtooth Script, a variable named "$TakeHome" is defined. "$TakeHome" is then assigned the value of the question "QIncomeVar" (answered on a previous page) multiplied by .85 and the result is returned. When the Sawtooth Script runs on the server, it might return:
<input type="hidden" name="ff_income" value="42500">
When the form is submitted, the data field "ff_income" now contains 42500.
You can then use this value throughout your survey and it is saved in your database.
• | Calling Other Perl Scripts – You can use Unverified Perl to call other Perl scripts on your server. For example: |
[%
Begin Unverified Perl
require "CustomPerl.pl";
my $Num = 5;
my $strResult = "";
$strResult = CustomPerl::MyFunction($Num);
End Unverified
%]
The "require" statement above makes all of the Perl code in "CustomPerl.pl" available for you to call in your Lighthouse survey. The function "MyFunction" which is declared in "CustomPerl.pl" is now available.
Perl code can be written in very inefficient ways that could cause your survey to needlessly run slow, and could cause problems on the web server. Below are some tips for writing more efficient code that will require less resources on the server and result in better performance.
•Use "elsif" With Mutually Exclusive Logic. If you have a list of "if" statements, and only one of those statements can ever be true, then you need to use "elsif" (short for "else if").
Consider this code:
if(GETVALUE("Q1") == 1)
{
ADD("brandList", 1);
}
if(GETVALUE("Q1") == 2)
{
ADD("brandList", 2);
}
if(GETVALUE("Q1") == 3)
{
ADD("brandList", 3);
}
Notice that only one of the "if" statements above can ever be true. If "Q1" is equal to 1 then there is no need to test if it is equal to 2 or 3 However the code above always evaluates all of the "if" statements. The code above is better written as:
if(GETVALUE("Q1") == 1)
{
ADD("brandList", 1);
}
elsif(GETVALUE("Q1") == 2)
{
ADD("brandList", 2);
}
elsif(GETVALUE("Q1") == 3)
{
ADD("brandList", 3);
}
Now if "Q1" is equal to 1 all of the rest of the code is ignored. There is no reason to then ask if "Q1" is equal to 2 or 3. Imagine if there were 100 or more of these "if" statements. In this case "elsif" could really help the code be more efficient.
The "GETVALUE" function retrieves a value from the database. Decreasing the number of times it needs to be called can really improve the efficiency of the code and increase performance
•Use Variables. You might consider assigning the result of "GETVALUE" into a variable. This can help with the performance of the code and can also make your code more maintainable. Consider this code:
my $q1_value = GETVALUE("Q1");
if($q1_value == 1)
{
ADD("brandList", 1);
}
elsif($q1_value == 2)
{
ADD("brandList", 2);
}
elsif($q1_value == 3)
{
ADD("brandList", 3);
}
In the example above "GETVALUE" is only called once. The value is then stored into a variable named "$q1_value". That variable can then be used over and over without having to call "GETVALUE" every time. The code is also nice because if you change the name of "Q1" you would only have to update the name in one place.
•Group Similar Code Together. Consider this code:
if(GETVALUE("Q1") == 1)
{
ADD("brandList", 1);
}
if(GETVALUE("Q1") == 1)
{
ADD("brandList", 2);
}
if(GETVALUE("Q1") == 1)
{
ADD("brandList", 2);
}
If "Q1" is equal to 1 the code above will add list items 1, 2, and 3. However the same "if" logic has to run three times. This code would be more efficient if written this way:
if(GETVALUE("Q1") == 1)
{
ADD("brandList", 1);
ADD("brandList", 2);
ADD("brandList", 3);
}
Only one "if" statement is executed.