-
Notifications
You must be signed in to change notification settings - Fork 12
Working with Plugins
Plugins are the way to customize the tasks the researcher wants to use in a study. Each task must use one of the available plugins, if the researcher wants to build its own plugin, this is the guide to do it.
Some of the built-in available plugins are:
- Sudoku - Simple sudoku game.
- Whack-A-Mole - A simple click on the appearing mole
- Typing - Allows subjects to type at the same time, similar to Google Docs.
- Typing with colors - Allows subjects to first pick the color they will use.
- Equation - Allow users to type equations that comply with the imposed rules, like not allowing or enforcing specific digits.
- Memory Grid - A memory game, that first shows the texts to be memorized and then allows users to input the answers in a grid
- Minimum effort - A minimum effort game
- Survey - A form like survey that can use some variables like the subjects names and tasks names
- Survey with two fields - Allows for one question to have to answer fields that require different subject's answers.
All tasks plugins reside under src/resources/plugins
.
All plugins must be responsible for everything a task is meant to do:
- Allow researchers to configure different parameters
- Display the task as expected
- Score itself or know how to delegate to an external server
Before we explain the plugin a quick recap of how a task works in POGS:
All tasks have the following lifecyle:
- Task Intro
- Task Primer
- Task work
The plugins have more stages:
- Editing and setup
- Execution stage
- Task Before Work
- Task Primer
- Task Work
- Task After work
- Scoring
In order to achieve the desired behavior the plugins have the following folder structure:
pluginName/
- pluginProperties.yml
- task.css
- taskEdit.js
- taskEdit.html
- taskBeforeWork.js
- taskPrimer.js
- taskPrimer.html
- taskWork.js
- taskWork.html
- taskAfterWork.js
- taskScore.js
Now we explain what each file does:
File name | Responsability | Execution state | Where the code runs |
---|---|---|---|
pluginProperties.yml | File that describes the plugin and allows the developer to setup the kind of scoring option to use: script/externalService | Basic configuration | Server |
task.css | The CSS file for styling of all files that require html handling. | Editing, Primer, Work | Researcher browser and Subject browser |
taskEdit.js | Where the logic to allow configurations to be saved is implemented. | Editing | Researcher browser |
taskEdit.html | The html boilerplate to be used for editing the task configurations | Editing | Researcher browser |
taskBeforeWork.js | The script to be run by the server before the task starts. Used to create random subject order, or color assignment | Before work | Server |
taskPrimer.js | The code that makes logic changes to the primer page. Ex. Display texts to be memorized fading in and out at the primer page. | Primer | Subject browser |
taskPrimer.html | Html boilerplate to be used by the primer script | Primer | Subject browser |
taskWork.js | The actual code for the task execution | Work | Subject browser |
taskWork.html | Html boilerplate to be used by the work script | Work | Subject browser |
taskAfterWork.js | The script that runs after task execution. Ex.: to save new subject attributes according to their answers | After work | Server |
taskScore.js | The script to calculate the final score for a task | Scoring | Server |
We will explain in the order of usage by the researcher until the final execution
The first thing a researcher does when he/she wants to use a plugin is create a new configuration for it.
The Task plugin configuration has two parts. The Basic
configuration, which is the same for all plugins and the Advanced
configuration, which is unique per plugin.
In the Basic
configuration the researcher can define the plugin name, the research group the configuration belongs to and the script overrides.
This is better defined in Working with Executable Scripts.
The advanced configuration is rendered under the basic section, and it uses the task.css
, taskEdit.html
and taskEdit.js
to provide the logic to display and save changes to plugin specific information
This is a boilerplate of the taskEdit.js code.
class PluginTaskEdit {
init(taskConfigId, currentAttributes){
}
setupHtmlFromAttributeString(bluePrint, answerSheet){
}
setupAttributesFromHtml(){
return {bluePrint: bluePrintString, answerSheet: sudokuSolveString};
}
beforeSubmit(){
}
}
pogsTaskConfigEditor.register(new PluginTaskEdit());
The developer must register a TaskEdit object with the following mandatory methods:
-
init(configId, currentAttributes)
- Where the initialization code must be done. -
beforeSubmit()
- This is where the attributes to be saved must be treated and where validation must be done, if this method returns a string, the system will popup a warning. It is called when the researcher clicks on theSave configuration
button.
There are two other methods that we have established as an informal pattern and are not required:
-
setupHtmlFromAttributeString(bluePrint, answerSheet)
- That populates the html from the saved attributes -
setupAttributesFromHtml()
- That populates the variables form the HTML.
The pogsTaskConfigEditor script provides this handy function to save the changes to the attributes:
function createOrUpdateAttribute(attributeName, stringValue, intValue, doubleValue,taskConfigurationId, index, id);
Ex.: Sudoku It is a good practice to save at least two attributes:
- the
bluePrint
of what is being saved, in this case the grid layout, with all of the occupied cells, and also the empty ones. - the
answerSheet
of the empty cells, so that the scoring script can compare the answers easily.
This is a strong suggestion, but not mandatory.
##taskBeforeWork.js The first script to run if set is the task before work. It is covered in details in Working with Executable Scripts
##taskPrimer.js The task primer will run once the subjects get to the primer page of the task associated with this plugin.
The file must implement the following code:
let xxxTaskPrimerPlugin = pogs.createPlugin('xxxTaskPrimerPlugin',function(){
//put your code here
});
The section of task work will explain this createPlugin method in more detail.
##taskWork.js This is the actual work that should be done by the subjects. This script must register itself using a factory patter,
Where xxx could be your plugin name or anything else. This callback function will be called,
as soon as the page loads but after all POGS objects are instantiated. There are a lot of methods that
can be called from the this
context of this taskplugin object.
Normally we encapsulate the this
reference to use in later stages.
The following code is a suggestion, but not mandatory:
var xxxxTaskPlugin = pogs.createPlugin('xxxTaskPlugin',function(){
let myNewPogsPluginTask = new MyNewPogsPluginTask(this);
this.subscribeTaskAttributeBroadcast(myNewPogsPluginTask.broadcastReceived.bind(memoryGridTask))
});
class MyNewPogsPluginTask {
constructor(pogsPlugin) {
this.pogsPlugin = pogsPlugin; //saving the plugin reference for later usages.
}
broadcastReceived(message){
}
....
}
There are three important sections of the code above.
- The plugin registration inside the callback function. That will give access to the reference of this plugin object.
- The instantiation of the
MyNewPogsPluginTask
to hold all logic related to the plugin implementation, that receives the reference to thepogsPlugin
object in its constructor. - The usage of one of the methods of the
pogsPlugin
object, that register the plugin to receive the broadcasts coming from the websocket.
The available methods for pogsPlugin can be devided by the scope of their usage.
- Message exchange
- Subject information
- Task configuration attributes
- Others
Pogs plugins provide easy access to the message broker under POGS that allows subjects to share information.
-
subscribeTaskAttributeBroadcast(callback)
- this method registers a callback function to be called everytime a new message is received. The incoming message is passed as an argument of the callback. -
saveCompletedTaskAttribute
- This saves a new message to the server. This attributes will be broadasted while the ones created withsaveCompletedTaskAttributeWithoutBroadcast
. They can also be logged(saved to the database or not). This way the developer is in charge of what he wants to be saved or not.
-
getSubjectByExternalId
- Gets the subject object with all its attributes, by its external id property. -
getTeammates
- All teammates including the current user. -
getTeammateAttribute
- Get the attributes of one specific user. -
getSubjectId
- The current subject's external id.
-
getStringAttribute
, float int boolean -
getCompletedTaskStringAttribute
, float int boolean
All other methods that may be relevant to the implementation can be found in the pogsPlugin.js file at:
src/main/resources/static/js/pogsPlugin.js
.
##taskAfterWork.js The script to run right after the work has ended if set is the task after work. It is covered in details in Working with Executable Scripts
It is covered in details in Working with Executable Scripts