Variables🔗

programming

You may want to save yourself some typing by using variables. For example, pi = 3.14159, right? If for some reason you need to use pi a lot in your program, you can set the variable like this:

>> pi = 3.14159

Setting a variable simply means adding two >> angle brackets to the program, then writing the name of the variable you want to set (e.g. pi) and the value of that variable. Let's go back to our previous example now.

>> pi = 3.14159

The value of pi is {pi}.

To inject a variable's value into the middle of some text, you can simply put that variable in {braces}. Variable names are case sensitive. In our example above, you'd have to write {pi}; using {PI} would not work. With this code, your users would see the line "The value of pi is 3.14159."

The value of a variable can be an equation (e.g. >> area = height * width), where the variable whose value you're assigning or updating is on the left, and the value to be assigned is on the right. In other words:

>> someVariableName = someValue

Another way to create a variable is by saving the answer to a question using the *save keyword:

*question: What is the value of pi?
	*save: pi

The value of pi is {pi}.

This way you allow the users to your program to set the value of a variable.

If you're assigning a value to variable using an equation, then any other variables used (on the right side of the equals sign) must have already been saved (e.g., in the example >> area = height * width, height and width must have already been given values).

>> pi = 3.14159

*question: What is the radius of your circle?
	*save: r

>> area = pi * r * r
The area of your circle is {area}.

In this example, users will see a question asking them to list the radius of their circle. After they answer, their answer will be saved as r. If the users enter "2" as their answer, they will then see the line "The area of your circle is 12.57."

Note: in this example, it is important to set the area variable only after assigning a value to r. If you had tried to set the area variable before the question about the radius had been asked (and r had received a value), then this program would not have worked.

You can also change the value of a variable. Once a variable is set, you can always modify it later, as in this example.

>> scoops = 5

*question: You have {scoops} of ice cream. How many will you eat right now?
	2
		>> scoops = scoops - 2
	5
		>> scoops = scoops - 5

Now you have {scoops} scoops of ice cream.

If users select to eat 2 scoops of ice cream now, then the variable will be changed as follows:

>> scoops = scoops - 2

This equation is essentially saying: "the new number of scoops = the prior number of scoops (which is 5) - 2." Users will thus see the line, "Now you have 3 scoops of ice cream." If users select to eat 5 scoops of ice cream now, then they will see the line, "Now you have 0 scoops of ice cream."

The value of a variable can also be a word (or sentence or paragraph or any other text string), as this example shows.

*question: Would you like to read a story about a girl or a boy?
	Girl
		>> characterName = "Stacey"
	Boy
		>> characterName = "Brian"

Once upon a time, {characterName} got lost in the woods and eaten by dinosaurs. The end.

In this example, the user is able to choose whether they'd like to read a story about a girl or a boy. Depending on what they select, the program will either set the characterName variable as "Stacey" or "Brian." Note that it's important that you put the value of text variables in "quotes"; otherwise, the program won't work. (In other words, if you want to assign a text string value to a variable, then that text string must be enclosed in quotation marks. But if you want to assign some other kind of data to a variable (like a number), then you don't need quotation marks. For example: >> numberOfFriends = 5 versus >> bestFriendName = "James") Users who had selected "girl" will next see the line, "Once upon a time, Stacey got lost in the woods and eaten by dinosaurs. The end."

Storing custom data for the CSV file using data::store🔗

Any variable that you create in your program will show as a column in the CSV file when you download the generated data. The name of the column will be the variable name.

Now, think of this example where you ask users to enter the last three movies they watched and save it into a variable called movies:

*question: Please, type in the last three movies you watched:
	*save: movies
	*multiple

Then you ask the users to rate each movie that they entered:

*for: movie in movies
	*question: How many stars would you give the movie {movie}?
		*answers: [5, 4, 3, 2, 1]
		*save: answer

When you download the CSV file you will have a column with the name "How many stars would you give the movie {movie}?", and for each run you will have all the ratings that the user provided separated by a pipe(|). The variable with the name "answer" will also be displayed in the CSV file, and it will only have the last rating the user provided (since its value gets overwritten in every iteration).

Ideally, you should have a separate column for each movie, with its corresponding rating if a particular user selected that movie. You can accomplish this using >> data::store(columnName, value):

*for: movie in movies
	*question: How many stars would you give the movie {movie}?
		*answers: [5, 4, 3, 2, 1]
		*save: answer
	>> data::store(movie, answer)

If the value of movies is, for example ["Titanic", "Easy Rider", "Dune"], there will be three columns on the CSV file with the names "Titanic", "Easy Rider" and "Dune", with the ratings provided by the users who watched either of those movies.

Types of variable🔗

See the API page for a list of all variable types with code examples.

Math operations with numeric variables🔗

Currently, GuidedTrack supports these math operators:

Operation Operator Sample Code
+ addition >> totalNumberOfPets = numberOfCats + numberOfDogs + numberOfGoldfish + numberOfTurtles
- subtraction >> moneyIHaveLeft = moneyIHadInTheMorning - moneyISpentToday
* multiplication >> totalPeopleInTheTrain = numberOfWagons * numberOfPeoplePerWagon
/ division >> slicesOfPizzaPerPerson = totalSlicesOfPizza / numberOfPeopleEatingPizza
^ power >> myVarSquare = myVar ^ 2

Use parenthesis () to alter the order of operations. You can also nest them if needed!

>> output = 2 * (input + (1 / 3 + 8))

It is also worth mentioning that spacing does not matter when performing calculations. For example, the two lines below would display exactly the same thing:

That's about {(age - 2) * 4 + 21} in dog years
That's about {(age-2)*4+21} in dog years
Other math operations🔗

Here are some examples of how you might perform some other common math operations:

Absolute value🔗
-- myVar is the variable whose absolute value you want to calculate
>> absOfMyVar = myVar
*if: myVar < 0
	>> absOfMyVar = -myVar
Square root🔗

You can easily calculate square roots if you write them in exponential form:

-- myVar is the variable whose square root you want to calculate
>> myVarSquareRoot = myVar ^ (0.5)
Natural logarithms (ln, or log base e)🔗

The program ln - natural log - public aproximates the natural log of a given number. Find it through the search bar, or copy and paste the code below into your program:

-- Enter the number whose natural log you want to find out
>> in_numberForLn = 20

*program: ln - natural log - public
-- outputs:
-- out_naturalLog
Decimal logarithms (log, or log base 10)🔗

The relationship between a number's natural log and decimal log is: ln(x) ≈ 2.303 * log(x). Therefore, in order to calculate a number's decimal log, you can calculate its natural log as explained above and divide by 2.303 afterward:

>> in_numberForLn = myVar
*program: ln - natural log - public
>> myVarsLog = out_naturalLog / 2.303

You can also apply the logarithmic change-of-base rule to convert to base 10 (or any other base). According to the rule, log10x = (logex) / (loge10). So, for example, log105 = ln(5) / ln(10), which could be computed this way:

-- get the natural log of 5
>> in_numberForLn = 5
*program: ln - natural log - public
>> ln_of_5 = out_naturalLog

-- get the natural log of 10
>> in_numberForLn = 10
*program: ln - natural log - public
>> ln_of_10 = out_naturalLog

-- compute the log base 10 of 5
>> log_base_10_of_5 = ln_of_5 / ln_of_10

Using Points as a Variable🔗

Finally, you can use variables to further manipulate points. You can automatically give users points, or modify their existing points.

You have points!
>> points = 100

In this example, users will see an animation and 100 points added to their tally on their screen. They will also see the line "You have points!"

If the user already has points, then it is not necessary to write >> points = 100 (or another amount other than 100). However, you could do this if you wanted the user to have a point tally that you set and control. The below example would also work to manipulate points.

*question: Click the number of points you want:
	50
		*points: 50
	100
		*points: 100
	1,000
		*points: 1000

Oh no, you were attacked by a sea monkey and just got robbed of half your points!
>> points = points * 0.5

Count Stuff that Appears in Your Text or Collection Variable🔗

occurrences, find all, how many

With variableName.count("thing to count"), you can count up all the times that thing appears in a collection or text variable.

For example, let's say that users are taking your refined quiz, "What puffy snack product are you?" You might count up the values in a collection of their answers like this:

>> cheeseCurlTotal = puffySnackAnswers.count("cheese curl")
>> cheeseBallTotal = puffySnackAnswers.count("cheese ball")
>> riceCakeTotal = puffySnackAnswers.count("rice cake")
>> chickpeaPuffTotal = puffySnackAnswers.count("chickpea puff")

Here are other examples:

  • Count how many times a user did a particular anxiety-busting activity, in a collection of all activities completed.
  • Count the number of times a user stealthily added the word "meow" to a story.
  • Count up the 1s in a collection of 0s and 1s (to get a total score on a true/false quiz).
  • Count the number of times a letter appears in a variable, like: There are an astonishing {usersStory.count("e")} e's in your story.

Find Where Something Occurs in Your Text or Collection Variable🔗

locate, search, position

The .find function lets you locate things of interest in a collection or variable.

Let's say you ask your users to rank their top five favorite food-related, feel-good movies in order of their awesomeness. The result produces a collection that might look something like:

>> FavFoodieFlicks = ["Chef", "The Lunchbox", "Like Water for Chocolate", "The Hundred-Foot Journey", "Ratatouille"]

If you want to know what rank your user gave The Lunchbox, you could do the following:

/The Lunchbox/ came in at #{FavFoodieFlicks.find("The Lunchbox")}.

Users would see: "The Lunchbox came in at #2."

You can also use .find to:

  • Locate the position, if any, of certain flagged words in a user's open-ended response (e.g. "depressed").
  • Find out when a user did a task of interest in a collection of tasks they could do in any order.
  • Find certain symbols or keywords in order to replace them with something else.

The .find function starts searching from the beginning. So if the item in question is the first item, .find will return the number 1. If it's the second item, it'll return with 2. If there are multiple entries, in say positions 3 and 5, it'll just return with the first one it encounters (i.e., 3).

If the item in question can't be located, it'll display as blank if used inline (with {braces}), or you could do something like the following:

>> introduction = "Hi there"
>> locationFound = introduction.find("z")

*if: not locationFound
	"z" wasn't found!

Above, "'z' wasn't found!" will display, since there aren't any z's in the text searched.

Getting the Size of a Text or Collection Variable🔗

length, number of items

You may be familiar with using .size to learn how many entries are in a collection variable (for example, in a collection of >> pets = ["cat", "dog", "monkey"], pets.size would equal 3).

You can also use .size to learn things about text-based variables, like:

  • Did your users write too little in the question you asked?
  • Did they use too many characters?

For example:

*question: Tell me a story.
	*save: story

Your story has {story.size} characters.

*if: story.size < 15
	Your story sucks.

Sort of relatedly, you can also get the exact character in any position of a text variable using [square brackets], like: variableName[position]. For example:

*question: First name
	*save: first

*question: Last name
	*save: last

>> firstInitial = first[1]
>> lastInitial = last[1]
I'm gonna call you {firstInitial}.{lastInitial}.

In the code above, you can find out a person's initials by getting the first character of their first and last names.

Iterating through the elements of a collection or association, or through the characters in a text🔗

You can use the *for keyword to loop through the elements of a collection or association. Follow these links (collections, associations) for a detailed explanation on how to do it.

The *for keyword also allows you to go through all the characters in a string. For example, this is program displays a text variable called word letter by letter:

*for: character in word
	*clear
	*header: {character}
	*wait: 2.seconds

You could also retrieve the position of each character as well:

*question: Enter a word and I will spell it out for you!
	*save: word

*for: index, char in word
	*clear
	*header: The letter in position {index} is {char}
	*wait: 2.seconds

â–¶ Run

Association and collection variables as values of another association and collection🔗

When you put collectionA or associationA inside collectionB, you are putting the actual variable itself and not just its current value into collectionB. In other words, if collectionA or associationA changes, then so does collectionB. The same happens when you use a collection or association as a value inside another association.

Here's an example:

>> mathGrades = [100, 80, 90]
>> physicsGrades = [76, 50, 92]
>> myGrades = {"math" -> mathGrades, "physics" -> physicsGrades}

>> mathGrades.add(78)
>> physicsGrades.add(99)

Here are my grades: {myGrades}

In this program, the initial value of mathGrades is a collection with the scores on three tests; similarly, physicsGrades is a collection with three scores. We created an association, myGrades, to keep all the scores together.

Later in the program, we added a new score to mathGrades and a new score to physicsGrades. Updating these collections will also update the association myGrades. So the output at the end will be:

"Here are my grades: { 'math' -> 100, 80, 90, 78, 'physics' -> 76, 50, 92, 99 }"

But what if you want to keep the current values of a collection or association? Well, see the next section for the answer!

Making a copy of a collection to save its current values🔗

Imagine you have a collection, grades, where you have added the grades of your tests in the same order that you took them (so the first element of the collection will be the grade of your first test, the second element will be the score of your second test, and so on). You want to sort your grades from high to low, but you also want to save a copy of the scores in their original order. Here is how you would do it:

>> grades = [69, 89, 87]

-- make an unsorted copy:
>> unsortedGrades = []
>> unsortedGrades.combine(grades)

-- then sort the original copy:
>> grades.sort("decreasing")

When you use the function .combine, you are taking the values of the collection grades and adding them to unsortedGrades (which is empty, and which therefore produces a new collection that just contains the original values from grades). This way, whatever changes you make to the collection grades will not affect the value of the collection unsortedGrades.

Making a copy of an association to save its current values🔗

Imagine you have a program where you are saving your grades in the association mostRecentGrades. Currently, these grades happen to be the mid-term ones. This association will be updated later when we enter the grades of the finals, and you want to save a copy of the mid-term grades for your records. Here is how you would do it:

>> mostRecentGrades = {"Math" -> 89, "Physics" -> 78}
>> midTermGrades = {}

-- loop over the association
*for: key, value in mostRecentGrades
	-- add the key-value pair to the new association
	>> midTermGrades[key] = value

Functions🔗

Functions manipulate your variables either to modify them or to return a value. We have already introduced the functions .size, .find, and .count, but there are many more. Some functions work with any variable type, whereas others are specific for certain types of variable. You can find a list of all functions by variable type in the next section.

This is an example of a function that returns a value. The .size function returns the number of elements in a collection:

>> myCollectionSize = myCollection.size

This is an example of a function that modifies a variable. The .shuffle function randomly rearranges the elements in a collection. (Be sure to make a copy of a collection before you apply the .shuffle function if you want to keep the original order of the elements!)

>> myCollection.shuffle

List of functions by variable type🔗

See the API page for a list of each variable's functions.

Waiting a Specified Amount of Time🔗

pause, stop, timer

Suppose that you wanted to create a pause so that some time lapses between when one thing is shown to the user and when the next thing is displayed. You could do that easily using a program like this one:

Take a few seconds to solve all your problems.
*wait: 5.seconds
Time's up!

â–¶ Run

This program would display "Take a few seconds now to solve all your problems." Then, nothing would happen for 5 seconds. Afterward, "Time's up!" would be displayed. The *wait keyword can be useful if you want to make sure the user takes a few seconds to think before moving on, or if you want to show some text, and give the user time to read it, before you display more text. You can designate the amount of time you'd like the program to wait by writing out the words "seconds" and/or "minutes", such as:

*wait: 5.seconds
*wait: 2.minutes
*wait: 3.minutes + 15.seconds

You can also have your program wait a fraction of minutes or seconds, as in the example:

*image: https://images2.imgbox.com/0d/33/kMitQeXV_o.jpg
*wait: 0.7.seconds
*clear
How many puppies did you see?

â–¶ Run

And you can use variables to set the wait time as well:

*question: For how many seconds do you want to see a pretty picture?
	*type: number
	*save: answer

*image: https://images2.imgbox.com/90/74/9h3LWuXb_o.jpg
*wait: answer.seconds
*clear

â–¶ Run

Wait forever🔗

You can use *wait without specifying a wait time to stop the navigation indefinitely without ending the run of your program. In this case, the user of your program would need to click either a navigation element or *component at that point if anything else is going to happen:

*navigation
	Mountaineering
		It seems you like the outdoors, check out these [pictures|https://tinyurl.com/qnnnbzz] of beautiful mountains.
	Long-distance running
		Do you want to run the extra mile? Look at this [tips|https://tinyurl.com/qt2suj8].
	Chess
		Fun fact: The longest tournament chess game took 20 hours and 15 minutes!

*wait

â–¶ Run

(Click here to see what the program looks like without *wait.)

Wait until data is synced up🔗

You can also pause your program long enough for all the data the user has entered to sync up with the system. Data is stored periodically throughout your user's run anyway, but this keyword may be useful in spots where users may close out of your program too soon. This allows you to control, at any point in the program, that the data is totally synced.

I'm crunching all of your answers.
Please wait just a moment.
*wait: data
Thanks!

Special Settings🔗

Back buttons🔗

return

By default, there are no back buttons on GT programs, so users cannot return to a previously cleared screen. However, back buttons can be added using a special setting.

To add back buttons for the entire program, use the following command in the beginning of the program:

*settings
	*back: yes

This will allow back buttons to be a feature on all the screens of your program, excluding the first page, which doesn't need a back button.

NOTE: The back button only takes the user from one page to the previous one that was displayed but does not restore variables to the value they had when the previous page was initially loaded. Click here to see an example.

When back buttons are pressed, users will be able to see the original answers they gave to past questions and they can edit those answers. This will make editing paragraph responses a breeze for users. This feature works whether the question type is text, paragraph, multiple choice, or checkbox.

Back buttons (1)

In the above multiple choice example, this user can see their original answer was "Going out," and they can change it or keep it by pressing either option.

The back button feature can be enabled or disabled both at the global level (for the entire program) and at the local level (for individual pages).

When adding the back button feature to an individual question, you are indicating that the global back button setting should be temporarily overridden.

*question: How are you?
	*back: no

Glad to hear it!

In this example, users will answer the question, then see the text "Glad to hear it!" Once they see the text though, they will not be able to go back to change their answer, even if back buttons are turned on for the whole program using *settings.

*question: How are you?
	*back: yes

Glad to hear it!

In this example, users will answer the question, then see the text "Glad to hear it!" Once they see this text, they will also see a small back button, which will allow them to return to the question and re-enter an answer, even if back buttons are turned off for the whole program.

An example to further understand how the back button works🔗

The program below is part of an assessment on how many US states a person has visited. It outputs the variable totalNumberOfStatesVisited. Each page asks the user if they have been to a particular state.

*question: I have been to Alabama
	Yes
		>> totalNumberOfStatesVisited = totalNumberOfStatesVisited + 1
	No

*question: I have been to Alaska
	Yes
		>> totalNumberOfStatesVisited = totalNumberOfStatesVisited + 1
	No

*question: I have been to Arizona
	Yes
		>> totalNumberOfStatesVisited = totalNumberOfStatesVisited + 1
	No

-- And so on...

Imagine the user says they have not been to Alabama and they have been to Alaska. When the third question loads, the value of totalNumberOfStatesVisited is 1. Then they suddenly remember that one time they visited Alabama as a kid, so they click the back button to go back two questions. This time they answer "yes" to having been to Alabama, so totalNumberOfStatesVisited becomes 2. But then they answer again that they have been to Alaska, making totalNumberOfStatesVisited increase to 3!

How do you keep this from happening? If you are allowing users to go back, you should not sum up the score as they progress through the assessment. Instead, save the answers as individual variables, and add them up at the end of the assessment, like this:

>> answerScale = [["Yes", 1], ["No", 0]]

*question: I have been to Alabama
	*answers: answerScale
	*save: beenToAlabama

*question: I have been to Alaska
	*answers: answerScale
	*save: beenToAlaska

*question: I have been to Arizona
	*answers: answerScale
	*save: beenToArizona

-- And so on...
-- Then, at the end of the test:

>> totalNumberOfStatesVisited = beenToAlabama + beenToAlaska + beenToArizona
-- plus other state variables, etc.

Wow! You've been to {totalNumberOfStatesVisited} states!

Next: