This tutorial describes the sequence of events that happen during an app. In particular, it points out the various functions that can be used to design an app. For more details about this procedure, see the advanced tutorial.
In a jtree app, participants progress through a series of periods and stages. Within each period repeats the stages. In doing so, they take the form of players and groups. Broadly speaking, each object calls playerStart (or groupStart) and playerEnd (or groupEnd) whenever a player (or group) begins or finishes that part of the experiment.
For example, in a simple app the sequence of events might be:
- stage1.groupStart(G1);
- stage1.playerStart(P1);
- stage1.playerStart(P2);
- stage1.playerEnd(P1);
- stage1.playerEnd(P2);
- stage1.groupEnd(G1);
(Note that the order of the player functions (P1, P2) depends on how quickly each player progresses through the app.)
The logic of the app is implemented by overwriting each of these "start" and "end" methods.
This is done in the app's source file. This file has access to the App object, from which Stages can be created via the App.newStage(id) function. Periods can be customized by overwriting the App.createPeriod(id) method.
The rest of this tutorial describes approximately the order in which events take place within a session. Due to the option of letting participants progress through different stages without waiting for each other, the actual order of these events may differ in actual sessions.
At the beginning of an app, the following functions are called:
eval(app.js) // evaluates the contents of app.js
App.participantStart(participant)
// Clients are updated via a "startNewApp" message.
// Participants go through the Periods of the App.
App.participantEnd(participant)
Within the app, participants go through a series of periods. At the beginning of the period, participants are assigned to a player, and the players are assigned to groups, according to the output of App.getGroupIdsForPeriod(period). Thus, each period calls the following functions:
App.getGroupIdsForPeriod(period)
Period.groupStart(group)
Period.playerStart(player)
// Players go through the stages of the app.
Period.playerEnd(player)
Period.groupEnd(group)
Within each period, players and groups progress through the stages of the app. Within each stage, the following functions are called for the groups and players:
player.statusis set to'ready'.- If
Stage.waitToStart == trueand not all players in group are ready, stop. - If
Stage.groupStart(group)has not already been called, call it. - If
Stage.canPlayerParticipate(player)is true: player.statusis set to'playing'.Stage.playerStart(player)is called.- Players are shown the active screen.
player.statusis set to'done'.- If
Stage.waitToEnd == trueand not all players in group are done, stop. Stage.playerEnd(player)is called.player.statusis set to'finished'.- Player begins from step 1 for next stage in session, if any.
- Once all players in the group have ended the stage,
Stage.groupEnd(group)is called. - Group begins procedure for next stage in session, if any.
When a session is started, all players begin the first app of the session.
If Stage.waitToStart is true, no player can start the stage (Step 3) until all players in the group are ready.
If Stage.waitForAllGroups is true, no group starts the stage until every player of the period, in every group, is ready; then Stage.allGroupsStart(period) is called once, before each group's groupStart.
If Stage.waitToEnd is true, no player can end the stage (Step 9) until all players in the group are finished.
As soon as a player ends the stage, they move to the next stage in the session (if there is one) and begin again at the first step of this procedure.
Groups belong to Periods. This means that whenever a stage has waitToStart as false, groups can "start" that stage before finishing one or more of the group's previous stages.
Stages with stages
A stage is an app: it can have stages of its own, or be an app's file (see apps and stages). When a player starts such a stage, after playerStart, their participant plays its stages, in periods and groups of its own, as in an app of the session; when they have played them, or the stage's duration is up, the player ends the stage, as if they had submitted it: playerEnd, then (once the group has ended it) groupEnd.
Timeouts
A stage with a duration (in seconds) times out when that time is up. Players who have not ended the stage by then have player.timedOut set to true while the stage ends, so playerEnd and groupEnd can tell them apart; it is false again from the next stage.
If Stage.waitOnTimerEnd is true (the default), each of those players' pages is asked to submit what it has, as if the participant had pressed OK. Players whose page does not within Stage.timeoutGrace seconds (5 by default, set for all stages of an app with app.stageTimeoutGrace), for example because it was closed, are ended by the server, with nothing submitted. With timeoutGrace set to null, the server waits for the pages however long they take. If waitOnTimerEnd is false, the stage ends for everyone at once, without asking the pages.
A player can also have time of their own for a stage, from when they start it: Stage.clientDuration seconds, or Stage.getClientDuration(player) for a different time per player. Their page counts down and submits; if it does not, the server ends the stage for them after timeoutGrace, as for a group's timeout. With Stage.endOnTimeout false, a stage whose time is up (the group's or a player's) only marks the players timedOut and stays open until they submit.
App and period hooks
Besides its stages' hooks, an app can set:
app.appStart = function() {}; // once, when the first participant starts the app
app.periodStart = function(period) {}; // once per period: its groups and players exist, no stage has started
app.periodEnd = function(period) {}; // once per period: its last group has ended its last stage
app.end = function() {}; // once, when every participant has finished the app
When a group ends a stage that waits for everyone (waitToEnd), its players move on only after groupEnd, and at the end of a period after periodEnd: what those set is there when the next stage starts. Errors in any of these hooks are logged, and the session goes on.