Skip to content

Working with Plugins

Carlos Botelho edited this page Dec 26, 2019 · 7 revisions

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.

Anatomy of a POGS Plugin

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:

  1. Task Intro
  2. Task Primer
  3. Task work

The plugins have more stages:

  1. Editing and setup
  2. Execution stage
    • Task Before Work
    • Task Primer
    • Task Work
    • Task After work
    • Scoring

Folder structure

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

Editing and setup

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

taskEdit.js

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 the Save 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 the pogsPlugin 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

Message exchange

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 with saveCompletedTaskAttributeWithoutBroadcast. 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.

Subject information

  • 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.

Task configuration attributes

  • getStringAttribute, float int boolean
  • getCompletedTaskStringAttribute, float int boolean

Others

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

##taskScore.js

It is covered in details in Working with Executable Scripts