Logic Dictionary: Difference between revisions

From Lifeguide Wiki
Jump to navigation Jump to search
No edit summary
 
(34 intermediate revisions by 3 users not shown)
Line 3: Line 3:
It is important to insert '''Next''' buttons on your pages (instead of '''Jump''' buttons) whenever possible in order for your logic to work correctly. If you show a page and have a vital line of logic written after you show that page (such as randomisation or saving logic), or have error messages on that page, your intervention will not work correctly if you use a '''Jump''' button - you will jump to another page and skip parts of the logic in your logic file and Error Messages section.
It is important to insert '''Next''' buttons on your pages (instead of '''Jump''' buttons) whenever possible in order for your logic to work correctly. If you show a page and have a vital line of logic written after you show that page (such as randomisation or saving logic), or have error messages on that page, your intervention will not work correctly if you use a '''Jump''' button - you will jump to another page and skip parts of the logic in your logic file and Error Messages section.


==A==
'''Tip for new users:''' many of the examples below use a variable called <code>username</code> to represent the identifier of the currently logged-in end-user. Older interventions created this variable manually near the top of the logic file (see [[#set|<code>set</code>]]). Current best practice is to use the built-in [[#currentuser|<code>currentuser()</code>]] function instead, which always returns the identifier of whoever is currently logged in, with nothing to set up first - simply use <code>currentuser()</code> anywhere you see <code>username</code> in an example below.


= <code> add </code> =
'''How to read the examples below:''' where a command takes information in brackets, e.g. <code>savevalue(username, "valuename", value)</code>, each item inside the brackets is called an '''argument''', and the commas separate one argument from the next. Most entries below list what each argument means and what you should put there. Text written in quotation marks (e.g. <code>"seconds"</code>) must be typed exactly as shown, including the quotation marks themselves - this tells the intervention you mean a fixed piece of text, not a variable.


This may also be written as '''sum''' or '''+'''. The '''add''' command is used when performing calculations in the logic.
=A=
 
== <code> add </code> ==
 
'''add''' can also be written as '''sum''' or '''+'''. It adds two or more numbers together - for example, several numeric responses, or scores you have calculated earlier in the logic.
 
<code>add (value1, value2, value3, ...)</code>
 
* '''value1, value2, ...''' - the numbers you want to add together. Each one can be a plain number, an interaction response (e.g. <code>page1.interaction1</code>), or a variable you have already calculated (e.g. <code>score1</code>). You can list as many as you need, separated by commas.


'''Example 1'''
'''Example 1'''
Line 19: Line 27:
The '''add''' or '''sum''' commands can also be used to calculate variables that have been set earlier in the session:
The '''add''' or '''sum''' commands can also be used to calculate variables that have been set earlier in the session:


<code>set overallscore to add (score1, score2, score3)</code>
<code>set overallscore to sum (score1, score2, score3)</code>
 
If you only ever need to add or subtract exactly two numbers, you can use <code>+</code> and <code>-</code> instead, for example:
 
<code>set score to (100 - page1.interaction1)</code>
 
Make sure you leave a space on either side of the <code>-</code> symbol.


== <code> after </code> ==
== <code> after </code> ==


The '''after''' command is used after a page to perform functions that relate to that page.
'''after''' lets you run logic once a particular page has been shown to the end-user - for example, to check their answers and decide which page to send them to next.


It is likely that you will use this command quite regularly in your intervention logic. The most common way of using the '''after''' command is with the '''if''' and '''goto''' commands, e.g.
<code>after pagename if (condition) goto nextpage</code>


<code>show page1</code>
* '''pagename''' - the page this logic relates to. The logic will run once the end-user has been shown this page and clicked Next.
* '''condition''' - (optional) something that must be true for the rest of the line to happen, e.g. a response given on that page. You can leave this out if you always want the logic to run.
* '''nextpage''' - the page to send the end-user to if the condition is true.


<code>after page1 if (any_commands_you_want_to_relate_to_this_page) goto page3</code>
You will use the '''after''' command regularly. It is most often combined with '''if''' and '''goto''', as above, but any command in this dictionary can be used after a page in the same way.


'''Example 1'''
'''Example 1'''
Line 37: Line 53:
show page3</code>
show page3</code>


In the above example, the end-user will be directed to '''page3''' if they have answered '''yes''' to '''interaction1''' on '''page1'''. If they answer '''no''' to '''interaction1''', they will be directed to the next line of logic and will see '''page2'''.
In the above example, the end-user will be directed to '''page3''' if they answered '''yes''' to '''interaction1''' on '''page1'''. If they answered anything else, they will carry on to the next line of logic and will see '''page2'''.
 
'''NB If you use the <code>after</code> command with the <code>goto</code> command, the page that you goto should NOT be the next page shown in your logic, it should be a page further down in your logic''' as in the example above.


As will be seen throughout this dictionary, any command can be used with the '''after''' command.
'''Note:''' if you use '''after''' with '''goto''', the page you send the user to (in the example above, '''page3''') should '''not''' be the very next page in your logic - it needs to be a page further down, as shown above. Otherwise the end-user would see that page twice.


== <code> and </code> ==
== <code> and </code> ==


Can also be written as '''&&'''.
'''and''' can also be written as '''&&'''. It combines two or more conditions into one, and is only true when '''every''' condition inside it is true. It is commonly used to:
* check that several responses have been given before showing tailored feedback
* combine several checks into a single line of logic after a page


The '''and''' command can be used for a number of reasons:
<code>and (condition1, condition2, ...)</code>


# If there is more than one response that is involved in presenting tailored advice to end-users, i.e. if one response and another response is needed to show feedback to an end-user.
* '''condition1, condition2, ...''' - the individual conditions to check, separated by commas. You can list two or more. '''and''' is only true if '''all''' of them are true.
# If you need to perform a number of logic commands after a page


'''Example 1'''
'''Example 1'''
Line 56: Line 71:
<code>show page6 if (and(page3.exercise = "yes", page3.intensity = "moderate", page3.frequency = "three"))</code>
<code>show page6 if (and(page3.exercise = "yes", page3.intensity = "moderate", page3.frequency = "three"))</code>


End-users will be shown page6 if they selected '''yes''' to the interaction '''exercise''' on '''page3''', '''moderate''' to the interaction '''intensity''' on '''page3''' and '''three''' to the interaction '''frequency''' on '''page3'''.
End-users will be shown page6 only if they selected '''yes''' for the interaction '''exercise''' on '''page3''', '''moderate''' for '''intensity''' on '''page3''', '''and''' '''three''' for '''frequency''' on '''page3'''. If any one of those three answers is different, page6 will not be shown.
 


'''Example 2'''
'''Example 2'''


<code>after login_successful if (and( not(hasseen(username, "q_demographics")), (isempty (loadvalue(username, "baselinecomplete"))) )) goto q_intro </code>
<code>after login_successful if (and( not(hasseen(currentuser(), "q_demographics")), (isempty (loadvalue(currentuser(), "baselinecomplete"))) )) goto q_intro </code>


End-users will be shown '''q_intro''' if they have not seen page '''q_demographics''' and if the variable '''baselinecomplete''' is empty (i.e. '''the variable baselinecomplete hasn't been saved because the end-user hasn't finished the baseline questionnaire).
End-users will be shown '''q_intro''' if both of the following are true: they have not seen page '''q_demographics''', '''and''' the variable '''baselinecomplete''' is empty (i.e. it hasn't been saved yet, because they haven't finished the baseline questionnaire).


== <code> append </code> ==
== <code> append </code> ==


The <code>append</code> command allows you to attach logic commands together, and/or to attach a variable to a string (a string is something that you create - a sequence of characters between quotation marks, e.g. "session1".
'''append''' joins two or more pieces of text (and/or variables) together into a single, longer piece of text. A "piece of text" - also called a '''string''' - is anything written between quotation marks, such as <code>"session1"</code>, or a variable that already holds text.
 
<code>append (part1, part2, part3, ...)</code>
 
* '''part1, part2, ...''' - the pieces of text or variables you want to join together, in the order you want them joined, separated by commas. You can list as many as you need.


<code>append</code> is most often used with the logic commands <code>sendemail </code> and <code>cancelemail</code>
'''append''' is most often used with '''sendemail''' and '''cancelemail''', to build a unique name for each email (see below), but it is useful anywhere you need to combine text.


'''Example 1'''
'''Example 1'''


<code>sendemail (append(username,"user_reg1"), username, "StressLess - Session 1 is ready", append("Dear ", loadvalue (username, "personsname"), "\n\n", reg_part1, reg_part2), 10) </code>
<code>sendemail (append(currentuser(),"user_reg1"), currentuser(), "StressLess - Session 1 is ready", append("Dear ", loadvalue (currentuser(), "personsname"), "\n\n", reg_part1, reg_part2), 10) </code>


In this example, '''append''' is used to attach:
In this example, '''append''' is used twice:


*a username (which has been set in a previous part of the logic) to the unique name of the email message:
*to join the current end-user's identifier onto a fixed piece of text, so that the email's name is unique to that end-user:
<code>append (username,"user_reg1")</code>
<code>append (currentuser(),"user_reg1")</code>


*a user's name to the text used in an email message (the append function here allows the content of the email message to be made of different parts):
*to build the text of the email out of several separate pieces:
<code>append ("Dear ", loadvalue (username, "personsname"), "\n\n", reg_part1, reg_part2)</code>
<code>append ("Dear ", loadvalue (currentuser(), "personsname"), "\n\n", reg_part1, reg_part2)</code>


The '''\n\n''' in the logic above means a new line in the email message content.
<code>\n\n</code> is a special code that means "start a new paragraph" in the email.


'''Example 2'''
'''Example 2'''


<code>cancelemail (append("user_regs2rem", username), username) </code>
<code>cancelemail (append("user_regs2rem", currentuser()), currentuser()) </code>
 
Here, '''append''' joins a fixed label onto the end-user's identifier, to rebuild the same unique email name that was used when the email was first set up:
<code>append ("user_regs1", currentuser())</code>
 
'''Example 3'''
 
'''append''' is not only useful for emails - it can also combine interaction responses, and the result can be saved with '''savevalue''':
 
<code>set fullname to append(registration.firstname, " ",registration.surname)
savevalue(currentuser(),"fullname", fullname)
</code>
 
This takes the responses given to the '''firstname''' and '''surname''' interactions on the '''registration''' page and combines them (with a space in between) into a single variable called '''fullname'''.
 
''Important:'' every item you pass to '''append''' must be a variable or a piece of text in quotation marks (even a single space, like " "). If you forget the quotation marks around plain text, it may not work.
 
'''Example 4'''
 
In this example, we add extra information onto a value that has already been saved, rather than replacing it:
 
<code>savevalue(currentuser(), "oldgoals","RESULTS_") if isempty(loadvalue(currentuser(),"oldgoals"))
set oldgoals to loadvalue(currentuser(),"oldgoals")
savevalue(currentuser(), "oldgoals", (append(oldgoals,"_", printtime(currenttime(),"dMy"),"_", goalsetpage.newgoal)))</code>


In this example, '''append''' is used to attach:
First, if the variable "oldgoals" doesn't exist yet, we create it and save a starting value. We then load whatever is currently stored in "oldgoals". Finally, we save "oldgoals" again, appending today's date and the new goal (from the page "goalsetpage") onto the end of whatever was already there. Underscores are used to separate each piece of data so it stays readable. Over time, this builds up a single variable that looks like this:


*a username to the unique name of the email message:
"RESULTS_181016_firstgoal_191016_secondgoal_221016_thirdgoal"
<code>append ("user_regs1", username)</code>


== <code> authenticateuser </code> ==
== <code> authenticateuser </code> ==


This is important logic for ensuring that a user is registered with the intervention and is written directly after the '''show login''' logic. This logic should be used with the <code> makenewuser </code> logic function, which creates a new user.
'''authenticateuser''' checks that a username (or email address) and password entered by an end-user match a registered account. It is used together with [[#makenewuser|<code>makenewuser</code>]], which is the command that creates the account in the first place, and is normally written directly after the logic that shows your login page.
 
<code>authenticateuser (username, password)</code>


* '''username''' - the page.interaction where the end-user typed their username or email address, e.g. <code>login.username</code>.
* '''password''' - the page.interaction where the end-user typed their password, e.g. <code>login.password</code>.


The <code>authenticateuser</code> command can be used in the logic (intervention.lgil) file or in the Error Message logic.
'''authenticateuser''' can be used either in the main logic file, or inside a page's '''Error Messages''' tab.


'''Example 1'''
'''Example 1'''
Line 108: Line 152:
show login_confirmation </code>
show login_confirmation </code>


The logic in this example is written in the logic file. The details that the end-user enters into the username and password interactions on the login page will be used to check they are a registered user. If they are not a registered user, they will be shown the '''login_fail''' page.
Here the logic is written in the logic file. If the username and password entered on the login page match a registered account, the end-user is sent to '''login_confirmation'''. If not, they will see the '''login_fail''' page.
 


'''Example 2'''
'''Example 2'''
Line 116: Line 159:
show err2 if (not(authenticateuser(username, password)))</code>
show err2 if (not(authenticateuser(username, password)))</code>


The logic in this example is written in the '''Error Messages''' tab of a page. The details that the end-user enters into the username and password interactions on the login page will be used to check they are a registered user. If they are not a registered user, they will be shown the error message '''err2''' and will not be able to proceed to the next page.
Here the logic is written in the '''Error Messages''' tab of the login page itself. If the username and password entered do not match a registered account, the end-user sees the error message '''err2''' and cannot move on to the next page.


=B=
=B=
== <code> begin </code> ==
== <code> begin </code> ==


The <code>begin</code> key command is always used with the <code>end</code> key command
'''begin''' marks the start of a named section of logic, and is always paired with an [[#end|<code>end</code>]] command that marks where the section finishes.
 
<code>begin sectionname</code>


If your intervention has separate sessions or groups (e.g. different weekly sessions in your behavioural intervention, or a different set of pages for different user groups) then splitting your pages into sections can make it easier for you to organise parts of your intervention and find sections easily.  
* '''sectionname''' - a name you choose for this section, e.g. <code>session1</code>. It must be different from any page or object name already used in your intervention.


Things to remember when splitting you intervention into sections:
If your intervention has separate sessions or groups (e.g. different weekly sessions, or different sets of pages for different study arms), grouping the related logic into a named section can make your logic file much easier to navigate.


* If you begin a section, you should always end the section.
A few things to remember:
* All the logic related to the section must be between <code>begin</code> and <code>end</code>
* Every '''begin''' must have a matching '''end'''.
* The name of the section should not be the same as any unique name that has been given to an object or page in your intervention.
* All the logic that belongs to the section must sit between its '''begin''' and '''end'''.
* As you can only ever end the section that you are currently in, you do not need to write the section name after end.
* You only ever need to close the section you are currently in, so you do not write the section's name after '''end''' - just <code>end</code> on its own.


'''Example 1'''  
'''Example 1'''


<code> begin session1 </code>
<code> begin session1 </code>
Line 142: Line 187:
<code>end </code>
<code>end </code>


This will begin session1, show page1 and page2, and will end session1. All the pages related to session1 (page1 and page2) are between begin session1 and end.
This begins the section '''session1''', shows '''page1''' and '''page2''', then ends '''session1'''. Both pages sit between '''begin session1''' and '''end''', so they belong to that section.


'''Example 2 Beginning and ending a section within another section'''
'''Example 2 - Beginning and ending a section within another section'''


<code> begin stress</code>
<code> begin stress</code>
Line 166: Line 211:
<code>end </code>
<code>end </code>


This will begin the section '''stress'''.  
This begins the outer section '''stress'''. Inside it, the section '''causes''' begins, showing '''page1''' and '''page2'''; the first '''end''' closes '''causes'''. Then the section '''relieve''' begins, showing '''page3''' and '''page4'''; the next '''end''' closes '''relieve'''. The final '''end''' closes the outer section, '''stress'''.
The section '''causes''' will then begin and '''page1''' and '''page2''' in the section '''causes''' will be shown.
The first <code>end</code> will end the section '''causes'''.  
The section '''relieve''' will then begin and '''page3''' and '''page4''' will be shown.
The next <code>end</code> will end the section '''relieve'''. The final <code>end</code> will end the section '''stress'''.


=C=
=C=
Line 176: Line 217:
== <code> cancelemail </code> ==
== <code> cancelemail </code> ==


Used to cancel an email that has been set up earlier in the logic.
'''cancelemail''' stops an email that was previously scheduled with [[#sendemail|<code>sendemail</code>]] from being sent, as long as it hasn't gone out yet. You might use this to:
 
* stop a reminder email if the end-user has already done the thing the reminder was about (e.g. logging in for a session)
You may want to:
* stop a "nudge" email to a study coordinator if the end-user has since completed the questionnaire it was chasing
* cancel emails to end-users (e.g. if you set up email reminders for end-users to login to upcoming sessions, you will need to cancel them if they login before the email is due to be sent.
* cancel emails to the study coordinator (e.g. if you set up email reminders to notify the study coordinator when end-users do not complete study questionnaires, you will need to cancel them if they complete the questionnaires.


This command uses the same basic formula:
<code>cancelemail (uniquename, emailaddress)</code>


<code>cancelemail (append(username, "unique_email_name", e-mail address))</code>
* '''uniquename''' - must exactly match the unique name that was used when the email was originally set up with '''sendemail''' (this is usually built with <code>append(currentuser(), "some_label")</code> - see the examples below).
* '''emailaddress''' - the address the (now cancelled) email would otherwise have been sent to.


'''Example 1'''
'''Example 1'''


<code>cancelemail(append(username, "email_session2r"), username)</code>
<code>cancelemail(append(currentuser(), "email_session2r"), currentuser())</code>


This will cancel the email '''email_session2r''' for an end-user. The '''append''' function links an end-user's '''username''' to the name of the email ('''email_session2r''') to give each email a unique name.
This cancels the email '''email_session2r''' for the current end-user. '''append''' rebuilds the same unique name (end-user identifier + '''email_session2r''') that was used to schedule the email in the first place.


'''Example 2'''
'''Example 2'''


<code>cancelemail(append(username,"q1_notcomplete"), "study@test.ac.uk")</code>
<code>cancelemail(append(currentuser(),"q1_notcomplete"), "study@test.ac.uk")</code>


This will cancel the email '''q1_notcomplete''' that was due to be sent to '''study@test.ac.uk'''. The '''append''' function links an end-users '''username''' to the name of the email ('''q1_notcompleteto''') to give each email a unique name.
This cancels the email '''q1_notcomplete''' that was due to be sent to '''study@test.ac.uk''' (a fixed address, rather than the end-user's own address).


== <code> cancelsms </code> ==
== <code> cancelsms </code> ==


This command cancels an SMS message that has already been set up earlier on in the logic.
'''cancelsms''' stops a text message that was previously scheduled with [[#sendtext|<code>sendtext</code>]] from being sent, as long as it hasn't gone out yet. It works the same way as '''cancelemail''', but for text messages.


It uses a similar basic formula that is used for cancelling emails except it uses the <code>cancelsms</code> command and a phone number:
<code>after pagename if cancelsms ("uniquename", phonenumber) goto nextpage</code>


<code> after pagename if cancelsms ("unique name for sms message", phonenumber) goto nextpage</code>
* '''"uniquename"''' - must exactly match the unique name used when the text message was originally scheduled with '''sendtext'''.
* '''phonenumber''' - the phone number the (now cancelled) text message would otherwise have been sent to.


== <code> changepassword </code> ==
== <code> changepassword </code> ==


Enables end-users to change their password.
'''changepassword''' lets an already-registered end-user change their password, as long as they can enter their current password correctly.
 
<code>changepassword (username, oldpassword, newpassword)</code>
 
* '''username''' - the identifier for the end-user changing their password. Use <code>currentuser()</code>.
* '''oldpassword''' - the page.interaction where they entered their current password.
* '''newpassword''' - the page.interaction where they entered their new, chosen password.


Please see the LifeGuide Community Website for a tutorial intervention that shows how to create the pages and write the logic for this.
Please see the LifeGuide Community Website for a tutorial intervention showing how to build the pages and logic for this.


'''Example 1'''
'''Example 1'''


<code> after passworddetails if changepassword (username, passworddetails.old, passworddetails.new) goto confirmchange</code>
<code> after passworddetails if changepassword (currentuser(), passworddetails.old, passworddetails.new) goto confirmchange</code>


This will allow a password to be changed if the old password is correctly entered into the interaction called '''old''' on page '''passworddetails''', and a new password is entered into the interaction called '''new''' on page '''passworddetails'''.
This changes the end-user's password, as long as their current password is entered correctly into the interaction called '''old''' on the page '''passworddetails''', and their new password is entered into the interaction called '''new''' on the same page.


== <code> checkemailvalidity </code> ==
== <code> checkemailvalidity </code> ==


Checks that the e-mail address a user has entered contains an @ symbol.
'''checkemailvalidity''' does a basic check that an email address entered by an end-user contains an @ symbol.
 
<code>checkemailvalidity (interactionname)</code>
 
* '''interactionname''' - the interaction where the end-user typed their email address, e.g. <code>email</code>.


This command is used with an error message and is written in the '''Error Messages''' tab (please refer to [[Adding Error Messages]] for information about writing error messages).
This command is normally used together with an error message, written in the '''Error Messages''' tab (please see [[Adding Error Messages]] for more information about writing error messages).


'''Example 1'''
'''Example 1'''
Line 228: Line 279:
<code> show invalidemail if (not (checkemailvalidity (email)))</code>
<code> show invalidemail if (not (checkemailvalidity (email)))</code>


'''invalidemail''' is the name of an error message and '''email''' is the name of the interaction on this page where the end-user would enter their e-mail address.
'''invalidemail''' is the name of an error message, shown when the interaction called '''email''' on this page doesn't contain a valid-looking address.


== <code> checkphonenumbervalidity </code> ==
== <code> checkphonenumbervalidity </code> ==


Checks that the mobile number a user has entered begins with '''+44''' or ''''0'''.
'''checkphonenumbervalidity''' checks that a mobile number entered by an end-user begins with '''+44''' or '''0'''.
 
<code>checkphonenumbervalidity (interactionname)</code>
 
* '''interactionname''' - the interaction where the end-user typed their phone number, e.g. <code>phone</code>.


This command is used with an error message (please see [[Adding error messages]] for more information.
This command is normally used with an error message (please see [[Adding error messages]] for more information).


'''Example 1'''
'''Example 1'''
Line 240: Line 295:
<code> show invalidnumber if (not (checkphonenumbervalidity (phone)))</code>
<code> show invalidnumber if (not (checkphonenumbervalidity (phone)))</code>


In this example '''invalidnumber''' is the name of the error message and '''phone''' is the name of the interaction on this page where the end-user would enter their phone number.  
'''invalidnumber''' is the name of the error message, shown when the interaction called '''phone''' on this page doesn't look like a valid number.


Please note that this logic is only set up to work with UK based numbers. Researchers will need to create their own error messages to check the correct numbers are entered for international numbers.
This check is designed for UK phone numbers only. If your study needs to accept international numbers, you will need to write your own error message logic instead.


== <code> checkuserenabled </code> ==
== <code> checkuserenabled </code> ==
'''checkuserenabled''' checks whether a user's account is currently '''enabled'''. An account can become disabled if, for example, a researcher disables it manually (e.g. because a participant has withdrawn from a study, or their account needs to be temporarily suspended).
<code>checkuserenabled (usernameoremail)</code>
* '''usernameoremail''' - the identifier to check - usually the page.interaction where the end-user entered their username or email address while logging in.
'''checkuserenabled''' is most often used together with '''authenticateuser''' as part of your login logic, so that a user is only let in if they have entered the correct details '''and''' their account is still enabled.
'''Example 1'''
<code>show login
after login if (and(authenticateuser (login.username, login.password), checkuserenabled (login.username))) goto login_confirmation
show login_fail
show login_confirmation </code>
The end-user is only directed to '''login_confirmation''' if the username and password they entered are correct '''and''' their account is enabled. If either check fails, they are shown the '''login_fail''' page.


== <code> checkuserexists </code> ==
== <code> checkuserexists </code> ==


This command checks whether an email address or username has already been registered with the intervention (i.e. if the details that have been entered are already registered with another user). This command is often used with an error message (please see the '''How to guide''' for details on how to write error messages)
'''checkuserexists''' checks whether a username or email address has already been registered with the intervention - for example, to stop someone signing up twice with the same details.
 
<code>checkuserexists (usernameoremail)</code>
 
* '''usernameoremail''' - the interaction where the end-user typed the username or email address you want to check, e.g. <code>email</code>.
 
This command is often used with an error message (please see the '''How to''' guide for details on how to write error messages).


'''Example 1'''
'''Example 1'''
Line 254: Line 332:
<code>show registeredemail if (checkuserexists (email))</code>
<code>show registeredemail if (checkuserexists (email))</code>


In this example '''registeredemail''' is the name of the error message that would show if a user enters an email address that has already been registered in the text box called '''email'''.
'''registeredemail''' is the name of the error message shown if the end-user enters an email address (into the interaction called '''email''') that is already registered to another user.


== <code> comparetimes </code> ==
== <code> comparetimes </code> ==
 
This command can be used to compare two points in time.
'''comparetimes''' works out the difference between two points in time, and converts that difference into whichever unit you choose (seconds, minutes, hours, days, weeks or months).
 
<code>comparetimes (time1, time2, "unit")</code>
 
* '''time1''' - the earlier point in time you are comparing, e.g. a time you saved previously with <code>loadvalue(currentuser(), "sometime")</code>.
* '''time2''' - the later point in time you are comparing, e.g. <code>currenttime()</code>.
* '''"unit"''' - what you want the difference measured in: <code>"seconds"</code>, <code>"minutes"</code>, <code>"hours"</code>, <code>"days"</code>, <code>"weeks"</code> or <code>"months"</code> (don't forget the '''s''' at the end of each one).
 
The result is '''time2''' minus '''time1''', converted into the unit you chose - so it will normally be a positive number if '''time2''' is later than '''time1'''.


'''Example 1'''
'''Example 1'''


This example shows how <code>comparetimes</code> can be used to control users’ access to different sessions or pages within an intervention.
This example shows how '''comparetimes''' can be used to control end-users' access to different sessions or pages within an intervention.
 
There is no need to create your own <code>username</code> variable before using '''comparetimes''' - simply use <code>currentuser()</code> wherever you need to identify the end-user (see [[#currentuser|<code>currentuser()</code>]]).
 
The order of your logic matters when using '''comparetimes''':
 
'''1.''' Show the page users see before they are directed to a particular session (e.g. "mainpage"):
 
<code>show</code> mainpage


'''2.''' Write the logic that sends the user to a particular session or page, depending on how much time has passed:


In your logic, you will first need to create a new variable (e.g. "username") which will tell the intervention which user times need to be compared for: 
<code>after</code> mainpage <code>if</code> ( <code>comparetimes</code> ( <code>loadvalue</code> ( currentuser(), <code>"session4time"</code>) , <code>currenttime</code> ( ), <code>"seconds"</code> ) <code>>=</code> 120 ) <code>goto</code> endpage


<code>set</code> username <code>to</code> login.name
This says: if at least 120 seconds (two minutes) have passed since the value <code>"session4time"</code> was saved, send the user to '''endpage'''.


<code>if</code> ( <code>not</code> ( <code>isempty</code> ( signup.name ) ) ) <code>set</code> username to signup.name
<code>after</code> mainpage <code>if</code> ( <code>comparetimes</code> ( <code>loadvalue</code> ( currentuser(), <code>"session3time"</code> ), <code>currenttime</code> ( ), <code>"seconds"</code> ) <code>>=</code> 120 ) <code>goto</code> session4


(For this logic to work, you will need to have already created '''login''' and '''signup''' pages, which contain text-entry interactions to allow end-users to enter their email address and password)
This says: if at least two minutes have passed since '''session3''' was completed, let the user continue to '''session4'''.
 


The order of your logic is very important when using the <code>comparetimes</code> function:
<code>after mainpage if ( comparetimes ( loadvalue ( currentuser(), "session3time" ), currenttime ( ), "seconds" ) <= 120 ) goto waitpage</code>
 


'''1.''' You first need to show the page users see before they are directed to particular sessions (e.g. "mainpage"):
This says: if less than two minutes have passed since '''session3''' was completed, send the user to a '''waitpage''' instead, since they cannot continue yet.


<code>show</code> mainpage
Repeat this pattern for every session or page you want to control access to. The variables <code>"session3time"</code> and <code>"session4time"</code> are created in step 3, below.


'''3.''' Finally, show the individual pages or sessions, and record the time each one was completed:


'''2.''' Using the <code>comparetimes</code> function you now need to write the logic which directs the user to a particular session or page of the intervention:   
<code>show</code> waitpage


<code>after</code> mainpage <code>if</code> ( <code>comparetimes</code> ( <code>loadvalue</code> ( username, <code>"session4time"</code>) , <code>currenttime</code> ( ), <code>"seconds"</code> ) <code>>=</code> 120 ) <code>goto</code> endpage
<code>show</code> session3


This tells the intervention that the user can continue to the end of the website if the difference between the current time, and the time the user completed session4, is more than or equal to two minutes.  <code>“seconds”</code> may be replaced by <code>“minutes”</code>, <code>“hours”</code>, <code>“days”</code>, <code>“weeks”</code> or <code>“months”</code> (Don’t forget to end each with an ‘'''s'''’!) 
<code>after</code> session3 <code>if</code> ( <code>savevalue</code> ( currentuser(), <code>"session3time"</code>,
<code>currenttime</code> ( ) ) )<code>goto</code> session3end


<code>show</code> session3end


<code>after</code> mainpage <code>if</code> ( <code>comparetimes</code> ( <code>loadvalue</code> ( username, <code>"session3time"</code> ), <code>currenttime</code> ( ), <code>"seconds"</code> ) <code>>=</code> 120 ) <code>goto</code> session4
Using [[#currenttime|<code>currenttime</code>]], this saves a new variable, <code>"session3time"</code>, recording the moment the user completed session3. This is the value that '''comparetimes''' will read back in step 2.


This line tells the intervention that the user can continue to session4 of the intervention if it has been at least two minutes since they completed session3
So, altogether, this example compares the time a user completed a section of the intervention with the current time, to decide whether enough time has passed to let them continue.


'''Example 2'''


<code>after mainpage if ( comparetimes ( loadvalue ( username, "session3time" ), currenttime ( ), "seconds" ) <= 120 ) goto waitpage</code>
In this example we use '''comparetimes''' to break the time until Christmas 2016 down into weeks, days, hours, minutes and seconds, so it can be displayed to the user in a friendly way.


This line of logic tells the intervention that the user cannot continue to session 4 because it has been less than two minutes since they completed session 3.  Users are directed to a “waitpage” instead.
<code>set timenow to (currenttime())
set christmas to (1482624000)


Repeat this process for the various sessions or pages contained within your intervention, for which you want to control access.  The variables <code>"session3time"</code> and <code>"session4time"</code> are created in step 3.
set weeks to (comparetimes(timenow,christmas,"weeks"))
set days to (comparetimes(timenow,christmas,"days"))
set hrs to (comparetimes(timenow,christmas,"hours"))
set mins to (comparetimes(timenow,christmas,"minutes"))


'''3.''' Finally, using the <code>show</code> function you need to display the individual pages or sessions of your intervention, e.g.:
set days2 to (days - (weeks*7))
set hrs2 to (hrs - (days*24))
set mins2 to (mins - (hrs*60))
set secs to ((christmas - timenow) - (mins*60))
</code>


<code>show</code> waitpage
This first uses '''comparetimes''' to work out the '''total''' difference between now and Christmas in weeks, in days, in hours and in minutes. But we don't want to display "total days" or "total hours" - we want a friendly breakdown, like a countdown timer would show (e.g. "2 weeks, 3 days, 4 hours...").


<code>show</code> session3
To do that, we take the total number of days and subtract the days already counted in the weeks figure, so what's left is less than 7. We do the same for hours (subtracting whole days) and minutes (subtracting whole hours).


<code>after</code> session3 <code>if</code> ( <code>savevalue</code> ( username, <code>“session3time”</code>,  
For seconds, we simply take the raw difference between '''christmas''' and '''timenow''' and subtract the whole minutes we've already counted - there's no need to use '''comparetimes''' for this step, because '''currenttime''' is already measured in seconds.
<code>currenttime</code> ( ) ) )<code>goto</code> session3end


<code>show</code> session3end
To display the countdown on a page, the following logic can be used:


Using the <code>currenttime function</code> (see [[2.15 currenttime]]), this logic instructs the intervention to save a new variable <code>“session3time”</code>. This new variable records the time at which the user completed session3.  
<code>show intro
 
set intro.hrs to hrs2
So, in this example, the intervention compares the time at which the user completed a given section of the intervention, with the current time, to determine whether enough time has elapsed to allow them to continue on to the next session.
set intro.mins to mins2
set intro.secs to secs
set intro.days to days2
set intro.weeks to weeks
</code>


== <code> contains </code> ==
== <code> contains </code> ==


Used with multiple-choice interactions. It is used to show tailored information based on a specific response an end-user has given.
'''contains''' is used with multiple-choice interactions, to check whether one particular option was among those an end-user selected.
 
<code>interactionname contains "value"</code>
 
* '''interactionname''' - the multiple-choice interaction to check, e.g. <code>page1.exercise</code>.
* '''"value"''' - the '''Unique Response Name''' of the option you're checking for, in quotation marks.


'''Example 1'''
'''Example 1'''
Line 324: Line 436:
<code> after page1 if (page1.exercise contains "none") goto page4</code>
<code> after page1 if (page1.exercise contains "none") goto page4</code>


In this example, the end-user will be directed to '''page4''' if they had selected '''none''' to the interaction '''exercise''' on '''page1'''.
The end-user is directed to '''page4''' if '''none''' was one of the options they selected for the interaction '''exercise''' on '''page1'''.
 
'''Example 2'''
 
<code> after page1 if (or( page1.exercise contains "1day", page1.exercise contains "2days" )) goto page4</code>
 
The end-user is shown '''page4''' if they selected either '''1day''' or '''2days''' for the interaction '''exercise''' on '''page1'''.
 
== <code> converttointeger </code> ==
 
Interactions where an end-user types in a number - such as a text-entry interaction asking for someone's age - store the response as text (a series of characters), not as a number. This means the response can't reliably be used with comparison commands (<code>morethan</code>, <code>lessthan</code>, etc.) or calculation commands (<code>add</code>, <code>multiply</code>, etc.) until it has been converted into a whole number. '''converttointeger''' does this conversion for you.
 
<code>converttointeger (interactionname)</code>
 
* '''interactionname''' - the text-entry interaction whose response you want to convert, e.g. <code>signup.age</code>. The response should only contain digits (a whole number) for the conversion to work correctly.
 
'''Example 1'''
 
<code>show screening_fail if (converttointeger(signup.age) < 18)</code>


This shows the error message '''screening_fail''' if the number entered into the text-entry interaction '''age''' on the '''signup''' page converts to less than '''18'''.


'''Example 2'''
'''Example 2'''


<code> after page1 if (or( page1.exercise contains "1day", page1.exercise contains "2days" )) goto page4</code>
<code>savevalue(currentuser(), "age_years", converttointeger(signup.age))</code>


An end-user will be shown '''page4''' if they selected '''1day''' or '''2days''' to the interaction '''exercise''' on '''page1'''.
This converts the text response given to the '''age''' interaction into a whole number, and saves it as the variable '''age_years''' for the current end-user, so it can be used in calculations later in the intervention.


== <code> countif </code> ==
== <code> countif </code> ==


This command can be used to count how many interactions an end-user has filled in.
'''countif''' counts how many of a list of conditions are currently true - for example, how many interactions on a page an end-user has filled in.
 
<code>countif (condition1, condition2, ...)</code>
 
* '''condition1, condition2, ...''' - the conditions to check, separated by commas. '''countif''' returns the number of these that are true.


'''Example'''
'''Example'''


<code>after page1 if (countif (not (isempty (page1.interaction1))), (not (isempty (page1.interaction2))), (not (isempty (page1.interaction3))), (not (isempty (page1.interaction4)))) <3) goto page4</code>
<code>after page1 if (countif( not(isempty(page1.interaction1)), not(isempty(page1.interaction2)), not(isempty(page1.interaction3)), not(isempty(page1.interaction4)) ) < 3) goto page4</code>


This example counts how many interactions on page1 that the enduser fills in. If they respond to less than 3 of the interactions they will be directed to page4 of the interaction.
This checks four interactions on '''page1''' and counts how many of them have '''not''' been left empty (i.e. how many the end-user has answered). If they have answered fewer than 3 of the 4, they are directed to '''page4'''.


== <code> currenttime </code> ==
== <code> currenttime </code> ==


This command instructs the intervention logic to load or save the time as it is at that particular moment.  
'''currenttime()''' returns the date and time at the exact moment it runs. It takes no arguments - it is always written with empty brackets, <code>currenttime()</code>, which tells the intervention this is a function rather than a variable you have created yourself.
 
You can use '''currenttime''' to record when something happened (by saving it), or to compare against a time you saved earlier (using [[#comparetimes|<code>comparetimes</code>]]).
 
'''1.''' There is no need to create your own username variable before using '''currenttime''' - simply use <code>currentuser()</code> wherever you need to identify the end-user (see [[#currentuser|<code>currentuser()</code>]]).
 
'''2.''' To save the time a user completes a particular section of your intervention (in this example, "session 3"):
 
<code>show session3</code>
 
<code>after session3 if ( savevalue ( currentuser(), "session3time", currenttime ( ) ) )goto session3end</code>
 
<code>show session3end</code>
 
This saves the moment the user completes the session3 page as a new variable called <code>"session3time"</code>.


The <code>currenttime</code> function can be used to create new variables which save the time at which users completed a particular session of the intervention. 
'''3.''' '''currenttime''' can also be used as a reference point to compare against, which is particularly useful for putting time controls on when users can access particular sessions (see also [[#comparetimes|<code>comparetimes</code>]]):


'''1.''' In your logic, you will first need to create a new variable (e.g. “username”) which will tell the intervention which particular user a time is being saved for: 
<code>after mainpage if ( comparetimes ( loadvalue ( currentuser(), "session3time" ), currenttime ( ), "minutes" ) >= 120 ) goto session4</code>


<code>set username to login.name</code>
This lets the user continue to session 4 if it has been at least two hours since they completed session 3.


<code>if ( not ( isempty ( signup.name ) ) ) set username to signup.name</code>
<code>after mainpage if ( comparetimes ( loadvalue ( currentuser(), "session3time" ), currenttime ( ), "minutes" ) <= 120 ) goto waitpage</code>


(For this logic to work, you will need to have already created “login”, “signup” pages which contain free text interactions to allow the user to enter their name or other identifier such as an email address – see also [[1.12 set]])
This sends the user to a "waitpage" instead, if less than two hours have passed since they completed session 3.


'''2.''' Using the “username” variable you have just created, you can then save the time at which each user completes a particular section of your intervention, in this case ‘session 3’: 
'''currentuser()''' and '''midnight()''' work the same way as '''currenttime()''' - all three are functions that take no arguments, so they are always written with empty brackets.


<code>show session3</code>  
== <code> currentuser </code> ==


<code>after session3 if ( savevalue ( username, “session3time”, currenttime ( ) ) )goto session3end</code>  
'''currentuser()''' returns the identifier (i.e. the username) of whichever end-user is currently logged in to the intervention. It takes no arguments - it is always written with empty brackets, <code>currentuser()</code>. It can be used anywhere you would otherwise need a username variable - for example with <code>savevalue</code>, <code>loadvalue</code>, <code>sendemail</code>, <code>hasseen</code> and most other commands that refer to a specific end-user.


<code>show session3end</code>  
'''Best practice:''' older interventions had to create their own <code>username</code> variable near the top of the logic file, by loading it from the login or signup page (see [[#set|<code>set</code>]], Example 1). '''currentuser()''' removes the need for this step, because it always refers to whichever end-user is logged in at that point in the intervention - there is nothing to set up first. This is now the recommended way to refer to the current end-user throughout your logic.


Here, the logic instructs the intervention to save the time at the particular moment a user completes the session 3 page. The saved time is represented as a new variable called <code>"session3time".</code> 
'''Note:''' '''currentuser()''' only returns a sensible result once someone has actually logged in (for example, after '''authenticateuser''' or '''makenewuser''' has run successfully). Using it on a page shown before login, such as the login page itself, will not identify anyone.


'''3.''' The <code>currenttime</code> function can also be used as a comparison or reference point.  This is particularly useful if you want to put time controls on when users can access particular sessions of the website (see also [[2.12 comparetimes]]):   
'''Example 1'''


<code>after mainpage if ( comparetimes ( loadvalue ( username, "session3time" ), currenttime ( ), "minutes" ) >= 120 ) goto session4</code>  
<code>savevalue(currentuser(), "session1complete", "yes")</code>


This line tells the intervention that the user can continue to session 4 of the intervention if it has been at least two hours since they completed session 3
This saves the variable '''session1complete''' for whichever end-user is currently logged in - there is no need to set up a separate username variable first.


<code>after mainpage if ( comparetimes ( loadvalue ( username, "session3time" ), currenttime ( ), "minutes" ) <= 120 ) goto waitpage</code>
'''Example 2'''


This line of logic tells the intervention that the user cannot continue to session 4 because it has been less than two hours since they completed session 3. Users are directed to a “waitpage” instead.
<code>show welcome
set welcome.firstname to loadvalue(currentuser(), "firstname")</code>


You may have noticed that the <code>currenttime</code> function is always followed by ().  These empty brackets tell the intervention that <code>currenttime</code> should act as a logic function rather than an intervention variable that you have created yourself.
This loads the value '''firstname''' that was previously saved for the current end-user, and displays it on the page '''welcome''' in place of the word 'firstname'.


=D=
=D=
Line 383: Line 533:
== <code> decimalplaces </code> ==
== <code> decimalplaces </code> ==


This command will round a number to a specified number of decimal places. For example, it would round 6.6666666 to 6.67 if 2 decimal places was selected or 6.6667 for 4 decimal places. If you want to round a number to 0 decimal places (i.e. you want a whole number), the simpler <code>round</code> command can be used.
'''decimalplaces''' rounds a number to a specified number of digits after the decimal point. For example, it would round 6.6666666 to 6.67 if you asked for 2 decimal places, or to 6.6667 for 4 decimal places. If you want to round to a whole number (0 decimal places), the simpler [[#round|<code>round</code>]] command can be used instead.
 
<code>decimalplaces (number, decimalplacecount)</code>
 
* '''number''' - the number (or a variable/calculation that produces a number) you want to shorten.
* '''decimalplacecount''' - how many digits you want to keep after the decimal point.
 
You cannot use '''decimalplaces''' to abbreviate whole numbers to a number of significant figures (e.g. turning 1,234,567 into 1,234,600) by asking for a negative number of decimal places - a negative number here is simply treated as 0. To round a whole number like this, use '''round''' instead (see Example 3 of [[#round|<code>round</code>]]).


'''Example 1'''
'''Example 1'''
Line 391: Line 548:
<code>set numberpi to decimalplaces(3.1415926,4)</code>
<code>set numberpi to decimalplaces(3.1415926,4)</code>


This will set the value of <code>numberpi</code> to 3.1416.
This sets the value of '''numberpi''' to 3.1416.
 


'''Example 2'''
'''Example 2'''
Line 414: Line 570:
</code>
</code>


Firstly we get the radius from the user's interaction on <code>circle_page</code>.
First we get the radius from the user's response on '''circle_page'''. Then we set the value of pi. Then we calculate the area of the circle using the formula area = pi × (radius × radius). We then shorten the result to 2 decimal places for display, while still keeping the full, unrounded value stored in '''carea''' in case we want to use it in further calculations later (like the volume of a cylinder). On '''results_page''' we show the user the area of the circle, to 2 decimal places.
 
== <code> default </code> ==
 
'''default''' sets an interaction on a page to show a previously saved value, so the end-user sees their earlier answer already filled in. It is used together with the [[#save|<code>save</code>]] command - see '''save''' for an example.
 
To recall information the end-user entered earlier on the '''same''' page (rather than a different page or session), use [[#saveandload|<code>saveandload</code>]] instead.
 
== <code> deletevalue </code> ==
 
'''deletevalue''' removes a value that was previously saved with [[#savevalue|<code>savevalue</code>]]. This is useful when you want to clear a saved value so a fresh answer can be stored later in the intervention - for example, because an end-user is updating information about themselves that can change over time.
 
<code>deletevalue (username, "valuename")</code>


Then we set the value of pi.
* '''username''' - the end-user whose saved value you want to remove. Use <code>currentuser()</code>.
* '''"valuename"''' - the exact name that was used when the value was originally saved with '''savevalue''', in quotation marks.


Then we calculate the area of the circle using the formula area=pi*(radius*radius).
'''Example 1'''


We then shorten the value back to 2 decimal places. We still have the full value stored in case we want to calculate things with it later on - like the volume of a cylinder.
<code>deletevalue(currentuser(), "currentgoal")
savevalue(currentuser(), "currentgoal", goalpage.newgoal)</code>


On <code>results_page</code> we show the user the area of the circle, to 2 decimal places.
This deletes the previously saved value '''currentgoal''' for the current end-user, before saving a new response to the same variable. Deleting the old value first ensures that only the most recent goal is stored, rather than the new value being added alongside the old one.


== <code> divide </code> ==
== <code> divide </code> ==


The symbol <code>/</code> can also be used. The command <code>divide</code> is used when performing calculations.  
'''divide''' is used when performing calculations. The symbol <code>/</code> can also be used instead.
 
<code>value1 / value2</code>
 
* '''value1''' - the number being divided (the dividend).
* '''value2''' - the number to divide it by (the divisor).


'''Example 1'''
'''Example 1'''
Line 432: Line 607:
<code> set score1 to (page1.interaction1 / page1.interaction2)</code>
<code> set score1 to (page1.interaction1 / page1.interaction2)</code>


'''score1''' would be the result of dividing the response given in '''interaction1''' by the response given in '''interaction2'''.
'''score1''' is the result of dividing the response given for '''interaction1''' by the response given for '''interaction2'''.


'''Example 2'''
'''Example 2'''
Line 438: Line 613:
<code> set overallscore to (score1 / score2)</code>
<code> set overallscore to (score1 / score2)</code>


In this example, '''overallscore''' is calculated by dividing '''score1''' by '''score2''', where '''score1''' and '''score2''' have already been calculated elsewhere in the logic.
Here, '''overallscore''' is calculated by dividing '''score1''' by '''score2''', where both have already been calculated elsewhere in the logic.


=E=
=E=
== <code> else </code> ==
'''else''' is used only together with [[#if|<code>if</code>]]. It lets you specify something to do when the '''if''' condition on the line above is '''not''' met.
<code>if not(or(isempty(page1.q1),isempty(page1.q2))) set page1_complete to 1
else set page1_complete to 0</code>
This checks whether both interactions on '''page1''' have been answered. If they have, '''page1_complete''' is set to 1. The '''else''' line then sets '''page1_complete''' to 0 if they have '''not''' both been answered.


== <code> end </code> ==
== <code> end </code> ==


Please see <code>begin</code> for details of how to use <code>end</code>. The <code>end</code> command is always used with the <code>begin</code> command.
'''end''' closes a section that was opened with [[#begin|<code>begin</code>]]. Please see '''begin''' for details and examples. '''end''' takes no arguments - you never need to repeat the section's name, since it always closes whichever section is currently open.


=F=
=F=
Line 450: Line 635:
== <code> for </code> ==
== <code> for </code> ==


The <code>for</code> key command is used with the <code>save</code> and <code>graph</code> key commands.
'''for''' is used together with the [[#save|<code>save</code>]] and [[#graph|<code>graph</code>]] commands, to say which end-user a page or a piece of graph data belongs to (e.g. <code>save page1 for currentuser()</code>). See those entries for full examples.


=G=
=G=
Line 456: Line 641:
== <code> getuserid </code> ==
== <code> getuserid </code> ==


This function gives you the database ID for a user, which is a number that is unique to each LifeGuide server. This number is automatically generated and can be used to uniquely identify a user without having to refer to their identifier (i.e. username). This number can also be included in your data export by ticking the '''User Number''' box when you export your data.
'''getuserid''' returns the database ID for a user - a number that LifeGuide generates automatically and that is unique to each account on that server. This can be useful if you need a short, unique identifier for a user without referring to their username or email address directly. It can also be included in your data export by ticking the '''User Number''' box when you export your data.
 
<code>getuserid (username)</code>
 
* '''username''' - the end-user whose database ID you want. Use <code>currentuser()</code>.


'''Example 1'''
'''Example 1'''


<code>getuserid(username)</code>
<code>getuserid(currentuser())</code>


== <code> goto</code> ==
== <code> goto</code> ==


The <code>goto</code> command is always used with the <code>after</code> command. It tells the logic which page the user should '''goto''' after that line. See <code>after</code> for details.
'''goto''' is always used together with the [[#after|<code>after</code>]] command. It tells the logic which page to send the end-user to next.
 
<code>after pagename if (condition) goto nextpage</code>
 
* '''nextpage''' - the page the end-user should be sent to when the condition is true. See '''after''' for a full explanation and examples.


== <code> graph </code> ==
== <code> graph </code> ==


The <code>graph</code> key command is used when you have used the graph interaction. It is used to plot the information given by end-users to the graph.
'''graph''' is used together with the graph interaction, to plot information given by end-users onto a graph - for example, showing someone their weight or mood over time.
 
It always follows the same two-part pattern, and requires end-users to have a registered account.
 
'''1.''' Wherever you collect the data you want to plot, record it with:


This key command always follows the same formula and requires users to set up a user account.
<code>graph interactionvalue to "variablename" for username</code>


<code>graph value to "data variable determined on the graph interaction" for unique_identifier_for_the_end-user_e.g._a_username</code>
* '''interactionvalue''' - the response you want to plot, written as <code>page.interaction</code> (e.g. <code>progresschart.kg</code>).
* '''"variablename"''' - a name you choose for this piece of data, in quotation marks. Use the same name every time you record data for the same graph.
* '''username''' - the end-user this data point belongs to. Use <code>currentuser()</code>.


Another line of logic is then needed for the page where the graph occurs. This will also always follow the same formula:  
'''2.''' On the page where the graph interaction itself is shown, add a line to tell it which data to display:


<code>set pagename.graph-1 to graph "data variable determined on the graph interaction" for username</code>
<code>set pagename.graph-1 to graph "variablename" for username</code>


Here, pagename.graph-1 is the automatically generated name of the graph that has been put on the page where the graph occurs.
Here, '''pagename.graph-1''' is the name LifeGuide automatically gives to a graph interaction (you can check the exact name in the interaction's properties), and '''"variablename"''' must match the name used when the data was recorded in step 1.


''' Example1'''
'''Example 1'''


In this example the number entered in the interaction ‘kg’ on the page ‘progresschart’ will be used as the data for the “weight” variable for the graph. The variable username has been set earlier in the logic as the unique identifier for the end-user (see the <code>set</code> key command for more information).
In this example, the number entered into the interaction '''kg''' on the page '''progresschart''' is recorded as the data for a graph variable called "weight".


<code>show progresschart
<code>show progresschart
graph progresschart.kg to "weight" for username</code>
graph progresschart.kg to "weight" for currentuser()</code>


Later in the logic the following line is needed after the page where the graph occurs:
Later in the logic, on the page where the graph is actually displayed:


<code>show weightgraph
<code>show weightgraph
set weightgraph.graph-1 to graph "weight" for username</code>
set weightgraph.graph-1 to graph "weight" for currentuser()</code>


A full tutorial for using graphs will soon be available.
A full tutorial for using graphs will soon be available.
Line 497: Line 696:
== <code> hasseen </code> ==
== <code> hasseen </code> ==


<code>hasseen</code> is used to show end-users pages based on what they have or have not seen before.  
'''hasseen''' checks whether an end-user has already been shown a particular page, so you can tailor what they see next based on their previous visits.
 
<code>hasseen (username, "pagename", scope)</code>
 
* '''username''' - the end-user to check. Use <code>currentuser()</code>.
* '''"pagename"''' - the unique name of the page you want to check, in quotation marks.
* '''scope''' - (optional, only relevant if your intervention uses sessions - see below) leave this out entirely to check previous sessions only, or write <code>"true"</code> to include the current session, or <code>"this"</code> to check the current session only.


Tip - if you have more than one session in your intervention, we recommend that you use '''savevalue''' and '''loadvalue''' instead of hasseen as these values can be edited after your intervention has gone live (this is useful in case something goes wrong in your intervention).
'''Tip:''' if your intervention has more than one session, we recommend using [[#savevalue|<code>savevalue</code>]] and [[#loadvalue|<code>loadvalue</code>]] instead of '''hasseen''', since saved values can be corrected after your intervention has gone live if something goes wrong, whereas page-view history cannot.


'''Example 1'''
'''Example 1'''


If you wanted to show end-users a different page each time they logged in depending on what sessions they had seen before you may use the hasseen command like so:
If you want to show end-users a different page each time they log in, depending on which sessions they have already seen, you can use '''hasseen''' like this:


<code>show login</code>
<code>show login</code>


<code>show s1welcome if (not(hasseen (username, "s1welcome")))</code>
<code>show s1welcome if (not(hasseen (currentuser(), "s1welcome")))</code>


<code>show s2welcome if (not(hasseen (username, "s2welcome")))</code>
<code>show s2welcome if (not(hasseen (currentuser(), "s2welcome")))</code>


<code>show s3welcome if (not(hasseen (usernme, "s3welcome")))</code>
<code>show s3welcome if (not(hasseen (currentuser(), "s3welcome")))</code>


This would mean that the first time they login they would see the page '''s1welcome'''. The next time they log in, because they have already seen the '''s1welcome''' page, the logic will skip that line and show '''s2welcome''' because they have not yet seen the '''s2welcome''' page.
The first time someone logs in, they will see '''s1welcome'''. The next time, because they have already seen '''s1welcome''', the logic skips that line and shows '''s2welcome''' instead, since they have not yet seen it.


'''Example 2'''
'''Example 2'''


The hasseen logic can also be used without <code>not</code>, to tailor the intervention for users.
'''hasseen''' can also be used without '''not''', to tailor the intervention for users who '''have''' already seen a page.


For example, you may want to show a page only if an end-user has seen a previous page.
<code>show s1_feeback2 if (hasseen (currentuser(), "s1_feedback1")))</code>


<code>show s1_feeback2 if (hasseen (username, "s1_feedback1")))</code>
<code>show s1_feeback3 if (hasseen (currentuser(), "s1_feedback2")))</code>


<code>show s1_feeback3 if (hasseen (username, "s1_feedback2")))</code>
===Using hasseen in sessions===


If your intervention is split into sessions, the '''scope''' argument controls which sessions '''hasseen''' looks at:


===Using hasseen in sessions===
<code> show session2.interaction1 if (hasseen (currentuser(), "session1final"))</code>


You can use the hasseen logic in one of three ways:
With no third argument, this shows '''interaction1''' if the end-user has seen '''session1final''' in any '''previous''' session (but not the one they're currently in).


<code> show session2.interaction1 if (hasseen (currentuser(), "session1final", "true"))</code>


<code> show session2.interaction1 if (hasseen (username, "session1final"))</code>
Adding <code>"true"</code> shows '''interaction1''' if the end-user has seen '''session1final''' in '''any''' session, including the current one.


This will show the end-user '''interaction1''' if they have seen '''session1final''' in any session EXCEPT the one they are currently in (i.e. in previous sessions only).
<code> show session2.interaction1 if (hasseen (currentuser(), "session1final", "this"))</code>


Adding <code>"this"</code> shows '''interaction1''' only if the end-user has seen '''session1final''' earlier in the '''current''' session.


<code> show session2.interaction1 if (hasseen (username, "session1final", "true"))</code>
== <code> hmacencode </code> ==


Adding '''true''' to the hasseen command will show '''interaction1''' if the end-user has seen '''session1final''' in ANY session, INCLUDING the current one.
'''hmacencode''' is an advanced command that scrambles (encrypts) a piece of text so it cannot be read. There is no way to reverse this and get the original text back (it cannot be decrypted) - its main use is to check that data passed from one intervention to another has not been tampered with or corrupted along the way.


<code>hmacencode (text, secretkey)</code>


<code> show session2.interaction1 if (hasseen (username, "session1final", "this"))</code>
* '''text''' - the piece of text you want to encode, in quotation marks (or a variable containing text).
* '''secretkey''' - a password-like piece of text, shared between the systems that need to check the data, used to scramble it.


Adding '''this''' to the hasseen command will show '''interaction1''' if the end-user has seen '''session1final''' in the current session ONLY.
<code>set encoded to hmacencode("This message is encoded", "secret")</code>


=I=
=I=
Line 549: Line 759:
== <code> if </code> ==
== <code> if </code> ==


The <code>if</code> command is '''always''' used with another command (e.g. after, show). It is a conditional command so it should always be followed by a true or false statement (i.e. a statement that will be carried out if it is true OR a statement that will be carried out if it is false).
'''if''' is always used together with another command (e.g. '''after''', '''show''', '''set'''). It is followed by a '''condition''' - something that can only be true or false, such as <code>page1.interaction1 = "yes"</code>. The command in front of '''if''' is only carried out when that condition is true.
 
<code>command if (condition)</code>
 
* '''condition''' - the thing being checked. This is often built using other commands from this dictionary, such as '''and''', '''or''', '''not''', '''isempty''' or a comparison like <code>=</code>, <code><</code> or <code>>=</code>.


== <code> isempty </code> ==
== <code> isempty </code> ==


This command checks whether a response has been given to an interaction (i.e. if a response has not been given, the interaction '''isempty''').
'''isempty''' checks whether an end-user has given '''any''' response to an interaction - in other words, whether it has been left blank.
 
<code>isempty (interactionname)</code>
 
* '''interactionname''' - the interaction to check, e.g. <code>page1.interaction1</code>.


'''Example1'''
'''Example 1'''


<code>after page1 if (isempty (page1.interaction1)) goto page4</code>
<code>after page1 if (isempty (page1.interaction1)) goto page4</code>


The end-user would be directed to '''page4''' if they did not enter anything in '''interaction1''' on '''page1'''.
The end-user is directed to '''page4''' if they left '''interaction1''' on '''page1''' blank.


'''Example2'''
'''Example 2'''


<code>set none if (isempty (page1.interaction1))</code>
<code>set none if (isempty (page1.interaction1))</code>


If the end-user does not enter anything in '''interaction1''' on '''page1''', the variable '''none''' will be set.
If the end-user leaves '''interaction1''' on '''page1''' blank, the variable '''none''' is set.


=L=
=L=
Line 571: Line 789:
== <code> load </code> ==
== <code> load </code> ==


Please see the <code>save</code> command for more details. The <code>load </code> command is always used with the save command.
'''load''' is always used together with [[#save|<code>save</code>]], to bring back a page's saved responses so they can be shown again. Please see '''save''' for details and an example.


== <code> loadvalue </code> ==
== <code> loadvalue </code> ==


The '''loadvalue''' command is always used with the '''savevalue''' command. It loads the value that you have previously saved. Please see the '''savevalue''' command for more details.
'''loadvalue''' retrieves a value that was previously stored with [[#savevalue|<code>savevalue</code>]].
 
<code>loadvalue (username, "valuename")</code>
 
* '''username''' - the end-user whose data you want to retrieve. Use <code>currentuser()</code>.
* '''"valuename"''' - the exact name that was used when the value was saved with '''savevalue''', in quotation marks.
 
Please see [[#savevalue|<code>savevalue</code>]] for full examples of saving and loading values together.
 
== <code> loggedin </code> ==
 
'''loggedin()''' checks whether there is currently a logged-in end-user. It takes no arguments - it is always written with empty brackets, <code>loggedin()</code>. It returns '''true''' if someone is logged in, and '''false''' if not. This is useful for tailoring pages or navigation depending on whether someone is browsing your intervention as a registered, logged-in user - for example, to skip the login page for someone who is already logged in, or to hide content that should only be seen once someone has logged in.
 
'''Example 1'''
 
<code>show login
after login if (loggedin()) goto welcome_back
show login_fail
show welcome_back</code>
 
This directs the end-user straight to '''welcome_back''' if they are already logged in (for example, if they still have an active session from earlier), skipping the need to log in again.
 
'''Example 2'''
 
<code>show help_page
show help_page.membersonly if (loggedin())</code>
 
This shows the feedback box '''membersonly''' on '''help_page''' only to end-users who are currently logged in.


== <code> lessthan </code> ==
== <code> lessthan </code> ==


The symbol <code><</code> can also be used.
'''lessthan''' compares two values. The symbol <code><</code> can also be used instead.
 
<code>value1 lessthan value2</code> (or <code>value1 < value2</code>)
 
* '''value1''' - the first value.
* '''value2''' - the value it's being compared against. The condition is true when '''value1''' is smaller than '''value2'''.


This command is used when
This is used both for:
* performing calculations in the logic to check if one value is lower than another
* comparing numbers, e.g. interaction responses or calculated scores
* comparing time to check if one time occurs before another time (e.g. comparing the current time to the time the previous session was completed to check that one week has passed.
* comparing time, e.g. checking that less than a certain amount of time has passed since a previous session


'''Example 1'''
'''Example 1'''


<code>set condition1 if (page1.interaction1 < page1.interaction2) </code>
<code>set condition1 if (page1.interaction1 < page1.interaction2) </code>


'''Example 2'''
'''Example 2'''


<code>after login if (comparetimes (loadvalue(username, "session1_time"), currenttime(), "seconds" ) < 86400)</code>
<code>after login if (comparetimes (loadvalue(currentuser(), "session1_time"), currenttime(), "seconds" ) < 86400)</code>


== <code> lessthanequal </code> ==
== <code> lessthanequal </code> ==


The symbol <code> <= </code> can also be used.
'''lessthanequal''' works the same way as '''lessthan''', but is also true when the two values are equal. The symbol <code><=</code> can also be used instead.


This command is used in the same way as '''lessthan'''. It is used when:
<code>value1 lessthanequal value2</code> (or <code>value1 <= value2</code>)


* performing calculations in the logic to check if one value is lower than another
* '''value1''' - the first value.
* comparing time to check if one time occurs before another time (e.g. comparing the current time to the time the previous session was completed to check that one week has passed.
* '''value2''' - the value it's being compared against. The condition is true when '''value1''' is smaller than, or equal to, '''value2'''.


'''Example 1'''
'''Example 1'''


<code>set condition1 if (page1.interaction1 <= page1.interaction2) </code>
<code>set condition1 if (page1.interaction1 <= page1.interaction2) </code>


'''Example 2'''
'''Example 2'''


<code>after login if (comparetimes (loadvalue(username, "session1_time"), currenttime(), "seconds" ) <= 86400)</code>
<code>after login if (comparetimes (loadvalue(currentuser(), "session1_time"), currenttime(), "seconds" ) <= 86400)</code>


=M=
=M=


== <code> makenewuser </code> ==
'''makenewuser''' creates a new registered account for an end-user, using a username (or email address) and password that they choose.
<code>makenewuser (username, password)</code>


== <code> makenewuser </code> ==
* '''username''' - the page.interaction containing the identifier the end-user will log in with, e.g. <code>signup.signup_username</code>.
* '''password''' - the page.interaction containing their chosen password, e.g. <code>signup.signup_password</code>. This interaction should always be set to the '''password''' interaction type in its properties panel - if it isn't, the password will be visible as the end-user types it, and will not be stored securely, which can leave users unable to log in later.


The <code>makenewuser</code> command is used to set up an for the end-user using a username (or e-mail address) and password.  
'''makenewuser''' both creates the account '''and''' signs the end-user in at the same time, so there is no need to also call [[#authenticateuser|<code>authenticateuser</code>]] straight afterwards.


'''Example'''
'''Example'''
Line 623: Line 877:
<code>show signup</code>
<code>show signup</code>


<code>makenewuser(signup.signup_username, signup.signup_password))</code>
<code>makenewuser(signup.signup_username, signup.signup_password)</code>
 
The information the end-user enters into the '''signup_username''' and '''signup_password''' interactions is used to create their account.


In the example above, the information the end-user enters into the interactions 'signup_username' and 'signup_password' is used to create a user account.
'''Tip:''' if you create accounts using an identifier other than a real email address (for example, a study ID), you can still associate a real email address with the account afterwards using [[#setemail|<code>setemail</code>]], so that commands like '''sendemail''' and '''resetpassword''' work correctly.


== <code> midnight </code> ==
== <code> midnight </code> ==


<code> midnight</code> is used set a function for a specific time, for example, you could send an email to an end-user at 7am as in the example below.
'''midnight()''' is similar to [[#currenttime|<code>currenttime()</code>]], but returns the time at midnight at the '''start''' of today, rather than right now. It takes no arguments - it is always written with empty brackets, <code>midnight()</code>. It's useful for scheduling something at a specific time of day, such as sending an email at 7am, one week after someone registers.


<code>set delay7am to + (midnight(), 25200, (-1 * currenttime()))</code>
<code>set delay7am to + (midnight(), 25200, (-1 * currenttime()))</code>


This logic would appear near the top of your logic file with other <code>set</code> logic you may be using.
This sets a variable called '''delay7am''' to: today's midnight, plus 25200 seconds, minus the time right now.
'''delay7am''' can be replaced with a word of your choice. '''25200''' is the number of seconds since midnight (in this case 25200 = 7 hours = 7am).
 
For example, at 10:30am on 2/9/2016, this would be 1472774400 + 25200 - 1472812200 = -12600.
 
Place this logic near the top of your logic file with your other '''set''' lines, or immediately before the '''sendemail''' logic that uses it.
 
'''delay7am''' can be replaced with a variable name of your choice. '''25200''' is the number of seconds since midnight that you want (in this case, 7 hours = 7am - you can change this to schedule a different time of day).
 
Your email logic would then look something like this:


Your email logic will then look similar to this:
<code> sendemail (append(currentuser(),"welcome_email"),currentuser(),"You have successfully registered to Stress Less", append("Dear ", loadvalue (currentuser(), "firstname"), "\n\n", welcome), (delay7am+604800)) </code>


<code> sendemail (append(username,"welcome_email"),username,"You have successfully registered to Stress Less", append("Dear ", loadvalue (username, "firstname"), "\n\n", welcome), delay7am) </code>
Because '''delay7am''' will be a '''negative''' number if the current time is already past 7am, you need to add at least one full day (in seconds) on top of it before using it as a delay - in the example above, one week (604800 seconds) has been added.


Please note that you will have to take in to consideration time differences in the UK between GMT and BST, and also time differences between the UK and other countries if you are using this function.
Remember to allow for the UK's clock changes between GMT and BST, and for time differences between the UK and other countries, if this matters for your study.


== <code> morethan </code> ==
== <code> morethan </code> ==


The symbol <code> > </code> can also be used.
'''morethan''' compares two values. The symbol <code>></code> can also be used instead.
 
<code>value1 morethan value2</code> (or <code>value1 > value2</code>)


This command is used when performing calculations in the logic to check if one value is higher than another.  
* '''value1''' - the first value.
* '''value2''' - the value it's being compared against. The condition is true when '''value1''' is bigger than '''value2'''.


'''Example 1'''
'''Example 1'''
Line 652: Line 918:
<code>set condition2 if (page1.interaction1 > page1.interaction2) </code>
<code>set condition2 if (page1.interaction1 > page1.interaction2) </code>


'''condition2''' will be set if the value selected for '''interaction1''' is greater than the value selected for '''interaction2'''.
'''condition2''' is set if the value given for '''interaction1''' is greater than the value given for '''interaction2'''.


== <code> morethanequal </code> ==
== <code> morethanequal </code> ==


The symbol <code> >= </code> can also be used.
'''morethanequal''' works the same way as '''morethan''', but is also true when the two values are equal. The symbol <code>>=</code> can also be used instead.
 
<code>value1 morethanequal value2</code> (or <code>value1 >= value2</code>)


This command is used when performing calculations in the logic to check if one value is more than or equal to another.
* '''value1''' - the first value.
* '''value2''' - the value it's being compared against. The condition is true when '''value1''' is bigger than, or equal to, '''value2'''.


'''Example 1'''
'''Example 1'''
Line 664: Line 933:
<code>set condition2 if (page1.interaction1 >= page1.interaction2) </code>
<code>set condition2 if (page1.interaction1 >= page1.interaction2) </code>


'''condition2''' will be set if '''interaction1''' is greater than or equal to '''interaction2'''.
'''condition2''' is set if '''interaction1''' is greater than or equal to '''interaction2'''.


== <code> multiply </code> ==
== <code> multiply </code> ==


The symbol <code> * </code> may also be used.
'''multiply''' is used to multiply one value by another. The symbol <code>*</code> can also be used instead.


This command is used when performing calculations to multiply one value by another. It may be taken from:
<code>value1 * value2</code>


* an end-user's response to an interaction
* '''value1''' and '''value2''' - the two numbers to multiply together. Each can come from an end-user's response to an interaction, or from a calculation performed elsewhere in the logic.
* calculations performed elsewhere in the logic


'''Example 1'''
'''Example 1'''
Line 679: Line 947:
<code>set score1 to (page1.interaction1 * page1.interaction2)</code>
<code>set score1 to (page1.interaction1 * page1.interaction2)</code>


This is taken from an end-user's response to an interaction. The response to '''interaction1''' is multiplied by the response to '''interaction2''' and set as '''score1'''.
The response to '''interaction1''' is multiplied by the response to '''interaction2''', and the result is saved as '''score1'''.


'''Example 2'''
'''Example 2'''
Line 685: Line 953:
<code> set overallscore to (score1 * score2) </code>
<code> set overallscore to (score1 * score2) </code>


This is taken from a calculation performed elsewhere in the logic ('''score1''' and '''score2''' have been '''set''' previously in the logic). '''score1''' is multiplied by '''score2''' and set as '''overallscore'''
Here, '''score1''' and '''score2''' were already calculated earlier in the logic, and are multiplied together to give '''overallscore'''.


=N=
=N=
Line 691: Line 959:
== <code> named </code> ==
== <code> named </code> ==


This command will re-show a page you have already shown.
'''named''' lets you re-show a page you have already shown once, under a new alias.
 
<code>show pagename named alias</code>


For example, if you had a page that you need to keep showing back to your end-users, you could use the <code>named</code> command as so (note that in the example below the line [etc, etc] has been used to indicate that there would be other lines of logic here):
* '''pagename''' - the page you have already created and shown earlier in your logic.
* '''alias''' - a new, unique name for this repeat showing of the page. This is '''not''' a separate page you need to create - it is simply a label that lets your logic refer to this particular instance of showing '''pagename''' again.


'''Example 1'''
'''Example 1'''
Line 701: Line 972:
[etc, etc]
[etc, etc]


<code>show page1 named page2</code>  
<code>show page1 named page2</code>


[etc, etc]
[etc, etc]


<code>show page1 named page3</code>
<code>show page1 named page3</code>
(Here, <code>[etc, etc]</code> stands in for other lines of logic that would appear in a real intervention.) This shows the same page, '''page1''', three times over the course of the intervention - once under its own name, then again labelled '''page2''', then again labelled '''page3'''.


== <code> not </code> ==
== <code> not </code> ==


The <code>not</code> command is used to form the opposite of statement.
'''not''' reverses whether a condition is treated as true or false - a condition that would normally be true becomes false, and vice versa.
 
<code>not (condition)</code>
 
* '''condition''' - the condition to reverse.


'''Example 1'''
'''Example 1'''
Line 715: Line 992:
<code>set condition1 if (not (page1.interaction1 = "yes"))</code>
<code>set condition1 if (not (page1.interaction1 = "yes"))</code>


'''condition1''' would be set for this user if they did not select '''yes''' for interaction1. We can then use this condition to tailor the rest of the intervention.
'''condition1''' is set if the end-user did '''not''' select '''yes''' for '''interaction1'''. This condition can then be used to tailor the rest of the intervention.
 
'''Note''': When using '''not''' with interactions, do not confuse <code>not</code> with <code>isempty</code>. The command <code>not</code> is used to refer to a specific response to an interaction that has not been chosen. <code>isempty</code> is used to refer to an interaction that an end-user has not answered.


<code>not</code> and <code>isempty</code> can be used together to refer to an interaction that is not empty (i.e. something has been entered):
'''Note''': don't confuse '''not''' with [[#isempty|<code>isempty</code>]]. '''not''' refers to a specific response '''not''' being chosen; '''isempty''' refers to an interaction that hasn't been answered at all. The two can be combined to check for "an answer was given, and it wasn't blank":


'''Examples 2 and 3:'''
'''Examples 2 and 3'''


<code> after page1 if (not (isempty (page1.interaction1))) goto page5</code>
<code> after page1 if (not (isempty (page1.interaction1))) goto page5</code>
Line 733: Line 1,008:
== <code> or </code> ==
== <code> or </code> ==


Also written as ||.
'''or''' can also be written as '''||'''. It combines two or more conditions into one, and is true if '''any''' one (or more) of them is true. It works the same way as [[#and|<code>and</code>]], but only needs one condition to succeed rather than all of them.
 
<code>or (condition1, condition2, ...)</code>


The <code>or</code> command is used in the same way as the <code>and</code> command. It can be used to check if a user has responded in a particular way to an interaction (or number of interactions):
* '''condition1, condition2, ...''' - the individual conditions to check, separated by commas. You can list two or more. '''or''' is true if '''at least one''' of them is true.


'''Example 1'''
'''Example 1'''
Line 742: Line 1,019:
after page1 if (or (page1.interaction1 = "none", page1.interaction1 = "sometimes")) goto page3</code>
after page1 if (or (page1.interaction1 = "none", page1.interaction1 = "sometimes")) goto page3</code>


This will show '''page3''' if '''none''' or '''sometimes''' is selected as the response to '''interaction1''' on '''page1'''.
This shows '''page3''' if the response to '''interaction1''' on '''page1''' was '''either''' '''none''' '''or''' '''sometimes'''.


'''Example 2'''
'''Example 2'''


<code>savevalue(username, "sport", "cardio") if (or( page1.interaction1 = "running", page2.interaction2 = "swimming"))</code>
<code>savevalue(currentuser(), "sport", "cardio") if (or( page1.interaction1 = "running", page2.interaction2 = "swimming"))</code>


This will save the variable '''sport''' if '''running''' is selected for '''interaction1''' on '''page1''' OR if '''swimming''' is selected for '''interaction2''' on '''page2'''.
This saves the variable '''sport''' if the end-user selected '''running''' for '''interaction1''' on '''page1''', '''or''' '''swimming''' for '''interaction2''' on '''page2''' (or both).


=P=
=P=
== <code> parsedate </code> ==
'''parsedate''' converts a date that has been entered or stored as text (for example, a response to a date-entry interaction) into a time value that can be used with commands such as [[#comparetimes|<code>comparetimes</code>]] and [[#currenttime|<code>currenttime</code>]].
<code>parsedate (datestring, "format")</code>
* '''datestring''' - the interaction response (or variable) containing the date as text, e.g. <code>signup.date_of_birth</code>.
* '''"format"''' - describes how that text is laid out, using the same letters as [[#printtime|<code>printtime</code>]] (see the table under '''printtime''' for the full list) - for example, <code>"yyyy-MM-dd"</code> for a date written like 1990-05-21.
'''Example 1'''
<code>set dob to parsedate(signup.date_of_birth, "yyyy-MM-dd")</code>
This converts the response given to the '''date_of_birth''' interaction on the '''signup''' page - entered in the format '''yyyy-MM-dd''', e.g. "1990-05-21" - into a time value, stored as the variable '''dob'''.
'''Example 2'''
<code>show screening_fail if (comparetimes(parsedate(signup.date_of_birth, "yyyy-MM-dd"), currenttime(), "days") < 6570)</code>
This shows the error message '''screening_fail''' if fewer than '''6570''' days (approximately 18 years) have passed between the date of birth entered by the end-user and now - for example, to screen out end-users who are under 18.


== <code> patternmatch </code> ==
== <code> patternmatch </code> ==


The <code>patternmatch</code> command is used when users are required to enter a specific combination of characters into a text entry interaction, e.g. a study code. The logic <code>patternmatch(characters,interactionname)</code> will check if the characters entered by the user, match the characters that you have pre-defined.
'''patternmatch''' checks whether the text an end-user has typed into a text-entry interaction matches a pattern you define - for example, a study code in a specific format.
 
<code>patternmatch ("pattern", interactionname)</code>
 
* '''"pattern"''' - the pattern of characters to match against, in quotation marks, written using '''Regular Expressions''' (see the table below for the basics).
* '''interactionname''' - the text-entry interaction whose response you want to check, e.g. <code>password</code>.


<code>Patternmatch</code> uses "Regular Expressions" to define a pattern of characters. Some basics are described below but for more detailed information, you can find guides to "Regular Expressions" on the Internet.
Some regular expression basics are described below - for more detailed information, you can find guides to "Regular Expressions" online.


{| class="wikitable"
{| class="wikitable"
Line 767: Line 1,070:
|A
|A
|A
|A
|match a single upper-case character.  
|match a single upper-case character.
|-
|-
|abc
|abc
Line 815: Line 1,118:
|a(bc)+d
|a(bc)+d
|abcbcbcd
|abcbcbcd
|() groups things together  
|() groups things together
|-
|-
|ab&#124;cd
|ab&#124;cd
Line 824: Line 1,127:
'''Example 1'''
'''Example 1'''


This function may be useful if you have assigned each participant in your study a different code which they will need to enter in order to take part.  This will ensure that only users who have been invited to use the intervention can gain access to it. To do this, you will need to write an error message on the page which contains your text entry interaction e.g.      
This function is useful if you have assigned each participant in your study a different code, which they must enter correctly in order to take part - this ensures that only people who have been invited can gain access to the intervention. To do this, write an error message on the page containing your text-entry interaction, e.g.


<code> Show nomatch if( not( patternmatch( “study[0-9][0-9]id[0-9][0-9], password ) ) ) </code>
<code> show nomatch if( not( patternmatch( "study[0-9][0-9]id[0-9][0-9]", password ) ) ) </code>


In this example, the error message named '''nomatch''' will be shown to users if they enter a string of characters in the text entry interaction named '''password''' which does not fit with the pattern specified in the square brackets.
Here, the error message named '''nomatch''' is shown to users if the text they enter into the interaction named '''password''' doesn't fit the pattern in the square brackets. The pattern used here means a code shaped like '''studyxxidxx''', where each '''x''' is any digit from 0 to 9.


The string of characters needed in this example is '''studyxxidxx''', where '''x''' is any number between '''0 and 9'''.
See also [[Adding Error Messages]] (example 7).


See also [[Adding Error Messages]] (example 7). 
'''Example 2'''


'''Example 2'''  
'''patternmatch''' can also be used to direct users to specific conditions, sections or pages within an intervention, e.g.


The <code>patternmatch</code> function could also be used to direct users to specific conditions, sections or pages within an intervention e.g.
<code> show page1 if (patternmatch("[0-9][0-9]a[0-9][0-9]", interaction1)) </code>


<code> show page1 if (patternmatch([0-9][0-9]a[0-9][0-9], interaction1)) </code>
<code> show page2 if (patternmatch("[0-9][0-9]b[0-9][0-9]", interaction1)) </code>


<code> show page2 if (patternmatch(“[0-9][0-9]b[0-9][0-9]”, interaction1)) </code>
Here, if a user enters a code shaped like xx'''a'''xx (where each x is a digit), they see '''page 1'''. If they enter xx'''b'''xx, they see '''page 2'''.


In this example, if users enter the string xx'''a'''xx, where x represents a number between 0 and 9 they will see '''page 1''' of the intervention.  If they enter the string xx'''b'''xx they will see '''page 2''' of the intervention.  
Instead of 0-9, you could use [a-z] to require any letter from a to z, or [a-z0-9] to allow either a letter or a number.


'''Note:''' '''patternmatch''' is case sensitive. '''[a-z]''' only matches lowercase letters, '''[A-Z]''' only matches uppercase letters, and '''[a-zA-Z]''' matches either.


Instead of 0-9, you could use [a-z], which means the user will need to enter any letter between a and z in the alphabet.  You could also specify [a-z0-9] – this will mean the user will need to enter either a letter or a number.     
[[Category: patternmatch]]


NB The <code> patternmatch </code>function is '''case sensitive'''.  If you specify '''[a-z]''', the user will need to enter a '''lowercase''' letter.  If you specify '''[A-Z]''', the user will need to enter an '''uppercase''' letter.  If you specify '''[a-zA-Z]''' the user may enter '''either an uppercase or a lower case letter'''.
== <code> printtime </code> ==


[[Category: patternmatch]]
'''printtime''' formats a time value so it can be displayed to the end-user as a readable date or time.


== <code> printtime </code> ==
<code>printtime (timevalue, "format")</code>


This command can be used to instruct the intervention to display a particular time or date to the user. It can display the time in many different ways, using letters to display them.
* '''timevalue''' - the time you want to display, usually <code>currenttime()</code> or a time you've loaded with <code>loadvalue(...)</code>.
* '''"format"''' - describes how you want the time or date to look, built from the letters in the table below (e.g. <code>"H:m d-M-y"</code>).


The letters that can be used to display time are:
The letters that can be used to build a format are:


{| class="wikitable"
{| class="wikitable"
Line 863: Line 1,168:
| G      || Era designator      || AD
| G      || Era designator      || AD
|-
|-
| y      || Year in four digits      || 2001
| y     || Year in two digits      || 01
|-
| yyyy     || Year in four digits      || 2001
|-
| M      || Month in year      || 7
|-
|-
| M     || Month in year      || July or 07
| MMMM     || Month in year      || July
|-
|-
| d      || Day in month      || 10
| d      || Day in month      || 10
Line 877: Line 1,186:
| s      || Second in minute    || 55
| s      || Second in minute    || 55
|-
|-
| S     || Millisecond    || 234
| E     || Day in week      || Tues
|-
|-
| E     || Day in week      || Tuesday
| EEEE     || Day in week      || Tuesday
|-
|-
| D    || Day in year      || 360
| D    || Day in year      || 360
Line 896: Line 1,205:
|}
|}


For digits, e.g. minutes, '''use the number of letters for the number of digits you want to display'''. For example, '''9:01:07''' should be written as <code>h:mm:ss</code>
''Advanced users, please see more options on [http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html#month Java SimpleDateFormat].''
'''printtime''' cannot display the difference between two times if that difference is greater than one day - to display a difference between two times, use '''comparetimes''' instead (see [[#comparetimes|<code>comparetimes</code>]], Example 2).


'''Example 1'''
'''Example 1'''


This example shows how you can use the <code>printtime</code> and <code>currenttime</code> functions to display the time/date a user is shown a specific page of the intervention:
This example shows how you can use '''printtime''' and '''currenttime''' together, to display the time and date a user is shown a specific page:
 
<code>show welcome</code>
 
<code>set welcome.time to printtime (currenttime (), "H:m d-M-y")</code>


<code>show welcome</code>
Here, the word 'time' on the page '''welcome''' has been set as a variable. This displays the hour, minute, day, month and year at which the user is shown '''welcome''', in place of the word 'time'.


<code>set welcome.time to printtime (currenttime (), "H:m d-M-y")</code> 
'''Example 2'''


In this example, the word 'time' on the page called 'welcome' has been set as a variable.  This logic tells the intervention to display the hour, minute, day, month, and year at which the user is shown the page named 'welcome' in place of the word 'time'.
This example shows how to mix your own words in with '''printtime''' and store the result as a user variable.


<code>set midnighttext to printtime (currenttime(), "'When you registered, it was 'H'hrs and 'm' minutes and 's' seconds since midnight'")


'''Example 2'''
savevalue(currentuser(), "midnighttext", midnighttext)</code>


This example shows how you can use the <code>printtime</code> function to display particular times or dates that you have saved in your intervention logic, such as the time/date a user signed up for the intervention and the time/date they logged back into the intervention.
To add your own words or values in between the '''printtime''' format letters, wrap them in single quotes, as shown above. The output of '''printtime''' can be stored or saved like any other user variable, but note that it is always stored as text - it cannot be used in further number calculations.


<code>show signup</code>
'''Example 3'''


<code>after signup if (and (makenewuser (signup.name, signup.password), savevalue(signup.name, “currentlogintime”, currenttime()))) goto welcome</code>
This example shows how to display particular times or dates you have saved earlier in your logic, such as when a user signed up and when they last logged back in.


The first part of this logic tells the intervention to set up an account for the user using the username (signup.name) and password (signup.password) they created (see [[makenewuser]]).  The second part of this logic uses the <code>currenttime</code> function to instruct the intervention to save the time/date a user signed up to the intervention as the variable <code>"currentlogintime"</code>.     
<code>show signup</code>


<code>show welcome</code>  
<code>after signup if (and (makenewuser (signup.name, signup.password), savevalue(currentuser(), "currentlogintime", currenttime()))) goto welcome</code>


<code>set welcome.signuptime to printtime(loadvalue(signup.name, "currentlogintime"), "H:m d-M-y")</code>  
The first part of this logic sets up an account for the user, using the username (signup.name) and password (signup.password) they chose (see [[makenewuser]]). The second part uses '''currenttime''' to save the time the user signed up, as the variable <code>"currentlogintime"</code>.


This logic tells the intervention to display the time/date a user signed up to the intervention on the page named 'welcome' in place of the word 'signuptime'. 
<code>show welcome</code>


<code>show login</code>  
<code>set welcome.signuptime to printtime(loadvalue(currentuser(), "currentlogintime"), "H:m d-M-y")</code>


<code>after login if (and(savevalue(login.name, "lastlogintime", loadvalue(login.name, "currentlogintime")), savevalue(login.name, "currentlogintime", currenttime()))) go to loginhistory</code>
This displays the date and time the user signed up, on the page '''welcome''', in place of the word 'signuptime'.


This first part of this logic uses the previously created variable <code>"currentlogintime"</code> to create a new variable called <code>"lastlogintime"</code> – the time at which the user first signed up to the intervention <code>("currentlogintime"</code>) now becomes the time at which they last logged in to the intervention <code>("lastlogintime"</code>).
<code>show login</code>


The second part of this logic uses the <code>currenttime</code> function to re-create a new <code>"currentlogintime"</code> variable.  Instead of saving the time at which the user first signed up for the intervention this variable now saves the time the user logged back into the intervention.   
<code>after login if (and(savevalue(currentuser(), "lastlogintime", loadvalue(currentuser(), "currentlogintime")), savevalue(currentuser(), "currentlogintime", currenttime()))) goto loginhistory</code>


<code>show loginhistory</code>  
The first part of this reuses the variable <code>"currentlogintime"</code> to create a new variable, <code>"lastlogintime"</code> - so whatever time was previously stored as "when they signed up or last logged in" now becomes "when they '''last''' logged in". The second part then saves a fresh <code>"currentlogintime"</code>, recording that they have logged back in right now.


<code>set loginhistory.lastlogintime to printtime (loadvalue(login.name, "lastlogintime"), "H:m d-M-y")</code>
<code>show loginhistory</code>


<code>set loginhistiry.currentlogintime to printtime (loadvalue(login.name, "currentlogintime"), "H:m d-M-y")</code>  
<code>set loginhistory.lastlogintime to printtime (loadvalue(currentuser(), "lastlogintime"), "H:m d-M-y")</code>


This logic tells the intervention to display the time a particular user first signed up to the intervention <code>("lastlogintime"</code>) and the time they logged back into the intervention <code>("currentlogintime"</code>) in place of the words ‘lastlogintime’ and ‘currentlogintime’.
<code>set loginhistory.currentlogintime to printtime (loadvalue(currentuser(), "currentlogintime"), "H:m d-M-y")</code>


This displays both the time the user last logged in ("lastlogintime") and the time they are logging in right now ("currentlogintime"), on the page '''loginhistory'''.


'''Example 3'''
'''Example 4'''


In this example, a time that was saved in a previous session is loaded and 1 week (in seconds) added to it:
In this example, a time saved in a previous session is loaded, and one week (in seconds) is added to it:


<code>savevalue (username, "goaltime", midnight())</code>
<code>savevalue (currentuser(), "goaltime", midnight())</code>


<code>show examplepage</code>
<code>show examplepage</code>


<code>set examplepage.weeklater to printtime((loadvalue(username,"goaltime")+delay), "E, d/M/y")</code>
<code>set examplepage.weeklater to printtime((loadvalue(currentuser(),"goaltime")+delay), "E, d/M/y")</code>


The output of this might be '''Tue, 09/08/2016''', a week after the time that the goal was set.
The output of this might be '''Tue, 09/08/2016''', a week after the time the goal was set.


=R=
=R=
Line 957: Line 1,277:
== <code> randomnumber </code> ==
== <code> randomnumber </code> ==


This command allows you to randomise your users into different groups and always follows the same formula:
'''randomnumber''' returns a random whole number within a range you choose, which is commonly used to randomly assign end-users into different groups.
 
<code>randomnumber (lowestvalue, highestvalue)</code>
 
* '''lowestvalue''' - the smallest number that could be returned.
* '''highestvalue''' - the largest number that could be returned.
 
<code>after page1 if (randomnumber (lowestvalue, highestvalue) = value) goto page3</code>


<code> after page1 if (randomnumber (lowestvalue , highestvalue) = </code>value) <code> goto page3</code>
For example:
For example:


Line 969: Line 1,294:
<code> show page3</code>
<code> show page3</code>


Thus, users that are randomised to group 1 will be directed to page3. Those that are randomised to group 0 will carry on to page2.
Here, end-users randomly assigned the number 1 are directed to '''page3'''; those assigned 0 carry on to '''page2'''.


A full tutorial for randomisation is available in the LifeGuide Researcher Help Manual.
A full tutorial on randomisation is available in the LifeGuide Researcher Help Manual.


== <code> replaceall </code> ==
== <code> replaceall </code> ==


This command replaces text in a string (a string is a variable that you create - it appears in blue in the logic file).
'''replaceall''' searches through a piece of text and replaces every occurrence of one thing with another.
 
<code>replaceall ("find", "replacewith", sourcetext)</code>
 
* '''"find"''' - the character(s) or text you want to search for, in quotation marks.
* '''"replacewith"''' - the character(s) or text to put in its place, in quotation marks.
* '''sourcetext''' - the text (or interaction response, or variable) to search within. This does not need quotation marks if it's a variable or interaction response.


'''Example 1'''
'''Example 1'''
Line 981: Line 1,312:
<code>replaceall ("c", "b", "caked car")</code>
<code>replaceall ("c", "b", "caked car")</code>


This would replace all the '''c's''' in the string to '''b's'''. So this would change '''caked car''' to '''baked bar'''.
This replaces every '''c''' in the text with '''b''', changing '''caked car''' into '''baked bar'''.


'''Example 2'''
'''Example 2'''


This example shows a workaround for showing responses to a single-choice interaction back to the user. A workaround is needed because the '''Unique Response Name''' (not the Response text) is saved and shown to the user when a single-choice drop-down interaction is used.
This example shows a workaround for displaying a single-choice interaction's response back to the end-user. A workaround is needed because it is the '''Unique Response Name''' (not the response text shown on screen) that gets saved, and that would otherwise be shown back to the user.


<code>savevalue (username, "s1_home", replaceall("_", " ", s1_whattodo1.home)) if (or( s1_fatigue.home = "Other_aspects_of_home_life", s1_fatigue.home = "I_find_it_hard_doing_things_around_the_house",s1_fatigue.home = "I_cannot_get_out_and_about_the_way_I_used_to" ))</code>
<code>savevalue (currentuser(), "s1_home", replaceall("_", " ", s1_whattodo1.home)) if (or( s1_fatigue.home = "Other_aspects_of_home_life", s1_fatigue.home = "I_find_it_hard_doing_things_around_the_house",s1_fatigue.home = "I_cannot_get_out_and_about_the_way_I_used_to" ))</code>


This example is specific to a drop-down single-choice interaction, where you want to show the response selected for the interaction '''home''' on page '''s1_fatigue''' back to the end-user. All of the '''_''' in each '''Unique Reponse Name''' in the interaction will be replaced with a space, which you can show back to your user.
This is specific to a drop-down single-choice interaction, where you want to show the response chosen for the interaction '''home''' on page '''s1_fatigue''' back to the end-user. Every underscore ('''_''') in the '''Unique Response Name''' is replaced with a space, so it reads naturally when shown back to the user.


You can then use feedback boxes and a container to show the responses on a later page:
You can then use feedback boxes and a container to show the response on a later page:


<code>show s1_fatigue2.home1 if (s1_fatigue.home = "Other_aspects_of_home_life")
<code>show s1_fatigue2.home1 if (s1_fatigue.home = "Other_aspects_of_home_life")
Line 997: Line 1,328:
show s1_fatigue2.home3 if (s1_fatigue.home = "I_cannot_get_out_and_about_the_way_I_used_to")</code>
show s1_fatigue2.home3 if (s1_fatigue.home = "I_cannot_get_out_and_about_the_way_I_used_to")</code>


'''home1''' is a feedback textbox which will be shown on '''s1_fatigue2''' if '''Other_aspects_of_home_life''' was chosen for the interaction '''home''' on page '''s1_fatigue'''.
'''home1''' is a feedback textbox shown on '''s1_fatigue2''' if '''Other_aspects_of_home_life''' was chosen for the interaction '''home''' on page '''s1_fatigue'''.


== <code> resetpassword </code> ==
== <code> resetpassword </code> ==


This command allows users to reset their password if they forget it. A new password will be emailed to them and they can use it to login. You can create additional pages to allow users to change their password to a personal and memorable one when they next login.
'''resetpassword''' lets an end-user reset a forgotten password. A new, temporary password is emailed to them, which they can use to log in - you can then add further pages to let them choose a new, memorable password once logged in.
 
<code>resetpassword (emailinteraction)</code>
 
* '''emailinteraction''' - the interaction where the end-user entered the email address registered to their account.


'''Example 1'''
'''Example 1'''
Line 1,007: Line 1,342:
<code>after resetpass if (resetpassword(resetpass.email)) goto resetpass_confirm </code>
<code>after resetpass if (resetpassword(resetpass.email)) goto resetpass_confirm </code>


This logic will change a user's password if they enter a registered email address into the text-entry box called '''email''', and will show them the '''resetpass_confirm''' page.
This resets the end-user's password, as long as they enter a registered email address into the text-entry box called '''email''', and shows them the '''resetpass_confirm''' page.


Please see the '''Changing and resetting users passwords''' tutorial intervention on the LifeGuide Community Website for a demo showing how this logic is used.
Please see the '''Changing and resetting users passwords''' tutorial intervention on the LifeGuide Community Website for a full demo of how this logic is used.


== <code> round </code> ==
== <code> round </code> ==


The <code>round</code> command rounds a number to the nearest whole number. 5.49 rounds down to 5 and 5.5 rounds up to 6. This is useful if you want to calculate values and then present them to the user based on a quiz score. If you want to round a number to multiple decimal places, you should use the <code>decimalplaces</code> command.
'''round''' rounds a number to the nearest whole number. For example, 5.49 rounds down to 5, and 5.5 rounds up to 6. This is useful for presenting calculated values (such as a quiz score) in a clean, whole-number form. To round to a set number of decimal places instead of a whole number, use [[#decimalplaces|<code>decimalplaces</code>]].
 
<code>round (number)</code>
 
* '''number''' - the number (or a variable/calculation that produces a number) you want to round.


'''Example 1'''
'''Example 1'''


In this example we calculate 100 divided by 3 (33.333333). When we display it to the user on <code>examplepage</code> we want it to display 33.
In this example we calculate 100 divided by 3 (33.333333). When we display it to the user on '''examplepage''' we want it to show 33.


<code>set exactthird to (100/3)
<code>set exactthird to (100/3)
Line 1,029: Line 1,368:
'''Example 2'''
'''Example 2'''


In this example we collect the scores from a 3 item yes/no quiz and present the scores as a percentage.
In this example we mark a 3-item true/false quiz and present the score as a percentage.


<code>
<code>
Line 1,045: Line 1,384:


if exp.question3="false" set q2 to 0
if exp.question3="false" set q2 to 0


set totalscore to (sum(q1,q2,q3))
set totalscore to (sum(q1,q2,q3))
Line 1,052: Line 1,390:


set scoreround to round(scorepercent)
set scoreround to round(scorepercent)


show results_page
show results_page
Line 1,060: Line 1,397:
</code>
</code>


First we grade the quiz by giving each question a score of 1 (correct) or 0 (wrong).
First we mark the quiz, giving each question a score of 1 (correct) or 0 (incorrect). We add the scores together using '''sum'''. To turn this into a percentage, we divide the total by three and multiply by 100. We then round the result and display it to the user on '''results_page'''.
We then add together the scores using <code>sum</code>.
 
To calculate the percentage, we divide the total by three and multiply by 100.
'''Example 3'''
We then round the number and display it to the user on the <code>results_page</code>.
 
In this example we round a large number to the nearest hundred.
 
<code>set largenumber to 1234567
 
set roundnumber to round(largenumber/100)
 
set largenumbertwo to (roundnumber*100)</code>
 
This takes 1,234,567, divides it by 100 to get 12,345.67, rounds that to the nearest whole number (12,346), then multiplies it back up by 100, giving a final result of 1,234,600.


=S=
=S=


== <code> save </code> ==
== <code> save </code> ==
The <code> save </code> key command allows you to save the responses that an end-user enters on a page. This can then be loaded using the <code> load </code> key command onto another page to re-show it to your end-user. The save and load commands can be used across sessions and requires end-users to have registered a user account.


Example:
'''save''' stores all the responses an end-user gave on a page, so they can be shown again later using [[#load|<code>load</code>]] - either on another page in the same session, or in a future session. This requires end-users to have a registered account.
 
<code>save pagename for username</code>
 
* '''pagename''' - the page whose responses you want to store.
* '''username''' - the end-user this data belongs to. Use <code>currentuser()</code>.
 
'''Example'''


<code> show page1</code>
<code> show page1</code>


<code> save page1 for username</code>
<code> save page1 for currentuser()</code>


Then, later on in the logic (either in the same session or a later session) the following logic would be used:
Later in the logic (either in the same session, or a future one):


<code> show page20</code>
<code> show page20</code>


<code> set default page20.interaction2 to load page1.interaction1 for username</code>
<code> set default page20.interaction2 to load page1.interaction1 for currentuser()</code>
 
* '''page1.interaction1''' - the previously-saved response you want to bring back.
* '''currentuser()''' - the end-user whose saved response you want.


So, in the first part of this logic page1 is saved for the end-user. Then when they get to page20 in the intervention the response that they entered on interaction1 on page1 will be reshown to them on interaction2 on page20.
So, '''page1''' is saved for the end-user in the first part of this logic. Then, when they reach '''page20''', the response they gave earlier for '''interaction1''' on '''page1''' is shown again, this time in '''interaction2''' on '''page20'''.


== <code> saveandload </code> ==
== <code> saveandload </code> ==


This command is used after a page that contains interactions. If an end-user clicks on a '''next''' button on that page and then returns to it, the page will automatically show them the responses they entered the last time they saw that page.
'''saveandload''' is used on a page that contains interactions. If the end-user clicks Next and then comes back to that same page later, it automatically shows them the responses they gave the last time they were there.
 
<code>saveandload pagename for username</code>
 
* '''pagename''' - the page whose responses should be remembered.
* '''username''' - the end-user this data belongs to. Use <code>currentuser()</code>.


'''Example 1'''
'''Example 1'''
Line 1,092: Line 1,452:
<code>show page1
<code>show page1


saveandload page1 for username</code>
saveandload page1 for currentuser()</code>


Any interaction on page1 will be saved and then loaded each time the end-user comes back to that page.
Every interaction on '''page1''' will be saved, and shown again automatically, each time the end-user returns to that page.


== <code> set </code> ==
== <code> set </code> ==


The <code>set</code> command can be used to set variables within the logic or for performing calculations.
'''set''' stores a value in a variable, which you can then refer to elsewhere in your logic. It is also used to perform calculations.
 
<code>set variablename to value</code>
 
* '''variablename''' - the name you choose for this variable.
* '''value''' - what you want to store: plain text (in quotation marks), a number, an interaction response, or the result of another command.


'''Example 1'''
'''Example 1'''


The most common use of setting variables will be to set a username for the user. Many of the logic commands such as <code>save</code> will need a username to be set. This will need to be done at the start of your logic file.
Older interventions commonly used '''set''' to create a variable representing the current end-user's identifier, e.g.:
 
<code>set username to login.loginuname</code>


<code>Set username to login.loginuname</code>
This sets the variable '''username''' to whatever the end-user typed into the interaction uniquely named '''loginuname''' (usually an email address) on the login page.


This will set the variable '''username''' to whatever the end-user enters into the interaction uniquely named '''loginuname''' (usually an email address) on the login page. The word '''username''' can then be used any time throughout the logic to refer to the text an end-user entered into that interaction.
'''Current best practice is to skip this step entirely and use [[#currentuser|<code>currentuser()</code>]] directly''' wherever you need to identify the current end-user, instead of creating your own username variable. You may still see the pattern above in older interventions.


'''Example 2'''
'''Example 2'''


You can '''set''' timings in your logic. Setting timings means you can change the timings for testing and change them back again to real-time easily, and it reduces the likelihood of mistakes being made.
You can also use '''set''' to store timing values, such as how many seconds are in a day, as named variables. This makes it easy to switch between short test timings and real timings, and reduces the risk of mistakes.


In this example, '''twelvemonth''' has been set to the number of seconds in 12 months:
In this example, '''twelvemonth''' is set to the number of seconds in 12 months:


<code>set twelvemonth to "31536000"</code>
<code>set twelvemonth to "31536000"</code>


You can then use this in your login logic as follows:
You can then use this in your login logic:
 
<code>after login if (comparetimes(loadvalue(currentuser(),"baselinetime"), currenttime(),"seconds") >= twelvemonth) goto studyfinished </code>


<code>after login if (comparetimes(loadvalue(username,"baselinetime"), currenttime(),"seconds") >= twelvemonth) goto studyfinished </code>
This shows the page '''studyfinished''' if it has been more than 12 months since '''baselinetime'''.
The above logic will show the page '''studyfinished''' if it has been more than 12 months since '''baselinelinetime'''.


'''Example 3'''
'''Example 3'''


You can '''set''' text such as an email address to avoid having to type it out each time, e.g. the study coordinator's email address:
You can also '''set''' fixed pieces of text, such as an email address, so you don't have to type it out repeatedly - for example, the study coordinator's email address:


<code>set studyemail to "study@soton.ac.uk" </code>
<code>set studyemail to "study@soton.ac.uk" </code>


This logic should appear near the top of your logic file. An advantage to using this function this way is that if you decide to change the study coordinator's email address, you only have to change it once (where you '''set''' it).
Place this logic near the top of your logic file. This way, if the study coordinator's email address ever changes, you only have to update it in one place.


You can also '''set''' the text and timings in emails:
You can also '''set''' the text and timings used in emails:


<code>set 3monthemail to "Thank you for taking part in The Reactivate Study. It is now time to complete your 3 month questionnaire. Your answers are very important to us. Please use the following link to login:\n\nwww.webaddress.co.uk\n\nIf you have any questions about the study, or no longer wish to participate, please contact us on study@soton.ac.uk\n\nFrom The Reactivate Team."</code>
<code>set 3monthemail to "Thank you for taking part in The Reactivate Study. It is now time to complete your 3 month questionnaire. Your answers are very important to us. Please use the following link to login:\n\nwww.webaddress.co.uk\n\nIf you have any questions about the study, or no longer wish to participate, please contact us on study@soton.ac.uk\n\nFrom The Reactivate Team."</code>
Line 1,137: Line 1,504:
set oneweek to "604800"</code>
set oneweek to "604800"</code>


The advantages to setting text in emails are:
The advantages of setting text like this are:
* They can be changed easily as you only have to change one line instead of multiple lines throughout your logic. It's common to overlook vital lines if you have many lines of logic and setting text reduces the likelihood of mistakes being made.
* It's easy to change - you only have to update one line, rather than hunting through your whole logic file for every place the text appears.
* The lines are easy to find as they are placed at the top of the logic file.
* It's easy to find, since these lines are usually kept together near the top of the logic file.


Please see the command <code>sendemail</code> for more information on how to write email logic.
Please see [[#sendemail|<code>sendemail</code>]] for more information on how to write email logic.


'''Example 4'''
'''Example 4'''


The <code>set</code> key command can also be used to set a variable based on how end-users respond to certain interactions. This can then be used to tailor the intervention based on this variable.
'''set''' can also create a variable based on how an end-user responds to an interaction, which you can then use to tailor the rest of the intervention.


<code>show page1</code>
<code>show page1</code>
Line 1,153: Line 1,520:
<code>after page1 if condition1 goto page3</code>
<code>after page1 if condition1 goto page3</code>


So in example 2, the variable '''condition1''' is set if end-users select '''optiona''' and '''optionc''' from the interaction '''chooseoptions''' on '''page1'''. Then those that are in this condition are sent to page 3 where they will receive tailored information based on the options they selected.
Here, '''condition1''' is set if the end-user selects both '''optiona''' '''and''' '''optionc''' from the interaction '''chooseoptions''' on '''page1'''. Anyone in this condition is then sent to page 3, where they receive tailored information based on the options they chose.


'''Example 5'''
'''Example 5'''


In this example, the <code>set</code> key command is used to set a score based on the calculation that follows. In this calculation the number that the end-user selects in the interaction ‘dailyexercise’ on page1 is multiplied by 5 to create their exercise score
In this example, '''set''' is used to calculate a score. The number the end-user selects for the interaction 'dailyexercise' on page1 is multiplied by 5 to create their exercise score:


<code>set exercisescore to (page1.dailyexercise * 5)</code>
<code>set exercisescore to (page1.dailyexercise * 5)</code>


== <code> saveuniquevalue </code> ==
== <code> setemail </code> ==
The '''saveuniquevalue''' function is used in the same way as the '''savevalue''' function. The only difference is that with '''saveuniquevalue''', if the value entered by an end-user is not unique, the function will return a 'false' input, and you can use this to stop end-users continuing with the intervention until they have entered a value which is unique and you can send the study coordinator an email to alert them of this.
 
'''setemail''' sets or updates the email address associated with a user's account. This is useful if you create accounts using an identifier other than a real email address (e.g. a study ID, using [[#makenewuser|<code>makenewuser</code>]]), but still want a real email address linked to the account - for example, so that '''sendemail''' and '''resetpassword''' work correctly for that user.
 
<code>setemail (username, emailaddress)</code>


* '''username''' - the account to update. Use <code>currentuser()</code>.
* '''emailaddress''' - the interaction where the end-user entered their real email address.


'''Example 1'''
'''Example 1'''


To save and check a variable entered by an end-user is unique:
<code>show signup
makenewuser(signup.studyid, signup.password)
setemail(currentuser(), signup.email_address)</code>


<code>saveuniquevalue(username, "studyid", page1.interaction1)</code>
This creates a new user account using the '''studyid''' and '''password''' entered on the '''signup''' page, then sets the email address for that account to whatever was entered into the '''email_address''' interaction on the same page.


== <code> saveuniquevalue </code> ==


'''Example 2'''
'''saveuniquevalue''' works in the same way as [[#savevalue|<code>savevalue</code>]], but with one extra check: if the value being saved is not unique (i.e. another end-user has already saved the exact same value for the same variable name), it returns '''false''' instead of saving it. You can use this to stop an end-user continuing until they enter a genuinely unique value, such as a study ID.
 
If an end-user has entered a response that is not unique, you can allow them to continue with the intervention and send an email to the study coordinator.


<code> after registration if (and(not(saveuniquevalue(username, "studyid", registration.interaction1)), sendemail( append(username,"not_unique"), "study@soton.ac.uk", "Participant - not unique", append("Participant ", loadvalue (username, "idnumber"), "has entered information that is not unique."),10) )) goto registrationfinish </code>
<code>saveuniquevalue (username, "valuename", value)</code>


* '''username''' - the end-user this data belongs to. Use <code>currentuser()</code>.
* '''"valuename"''' - a name you choose for this piece of data, in quotation marks.
* '''value''' - the response to check and save, e.g. an interaction response.


For more information on saveuniquevalue [[How to check whether users have entered a unique value, e.g. Study ID code|please click here]]
'''Example 1'''


To save a variable entered by an end-user, while checking it is unique:


<code>saveuniquevalue(currentuser(), "studyid", page1.interaction1)</code>


'''Example 2'''


If an end-user enters a value that turns out '''not''' to be unique, you can still let them continue with the intervention, while alerting the study coordinator by email:


<code> after registration if (and(not(saveuniquevalue(currentuser(), "studyid", registration.interaction1)), sendemail( append(currentuser(),"not_unique"), "study@soton.ac.uk", "Participant - not unique", append("Participant ", loadvalue (currentuser(), "idnumber"), "has entered information that is not unique."),10) )) goto registrationfinish </code>


For more information on '''saveuniquevalue''', [[How to check whether users have entered a unique value, e.g. Study ID code|please click here]].


[[Category: saveuniquevalue]]
[[Category: saveuniquevalue]]
Line 1,191: Line 1,573:
== <code> savevalue </code> ==
== <code> savevalue </code> ==


The '''savevalue''' command saves a variable that can be loaded again in later sessions. It is used if users have to create an account to access your intervention and you want to save information to a user.
'''savevalue''' stores a piece of information against a specific end-user's account, so it can be loaded again later - in the same session, or in a future one. Your end-users need to have a registered account for this to work.
 
<code>savevalue (username, "valuename", value)</code>


It can be used to:
* '''username''' - the end-user this data belongs to. Use <code>currentuser()</code>.
* create a variable and save it to a user
* '''"valuename"''' - a name you choose for this piece of data, in quotation marks. This becomes the column heading for this data in your exported study data.
* save a response a user has given to an interaction
* '''value''' - the information to store. This can be plain text (in quotation marks), a number, an interaction response (e.g. <code>page1.interaction1</code>), or the result of another command (e.g. <code>currenttime()</code>).
* save the time
* save a questionnaire or session as 'complete'


Common uses include:
* creating and saving a new piece of information about a user
* saving a response an end-user has given to an interaction
* saving the current time
* marking a questionnaire or session as 'complete'


'''Example 1 - Create and save a text variable'''
'''Example 1 - Create and save a text variable'''


<code>savevalue(username, "group", "web_support")</code>
<code>savevalue(currentuser(), "group", "web_support")</code>


This will save the variable '''web_support''' for a username. '''group''' will be the column heading in your data in the '''User data''' sheet.
This saves the text '''web_support''' as the variable '''group''' for the current end-user. '''group''' will be the column heading for this data in your '''User data''' export.


When loading this value later in your logic, you will use the command <code>loadvalue</code>, and the variables you have created - '''group''' and '''web_support''':
To load this value again later in your logic, use [[#loadvalue|<code>loadvalue</code>]] with the same variable name, '''group''':


<code>after page5 if (loadvalue(username, "group") = "web_support") goto page10</code>
<code>after page5 if (loadvalue(currentuser(), "group") = "web_support") goto page10</code>


'''Example 2 - Create and save a numeric variable'''


<code>savevalue(currentuser(), "work", 1)</code>


'''Example 2 - Create and save a numeric variable'''  
This saves the number '''1''' as the variable '''work'''. Again, '''work''' becomes the column heading for this data in your '''User data''' export.


<code>savevalue(username, "work", 1)</code>.
You can use this to show feedback on a page in a later session:


This will save '''1''' for the variable '''work'''. '''work''' will be the column heading in your data in the '''User data''' sheet.
<code>show s1area.summary if (loadvalue (currentuser(), "work")>0) </code>


You can use this to show feedback on a page in another session:
This shows the feedback '''summary''' on page '''s1area''' if the variable '''work''' is greater than '''0'''.


<code>show s1area.summary if (loadvalue (username, "work")>0) </code>
'''Example 3 - Save a response an end-user has given to an interaction'''


This logic will show the feedback '''summary''' on page '''s1area''' if the variable '''work''' is more than '''0'''.
<code>savevalue(currentuser(), "s1_fatigue", page1.interaction1)</code>


This saves the response given for '''interaction1''' on '''page1''' as the variable '''s1_fatigue''', for the current end-user.


'''Example 3 - Save a response a user has given to an interaction'''
To load this later in your logic:


<code>savevalue(username, "s1_fatigue", page1.interaction1)</code>
<code>set page5.fatigue_score to loadvalue (currentuser(),"s1_fatigue")</code>


This will save the response given to '''interaction1''' on '''page1''' to the variable '''s1_fatigue''' for the username.
This loads '''s1_fatigue''' and displays it in the text box '''fatigue_score''' on '''page5'''. For this to work, '''fatigue_score''' needs to be [[How to set text as a printed variable| set as a printed variable]].


To load this later in your logic, you would use the variable name '''s1_fatigue''':
'''Example 4 - Save the current time'''


<code>set page5.fatigue_score to loadvalue (username,"s1_fatigue")</code>
<code>savevalue(currentuser(), "s1_time", currenttime())</code>


This will load the variable '''s1_fatigue''' and will show it in the text box '''fatigue_score''' on '''page5'''. For this to function correctly, '''fatigue_score''' needs to be [[How to set text as a printed variable| set as a printed variable]].
This saves the current time as the variable '''s1_time'''.


You can load this later in your logic - for example, to stop end-users seeing session 2 until a week has passed:


'''Example 4 - Save the time'''
<code>after login_successful if (comparetimes(loadvalue(currentuser(), "s1_time"), currenttime(), "seconds" ) > 604800) goto s2_welcome</code>


<code>savevalue(username, "s1_time", currenttime())</code>
'''Example 5 - Mark a questionnaire or session as complete'''


This will save the current time as '''s1_time'''.
<code>savevalue(currentuser(), "baselinecomplete", "yes")</code>


You can load this later in your logic to ensure that end-users do not see session 2 until 1 week later:
This creates the variable '''baselinecomplete''' and saves '''yes'''. You could also use a number instead, if you prefer:


<code>after login_successful if (comparetimes(loadvalue(username, "s1_time"), currenttime(), "seconds" ) > 604800) goto s2_welcome</code>
<code>savevalue(currentuser(), "baselinecomplete", "1")</code>


You can then check this later in your logic, to see whether an end-user has completed their baseline questionnaire:


'''Example 5 - Save a questionnaire or session as complete'''
<code>after login_successful if (and( hasseen(currentuser(), "qintro"), (isempty(loadvalue(currentuser(), "baselinecomplete"))) )) goto q_notcomplete </code>


<code>savevalue(username, "baselinecomplete", "yes")</code>
This shows the page '''q_notcomplete''' if the end-user has seen '''qintro''', but '''baselinecomplete''' is still empty (meaning they haven't yet finished the baseline questionnaire).


This will create the variable '''baselinecomplete''' and will save '''yes'''. In this example, you can use a number instead of '''yes''':
'''Tip:''' if you need to clear a saved value so a fresh answer can be stored, use [[#deletevalue|<code>deletevalue</code>]] before saving the new one.


<code>savevalue(username, "baselinecomplete", "1")</code>
== <code> sendemail </code> ==


You can load this in your logic to check that an end-user has completed their baseline questionnaire:
'''sendemail''' schedules an email to be sent to an end-user (or anyone else, such as a study coordinator) at a chosen point in the intervention.


<code>after login_successful if (and( hasseen(username, "qintro"), (isempty(loadvalue(username, "baselinecomplete"))) )) goto q_notcomplete </code>
<code>sendemail (uniquename, emailaddress, "subject", "content", delayinseconds)</code>


This will show the page '''q_notcomplete''' if the end-user has seen '''qintro''', but the variable '''baselinecomplete''' is empty (because the baseline questionnaire has not yet been completed).
* '''uniquename''' - a name that must be '''different for every email you send'''. Because many end-users will trigger the same line of logic, this is normally built with <code>append(currentuser(), "some_label")</code>, so each end-user gets their own unique version of the name. If you skip this and just use a fixed name, only the very first email sent with that name will go out - all later ones with the same name will be treated as duplicates and won't be sent.
* '''emailaddress''' - who the email should go to. This is often <code>currentuser()</code> (if end-users register with their email address), or a fixed address in quotation marks, such as <code>"study@example.ac.uk"</code>.
* '''"subject"''' - the email's subject line, in quotation marks.
* '''"content"''' - the body of the email, in quotation marks (this is often built up using '''append'''). Use <code>\n\n</code> to start a new paragraph.
* '''delayinseconds''' - how long to wait, in seconds, after the end-user reaches the page this logic is attached to, before the email is sent. Use a small number like <code>10</code> to send it almost immediately.


== <code> sendemail </code> ==
'''Example 1'''
 
This is the command for setting up e-mails to send out to end-users at specific points in the intervention. The function for sending out an e-mail always uses the same basic formula:


<code>after pagename1 if sendemail(append(username,"unique name for e-mail"), e-mail address, "Subject message for e-mail", "E-mail content", number in seconds indicating how long after the end-user views pagename1 that you want the e-mail sent out) goto pagename2</code>
<code>sendemail (append(currentuser(),"welcome_email"),currentuser(),"You have successfully registered to Stress Less", append("Dear ", loadvalue (currentuser(), "firstname"), "\n\n", welcome), 10)</code>


'''Example 1'''
Here, <code>append(currentuser(),"welcome_email")</code> builds the unique name for this email, by joining the end-user's identifier onto the label '''welcome_email'''. This matters because, without '''append''', every end-user's email would share the exact same name ('''welcome_email''') - only the first one sent would count as unique, and every other end-user's copy would be silently skipped.


<code>sendemail (append(username,"welcome_email"),username,"You have successfully registered to Stress Less", append("Dear ", loadvalue (username, "firstname"), "\n\n", welcome), 10)</code>
A full tutorial is available for [[Sending Emails]], including details of how to send emails to a researcher or healthcare professional instead of the end-user.
 
In this example, the first part of the logic ,<code>(append(username,"welcome_email")</code>, is the unique name of the email. The '''append''' function joins the '''username''' to the name of the email ('''welcome_email''') to make sure that every email is unique. If the append function is not used, every email will be called '''welcome_email''' and only the first one will be unique - the other emails will not be unique and will not be sent out.


== <code> sendtext </code> ==


A full tutorial is available for [[Sending Emails]] including details of how to send e-mails to a researcher or healthcare professional instead of the end-user.
'''sendtext''' schedules an SMS text message to be sent to an end-user. It works in a similar way to '''sendemail''', with a few differences:
* it uses the end-user's mobile phone number instead of an email address
* it doesn't need a subject line
* there is a limit on how long the message can be


== <code> sendtext </code> ==
<code>sendtext ("uniquename", phonenumber, "message", delayinseconds)</code>


This is the command for sending sms text messages to an end-user. It uses a similar basic formula as the command for sending email messages. The only differences are:
* '''"uniquename"''' - a name that must be different for every text message, in the same way as for '''sendemail''' (usually built with <code>append(currentuser(), "some_label")</code>).
* it uses the end-user's mobile phone number instead of an e-mail address
* '''phonenumber''' - the interaction (or variable) containing the end-user's mobile number.
* it does not need a subject message
* '''"message"''' - the text of the message, in quotation marks.
* there is a restriction for how long a text message can be
* '''delayinseconds''' - how long to wait, in seconds, before the message is sent.


<code>after page1 if sendtext ("welcometext", login.phone, "Thank you for registering for the lifestyle intervention. Please remember to check back regularly for more information.", 60) goto page1</code>
<code>after page1 if sendtext ("welcometext", login.phone, "Thank you for registering for the lifestyle intervention. Please remember to check back regularly for more information.", 60) goto page1</code>


'''Note:''' You will need to set up an sms account for your intervention before you can send sms messages. See [[LifeGuide Community Website FAQs]] for more information.
'''Note:''' you will need to set up an SMS account for your intervention before you can send text messages. See [[LifeGuide Community Website FAQs]] for more information.


== <code> stringlength </code> ==
== <code> stringlength </code> ==


This command tells the intervention how many characters a user has entered into a free text interaction.
'''stringlength''' tells you how many characters an end-user has typed into a free-text interaction.
 
<code>stringlength (interactionname)</code>


This can be useful if you want your users to create usernames that are a specific number of characters.
* '''interactionname''' - the free-text interaction to check, e.g. <code>username</code> (here, "username" is just the name given to this particular text box on the page - it is unrelated to the <code>currentuser()</code> identifier discussed elsewhere in this dictionary).


To use this function you will need to write an error message:  
This is useful if, for example, you want end-users to create usernames of a specific minimum length. To use it, write an error message:


<code>show namemessage if (stringlength (username) < 5)</code>
<code>show namemessage if (stringlength (username) < 5)</code>


In this example, the error message called “namemessage” will be shown to users if they have entered less than 5 characters in the interaction called “username”.
Here, the error message '''namemessage''' is shown to users who have entered fewer than 5 characters into the interaction called '''username'''.


[[Category:Stringlength]]
[[Category:Stringlength]]
Line 1,306: Line 1,704:
== <code> sum </code> ==
== <code> sum </code> ==


Please see <code>add</code>
Please see [[#add|<code>add</code>]].


== <code> show </code> ==
== <code> show </code> ==


The <code>show</code> command is the first logic command you will need to know.  It is also probably the most common one that you will use.
'''show''' is the first logic command you will need to know, and probably the one you will use most often. It displays each of your pages, in the order they are written in the logic - when an end-user clicks Next on a page, they move on to whichever page is written next.
 
<code>show pagename</code>


This command shows each of the pages you have created. Pages will be shown in the order they are written in the logic. When an end-user clicks on a Next button on a page, they will be moved to the next page written in the logic.
* '''pagename''' - the page to display next.


'''Example 1'''
'''Example 1'''
Line 1,324: Line 1,724:
show page4</code>
show page4</code>


In the example above, the end-user will be shown the page named ‘page1’. When they click on the next button on '''page1''', they will see the page called ''page2’''. This is followed by ‘''page3’'' and finally ‘''page4’''.
Here, the end-user first sees '''page1'''. When they click Next, they see '''page2''', then '''page3''', and finally '''page4'''.
 
'''NB Before you can preview your intervention, you will need to have the '''show''' command in the logic file for each page you want to view.'''


As the logic requires you to use unique names for each page in your logic, you can only use the '''show''' command once for each page. However, you can re-show the same page to users - see the <code>named</code> command above for more details.
'''Note:''' before you can preview your intervention, every page must appear in a '''show''' command in the logic file at least once.


You can also reshow pages to your end-user by using a jump button on a previous page.
Because pages must have unique names, you can only write '''show pagename''' once for each page - but you '''can''' show the same page again later using [[#named|<code>named</code>]], or by using a Jump button on an earlier page.


=T=
=T=
Line 1,336: Line 1,734:
== <code> timesincelogin </code> ==
== <code> timesincelogin </code> ==


This command can be used to show users how much time has passed since they last logged into the intervention.
'''timesincelogin''' tells you how much time has passed since an end-user last logged into the intervention.
 
'''Example'''


Using the <code> timesincelogin </code> command involves 3 basic steps: 
<code>timesincelogin (username, "unit")</code>


'''1.''' In your logic, show the page (e.g. “time”) where you want to display how long it has been since the user last logged into the website:
* '''username''' - the end-user to check. Use <code>currentuser()</code>.
* '''"unit"''' - what you want the result measured in: <code>"seconds"</code>, <code>"minutes"</code>, <code>"hours"</code>, <code>"days"</code>, <code>"weeks"</code> or <code>"months"</code>.


<code> show </code> time
There is no need to create your own username variable first - simply use <code>currentuser()</code> (see [[#currentuser|<code>currentuser()</code>]]).


'''2.''' In your logic, create a new variable (e.g. “username”) to tell the intervention, which user, time since login data should be displayed for:
'''Example'''


<code> set </code> username <code> to </code> login.name
'''1.''' Show the page where you want to display how long it's been since the end-user last logged in (e.g. "time"):
<code> if </code> (<code>not</code>(<code>isempty</code> (signup.name))) <code> set </code> username <code> to </code> signup.name


(For this logic to work, you will need to have already created “login” and “signup” pages which contain free text interactions to allow the user to enter their name or other identifier such as an email address – see also [[1.12 set]])
<code> show </code> time
 
'''3.''' On your “time” page, create a new variable to represent where the time since login data should be displayed to the user (e.g. “secs”).  (This is done using the ‘set as variable’ function).  Then, in your logic, set this variable to display the desired time since login for a particular user, using the <code> timesincelogin </code> command.   


<code> set </code> time.secs to <code> timesincelogin </code> (username, <code> "seconds"</code>)
'''2.''' On that page, create a variable to hold the value (e.g. "secs"), using the 'set as variable' function, then set it using '''timesincelogin''':


So, in this example, on the page named “time” you have shown the user the time in seconds since they last logged into the intervention.
<code> set </code> time.secs to <code> timesincelogin </code> (currentuser(), <code> "seconds"</code>)


The third step can be repeated to show the user the time in “minutes”, ”hours”, “days”, “weeks” or “months” since they last logged into the intervention.
This shows the end-user, on the page named "time", how many seconds have passed since they last logged in. You can repeat this step using <code>"minutes"</code>, <code>"hours"</code>, <code>"days"</code>, <code>"weeks"</code> or <code>"months"</code> instead, to display the same information in a different unit.


== <code> to </code> ==
== <code> to </code> ==


The <code>to</code> key command is used with the <code>set</code> key command to set variables.
'''to''' is used together with the [[#set|<code>set</code>]] command, as in <code>set variablename to value</code>. See '''set''' for full details and examples.


=U=
=U=
Line 1,369: Line 1,763:
== <code> urlencode </code> ==
== <code> urlencode </code> ==


<code> urlencode(string) </code>
'''urlencode''' converts a piece of text into a form that is safe to use inside a web address (URL). This is an advanced command, needed only when you are building a dynamic URL (i.e. one that includes a variable that might contain spaces or symbols).
 
<code>urlencode (string)</code>
 
* '''string''' - the piece of text (often a variable) you want to make URL-safe.
 
Certain characters (such as ? and &) have special meaning inside a URL and must be converted into a different format so they don't break the link (for example, the '''&''' symbol becomes '''%26'''). '''urlencode''' takes care of this for you.


This is an a function for advanced users. It returns a URL encoded version of a string and should be used only when creating a dynamic URL (i.e. using a variable). It is used when  the variable might contain non alphanumeric characters. It converts a string into the correct format to prevent usual characters from breaking the link. This is because certain characters (such as ? and &) have special functions when included in a URL and have to be encoded in a different format (e.g. the & symbol gets converted to %26).
URL encoding is a common, standard technique - you can find more information here: http://en.wikipedia.org/wiki/Percent-encoding


URL encoding is common and you will find more information here: http://en.wikipedia.org/wiki/Percent-encoding
[[Category: Error Messages]]

Latest revision as of 13:03, 22 July 2026

A quick reference guide to LifeGuide logic. For more detailed information, please refer to the How to... Guide.

It is important to insert Next buttons on your pages (instead of Jump buttons) whenever possible in order for your logic to work correctly. If you show a page and have a vital line of logic written after you show that page (such as randomisation or saving logic), or have error messages on that page, your intervention will not work correctly if you use a Jump button - you will jump to another page and skip parts of the logic in your logic file and Error Messages section.

Tip for new users: many of the examples below use a variable called username to represent the identifier of the currently logged-in end-user. Older interventions created this variable manually near the top of the logic file (see set). Current best practice is to use the built-in currentuser() function instead, which always returns the identifier of whoever is currently logged in, with nothing to set up first - simply use currentuser() anywhere you see username in an example below.

How to read the examples below: where a command takes information in brackets, e.g. savevalue(username, "valuename", value), each item inside the brackets is called an argument, and the commas separate one argument from the next. Most entries below list what each argument means and what you should put there. Text written in quotation marks (e.g. "seconds") must be typed exactly as shown, including the quotation marks themselves - this tells the intervention you mean a fixed piece of text, not a variable.

A

add

add can also be written as sum or +. It adds two or more numbers together - for example, several numeric responses, or scores you have calculated earlier in the logic.

add (value1, value2, value3, ...)

  • value1, value2, ... - the numbers you want to add together. Each one can be a plain number, an interaction response (e.g. page1.interaction1), or a variable you have already calculated (e.g. score1). You can list as many as you need, separated by commas.

Example 1

This can be used to perform a calculation using the end-user's responses to specific numeric value interactions:

set score1 to add (page1.interaction1, page1.interaction2, page1.interaction3)

Example 2

The add or sum commands can also be used to calculate variables that have been set earlier in the session:

set overallscore to sum (score1, score2, score3)

If you only ever need to add or subtract exactly two numbers, you can use + and - instead, for example:

set score to (100 - page1.interaction1)

Make sure you leave a space on either side of the - symbol.

after

after lets you run logic once a particular page has been shown to the end-user - for example, to check their answers and decide which page to send them to next.

after pagename if (condition) goto nextpage

  • pagename - the page this logic relates to. The logic will run once the end-user has been shown this page and clicked Next.
  • condition - (optional) something that must be true for the rest of the line to happen, e.g. a response given on that page. You can leave this out if you always want the logic to run.
  • nextpage - the page to send the end-user to if the condition is true.

You will use the after command regularly. It is most often combined with if and goto, as above, but any command in this dictionary can be used after a page in the same way.

Example 1

after page1 if (page1.interaction1 = "yes") goto page3 show page 2 show page3

In the above example, the end-user will be directed to page3 if they answered yes to interaction1 on page1. If they answered anything else, they will carry on to the next line of logic and will see page2.

Note: if you use after with goto, the page you send the user to (in the example above, page3) should not be the very next page in your logic - it needs to be a page further down, as shown above. Otherwise the end-user would see that page twice.

and

and can also be written as &&. It combines two or more conditions into one, and is only true when every condition inside it is true. It is commonly used to:

  • check that several responses have been given before showing tailored feedback
  • combine several checks into a single line of logic after a page

and (condition1, condition2, ...)

  • condition1, condition2, ... - the individual conditions to check, separated by commas. You can list two or more. and is only true if all of them are true.

Example 1

show page6 if (and(page3.exercise = "yes", page3.intensity = "moderate", page3.frequency = "three"))

End-users will be shown page6 only if they selected yes for the interaction exercise on page3, moderate for intensity on page3, and three for frequency on page3. If any one of those three answers is different, page6 will not be shown.

Example 2

after login_successful if (and( not(hasseen(currentuser(), "q_demographics")), (isempty (loadvalue(currentuser(), "baselinecomplete"))) )) goto q_intro

End-users will be shown q_intro if both of the following are true: they have not seen page q_demographics, and the variable baselinecomplete is empty (i.e. it hasn't been saved yet, because they haven't finished the baseline questionnaire).

append

append joins two or more pieces of text (and/or variables) together into a single, longer piece of text. A "piece of text" - also called a string - is anything written between quotation marks, such as "session1", or a variable that already holds text.

append (part1, part2, part3, ...)

  • part1, part2, ... - the pieces of text or variables you want to join together, in the order you want them joined, separated by commas. You can list as many as you need.

append is most often used with sendemail and cancelemail, to build a unique name for each email (see below), but it is useful anywhere you need to combine text.

Example 1

sendemail (append(currentuser(),"user_reg1"), currentuser(), "StressLess - Session 1 is ready", append("Dear ", loadvalue (currentuser(), "personsname"), "\n\n", reg_part1, reg_part2), 10)

In this example, append is used twice:

  • to join the current end-user's identifier onto a fixed piece of text, so that the email's name is unique to that end-user:

append (currentuser(),"user_reg1")

  • to build the text of the email out of several separate pieces:

append ("Dear ", loadvalue (currentuser(), "personsname"), "\n\n", reg_part1, reg_part2)

\n\n is a special code that means "start a new paragraph" in the email.

Example 2

cancelemail (append("user_regs2rem", currentuser()), currentuser())

Here, append joins a fixed label onto the end-user's identifier, to rebuild the same unique email name that was used when the email was first set up: append ("user_regs1", currentuser())

Example 3

append is not only useful for emails - it can also combine interaction responses, and the result can be saved with savevalue:

set fullname to append(registration.firstname, " ",registration.surname) savevalue(currentuser(),"fullname", fullname)

This takes the responses given to the firstname and surname interactions on the registration page and combines them (with a space in between) into a single variable called fullname.

Important: every item you pass to append must be a variable or a piece of text in quotation marks (even a single space, like " "). If you forget the quotation marks around plain text, it may not work.

Example 4

In this example, we add extra information onto a value that has already been saved, rather than replacing it:

savevalue(currentuser(), "oldgoals","RESULTS_") if isempty(loadvalue(currentuser(),"oldgoals")) set oldgoals to loadvalue(currentuser(),"oldgoals") savevalue(currentuser(), "oldgoals", (append(oldgoals,"_", printtime(currenttime(),"dMy"),"_", goalsetpage.newgoal)))

First, if the variable "oldgoals" doesn't exist yet, we create it and save a starting value. We then load whatever is currently stored in "oldgoals". Finally, we save "oldgoals" again, appending today's date and the new goal (from the page "goalsetpage") onto the end of whatever was already there. Underscores are used to separate each piece of data so it stays readable. Over time, this builds up a single variable that looks like this:

"RESULTS_181016_firstgoal_191016_secondgoal_221016_thirdgoal"

authenticateuser

authenticateuser checks that a username (or email address) and password entered by an end-user match a registered account. It is used together with makenewuser, which is the command that creates the account in the first place, and is normally written directly after the logic that shows your login page.

authenticateuser (username, password)

  • username - the page.interaction where the end-user typed their username or email address, e.g. login.username.
  • password - the page.interaction where the end-user typed their password, e.g. login.password.

authenticateuser can be used either in the main logic file, or inside a page's Error Messages tab.

Example 1

show login after login if (authenticateuser (login.username, login.password)) goto login_confirmation show login_fail show login_confirmation

Here the logic is written in the logic file. If the username and password entered on the login page match a registered account, the end-user is sent to login_confirmation. If not, they will see the login_fail page.

Example 2

show err1 if (isempty(username)) show err2 if (not(authenticateuser(username, password)))

Here the logic is written in the Error Messages tab of the login page itself. If the username and password entered do not match a registered account, the end-user sees the error message err2 and cannot move on to the next page.

B

begin

begin marks the start of a named section of logic, and is always paired with an end command that marks where the section finishes.

begin sectionname

  • sectionname - a name you choose for this section, e.g. session1. It must be different from any page or object name already used in your intervention.

If your intervention has separate sessions or groups (e.g. different weekly sessions, or different sets of pages for different study arms), grouping the related logic into a named section can make your logic file much easier to navigate.

A few things to remember:

  • Every begin must have a matching end.
  • All the logic that belongs to the section must sit between its begin and end.
  • You only ever need to close the section you are currently in, so you do not write the section's name after end - just end on its own.

Example 1

begin session1

show page1

show page2

end

This begins the section session1, shows page1 and page2, then ends session1. Both pages sit between begin session1 and end, so they belong to that section.

Example 2 - Beginning and ending a section within another section

begin stress

begin causes

show page1

show page2

end

begin relieve

show page3

show page4

end

end

This begins the outer section stress. Inside it, the section causes begins, showing page1 and page2; the first end closes causes. Then the section relieve begins, showing page3 and page4; the next end closes relieve. The final end closes the outer section, stress.

C

cancelemail

cancelemail stops an email that was previously scheduled with sendemail from being sent, as long as it hasn't gone out yet. You might use this to:

  • stop a reminder email if the end-user has already done the thing the reminder was about (e.g. logging in for a session)
  • stop a "nudge" email to a study coordinator if the end-user has since completed the questionnaire it was chasing

cancelemail (uniquename, emailaddress)

  • uniquename - must exactly match the unique name that was used when the email was originally set up with sendemail (this is usually built with append(currentuser(), "some_label") - see the examples below).
  • emailaddress - the address the (now cancelled) email would otherwise have been sent to.

Example 1

cancelemail(append(currentuser(), "email_session2r"), currentuser())

This cancels the email email_session2r for the current end-user. append rebuilds the same unique name (end-user identifier + email_session2r) that was used to schedule the email in the first place.

Example 2

cancelemail(append(currentuser(),"q1_notcomplete"), "study@test.ac.uk")

This cancels the email q1_notcomplete that was due to be sent to study@test.ac.uk (a fixed address, rather than the end-user's own address).

cancelsms

cancelsms stops a text message that was previously scheduled with sendtext from being sent, as long as it hasn't gone out yet. It works the same way as cancelemail, but for text messages.

after pagename if cancelsms ("uniquename", phonenumber) goto nextpage

  • "uniquename" - must exactly match the unique name used when the text message was originally scheduled with sendtext.
  • phonenumber - the phone number the (now cancelled) text message would otherwise have been sent to.

changepassword

changepassword lets an already-registered end-user change their password, as long as they can enter their current password correctly.

changepassword (username, oldpassword, newpassword)

  • username - the identifier for the end-user changing their password. Use currentuser().
  • oldpassword - the page.interaction where they entered their current password.
  • newpassword - the page.interaction where they entered their new, chosen password.

Please see the LifeGuide Community Website for a tutorial intervention showing how to build the pages and logic for this.

Example 1

after passworddetails if changepassword (currentuser(), passworddetails.old, passworddetails.new) goto confirmchange

This changes the end-user's password, as long as their current password is entered correctly into the interaction called old on the page passworddetails, and their new password is entered into the interaction called new on the same page.

checkemailvalidity

checkemailvalidity does a basic check that an email address entered by an end-user contains an @ symbol.

checkemailvalidity (interactionname)

  • interactionname - the interaction where the end-user typed their email address, e.g. email.

This command is normally used together with an error message, written in the Error Messages tab (please see Adding Error Messages for more information about writing error messages).

Example 1

show invalidemail if (not (checkemailvalidity (email)))

invalidemail is the name of an error message, shown when the interaction called email on this page doesn't contain a valid-looking address.

checkphonenumbervalidity

checkphonenumbervalidity checks that a mobile number entered by an end-user begins with +44 or 0.

checkphonenumbervalidity (interactionname)

  • interactionname - the interaction where the end-user typed their phone number, e.g. phone.

This command is normally used with an error message (please see Adding error messages for more information).

Example 1

show invalidnumber if (not (checkphonenumbervalidity (phone)))

invalidnumber is the name of the error message, shown when the interaction called phone on this page doesn't look like a valid number.

This check is designed for UK phone numbers only. If your study needs to accept international numbers, you will need to write your own error message logic instead.

checkuserenabled

checkuserenabled checks whether a user's account is currently enabled. An account can become disabled if, for example, a researcher disables it manually (e.g. because a participant has withdrawn from a study, or their account needs to be temporarily suspended).

checkuserenabled (usernameoremail)

  • usernameoremail - the identifier to check - usually the page.interaction where the end-user entered their username or email address while logging in.

checkuserenabled is most often used together with authenticateuser as part of your login logic, so that a user is only let in if they have entered the correct details and their account is still enabled.

Example 1

show login after login if (and(authenticateuser (login.username, login.password), checkuserenabled (login.username))) goto login_confirmation show login_fail show login_confirmation

The end-user is only directed to login_confirmation if the username and password they entered are correct and their account is enabled. If either check fails, they are shown the login_fail page.

checkuserexists

checkuserexists checks whether a username or email address has already been registered with the intervention - for example, to stop someone signing up twice with the same details.

checkuserexists (usernameoremail)

  • usernameoremail - the interaction where the end-user typed the username or email address you want to check, e.g. email.

This command is often used with an error message (please see the How to guide for details on how to write error messages).

Example 1

show registeredemail if (checkuserexists (email))

registeredemail is the name of the error message shown if the end-user enters an email address (into the interaction called email) that is already registered to another user.

comparetimes

comparetimes works out the difference between two points in time, and converts that difference into whichever unit you choose (seconds, minutes, hours, days, weeks or months).

comparetimes (time1, time2, "unit")

  • time1 - the earlier point in time you are comparing, e.g. a time you saved previously with loadvalue(currentuser(), "sometime").
  • time2 - the later point in time you are comparing, e.g. currenttime().
  • "unit" - what you want the difference measured in: "seconds", "minutes", "hours", "days", "weeks" or "months" (don't forget the s at the end of each one).

The result is time2 minus time1, converted into the unit you chose - so it will normally be a positive number if time2 is later than time1.

Example 1

This example shows how comparetimes can be used to control end-users' access to different sessions or pages within an intervention.

There is no need to create your own username variable before using comparetimes - simply use currentuser() wherever you need to identify the end-user (see currentuser()).

The order of your logic matters when using comparetimes:

1. Show the page users see before they are directed to a particular session (e.g. "mainpage"):

show mainpage

2. Write the logic that sends the user to a particular session or page, depending on how much time has passed:

after mainpage if ( comparetimes ( loadvalue ( currentuser(), "session4time") , currenttime ( ), "seconds" ) >= 120 ) goto endpage

This says: if at least 120 seconds (two minutes) have passed since the value "session4time" was saved, send the user to endpage.

after mainpage if ( comparetimes ( loadvalue ( currentuser(), "session3time" ), currenttime ( ), "seconds" ) >= 120 ) goto session4

This says: if at least two minutes have passed since session3 was completed, let the user continue to session4.

after mainpage if ( comparetimes ( loadvalue ( currentuser(), "session3time" ), currenttime ( ), "seconds" ) <= 120 ) goto waitpage

This says: if less than two minutes have passed since session3 was completed, send the user to a waitpage instead, since they cannot continue yet.

Repeat this pattern for every session or page you want to control access to. The variables "session3time" and "session4time" are created in step 3, below.

3. Finally, show the individual pages or sessions, and record the time each one was completed:

show waitpage

show session3

after session3 if ( savevalue ( currentuser(), "session3time", currenttime ( ) ) )goto session3end

show session3end

Using currenttime, this saves a new variable, "session3time", recording the moment the user completed session3. This is the value that comparetimes will read back in step 2.

So, altogether, this example compares the time a user completed a section of the intervention with the current time, to decide whether enough time has passed to let them continue.

Example 2

In this example we use comparetimes to break the time until Christmas 2016 down into weeks, days, hours, minutes and seconds, so it can be displayed to the user in a friendly way.

set timenow to (currenttime()) set christmas to (1482624000)

set weeks to (comparetimes(timenow,christmas,"weeks")) set days to (comparetimes(timenow,christmas,"days")) set hrs to (comparetimes(timenow,christmas,"hours")) set mins to (comparetimes(timenow,christmas,"minutes"))

set days2 to (days - (weeks*7)) set hrs2 to (hrs - (days*24)) set mins2 to (mins - (hrs*60)) set secs to ((christmas - timenow) - (mins*60))

This first uses comparetimes to work out the total difference between now and Christmas in weeks, in days, in hours and in minutes. But we don't want to display "total days" or "total hours" - we want a friendly breakdown, like a countdown timer would show (e.g. "2 weeks, 3 days, 4 hours...").

To do that, we take the total number of days and subtract the days already counted in the weeks figure, so what's left is less than 7. We do the same for hours (subtracting whole days) and minutes (subtracting whole hours).

For seconds, we simply take the raw difference between christmas and timenow and subtract the whole minutes we've already counted - there's no need to use comparetimes for this step, because currenttime is already measured in seconds.

To display the countdown on a page, the following logic can be used:

show intro set intro.hrs to hrs2 set intro.mins to mins2 set intro.secs to secs set intro.days to days2 set intro.weeks to weeks

contains

contains is used with multiple-choice interactions, to check whether one particular option was among those an end-user selected.

interactionname contains "value"

  • interactionname - the multiple-choice interaction to check, e.g. page1.exercise.
  • "value" - the Unique Response Name of the option you're checking for, in quotation marks.

Example 1

after page1 if (page1.exercise contains "none") goto page4

The end-user is directed to page4 if none was one of the options they selected for the interaction exercise on page1.

Example 2

after page1 if (or( page1.exercise contains "1day", page1.exercise contains "2days" )) goto page4

The end-user is shown page4 if they selected either 1day or 2days for the interaction exercise on page1.

converttointeger

Interactions where an end-user types in a number - such as a text-entry interaction asking for someone's age - store the response as text (a series of characters), not as a number. This means the response can't reliably be used with comparison commands (morethan, lessthan, etc.) or calculation commands (add, multiply, etc.) until it has been converted into a whole number. converttointeger does this conversion for you.

converttointeger (interactionname)

  • interactionname - the text-entry interaction whose response you want to convert, e.g. signup.age. The response should only contain digits (a whole number) for the conversion to work correctly.

Example 1

show screening_fail if (converttointeger(signup.age) < 18)

This shows the error message screening_fail if the number entered into the text-entry interaction age on the signup page converts to less than 18.

Example 2

savevalue(currentuser(), "age_years", converttointeger(signup.age))

This converts the text response given to the age interaction into a whole number, and saves it as the variable age_years for the current end-user, so it can be used in calculations later in the intervention.

countif

countif counts how many of a list of conditions are currently true - for example, how many interactions on a page an end-user has filled in.

countif (condition1, condition2, ...)

  • condition1, condition2, ... - the conditions to check, separated by commas. countif returns the number of these that are true.

Example

after page1 if (countif( not(isempty(page1.interaction1)), not(isempty(page1.interaction2)), not(isempty(page1.interaction3)), not(isempty(page1.interaction4)) ) < 3) goto page4

This checks four interactions on page1 and counts how many of them have not been left empty (i.e. how many the end-user has answered). If they have answered fewer than 3 of the 4, they are directed to page4.

currenttime

currenttime() returns the date and time at the exact moment it runs. It takes no arguments - it is always written with empty brackets, currenttime(), which tells the intervention this is a function rather than a variable you have created yourself.

You can use currenttime to record when something happened (by saving it), or to compare against a time you saved earlier (using comparetimes).

1. There is no need to create your own username variable before using currenttime - simply use currentuser() wherever you need to identify the end-user (see currentuser()).

2. To save the time a user completes a particular section of your intervention (in this example, "session 3"):

show session3

after session3 if ( savevalue ( currentuser(), "session3time", currenttime ( ) ) )goto session3end

show session3end

This saves the moment the user completes the session3 page as a new variable called "session3time".

3. currenttime can also be used as a reference point to compare against, which is particularly useful for putting time controls on when users can access particular sessions (see also comparetimes):

after mainpage if ( comparetimes ( loadvalue ( currentuser(), "session3time" ), currenttime ( ), "minutes" ) >= 120 ) goto session4

This lets the user continue to session 4 if it has been at least two hours since they completed session 3.

after mainpage if ( comparetimes ( loadvalue ( currentuser(), "session3time" ), currenttime ( ), "minutes" ) <= 120 ) goto waitpage

This sends the user to a "waitpage" instead, if less than two hours have passed since they completed session 3.

currentuser() and midnight() work the same way as currenttime() - all three are functions that take no arguments, so they are always written with empty brackets.

currentuser

currentuser() returns the identifier (i.e. the username) of whichever end-user is currently logged in to the intervention. It takes no arguments - it is always written with empty brackets, currentuser(). It can be used anywhere you would otherwise need a username variable - for example with savevalue, loadvalue, sendemail, hasseen and most other commands that refer to a specific end-user.

Best practice: older interventions had to create their own username variable near the top of the logic file, by loading it from the login or signup page (see set, Example 1). currentuser() removes the need for this step, because it always refers to whichever end-user is logged in at that point in the intervention - there is nothing to set up first. This is now the recommended way to refer to the current end-user throughout your logic.

Note: currentuser() only returns a sensible result once someone has actually logged in (for example, after authenticateuser or makenewuser has run successfully). Using it on a page shown before login, such as the login page itself, will not identify anyone.

Example 1

savevalue(currentuser(), "session1complete", "yes")

This saves the variable session1complete for whichever end-user is currently logged in - there is no need to set up a separate username variable first.

Example 2

show welcome set welcome.firstname to loadvalue(currentuser(), "firstname")

This loads the value firstname that was previously saved for the current end-user, and displays it on the page welcome in place of the word 'firstname'.

D

decimalplaces

decimalplaces rounds a number to a specified number of digits after the decimal point. For example, it would round 6.6666666 to 6.67 if you asked for 2 decimal places, or to 6.6667 for 4 decimal places. If you want to round to a whole number (0 decimal places), the simpler round command can be used instead.

decimalplaces (number, decimalplacecount)

  • number - the number (or a variable/calculation that produces a number) you want to shorten.
  • decimalplacecount - how many digits you want to keep after the decimal point.

You cannot use decimalplaces to abbreviate whole numbers to a number of significant figures (e.g. turning 1,234,567 into 1,234,600) by asking for a negative number of decimal places - a negative number here is simply treated as 0. To round a whole number like this, use round instead (see Example 3 of round).

Example 1

In this example we shorten a long decimal number to 4 decimal places.

set numberpi to decimalplaces(3.1415926,4)

This sets the value of numberpi to 3.1416.

Example 2

In this example we calculate the area of a circle and return the answer to 2 decimal places.

show circle_page

set cradius to circle_page.radius

set pi to 3.14159

set carea to ((cradius*cradius)*pi)

set careashort to decimalplaces(carea,2)

show results_page

set results_page.circle to careashort

First we get the radius from the user's response on circle_page. Then we set the value of pi. Then we calculate the area of the circle using the formula area = pi × (radius × radius). We then shorten the result to 2 decimal places for display, while still keeping the full, unrounded value stored in carea in case we want to use it in further calculations later (like the volume of a cylinder). On results_page we show the user the area of the circle, to 2 decimal places.

default

default sets an interaction on a page to show a previously saved value, so the end-user sees their earlier answer already filled in. It is used together with the save command - see save for an example.

To recall information the end-user entered earlier on the same page (rather than a different page or session), use saveandload instead.

deletevalue

deletevalue removes a value that was previously saved with savevalue. This is useful when you want to clear a saved value so a fresh answer can be stored later in the intervention - for example, because an end-user is updating information about themselves that can change over time.

deletevalue (username, "valuename")

  • username - the end-user whose saved value you want to remove. Use currentuser().
  • "valuename" - the exact name that was used when the value was originally saved with savevalue, in quotation marks.

Example 1

deletevalue(currentuser(), "currentgoal") savevalue(currentuser(), "currentgoal", goalpage.newgoal)

This deletes the previously saved value currentgoal for the current end-user, before saving a new response to the same variable. Deleting the old value first ensures that only the most recent goal is stored, rather than the new value being added alongside the old one.

divide

divide is used when performing calculations. The symbol / can also be used instead.

value1 / value2

  • value1 - the number being divided (the dividend).
  • value2 - the number to divide it by (the divisor).

Example 1

set score1 to (page1.interaction1 / page1.interaction2)

score1 is the result of dividing the response given for interaction1 by the response given for interaction2.

Example 2

set overallscore to (score1 / score2)

Here, overallscore is calculated by dividing score1 by score2, where both have already been calculated elsewhere in the logic.

E

else

else is used only together with if. It lets you specify something to do when the if condition on the line above is not met.

if not(or(isempty(page1.q1),isempty(page1.q2))) set page1_complete to 1

else set page1_complete to 0

This checks whether both interactions on page1 have been answered. If they have, page1_complete is set to 1. The else line then sets page1_complete to 0 if they have not both been answered.

end

end closes a section that was opened with begin. Please see begin for details and examples. end takes no arguments - you never need to repeat the section's name, since it always closes whichever section is currently open.

F

for

for is used together with the save and graph commands, to say which end-user a page or a piece of graph data belongs to (e.g. save page1 for currentuser()). See those entries for full examples.

G

getuserid

getuserid returns the database ID for a user - a number that LifeGuide generates automatically and that is unique to each account on that server. This can be useful if you need a short, unique identifier for a user without referring to their username or email address directly. It can also be included in your data export by ticking the User Number box when you export your data.

getuserid (username)

  • username - the end-user whose database ID you want. Use currentuser().

Example 1

getuserid(currentuser())

goto

goto is always used together with the after command. It tells the logic which page to send the end-user to next.

after pagename if (condition) goto nextpage

  • nextpage - the page the end-user should be sent to when the condition is true. See after for a full explanation and examples.

graph

graph is used together with the graph interaction, to plot information given by end-users onto a graph - for example, showing someone their weight or mood over time.

It always follows the same two-part pattern, and requires end-users to have a registered account.

1. Wherever you collect the data you want to plot, record it with:

graph interactionvalue to "variablename" for username

  • interactionvalue - the response you want to plot, written as page.interaction (e.g. progresschart.kg).
  • "variablename" - a name you choose for this piece of data, in quotation marks. Use the same name every time you record data for the same graph.
  • username - the end-user this data point belongs to. Use currentuser().

2. On the page where the graph interaction itself is shown, add a line to tell it which data to display:

set pagename.graph-1 to graph "variablename" for username

Here, pagename.graph-1 is the name LifeGuide automatically gives to a graph interaction (you can check the exact name in the interaction's properties), and "variablename" must match the name used when the data was recorded in step 1.

Example 1

In this example, the number entered into the interaction kg on the page progresschart is recorded as the data for a graph variable called "weight".

show progresschart graph progresschart.kg to "weight" for currentuser()

Later in the logic, on the page where the graph is actually displayed:

show weightgraph set weightgraph.graph-1 to graph "weight" for currentuser()

A full tutorial for using graphs will soon be available.

H

hasseen

hasseen checks whether an end-user has already been shown a particular page, so you can tailor what they see next based on their previous visits.

hasseen (username, "pagename", scope)

  • username - the end-user to check. Use currentuser().
  • "pagename" - the unique name of the page you want to check, in quotation marks.
  • scope - (optional, only relevant if your intervention uses sessions - see below) leave this out entirely to check previous sessions only, or write "true" to include the current session, or "this" to check the current session only.

Tip: if your intervention has more than one session, we recommend using savevalue and loadvalue instead of hasseen, since saved values can be corrected after your intervention has gone live if something goes wrong, whereas page-view history cannot.

Example 1

If you want to show end-users a different page each time they log in, depending on which sessions they have already seen, you can use hasseen like this:

show login

show s1welcome if (not(hasseen (currentuser(), "s1welcome")))

show s2welcome if (not(hasseen (currentuser(), "s2welcome")))

show s3welcome if (not(hasseen (currentuser(), "s3welcome")))

The first time someone logs in, they will see s1welcome. The next time, because they have already seen s1welcome, the logic skips that line and shows s2welcome instead, since they have not yet seen it.

Example 2

hasseen can also be used without not, to tailor the intervention for users who have already seen a page.

show s1_feeback2 if (hasseen (currentuser(), "s1_feedback1")))

show s1_feeback3 if (hasseen (currentuser(), "s1_feedback2")))

Using hasseen in sessions

If your intervention is split into sessions, the scope argument controls which sessions hasseen looks at:

show session2.interaction1 if (hasseen (currentuser(), "session1final"))

With no third argument, this shows interaction1 if the end-user has seen session1final in any previous session (but not the one they're currently in).

show session2.interaction1 if (hasseen (currentuser(), "session1final", "true"))

Adding "true" shows interaction1 if the end-user has seen session1final in any session, including the current one.

show session2.interaction1 if (hasseen (currentuser(), "session1final", "this"))

Adding "this" shows interaction1 only if the end-user has seen session1final earlier in the current session.

hmacencode

hmacencode is an advanced command that scrambles (encrypts) a piece of text so it cannot be read. There is no way to reverse this and get the original text back (it cannot be decrypted) - its main use is to check that data passed from one intervention to another has not been tampered with or corrupted along the way.

hmacencode (text, secretkey)

  • text - the piece of text you want to encode, in quotation marks (or a variable containing text).
  • secretkey - a password-like piece of text, shared between the systems that need to check the data, used to scramble it.

set encoded to hmacencode("This message is encoded", "secret")

I

if

if is always used together with another command (e.g. after, show, set). It is followed by a condition - something that can only be true or false, such as page1.interaction1 = "yes". The command in front of if is only carried out when that condition is true.

command if (condition)

  • condition - the thing being checked. This is often built using other commands from this dictionary, such as and, or, not, isempty or a comparison like =, < or >=.

isempty

isempty checks whether an end-user has given any response to an interaction - in other words, whether it has been left blank.

isempty (interactionname)

  • interactionname - the interaction to check, e.g. page1.interaction1.

Example 1

after page1 if (isempty (page1.interaction1)) goto page4

The end-user is directed to page4 if they left interaction1 on page1 blank.

Example 2

set none if (isempty (page1.interaction1))

If the end-user leaves interaction1 on page1 blank, the variable none is set.

L

load

load is always used together with save, to bring back a page's saved responses so they can be shown again. Please see save for details and an example.

loadvalue

loadvalue retrieves a value that was previously stored with savevalue.

loadvalue (username, "valuename")

  • username - the end-user whose data you want to retrieve. Use currentuser().
  • "valuename" - the exact name that was used when the value was saved with savevalue, in quotation marks.

Please see savevalue for full examples of saving and loading values together.

loggedin

loggedin() checks whether there is currently a logged-in end-user. It takes no arguments - it is always written with empty brackets, loggedin(). It returns true if someone is logged in, and false if not. This is useful for tailoring pages or navigation depending on whether someone is browsing your intervention as a registered, logged-in user - for example, to skip the login page for someone who is already logged in, or to hide content that should only be seen once someone has logged in.

Example 1

show login after login if (loggedin()) goto welcome_back show login_fail show welcome_back

This directs the end-user straight to welcome_back if they are already logged in (for example, if they still have an active session from earlier), skipping the need to log in again.

Example 2

show help_page show help_page.membersonly if (loggedin())

This shows the feedback box membersonly on help_page only to end-users who are currently logged in.

lessthan

lessthan compares two values. The symbol < can also be used instead.

value1 lessthan value2 (or value1 < value2)

  • value1 - the first value.
  • value2 - the value it's being compared against. The condition is true when value1 is smaller than value2.

This is used both for:

  • comparing numbers, e.g. interaction responses or calculated scores
  • comparing time, e.g. checking that less than a certain amount of time has passed since a previous session

Example 1

set condition1 if (page1.interaction1 < page1.interaction2)

Example 2

after login if (comparetimes (loadvalue(currentuser(), "session1_time"), currenttime(), "seconds" ) < 86400)

lessthanequal

lessthanequal works the same way as lessthan, but is also true when the two values are equal. The symbol <= can also be used instead.

value1 lessthanequal value2 (or value1 <= value2)

  • value1 - the first value.
  • value2 - the value it's being compared against. The condition is true when value1 is smaller than, or equal to, value2.

Example 1

set condition1 if (page1.interaction1 <= page1.interaction2)

Example 2

after login if (comparetimes (loadvalue(currentuser(), "session1_time"), currenttime(), "seconds" ) <= 86400)

M

makenewuser

makenewuser creates a new registered account for an end-user, using a username (or email address) and password that they choose.

makenewuser (username, password)

  • username - the page.interaction containing the identifier the end-user will log in with, e.g. signup.signup_username.
  • password - the page.interaction containing their chosen password, e.g. signup.signup_password. This interaction should always be set to the password interaction type in its properties panel - if it isn't, the password will be visible as the end-user types it, and will not be stored securely, which can leave users unable to log in later.

makenewuser both creates the account and signs the end-user in at the same time, so there is no need to also call authenticateuser straight afterwards.

Example

show signup

makenewuser(signup.signup_username, signup.signup_password)

The information the end-user enters into the signup_username and signup_password interactions is used to create their account.

Tip: if you create accounts using an identifier other than a real email address (for example, a study ID), you can still associate a real email address with the account afterwards using setemail, so that commands like sendemail and resetpassword work correctly.

midnight

midnight() is similar to currenttime(), but returns the time at midnight at the start of today, rather than right now. It takes no arguments - it is always written with empty brackets, midnight(). It's useful for scheduling something at a specific time of day, such as sending an email at 7am, one week after someone registers.

set delay7am to + (midnight(), 25200, (-1 * currenttime()))

This sets a variable called delay7am to: today's midnight, plus 25200 seconds, minus the time right now.

For example, at 10:30am on 2/9/2016, this would be 1472774400 + 25200 - 1472812200 = -12600.

Place this logic near the top of your logic file with your other set lines, or immediately before the sendemail logic that uses it.

delay7am can be replaced with a variable name of your choice. 25200 is the number of seconds since midnight that you want (in this case, 7 hours = 7am - you can change this to schedule a different time of day).

Your email logic would then look something like this:

sendemail (append(currentuser(),"welcome_email"),currentuser(),"You have successfully registered to Stress Less", append("Dear ", loadvalue (currentuser(), "firstname"), "\n\n", welcome), (delay7am+604800))

Because delay7am will be a negative number if the current time is already past 7am, you need to add at least one full day (in seconds) on top of it before using it as a delay - in the example above, one week (604800 seconds) has been added.

Remember to allow for the UK's clock changes between GMT and BST, and for time differences between the UK and other countries, if this matters for your study.

morethan

morethan compares two values. The symbol > can also be used instead.

value1 morethan value2 (or value1 > value2)

  • value1 - the first value.
  • value2 - the value it's being compared against. The condition is true when value1 is bigger than value2.

Example 1

set condition2 if (page1.interaction1 > page1.interaction2)

condition2 is set if the value given for interaction1 is greater than the value given for interaction2.

morethanequal

morethanequal works the same way as morethan, but is also true when the two values are equal. The symbol >= can also be used instead.

value1 morethanequal value2 (or value1 >= value2)

  • value1 - the first value.
  • value2 - the value it's being compared against. The condition is true when value1 is bigger than, or equal to, value2.

Example 1

set condition2 if (page1.interaction1 >= page1.interaction2)

condition2 is set if interaction1 is greater than or equal to interaction2.

multiply

multiply is used to multiply one value by another. The symbol * can also be used instead.

value1 * value2

  • value1 and value2 - the two numbers to multiply together. Each can come from an end-user's response to an interaction, or from a calculation performed elsewhere in the logic.

Example 1

set score1 to (page1.interaction1 * page1.interaction2)

The response to interaction1 is multiplied by the response to interaction2, and the result is saved as score1.

Example 2

set overallscore to (score1 * score2)

Here, score1 and score2 were already calculated earlier in the logic, and are multiplied together to give overallscore.

N

named

named lets you re-show a page you have already shown once, under a new alias.

show pagename named alias

  • pagename - the page you have already created and shown earlier in your logic.
  • alias - a new, unique name for this repeat showing of the page. This is not a separate page you need to create - it is simply a label that lets your logic refer to this particular instance of showing pagename again.

Example 1

show page1

[etc, etc]

show page1 named page2

[etc, etc]

show page1 named page3

(Here, [etc, etc] stands in for other lines of logic that would appear in a real intervention.) This shows the same page, page1, three times over the course of the intervention - once under its own name, then again labelled page2, then again labelled page3.

not

not reverses whether a condition is treated as true or false - a condition that would normally be true becomes false, and vice versa.

not (condition)

  • condition - the condition to reverse.

Example 1

set condition1 if (not (page1.interaction1 = "yes"))

condition1 is set if the end-user did not select yes for interaction1. This condition can then be used to tailor the rest of the intervention.

Note: don't confuse not with isempty. not refers to a specific response not being chosen; isempty refers to an interaction that hasn't been answered at all. The two can be combined to check for "an answer was given, and it wasn't blank":

Examples 2 and 3

after page1 if (not (isempty (page1.interaction1))) goto page5

Or:

set condition1 if (not (isempty (page1.interaction1)))

O

or

or can also be written as ||. It combines two or more conditions into one, and is true if any one (or more) of them is true. It works the same way as and, but only needs one condition to succeed rather than all of them.

or (condition1, condition2, ...)

  • condition1, condition2, ... - the individual conditions to check, separated by commas. You can list two or more. or is true if at least one of them is true.

Example 1

show page1 after page1 if (or (page1.interaction1 = "none", page1.interaction1 = "sometimes")) goto page3

This shows page3 if the response to interaction1 on page1 was either none or sometimes.

Example 2

savevalue(currentuser(), "sport", "cardio") if (or( page1.interaction1 = "running", page2.interaction2 = "swimming"))

This saves the variable sport if the end-user selected running for interaction1 on page1, or swimming for interaction2 on page2 (or both).

P

parsedate

parsedate converts a date that has been entered or stored as text (for example, a response to a date-entry interaction) into a time value that can be used with commands such as comparetimes and currenttime.

parsedate (datestring, "format")

  • datestring - the interaction response (or variable) containing the date as text, e.g. signup.date_of_birth.
  • "format" - describes how that text is laid out, using the same letters as printtime (see the table under printtime for the full list) - for example, "yyyy-MM-dd" for a date written like 1990-05-21.

Example 1

set dob to parsedate(signup.date_of_birth, "yyyy-MM-dd")

This converts the response given to the date_of_birth interaction on the signup page - entered in the format yyyy-MM-dd, e.g. "1990-05-21" - into a time value, stored as the variable dob.

Example 2

show screening_fail if (comparetimes(parsedate(signup.date_of_birth, "yyyy-MM-dd"), currenttime(), "days") < 6570)

This shows the error message screening_fail if fewer than 6570 days (approximately 18 years) have passed between the date of birth entered by the end-user and now - for example, to screen out end-users who are under 18.

patternmatch

patternmatch checks whether the text an end-user has typed into a text-entry interaction matches a pattern you define - for example, a study code in a specific format.

patternmatch ("pattern", interactionname)

  • "pattern" - the pattern of characters to match against, in quotation marks, written using Regular Expressions (see the table below for the basics).
  • interactionname - the text-entry interaction whose response you want to check, e.g. password.

Some regular expression basics are described below - for more detailed information, you can find guides to "Regular Expressions" online.

Character Example Comment
a a match a single lower-case character. Can be any character except .?+*[]\^$()|{}
A A match a single upper-case character.
abc abc match the exact sequence of characters
. a . means any character
a? a ? means zero or one of the preceding character
a* aaa * means any number of the preceding character
a+ aaaa + means one or more of the preceding character
[abc]+ cab [] means any character between the brackets
[^abc]+ fed ^ in a [] means none of the characters between the brackets
[0-9] 1 match any number between this range
[A-Z] LIFEGUIDE match any uppercase letter between this range
[a-z] lifeguide match any lowercase letter between this range
[A-Za-z]+ LifeGuide Any uppercase or lowercase letters
a(bc)+d abcbcbcd () groups things together
ab|cd cd | means 'or'

Example 1

This function is useful if you have assigned each participant in your study a different code, which they must enter correctly in order to take part - this ensures that only people who have been invited can gain access to the intervention. To do this, write an error message on the page containing your text-entry interaction, e.g.

show nomatch if( not( patternmatch( "study[0-9][0-9]id[0-9][0-9]", password ) ) )

Here, the error message named nomatch is shown to users if the text they enter into the interaction named password doesn't fit the pattern in the square brackets. The pattern used here means a code shaped like studyxxidxx, where each x is any digit from 0 to 9.

See also Adding Error Messages (example 7).

Example 2

patternmatch can also be used to direct users to specific conditions, sections or pages within an intervention, e.g.

show page1 if (patternmatch("[0-9][0-9]a[0-9][0-9]", interaction1))

show page2 if (patternmatch("[0-9][0-9]b[0-9][0-9]", interaction1))

Here, if a user enters a code shaped like xxaxx (where each x is a digit), they see page 1. If they enter xxbxx, they see page 2.

Instead of 0-9, you could use [a-z] to require any letter from a to z, or [a-z0-9] to allow either a letter or a number.

Note: patternmatch is case sensitive. [a-z] only matches lowercase letters, [A-Z] only matches uppercase letters, and [a-zA-Z] matches either.

printtime

printtime formats a time value so it can be displayed to the end-user as a readable date or time.

printtime (timevalue, "format")

  • timevalue - the time you want to display, usually currenttime() or a time you've loaded with loadvalue(...).
  • "format" - describes how you want the time or date to look, built from the letters in the table below (e.g. "H:m d-M-y").

The letters that can be used to build a format are:

Letter Description Example
G Era designator AD
y Year in two digits 01
yyyy Year in four digits 2001
M Month in year 7
MMMM Month in year July
d Day in month 10
h Hour in A.M./P.M. (1~12) 12
H Hour in day (0~23) 22
m Minute in hour 30
s Second in minute 55
E Day in week Tues
EEEE Day in week Tuesday
D Day in year 360
F Day of week in month 2 (second Wed. in July)
w Week in year 40
W Week in month 1
a A.M./P.M. marker PM
k Hour in day (1~24) 24
K Hour in A.M./P.M. (0~11) 10

For digits, e.g. minutes, use the number of letters for the number of digits you want to display. For example, 9:01:07 should be written as h:mm:ss

Advanced users, please see more options on Java SimpleDateFormat.

printtime cannot display the difference between two times if that difference is greater than one day - to display a difference between two times, use comparetimes instead (see comparetimes, Example 2).

Example 1

This example shows how you can use printtime and currenttime together, to display the time and date a user is shown a specific page:

show welcome

set welcome.time to printtime (currenttime (), "H:m d-M-y")

Here, the word 'time' on the page welcome has been set as a variable. This displays the hour, minute, day, month and year at which the user is shown welcome, in place of the word 'time'.

Example 2

This example shows how to mix your own words in with printtime and store the result as a user variable.

set midnighttext to printtime (currenttime(), "'When you registered, it was 'H'hrs and 'm' minutes and 's' seconds since midnight'")

savevalue(currentuser(), "midnighttext", midnighttext)

To add your own words or values in between the printtime format letters, wrap them in single quotes, as shown above. The output of printtime can be stored or saved like any other user variable, but note that it is always stored as text - it cannot be used in further number calculations.

Example 3

This example shows how to display particular times or dates you have saved earlier in your logic, such as when a user signed up and when they last logged back in.

show signup

after signup if (and (makenewuser (signup.name, signup.password), savevalue(currentuser(), "currentlogintime", currenttime()))) goto welcome

The first part of this logic sets up an account for the user, using the username (signup.name) and password (signup.password) they chose (see makenewuser). The second part uses currenttime to save the time the user signed up, as the variable "currentlogintime".

show welcome

set welcome.signuptime to printtime(loadvalue(currentuser(), "currentlogintime"), "H:m d-M-y")

This displays the date and time the user signed up, on the page welcome, in place of the word 'signuptime'.

show login

after login if (and(savevalue(currentuser(), "lastlogintime", loadvalue(currentuser(), "currentlogintime")), savevalue(currentuser(), "currentlogintime", currenttime()))) goto loginhistory

The first part of this reuses the variable "currentlogintime" to create a new variable, "lastlogintime" - so whatever time was previously stored as "when they signed up or last logged in" now becomes "when they last logged in". The second part then saves a fresh "currentlogintime", recording that they have logged back in right now.

show loginhistory

set loginhistory.lastlogintime to printtime (loadvalue(currentuser(), "lastlogintime"), "H:m d-M-y")

set loginhistory.currentlogintime to printtime (loadvalue(currentuser(), "currentlogintime"), "H:m d-M-y")

This displays both the time the user last logged in ("lastlogintime") and the time they are logging in right now ("currentlogintime"), on the page loginhistory.

Example 4

In this example, a time saved in a previous session is loaded, and one week (in seconds) is added to it:

savevalue (currentuser(), "goaltime", midnight())

show examplepage

set examplepage.weeklater to printtime((loadvalue(currentuser(),"goaltime")+delay), "E, d/M/y")

The output of this might be Tue, 09/08/2016, a week after the time the goal was set.

R

randomnumber

randomnumber returns a random whole number within a range you choose, which is commonly used to randomly assign end-users into different groups.

randomnumber (lowestvalue, highestvalue)

  • lowestvalue - the smallest number that could be returned.
  • highestvalue - the largest number that could be returned.

after page1 if (randomnumber (lowestvalue, highestvalue) = value) goto page3

For example:

after page1 if (randomnumber (0, 1) = 1) goto page3

show page2

show page3

Here, end-users randomly assigned the number 1 are directed to page3; those assigned 0 carry on to page2.

A full tutorial on randomisation is available in the LifeGuide Researcher Help Manual.

replaceall

replaceall searches through a piece of text and replaces every occurrence of one thing with another.

replaceall ("find", "replacewith", sourcetext)

  • "find" - the character(s) or text you want to search for, in quotation marks.
  • "replacewith" - the character(s) or text to put in its place, in quotation marks.
  • sourcetext - the text (or interaction response, or variable) to search within. This does not need quotation marks if it's a variable or interaction response.

Example 1

replaceall ("c", "b", "caked car")

This replaces every c in the text with b, changing caked car into baked bar.

Example 2

This example shows a workaround for displaying a single-choice interaction's response back to the end-user. A workaround is needed because it is the Unique Response Name (not the response text shown on screen) that gets saved, and that would otherwise be shown back to the user.

savevalue (currentuser(), "s1_home", replaceall("_", " ", s1_whattodo1.home)) if (or( s1_fatigue.home = "Other_aspects_of_home_life", s1_fatigue.home = "I_find_it_hard_doing_things_around_the_house",s1_fatigue.home = "I_cannot_get_out_and_about_the_way_I_used_to" ))

This is specific to a drop-down single-choice interaction, where you want to show the response chosen for the interaction home on page s1_fatigue back to the end-user. Every underscore (_) in the Unique Response Name is replaced with a space, so it reads naturally when shown back to the user.

You can then use feedback boxes and a container to show the response on a later page:

show s1_fatigue2.home1 if (s1_fatigue.home = "Other_aspects_of_home_life") show s1_fatigue2.home2 if (s1_fatigue.home = "I_find_it_hard_doing_things_around_the_house") show s1_fatigue2.home3 if (s1_fatigue.home = "I_cannot_get_out_and_about_the_way_I_used_to")

home1 is a feedback textbox shown on s1_fatigue2 if Other_aspects_of_home_life was chosen for the interaction home on page s1_fatigue.

resetpassword

resetpassword lets an end-user reset a forgotten password. A new, temporary password is emailed to them, which they can use to log in - you can then add further pages to let them choose a new, memorable password once logged in.

resetpassword (emailinteraction)

  • emailinteraction - the interaction where the end-user entered the email address registered to their account.

Example 1

after resetpass if (resetpassword(resetpass.email)) goto resetpass_confirm

This resets the end-user's password, as long as they enter a registered email address into the text-entry box called email, and shows them the resetpass_confirm page.

Please see the Changing and resetting users passwords tutorial intervention on the LifeGuide Community Website for a full demo of how this logic is used.

round

round rounds a number to the nearest whole number. For example, 5.49 rounds down to 5, and 5.5 rounds up to 6. This is useful for presenting calculated values (such as a quiz score) in a clean, whole-number form. To round to a set number of decimal places instead of a whole number, use decimalplaces.

round (number)

  • number - the number (or a variable/calculation that produces a number) you want to round.

Example 1

In this example we calculate 100 divided by 3 (33.333333). When we display it to the user on examplepage we want it to show 33.

set exactthird to (100/3)

set approxthird to round(exactthird)

show examplepage

set examplepage.number to approxthird

Example 2

In this example we mark a 3-item true/false quiz and present the score as a percentage.

show exp

if exp.question1="true" set q1 to 1

if exp.question1="false" set q1 to 0

if exp.question2="true" set q2 to 0

if exp.question2="false" set q2 to 1

if exp.question3="true" set q2 to 1

if exp.question3="false" set q2 to 0

set totalscore to (sum(q1,q2,q3))

set scorepercent to ((totalscore/3)*100)

set scoreround to round(scorepercent)

show results_page

set results_page.score to scoreround

First we mark the quiz, giving each question a score of 1 (correct) or 0 (incorrect). We add the scores together using sum. To turn this into a percentage, we divide the total by three and multiply by 100. We then round the result and display it to the user on results_page.

Example 3

In this example we round a large number to the nearest hundred.

set largenumber to 1234567

set roundnumber to round(largenumber/100)

set largenumbertwo to (roundnumber*100)

This takes 1,234,567, divides it by 100 to get 12,345.67, rounds that to the nearest whole number (12,346), then multiplies it back up by 100, giving a final result of 1,234,600.

S

save

save stores all the responses an end-user gave on a page, so they can be shown again later using load - either on another page in the same session, or in a future session. This requires end-users to have a registered account.

save pagename for username

  • pagename - the page whose responses you want to store.
  • username - the end-user this data belongs to. Use currentuser().

Example

show page1

save page1 for currentuser()

Later in the logic (either in the same session, or a future one):

show page20

set default page20.interaction2 to load page1.interaction1 for currentuser()

  • page1.interaction1 - the previously-saved response you want to bring back.
  • currentuser() - the end-user whose saved response you want.

So, page1 is saved for the end-user in the first part of this logic. Then, when they reach page20, the response they gave earlier for interaction1 on page1 is shown again, this time in interaction2 on page20.

saveandload

saveandload is used on a page that contains interactions. If the end-user clicks Next and then comes back to that same page later, it automatically shows them the responses they gave the last time they were there.

saveandload pagename for username

  • pagename - the page whose responses should be remembered.
  • username - the end-user this data belongs to. Use currentuser().

Example 1

show page1

saveandload page1 for currentuser()

Every interaction on page1 will be saved, and shown again automatically, each time the end-user returns to that page.

set

set stores a value in a variable, which you can then refer to elsewhere in your logic. It is also used to perform calculations.

set variablename to value

  • variablename - the name you choose for this variable.
  • value - what you want to store: plain text (in quotation marks), a number, an interaction response, or the result of another command.

Example 1

Older interventions commonly used set to create a variable representing the current end-user's identifier, e.g.:

set username to login.loginuname

This sets the variable username to whatever the end-user typed into the interaction uniquely named loginuname (usually an email address) on the login page.

Current best practice is to skip this step entirely and use currentuser() directly wherever you need to identify the current end-user, instead of creating your own username variable. You may still see the pattern above in older interventions.

Example 2

You can also use set to store timing values, such as how many seconds are in a day, as named variables. This makes it easy to switch between short test timings and real timings, and reduces the risk of mistakes.

In this example, twelvemonth is set to the number of seconds in 12 months:

set twelvemonth to "31536000"

You can then use this in your login logic:

after login if (comparetimes(loadvalue(currentuser(),"baselinetime"), currenttime(),"seconds") >= twelvemonth) goto studyfinished

This shows the page studyfinished if it has been more than 12 months since baselinetime.

Example 3

You can also set fixed pieces of text, such as an email address, so you don't have to type it out repeatedly - for example, the study coordinator's email address:

set studyemail to "study@soton.ac.uk"

Place this logic near the top of your logic file. This way, if the study coordinator's email address ever changes, you only have to update it in one place.

You can also set the text and timings used in emails:

set 3monthemail to "Thank you for taking part in The Reactivate Study. It is now time to complete your 3 month questionnaire. Your answers are very important to us. Please use the following link to login:\n\nwww.webaddress.co.uk\n\nIf you have any questions about the study, or no longer wish to participate, please contact us on study@soton.ac.uk\n\nFrom The Reactivate Team."

set oneday to "86400" set oneweek to "604800"

The advantages of setting text like this are:

  • It's easy to change - you only have to update one line, rather than hunting through your whole logic file for every place the text appears.
  • It's easy to find, since these lines are usually kept together near the top of the logic file.

Please see sendemail for more information on how to write email logic.

Example 4

set can also create a variable based on how an end-user responds to an interaction, which you can then use to tailor the rest of the intervention.

show page1

set condition1 to and (page1.chooseoptions contains "optiona", page1.chooseoptions contains "optionc")

after page1 if condition1 goto page3

Here, condition1 is set if the end-user selects both optiona and optionc from the interaction chooseoptions on page1. Anyone in this condition is then sent to page 3, where they receive tailored information based on the options they chose.

Example 5

In this example, set is used to calculate a score. The number the end-user selects for the interaction 'dailyexercise' on page1 is multiplied by 5 to create their exercise score:

set exercisescore to (page1.dailyexercise * 5)

setemail

setemail sets or updates the email address associated with a user's account. This is useful if you create accounts using an identifier other than a real email address (e.g. a study ID, using makenewuser), but still want a real email address linked to the account - for example, so that sendemail and resetpassword work correctly for that user.

setemail (username, emailaddress)

  • username - the account to update. Use currentuser().
  • emailaddress - the interaction where the end-user entered their real email address.

Example 1

show signup makenewuser(signup.studyid, signup.password) setemail(currentuser(), signup.email_address)

This creates a new user account using the studyid and password entered on the signup page, then sets the email address for that account to whatever was entered into the email_address interaction on the same page.

saveuniquevalue

saveuniquevalue works in the same way as savevalue, but with one extra check: if the value being saved is not unique (i.e. another end-user has already saved the exact same value for the same variable name), it returns false instead of saving it. You can use this to stop an end-user continuing until they enter a genuinely unique value, such as a study ID.

saveuniquevalue (username, "valuename", value)

  • username - the end-user this data belongs to. Use currentuser().
  • "valuename" - a name you choose for this piece of data, in quotation marks.
  • value - the response to check and save, e.g. an interaction response.

Example 1

To save a variable entered by an end-user, while checking it is unique:

saveuniquevalue(currentuser(), "studyid", page1.interaction1)

Example 2

If an end-user enters a value that turns out not to be unique, you can still let them continue with the intervention, while alerting the study coordinator by email:

after registration if (and(not(saveuniquevalue(currentuser(), "studyid", registration.interaction1)), sendemail( append(currentuser(),"not_unique"), "study@soton.ac.uk", "Participant - not unique", append("Participant ", loadvalue (currentuser(), "idnumber"), "has entered information that is not unique."),10) )) goto registrationfinish

For more information on saveuniquevalue, please click here.

savevalue

savevalue stores a piece of information against a specific end-user's account, so it can be loaded again later - in the same session, or in a future one. Your end-users need to have a registered account for this to work.

savevalue (username, "valuename", value)

  • username - the end-user this data belongs to. Use currentuser().
  • "valuename" - a name you choose for this piece of data, in quotation marks. This becomes the column heading for this data in your exported study data.
  • value - the information to store. This can be plain text (in quotation marks), a number, an interaction response (e.g. page1.interaction1), or the result of another command (e.g. currenttime()).

Common uses include:

  • creating and saving a new piece of information about a user
  • saving a response an end-user has given to an interaction
  • saving the current time
  • marking a questionnaire or session as 'complete'

Example 1 - Create and save a text variable

savevalue(currentuser(), "group", "web_support")

This saves the text web_support as the variable group for the current end-user. group will be the column heading for this data in your User data export.

To load this value again later in your logic, use loadvalue with the same variable name, group:

after page5 if (loadvalue(currentuser(), "group") = "web_support") goto page10

Example 2 - Create and save a numeric variable

savevalue(currentuser(), "work", 1)

This saves the number 1 as the variable work. Again, work becomes the column heading for this data in your User data export.

You can use this to show feedback on a page in a later session:

show s1area.summary if (loadvalue (currentuser(), "work")>0)

This shows the feedback summary on page s1area if the variable work is greater than 0.

Example 3 - Save a response an end-user has given to an interaction

savevalue(currentuser(), "s1_fatigue", page1.interaction1)

This saves the response given for interaction1 on page1 as the variable s1_fatigue, for the current end-user.

To load this later in your logic:

set page5.fatigue_score to loadvalue (currentuser(),"s1_fatigue")

This loads s1_fatigue and displays it in the text box fatigue_score on page5. For this to work, fatigue_score needs to be set as a printed variable.

Example 4 - Save the current time

savevalue(currentuser(), "s1_time", currenttime())

This saves the current time as the variable s1_time.

You can load this later in your logic - for example, to stop end-users seeing session 2 until a week has passed:

after login_successful if (comparetimes(loadvalue(currentuser(), "s1_time"), currenttime(), "seconds" ) > 604800) goto s2_welcome

Example 5 - Mark a questionnaire or session as complete

savevalue(currentuser(), "baselinecomplete", "yes")

This creates the variable baselinecomplete and saves yes. You could also use a number instead, if you prefer:

savevalue(currentuser(), "baselinecomplete", "1")

You can then check this later in your logic, to see whether an end-user has completed their baseline questionnaire:

after login_successful if (and( hasseen(currentuser(), "qintro"), (isempty(loadvalue(currentuser(), "baselinecomplete"))) )) goto q_notcomplete

This shows the page q_notcomplete if the end-user has seen qintro, but baselinecomplete is still empty (meaning they haven't yet finished the baseline questionnaire).

Tip: if you need to clear a saved value so a fresh answer can be stored, use deletevalue before saving the new one.

sendemail

sendemail schedules an email to be sent to an end-user (or anyone else, such as a study coordinator) at a chosen point in the intervention.

sendemail (uniquename, emailaddress, "subject", "content", delayinseconds)

  • uniquename - a name that must be different for every email you send. Because many end-users will trigger the same line of logic, this is normally built with append(currentuser(), "some_label"), so each end-user gets their own unique version of the name. If you skip this and just use a fixed name, only the very first email sent with that name will go out - all later ones with the same name will be treated as duplicates and won't be sent.
  • emailaddress - who the email should go to. This is often currentuser() (if end-users register with their email address), or a fixed address in quotation marks, such as "study@example.ac.uk".
  • "subject" - the email's subject line, in quotation marks.
  • "content" - the body of the email, in quotation marks (this is often built up using append). Use \n\n to start a new paragraph.
  • delayinseconds - how long to wait, in seconds, after the end-user reaches the page this logic is attached to, before the email is sent. Use a small number like 10 to send it almost immediately.

Example 1

sendemail (append(currentuser(),"welcome_email"),currentuser(),"You have successfully registered to Stress Less", append("Dear ", loadvalue (currentuser(), "firstname"), "\n\n", welcome), 10)

Here, append(currentuser(),"welcome_email") builds the unique name for this email, by joining the end-user's identifier onto the label welcome_email. This matters because, without append, every end-user's email would share the exact same name (welcome_email) - only the first one sent would count as unique, and every other end-user's copy would be silently skipped.

A full tutorial is available for Sending Emails, including details of how to send emails to a researcher or healthcare professional instead of the end-user.

sendtext

sendtext schedules an SMS text message to be sent to an end-user. It works in a similar way to sendemail, with a few differences:

  • it uses the end-user's mobile phone number instead of an email address
  • it doesn't need a subject line
  • there is a limit on how long the message can be

sendtext ("uniquename", phonenumber, "message", delayinseconds)

  • "uniquename" - a name that must be different for every text message, in the same way as for sendemail (usually built with append(currentuser(), "some_label")).
  • phonenumber - the interaction (or variable) containing the end-user's mobile number.
  • "message" - the text of the message, in quotation marks.
  • delayinseconds - how long to wait, in seconds, before the message is sent.

after page1 if sendtext ("welcometext", login.phone, "Thank you for registering for the lifestyle intervention. Please remember to check back regularly for more information.", 60) goto page1

Note: you will need to set up an SMS account for your intervention before you can send text messages. See LifeGuide Community Website FAQs for more information.

stringlength

stringlength tells you how many characters an end-user has typed into a free-text interaction.

stringlength (interactionname)

  • interactionname - the free-text interaction to check, e.g. username (here, "username" is just the name given to this particular text box on the page - it is unrelated to the currentuser() identifier discussed elsewhere in this dictionary).

This is useful if, for example, you want end-users to create usernames of a specific minimum length. To use it, write an error message:

show namemessage if (stringlength (username) < 5)

Here, the error message namemessage is shown to users who have entered fewer than 5 characters into the interaction called username.

sum

Please see add.

show

show is the first logic command you will need to know, and probably the one you will use most often. It displays each of your pages, in the order they are written in the logic - when an end-user clicks Next on a page, they move on to whichever page is written next.

show pagename

  • pagename - the page to display next.

Example 1

show page1

show page2

show page3

show page4

Here, the end-user first sees page1. When they click Next, they see page2, then page3, and finally page4.

Note: before you can preview your intervention, every page must appear in a show command in the logic file at least once.

Because pages must have unique names, you can only write show pagename once for each page - but you can show the same page again later using named, or by using a Jump button on an earlier page.

T

timesincelogin

timesincelogin tells you how much time has passed since an end-user last logged into the intervention.

timesincelogin (username, "unit")

  • username - the end-user to check. Use currentuser().
  • "unit" - what you want the result measured in: "seconds", "minutes", "hours", "days", "weeks" or "months".

There is no need to create your own username variable first - simply use currentuser() (see currentuser()).

Example

1. Show the page where you want to display how long it's been since the end-user last logged in (e.g. "time"):

show time

2. On that page, create a variable to hold the value (e.g. "secs"), using the 'set as variable' function, then set it using timesincelogin:

set time.secs to timesincelogin (currentuser(), "seconds")

This shows the end-user, on the page named "time", how many seconds have passed since they last logged in. You can repeat this step using "minutes", "hours", "days", "weeks" or "months" instead, to display the same information in a different unit.

to

to is used together with the set command, as in set variablename to value. See set for full details and examples.

U

urlencode

urlencode converts a piece of text into a form that is safe to use inside a web address (URL). This is an advanced command, needed only when you are building a dynamic URL (i.e. one that includes a variable that might contain spaces or symbols).

urlencode (string)

  • string - the piece of text (often a variable) you want to make URL-safe.

Certain characters (such as ? and &) have special meaning inside a URL and must be converted into a different format so they don't break the link (for example, the & symbol becomes %26). urlencode takes care of this for you.

URL encoding is a common, standard technique - you can find more information here: http://en.wikipedia.org/wiki/Percent-encoding