var pg = require('pg'); var pgc = require('../../private.js'); var Info = function(id, finishAction) { this.id = id; this.ready = { cameras: false, coins: false, arrows: false, resets : false, previousNext: false, hovered: false }; this.results = {}; this.finishAction = finishAction; // Connect to db var self = this; pg.connect(pgc.url, function(err, client, release) { self.client = client; self.release = release; self.execute(); }); }; Info.prototype.execute = function() { this.loadCameras(); this.loadCoins(); this.loadArrows(); this.loadResets(); this.loadPreviousNext(); this.loadHovered(); }; Info.prototype.tryMerge = function() { // If not ready, do nothing for (var i in this.ready) { if (!this.ready[i]) { return; } } // Release db connection this.release(); this.release = null; this.client = null; this.merge(); this.finishAction(this.finalResult); }; // Merges the results of every SQL requests done by the load... methods Info.prototype.merge = function() { this.finalResult = []; for (;;) { // Find next element var nextIndex = null; for (var i in this.results) { // The next element is placed at the index 0 (since the elements // gotten from the database are sorted) if (this.results[i].length !== 0 && (nextIndex === null || this.results[i][0].time < this.results[nextIndex][0].time)) { nextIndex = i; } } // If there is no next element, we're done if (nextIndex === null) { break; } // Add the next element in results and shift its table this.finalResult.push(this.results[nextIndex].shift()); } }; Info.prototype.loadCameras = function() { var self = this; this.client.query( "SELECT ((camera).position).x AS px, " + "((camera).position).y AS py, " + "((camera).position).z AS pz, " + "((camera).target).x AS tx, " + "((camera).target).y AS ty, " + "((camera).target).z AS tz, " + "time AS time " + "FROM keyboardevent WHERE exp_id = $1 ORDER BY time;", [self.id], function(err, result) { self.results.cameras = []; for (var i in result.rows) { self.results.cameras.push( { type: 'camera', position : { x: result.rows[i].px, y: result.rows[i].py, z: result.rows[i].pz }, target : { x: result.rows[i].tx, y: result.rows[i].ty, z: result.rows[i].tz }, time: result.rows[i].time } ); } self.ready.cameras = true; self.tryMerge(); } ); }; Info.prototype.loadCoins = function() { var self = this; this.client.query( "SELECT coin_id, time FROM coinclicked WHERE exp_id = $1 ORDER BY time;", [self.id], function(err,result) { self.results.coins = []; for (var i in result.rows) { self.results.coins.push( { type: 'coin', time: result.rows[i].time, id: result.rows[i].coin_id } ); } self.ready.coins = true; self.tryMerge(); } ); }; Info.prototype.loadArrows = function() { var self = this; this.client.query( "SELECT arrow_id, time FROM arrowclicked WHERE exp_id = $1 ORDER BY time;", [self.id], function(err, result) { self.results.arrows = []; for (var i in result.rows) { self.results.arrows.push( { type: 'arrow', time: result.rows[i].time, id: result.rows[i].arrow_id } ); } self.ready.arrows = true; self.tryMerge(); } ); }; Info.prototype.loadResets = function() { var self = this; this.client.query( "SELECT time FROM resetclicked WHERE exp_id = $1 ORDER BY time;", [self.id], function(err, result) { self.results.resets = []; for (var i in result.rows) { self.results.resets.push( { type: 'reset', time: result.rows[i].time } ); } self.ready.resets = true; self.tryMerge(); } ); }; Info.prototype.loadPreviousNext = function () { var self = this; this.client.query( "SELECT ((camera).position).x AS px, " + "((camera).position).y AS py, " + "((camera).position).z AS pz, " + "((camera).target).x AS tx, " + "((camera).target).y AS ty, " + "((camera).target).z AS tz, " + "time AS time " + "FROM previousnextclicked WHERE exp_id = $1 ORDER BY time;", [self.id], function(err, result) { self.results.previousNext = []; for (var i in result.rows) { self.results.previousNext.push( { type: 'previousnext', time: result.rows[i].time, previous: result.rows[i].previousnext == 'p', position : { x: result.rows[i].px, y: result.rows[i].py, z: result.rows[i].pz }, target : { x: result.rows[i].tx, y: result.rows[i].ty, z: result.rows[i].tz } } ); } self.ready.previousNext = true; self.tryMerge(); } ); }; Info.prototype.loadHovered = function() { var self = this; this.client.query( "SELECT start, time, arrow_id FROM hovered WHERE exp_id = $1 ORDER BY time;", [self.id], function(err, result) { self.results.hovered = []; for (var i in result.rows) { self.results.hovered.push( { type: "hovered", time: result.rows[i].time, start: result.rows[i].start, id: result.rows[i].arrow_id } ); } self.ready.hovered = true; self.tryMerge(); } ); }; var UserCreator = function(finishAction) { this.finishAction = finishAction; // Connect to db var self = this; pg.connect(pgc.url, function(err, client, release) { self.client = client; self.release = release; self.execute(); }); }; UserCreator.prototype.execute = function() { var self = this; this.client.query( "INSERT INTO users(name) VALUES('anonymous'); SELECT currval('users_id_seq');", [], function(err, result) { self.finalResult = result.rows[0].currval; self.finish(); } ); }; UserCreator.prototype.finish = function() { this.release(); this.client = null; this.release = null; this.finishAction(this.finalResult); }; var ExpCreator = function(user_id, scene_id, finishAction) { this.finishAction = finishAction; this.user_id = user_id; this.scene_id = scene_id; // Connect to db var self = this; pg.connect(pgc.url, function(err, client, release) { self.client = client; self.release = release; self.execute(); }); }; ExpCreator.prototype.execute = function() { var self = this; this.client.query( "INSERT INTO experiment(user_id, scene_id) VALUES($1,$2);", [self.user_id, self.scene_id], function(err, result) { self.client.query("SELECT MAX(id) AS id FROM experiment;", function(err, result) { self.finalResult = result.rows[0].id; self.finish(); }); } ); }; ExpCreator.prototype.finish = function() { this.release(); this.client = null; this.release = null; this.finishAction(this.finalResult); }; var UserIdChecker = function(id, finishAction) { this.id = id; this.finishAction = finishAction; var self = this; pg.connect(pgc.url, function(err, client, release) { self.client = client; self.release = release; self.execute(); }); }; UserIdChecker.prototype.execute = function() { var self = this; this.client.query( "SELECT count(id) > 0 AS answer FROM users WHERE id = $1;", [self.id], function(err, result) { self.finalResult = result.rows[0].answer; self.finish(); } ); }; UserIdChecker.prototype.finish = function() { this.release(); this.client = null; this.release = null; this.finishAction(this.finalResult); }; var ExpIdChecker = function(id, finishAction) { this.id = id; this.finishAction = finishAction; var self = this; pg.connect(pgc.url, function(err, client, release) { self.client = client; self.release = release; self.execute(); }); }; ExpIdChecker.prototype.execute = function() { var self = this; this.client.query( "SELECT scene_id FROM experiment WHERE id = $1;", [self.id], function(err, result) { if (result === undefined || result.rows.length === 0) { self.finalResult = null; } else { self.finalResult = result.rows[0].scene_id; } self.finish(); } ); }; ExpIdChecker.prototype.finish = function() { this.release(); this.client = null; this.release = null; this.finishAction(this.finalResult); }; var ExpGetter = function(finishAction) { this.finishAction = finishAction; var self = this; pg.connect(pgc.url, function(err, client, release) { self.client = client; self.release = release; self.execute(); }); }; ExpGetter.prototype.execute = function() { var self = this; this.client.query( "SELECT " + "experiment.id as exp_id, " + "users.name as username, " + "scene.name as scenename, " + "users.id as user_id " + "FROM experiment, users, scene " + "WHERE experiment.user_id = users.id and scene.id = experiment.scene_id " + "ORDER BY experiment.id;", [], function(err, result) { self.finalResult = result.rows; self.finish(); } ); }; ExpGetter.prototype.finish = function() { this.release(); this.client = null; this.release = null; this.finishAction(this.finalResult); }; var tryUser = function(id, callback) { if (id !== undefined && id !== null) { new UserIdChecker(id, function(clear) { if (clear) { callback(id); } else { new UserCreator(callback); } }); } else { new UserCreator(callback); } }; module.exports.getInfo = function(id, callback) { new Info(id, callback); }; module.exports.createUser = function(callback) { new UserCreator(callback); }; module.exports.createExp = function(id, scene_id, callback) { new ExpCreator(id, scene_id, callback); }; module.exports.checkUserId = function(id, callback) { new UserIdChecker(id, callback); }; module.exports.checkExpId = function(id, callback) { new ExpIdChecker(id, callback); }; module.exports.getAllExps = function(callback) { new ExpGetter(callback); }; module.exports.tryUser = tryUser;