Code Editor: Tutorial Tasks


Overview


In the Sample Projects folder, Code: Tutorial Tasks contains a series of five tasks that wil introduce you to the basics tools for writing a gorilla task in code. Below, we describe the contents of the tasks and the concepts they introduce

1) Hello World


The 'HelloWorld' task introduces the basic commands that all code-editor tasks in gorilla will need. These are

  • import gorilla, imports the gorilla package into your code and allows you to use all the gorilla functions
  • gorilla.ready, contains the functions to be run or setup once the page is ready for content
  • gorilla.run, begins execution of the code editor task and contains the first function to be run
  • gorilla.finish, ends the task

In the HelloWorld task, we display the heading 'HelloWorld' on the screen. We use a JQuery selector to add this heading to the main div element on the page, with the id gorilla. Gorilla creates this for you in every task and this div will always be accessible. We also use a timeOut to execute the gorilla.finish() command after 5 seconds. gorilla.finish() ends the task and, if your task is part of an experiment in the tree, will return control to the tree and move the participant on to the next node of your experiment.

You can create a basic task like this from the moment you create a new task in the code editor - you don't need to add any other features to the code editor from the toolbox!

2) Hello World Templates


The previous task didn't allow us to have much control over where the content we added appeared on the page - not without adding a lot more commands to our jQuery selector. In this task, we introduce 'Templates' to our gorilla code task. To add templates to your task, click on the Toolbox and check the box 'Use Templates'. Templates allow you to control the placement and appearence of elements on your page in more detail. You can also replicate the appearence of gorilla 'zones' from the Task Builder. This could be useful if you have an experiment using a mix of tasks from the builder and the code editor and want to keep the appearence of your tasks consistent for the participant.

We also introduce the following new gorilla commands

  • gorilla.populate, adds content to your page using your templates and additional arguments
  • gorilla.refreshLayout, makes sure that the content of our page is placed correctly

gorilla.populate functions in a similar way to the jQuery selector we had in the first tutorial task.
The contents of the template 'HelloWorld', along with any additional data in the third arguement, is turned into html and added to the div with the id 'gorilla'. In our HelloWorld template, we define two gorilla zones - one in the top half of our page and the other in the bottom half of the page. You can define the placement of these zones using data-left, data-right, data-top, data-bottom. These data points replicate the functionality of the handles on the zones in the gorilla task builder.

Rather than end the task using a timeOut, we add a button to the bottom half of our page labelled 'Finish' and bind a 'click' event to it using jQuery. This event triggers the gorilla.finish() function.

In the first HelloWorld task, all of our code was located in gorilla.ready. In this task, we put all of the code necessary to run our task inside the function 'DisplayHelloWorld.' This function is then set to execute once gorilla.run is called. Dividing the code of our task up into functions will allow us to create more complicated tasks in the future.

3) Display Stimuli


In this task, we're going to introduce displaying stimuli to the participant, as well as increasing the number of screens in our task and introduce an altenative to the timeOut from the first task. We will also introduce the use of the style file for the first time. The new gorilla functions added in this task are

  • gorilla.initialiseTimer, allows us to use the timing features available in gorilla
  • gorilla.populateAndLoad, an alternative to gorilla.populate useful for displaying images and videos
  • gorilla.addTimerSequence, an alternative to timeOut which gives us more control and functionality

In order to use stimuli and add more styling to our code, we need to check 'Use Styling' and 'Use Stimuli' in the Toolbox. In this task, we will display either a blue or orange circle to the user. If the circle is blue, we want the user to click on the circle. If it is orange, we want the user to do nothing.

To do this, we first need to upload our orange and blue circles. On the stimuli tab, click the 'Add New Stimuli' button to upload new stimuli to your task. In our 'trial' template we use stimuli image to include our stimuli on the page. 'stimuli' is an example of a handlebars helper. In this case it takes the name of our stimuli and puts the address to that stimuli in place of the code in braces. We pass in the name of the stimuli as part of the third argument in our populateAndLoad call. gorilla.populateAndLoad works similarly to gorilla.populate except it waits for all the elements on the template to have loaded and report that they are ready before displaying the templates contents. This is important if your task consists of larger images or videos that may take some time to buffer and load onto the page. Our images aren't very large so we don't really need it in this case - we use it just as an example. populateAndLoad takes as a fourth argument the function you want to run once the template has reported that it has finished loaded and is ready to be displayed.

In this task, we've added a click function to our stimuli image. In this, we call 'iterateAndProgress' which decides whether we execute another trial or gorilla.finish().

As well as clicking on the image, there is the case that the participant may not click on the image, if the image is orange. We use a 'sequence' to control this eventuality, creating it with gorilla.addTimerSequence. A sequence has three functions that can be added to it.

  • .delay(number), adds a delay or pause to the current sequence. The actions below the sequence won't be executed until the delay finishes.
  • .then(function), adds a function be run in the sequence.
  • .run(), indicates that we have added all the elements to the sequence required and that the sequence should be run()

We can add as many .delay and .then functions to the sequence, but the sequence must end with .run. Sequences are useful when we want to chain a series of actions together such as displaying a fixation and then displaying a stimuli. In this case, our stimuli executes iterateAndProgress after 3 seconds. If anything happens that means you want to ignore the contents of the sequence, remember to call .cancel() on your sequence. We do this in the click function for our image element.

4) Manipulations Recording Responses


In this task, we're going to demonstrate how you can control properties of your task from outside of the code, adding in manipulations as can be found in the task builder. We also add one of the most important components of any tasks, the ability to collect data, 'metrics' from the participant and upload them for later review. We'll also demonstrate some more advanced techniques for improving the way our task looks and runs.

The new gorilla functions added in this task are

  • gorilla.manipulation, to access manipulations that we set before running the task
  • gorilla.startStopwatch, gorilla.stopStopwatch, gorilla.getStopwatch, for using the stopwatch capabilities in gorilla, typically used for measuring reaction time
  • gorilla.metric, to upload data gathered during your experiment

Manipulations are elements of your task that you will want to change prior to running the task but without having to reqrite your code. You may want to change how many trails the task consists of, what parts of your task you want to use or how easy/hard the task is for the participant. To begin using manipulations, you will need to add them via the toolbox! Once you've done that, click 'Add Manipulation'.
You'll then be asked to enter the details of your manipulation, all of which are explained in the manipulations window. The part most important for your code is the 'Key'. This is used to access the value of the manipulation in your task. In this example, we've created a manipulation called 'Number of Trials' which we'll use to set the number of trials the participant will run through during the task. We can access the value we set for this in tasks code using gorilla.manipulation and the key we set for the manipulation, 'noOfTrials' in this case. This replaces the code form the previous tutorial task where we hard coded the number of trials for the participant to run through.

Next, we'll look at the stopwatch functionality.
At the beginning of our DisplayTrial() function, after setting up the page to be displayed we call gorilla.startStopwatch(). This starts the internal gorilla stopwatch which can be used to gather reaction time data. When the participant makes a choice on the screen, we then stop the stopwatch using gorilla.stopStopwatch() and retrieve the current time using gorilla.getStopwatch().

This leads into the final addition to this task gorilla.metric. Similarly to manipulations, in order to gather metrics from your participants, you first need to add the metrics tab from the toolbox and then define the metrics you want to gather. This is simplier than for manipulations: all you need is to chose a key for the metric and then the title for the column that metric data will then appear in in your data download. In the code, the call to gorilla.metric takes as an arguement an object consisting of key/value pairs. The keys are the keys defined on our metrics tab. In the tutorial task, we've assigned the value of gorilla.getStopwatch() to the variable responseTime, which we've then assigned to the key responseTime in our metrics object.

In this task's code, you'll see that we've divided the code up into distinct functions: DisplayInstructions() which handles all of the code for our instructions page, DisplayTrial() for our trial page and DisplayFinish() for our finish screen. There are some other functions too such as generateTrialNumbers(), which is used to randomnly pick two numbers from the set 0 - 9 and iterateAndProgress() which is used to check if we've reached our maximum number of trials. Primarily, this is just how I've chosen to arrange my code, fitting with my own style for writing and structuring my code. There is another reason for this structuring, which will become apparent in the next tutorial task. You can choose to arrange your code however you want, using whatever techniques you are used to. For example, the code I've used to generate a random set of digits is of my own creation and not in anyway unique to gorilla - you're free to right that however you want.

5) State Machine


This task is identical to the previous task except that we have replaced our main functions for the instructions, displaying trials and the finish screen with States using the StateMachine. This is a new method for structuring your task which adds additional functionality, making it easier to create more complicated tasks.

For this task we introduce a new package gorilla/state_machine and a new set of functions

  • new stateMachine.StateMachine(), the command to create a new statemachine object
  • addState, to add a state to our statemachine
  • start, to begin running our statemachine
  • transition, to move between states in our statemachine

Using a statemachine is an easy way to divide up the logic and functionality of our task by defining certain 'states' that our task can be in. For example we have created an instructions state, in which we display the instructions to the participant. We can define everything that can and cannot happen in this state and govern how we move from one state to another.

To begin, and to create our life a lot easier, we create an enumerated list called State where we list the states we're going to create: Instructions, Trial and Finish. Typescript see's these as the numbers 0, 1 and 2 but the names we've given them are much more helpful for us when writing the code. Next we create our state machine var SM = new stateMachine.StateMachine(); and begin adding states to it using the addState function. addState takes a set of arguments, the first being the number associated with the state we are created. Using our handy enumerated list, this is State.Instructions. We then pass up to three functions to our state: onEnter',onExit' and onEvent.

  • onEnter is called whenever the state is entered.
  • onExit is called whenever we leave the state, usually via .transition.
  • onEvent is called whenever an event is triggered in the task. onEvent is an important example of how useful a statemachine can be as there may be some events that we want to be available only on certain states. However, this is a more advanced example of the statemachine functionality which we won't go into in this tutorial.

onEnter is where we will usually put all of our state code. In this case we put almost the same code from our previous tutorial task except, where before we had a call to DisplayTrial we now call machine.transition(State.Trial). machine is an argument in the onEnter function which represents the internal Machine of our state machine. We can use it to move between states using .transitionon it. It normally takes as an argument the id number of the state we want to move to. Again, using our enumerated list we denote this as State.Trial.

Almost all the remaining code in our task is the same as before, except using machine.transition calls instead of our previous function calls.

Finally, in gorilla.run we use the Start function to indicate the state we wish to start in, the Instructions state in this case.

This is a simple introduction to the stateMachine and how you can use it to organise and run your trials. It has a lot more capabilities and functionality than is demonstrated here however. A much more advanced example is the Corsi Block Tapping task, where we make use of onEvent and onExit functions.

Next Steps


This is the end of our introductory tutorial series on the gorilla code editor. In this series, we've aimed to introduce to you the fundamental commands required to create a task in gorilla. If you want to see more of this code in action, have a look through the 'Code: Example Tasks' folder in the 'Samples' tab, available on your homepage.

If there is anything in this tutorial series that you feel was unclear, lacking or missing that is important to your understanding of the code editor, please drop us an email.

Further, if you ever have difficulties in implementing your task in gorilla and want some advice, don't hesitate to contact us.