You will spend most of your time editing the script file(s) under the data_includes folder of your experiment. PCIbex Farm comes with an internal editor that will show you suggestions as you type. Suggestions are particularly helpful because they prevent you from making typos and from entering an expression that is not part of the language, which would likely cause your experiment to crash, so make use of them.
Click on the edit link to the right of the file main.js, under data_includes to open the editor. Aligned to the right edge of the top bar are links to the PennController docs and ibex docs, which open in new windows. You can click the PennController docs link if you need to look up a PennController command, which you will probably do quite often.
There are four buttons aligned to the right edge of the bottom bar. The first button, Discard changes, closes the editor and you lose any changes made since last time you saved your script (same as clicking the cross button at the top-right corner of the editor). The second button, Save changes, saves your current script while leaving the editor open. The third button, Save and close, also saves your script but closes the editor afterwards. The last button, Save and test, saves your current script and opens your experiment in a new window (or refreshes the experiment window if you clicked the button before and didn’t close the experiment window in the meantime). You will likely click this last button a lot.
We will now quickly walk through the script. If you just created a new experiment on the PCIbex Farm, you should now be looking at the following script (your script additionally contains bits of text starting with
// at the end of most lines):
PennController.ResetPrefix(null); PennController( newImage("logo", "pcibex-logo.png") .settings.size(150,200) .print() , newButton("Start reading") .print() .wait() .remove() , getImage("logo") .remove() , newText("sentence", "Hello world") .print() , newTimer(2000) .start() .wait() , getText("sentence") .remove() , newText("<p>What did the sentence say?</p>") .print() , newTextInput() .print() , newText("<p>How confident are you that it is indeed what the sentence said?</p>") .print() , newScale(5) .settings.slider() .print() .wait() ).setOption("hideProgressBar",true)
The very first line is the command
ResetPrefix called with the prefix
PennController and the argument
null. By default, all the PennController commands should start with
PennController as is the case here, but the line
PennController.ResetPrefix(null) lifts this constraint for the commands you use in a trial definition. Unless you add modules to your experiment and you suspect that dropping the prefix could result in conflicts, you probably want to keep this command up there.
All the rest of the script is a big
PennController command creating a new trial: the command opens a parenthesis on the third line (
PennController() which is closed only on the last line (first character in
).setOption("hideProgressBar")). Between these two parentheses is a sequence of commands, in blocks separated by commas, that define how the trial unfolds.
The very first thing that happens in this trial (line 5,
newImage("logo", "pcibex-logo.png")) is the creation of an Image element (the bits of text that start with
//, not reported in the script above, are comments and they are not executed during runtime—they are just here for whoever is reading the script, namely you). The Image element uses the file
pcibex-logo.png from your project’s chunk_includes folder, and it is named
logo. Most of the time, naming elements is optional, but you have limited control over unnamed elements (more about that soon). Once the element is created, it is resized to 150x200px (line 6,
.settings.size(150,200)) and then it is printed onto the screen (line 7,
.print()—note the necessary presence of a pair of parentheses on commands even when they contain nothing). The page is still empty as these things happen first in your trial, and the image is therefore the first thing that gets displayed on the page.
Line 9 (
newButton("Start reading")) creates a new Button element containing the text Start reading. This element has no name. Line 10 (
.print()) adds the button onto the page. Since, at this point, there already is an image on the page, the button is added below the image. Line 11 (
.wait()) waits until the button is clicked before proceeding: all the commands below line 11 will not be executed until a click happens. Line 12 (
.remove()) is only executed after the button has been clicked, and its effect is to remove the button from the page.
Line 14 (
getButton("logo")) starts a block of commands that relate to the Image element that was created above and named logo (as you can see, naming elements makes it possible to refer back to them later). Line 15 (
.remove()) removes the image from the page, and since this happens immediately after the button was removed from the page, it effectively empties the content of the page.
You are probably getting the gist of how trial scripts work at this point. The rest of the script will add a Text element named sentence and reading Hello world onto the page, wait 2 seconds before proceeding (what this means is that, since the Button and Image elements were removed, the page will only show Hello world for 2s) then it will remove the text from the page, show a question and, below it, a text input box, another question, and a slider scale. The last command of the trial (line 41,
.wait()) is called on the Scale element and, as the last command, it will effectively halt the completion of the trial until a value is selected on the slider. As soon as selection happens, execution proceeds and since there is no more command, it is the end of the trial.
You now know how to read a script, and even though you may not have a full understanding of every expression in the PennController vocabulary, you can always look up the documentation as you would open a dictionary. Let us start to speak PennController by creating our first trial from scratch.