nodegame-openshift
Version:
Prepares a nodeGame instance to run on the openshift cloud.
341 lines (312 loc) • 12.7 kB
JavaScript
/**
* # Player code for Ultimatum Game
* Copyright(c) 2016 Stefano Balietti
* MIT Licensed
*
* Handles bidding, and responds between two players.
* Extensively documented tutorial.
*
* http://www.nodegame.org
*/
var ngc = require('nodegame-client');
var Stager = ngc.Stager;
var stepRules = ngc.stepRules;
var constants = ngc.constants;
// Export the game-creating function.
module.exports = function(treatmentName, settings, stager, setup, gameRoom) {
var game, cbs;
var channel = gameRoom.channel;
var node = gameRoom.node;
// The game object to return at the end of the function.
game = {};
// Import other functions used in the game.
cbs = require(__dirname + '/includes/player.callbacks.js');
// Specify init function, and extend steps.
// Init callback.
stager.setOnInit(cbs.init);
stager.setOnGameOver(function() {
// Do something if you like!
});
////////////////////////////////////////////////////////////
// nodeGame hint: step propreties.
//
// A step is a set of properties under a common label (id),
// i.e. the id of the step.
//
// Properties can be defined at multiple levels, and those defined
// at higher levels are inherited by each nested step, that in
// turn can overwrite them.
//
// For example, if a step is missing a property, it will be looked
// into the enclosing stage. If it is not defined in the stage,
// the value set with _setDefaultProperties()_ will be used. If
// still not found, it will fallback to nodeGame defaults.
//
// The property named `cb` is one of the most important.
//
// It defines the callback that will be called during the
// step. By default, each steps inherits an empty callback,
// so that it is not necessary to implement one, if the
// player has, for example, just to read a text.
//
// Another important property is `stepRule`
//
// A step rule is a function deciding what to do when a player has
// terminated a step and entered the stage level _DONE_.
//
// Some of the available step rules are:
//
// - 'SOLO': advances through the steps freely
// - 'WAIT': wait for a command from server to go to
// next step (Default)
//
// To add/modify properties use the commands:
//
// `stager.extendStep`: modifies a step
// `stager.extendStage`: modifies a stage, and all enclosed steps
// `stager.setDefaultProperty`: modifies all stages and steps
//
////////////////////////////////////////////////////////////
stager.extendStep('selectLanguage', {
frame: 'languageSelection.html',
cb: cbs.selectLanguage,
done: function() {
// The chosen language prefix will be
// added automatically to every call to W.loadFrame().
if (node.player.lang.name !== 'English') {
W.setUriPrefix(node.player.lang.path);
node.say('mylang', 'SERVER', node.player.lang);
}
}
});
stager.extendStep('precache', {
cb: cbs.precache
});
stager.extendStep('instructions', {
/////////////////////////////////////////////////////////////
// nodeGame hint: the settings object
//
// The settings object is automatically populated with the
// settings specified for the treatment chosen by the waiting
// room. The settings is sent to each remote client and it is
// available under: `node.game.settings`.
frame: settings.instructionsPage
});
stager.extendStep('quiz', {
/////////////////////////////////////////////////////////////
// nodeGame hint: the frame parameter
//
// The frame parameter is passed to `W.loadFrame` to
// load a new page. Additional options exist to automatically
// search & replace the DOM, and store a page in the cache.
// In its simplest form, it is just a string indicating the
// path to the page to load.
//
// Pages are loading from the public/ directory inside the
// game folder. However, they can also be loaded from the
// views/ directory (if not found in public/).
frame: 'quiz2.html', // ('quiz.html' to have forms in html)
cb: function() {
var w, qt, t;
t = this.settings.treatmentName;
qt = this.quizTexts;
/////////////////////////////////////////////////////////////
// nodeGame hint: the widget collection
//
// Widgets are re-usable components with predefined methods,
// such as: hide, highlight, disable, getValues, etc.
// Here we use the `ChoiceManager` widget to create a quiz page.
w = node.widgets;
this.quiz = w.append('ChoiceManager', W.getElementById('quiz'), {
id: 'quizzes',
title: false,
forms: [
w.get('ChoiceTable', {
id: 'howMuch',
shuffleItems: true,
title: false,
choices: qt.howMuchChoices,
correctChoice: 1,
mainText: qt.howMuchMainText
}),
w.get('ChoiceTable', {
id: 'reject',
shuffleItems: true,
title: false,
orientation: 'v',
choices: qt.rejectChoices,
correctChoice: 3,
mainText: qt.rejectMainText
}),
w.get('ChoiceTable', {
id: 'disconnect',
shuffleItems: true,
title: false,
orientation: 'v',
choices: qt.disconnectChoices,
correctChoice: t === 'pp' ? 1 : 3,
mainText: qt.disconnectMainText
})
]
});
},
done: function() {
var answers, isTimeup;
answers = this.quiz.getValues({
markAttempt: true,
highlight: true
});
isTimeup = node.game.timer.isTimeup();
if (!answers.isCorrect && !isTimeup) return false;
return answers;
}
});
stager.extendStep('mood', {
/////////////////////////////////////////////////////////////
// nodeGame hint: the widget property
//
// It is a shortcut to create widget-steps.
//
// In a widget-step, the following operations are performed:
//
// 1- The widget is loaded, possibly appended. If no frame
// is specified, the default page
// '/pages/default.html' will be loaded.
// 2- Upon `node.done`, the current values of the widget
// are validated, and if valid, and not timeup will be
// sent to server.
// 3- Upon exiting the step, the widget will be destroyed.
//
// If specified as an object, additional options can be set.
// For example:
//
// ```
// widget: {
// name: 'MoodGauge',
// id: 'myid',
// ref: 'myref', // It will be added as node.game[ref]
// options: { ... },
// append: false,
// checkAnswers: false,
// root: ...
// destroyOnExit: false
// }
// ```
widget: 'MoodGauge'
});
stager.extendStage('ultimatum', {
// Disable the donebutton for this step.
donebutton: false,
/////////////////////////////////////////////////////////////
// nodeGame hint: the init function
//
// It is a function that is executed before the main callback,
// and before loading any frame.
//
// Likewise, it is possible to define an `exit` function that
// will be executed upon exiting the step.
//
// Notice that if the function is defined at the level of the
// stage, it will be executed only once upone entering the
// stage. If, you need to have it executed every round the
// stage is repeated, add it to the first step of the stage.
init: function() {
node.game.rounds.setDisplayMode(['COUNT_UP_STAGES_TO_TOTAL',
'COUNT_UP_ROUNDS_TO_TOTAL']);
}
// `syncOnLoaded` forces the clients to wait for all the others to be
// fully loaded before releasing the control of the screen to the
// players. This options introduces a little overhead in
// communications and delay in the execution of a stage. It is probably
// not necessary in local networks, and it is FALSE by default.
// syncOnLoaded: true
});
stager.extendStep('matching', {
init: function() {
node.game.role = null;
node.game.other = null;
node.game.offerReceived = null;
}
});
stager.extendStep('bidder', {
/////////////////////////////////////////////////////////////
// nodeGame hint: the timeup parameter
//
// It can be a string (to be emitted as an event), or a
// function to be executed when `node.game.timer` expires.
// Note that if no `timer` property is set for current step,
// then the timeup function will not be automatically called.
//
// The default timeup is different for player and logic client
// types. For players, by default it is a call to `node.done()`.
timeup: function() {
if (this.role === 'BIDDER') node.game.bidTimeup();
},
cb: cbs.bidder
});
stager.extendStep('respondent', {
timeup: function() {
if (this.role === 'RESPONDENT') node.game.resTimeup();
},
cb: cbs.respondent
});
stager.extendStep('endgame', {
frame: 'ended.html',
cb: cbs.endgame,
/////////////////////////////////////////////////////////////
// nodeGame hint: the donebutton parameter
//
// It is read by the DoneButton widget, and it can set the
// the text on the button, or disable it (false).
donebutton: false
});
stager.extendStep('questionnaire', {
init: function() {
node.game.rounds.setDisplayMode(['COUNT_UP_STAGES_TO_TOTAL']);
},
cb: function() {
var qt;
qt = this.questTexts;
this.quest = node.widgets.append('ChoiceTable',
W.getElementById('quiz'),
{
id: 'quest',
mainText: qt.mainText,
choices: qt.choices,
freeText: qt.freeText,
title: false,
shuffleChoices: true,
orientation: 'v'
});
},
frame: 'questionnaire.html', // ('postgame.html' to have forms in html)
/////////////////////////////////////////////////////////////
// nodeGame hint: the done callback
//
// `done` is a callback execute after a call to `node.done()`
// If it returns FALSE, the call to `node.done` is canceled.
// Other return values are sent to the server, and replace any
// parameter previously passed to `node.done`.
done: function(args) {
var answers, isTimeup;
answers = this.quest.getValues();
isTimeup = node.game.timer.isTimeup();
if (!answers.choice && !isTimeup) {
this.quest.highlight();
return false;
}
return answers;
}
});
// We serialize the game sequence before sending it.
game.plot = stager.getState();
// Other settings, optional.
game.env = {
auto: settings.AUTO,
treatment: treatmentName
};
game.verbosity = 1000;
game.debug = settings.DEBUG;
game.nodename = 'player';
return game;
};