diff --git a/controllers/prototype/index.js b/controllers/prototype/index.js index 316af27..4751e1a 100644 --- a/controllers/prototype/index.js +++ b/controllers/prototype/index.js @@ -36,7 +36,7 @@ var checkId = function(req, res, next, callback, id) { }); } -var getPathFromId = function(req, res, callback, id) { +var addCamerasFromId = function(req, res, callback, id) { pg.connect(pgc.url, function(err, client, release) { client.query( "SELECT ((camera).position).x AS px, " + @@ -44,14 +44,17 @@ var getPathFromId = function(req, res, callback, id) { "((camera).position).z AS pz, " + "((camera).target).x AS tx, " + "((camera).target).y AS ty, " + - "((camera).target).z AS tz " + + "((camera).target).z AS tz, " + + "time AS time " + "FROM keyboardevent WHERE user_id = $1 ORDER BY time;", [id], function(err, result) { - res.locals.path = []; + res.locals.path = res.locals.path || []; for (var i in result.rows) { + console.log(result.rows[i].time); res.locals.path.push( { + type: 'camera', position : { x: result.rows[i].px, y: result.rows[i].py, @@ -61,7 +64,54 @@ var getPathFromId = function(req, res, callback, id) { x: result.rows[i].tx, y: result.rows[i].ty, z: result.rows[i].tz - } + }, + time: result.rows[i].time + } + ); + } + callback(); + release(); + } + ); + }); +} + +var addCoinsFromId = function(req, res, callback, id) { + pg.connect(pgc.url, function(err, client, release) { + client.query( + "SELECT coin_id, time FROM coinclicked WHERE user_id = $1", + [id], + function(err,result) { + res.locals.path = res.locals.path || []; + for (var i in result.rows) { + res.locals.path.push( + { + type: 'coin', + time: result.rows[i].time, + id: result.rows[i].coin_id + } + ); + } + callback(); + release(); + } + ); + }); +} + +var addArrowsFromId = function(req, res, callback, id) { + pg.connect(pgc.url, function(err, client, release) { + client.query( + "SELECT arrow_id, time FROM arrowclicked WHERE user_id = $1", + [id], + function(err, result) { + res.locals.path = res.locals.path || []; + for (var i in result.rows) { + res.locals.path.push( + { + type: 'arrow', + time: result.rows[i].time, + id: result.rows[i].arrow_id } ); } @@ -122,8 +172,20 @@ module.exports.replay_info = function(req, res) { // Parse id var id = tools.filterInt(req.params.id); - getPathFromId(req, res, function() { - res.send(JSON.stringify(res.locals.path)); + addCamerasFromId(req, res, function() { + addCoinsFromId(req, res, function() { + addArrowsFromId(req, res, function() { + res.locals.path.sort(function(elt1, elt2) { + // Dates as string can be compared + if (elt1.time < elt2.time) + return -1; + if (elt1.time > elt2.time) + return 1; + return 0; + }); + res.send(JSON.stringify(res.locals.path)); + }, id); + }, id); }, id); } diff --git a/posts/arrow-clicked/index.js b/posts/arrow-clicked/index.js index 279c7e6..8dd0a2b 100644 --- a/posts/arrow-clicked/index.js +++ b/posts/arrow-clicked/index.js @@ -8,8 +8,8 @@ module.exports.index = function(req, res) { pg.connect(secret.url, function(err, client, release) { client.query( - "INSERT INTO arrowclicked(user_id, arrow_id) VALUES($1,$2);", - [user_id, arrow_id], + "INSERT INTO arrowclicked(user_id, arrow_id, time) VALUES($1,$2, to_timestamp($3));", + [user_id, arrow_id, req.body.time], function(err, result) { release(); } diff --git a/posts/coin-clicked/index.js b/posts/coin-clicked/index.js index a6f9545..12edfb8 100644 --- a/posts/coin-clicked/index.js +++ b/posts/coin-clicked/index.js @@ -8,8 +8,8 @@ module.exports.index = function(req, res) { pg.connect(secret.url, function(err, client, release) { client.query( - "INSERT INTO coinclicked(user_id, coin_id) VALUES($1,$2);", - [user_id, coin_id], + "INSERT INTO coinclicked(user_id, coin_id, time) VALUES($1,$2, to_timestamp($3));", + [user_id, coin_id, req.body.time], function(err, result) { release(); } diff --git a/posts/keyboard-event/index.js b/posts/keyboard-event/index.js index 7384108..1877bfa 100644 --- a/posts/keyboard-event/index.js +++ b/posts/keyboard-event/index.js @@ -8,8 +8,8 @@ module.exports.index = function(req, res) { pg.connect(secret.url, function(err, client, release) { client.query( - "INSERT INTO keyboardevent(user_id, direction, camera)" + - "VALUES($1, NULL, ROW(ROW($2,$3,$4),ROW($5,$6,$7)));" , + "INSERT INTO keyboardevent(user_id, direction, camera, time)" + + "VALUES($1, NULL, ROW(ROW($2,$3,$4),ROW($5,$6,$7)), to_timestamp($8));" , [ user_id, camera.position.x, @@ -18,7 +18,9 @@ module.exports.index = function(req, res) { camera.target.x, camera.target.y, - camera.target.z + camera.target.z, + + req.body.time ], function(err, result) { release(); diff --git a/static/js/Logger.js b/static/js/Logger.js index 63411a3..9bcdb2f 100644 --- a/static/js/Logger.js +++ b/static/js/Logger.js @@ -2,6 +2,9 @@ var BD = {}; BD.Private = {}; BD.Private.sendData = function(url, data) { + // Append time to data + data.time = Date.now() / 1000; + var xhr = new XMLHttpRequest(); xhr.open("POST", url, true); xhr.setRequestHeader("Content-type", "application/json;charset=UTF-8"); diff --git a/static/js/ReplayCamera.js b/static/js/ReplayCamera.js index eae027c..d4c5781 100644 --- a/static/js/ReplayCamera.js +++ b/static/js/ReplayCamera.js @@ -28,7 +28,7 @@ var ReplayCamera = function() { self.path[0].target.z ); self.started = true; - self.move(self.path[++self.counter]); + self.nextEvent(); } } })(this); @@ -49,8 +49,15 @@ ReplayCamera.prototype.look = function() { // Update function ReplayCamera.prototype.update = function(time) { - if (this.started) - this.linearMotion(time); + if (this.started) { + if (this.event.type == 'camera') { + this.linearMotion(time); + } else if (this.event.type == 'arrow') { + this.hermiteMotion(time); + } else if (this.event.type == 'coin') { + // Nothing to do + } + } } ReplayCamera.prototype.linearMotion = function(time) { @@ -62,12 +69,48 @@ ReplayCamera.prototype.linearMotion = function(time) { this.t += 0.1 * time / 20; if (this.t > 1) { - this.counter++; - if (this.counter < this.path.length) { - this.move(this.path[this.counter]); - } else { - this.started = false; - } + this.nextEvent(); + } +} + +ReplayCamera.prototype.hermiteMotion = function(time) { + var eval = this.hermitePosition.eval(this.t); + this.position.x = eval.x; + this.position.y = eval.y; + this.position.z = eval.z; + + this.target = Tools.sum(this.position, this.hermiteAngles.eval(this.t)); + + this.t += 0.01 * time / 20; + + if (this.t > 1) { + this.nextEvent(); + } +} + +ReplayCamera.prototype.nextEvent = function() { + this.counter++; + + // Finished + if (this.counter >= this.path.length) { + this.started = false; + return; + } + + this.event = this.path[this.counter]; + + if (this.event.type == 'camera') { + this.move(this.event); + } else if (this.event.type == 'coin') { + coins[this.event.id].get(); + // Wait a little before launching nextEvent + (function(self) { + setTimeout(function() { + self.nextEvent(); + },500); + })(this); + } else if (this.event.type == 'arrow') { + this.moveHermite(cameras.cameras[this.event.id]); } } @@ -118,3 +161,20 @@ ReplayCamera.prototype.move = function(otherCamera) { this.t = 0; } + +ReplayCamera.prototype.moveHermite = function(otherCamera) { + this.movingHermite = true; + this.t = 0; + + this.hermitePosition = new Hermite.special.Polynom( + this.position.clone(), + otherCamera.position.clone(), + Tools.mul(Tools.diff(otherCamera.target, otherCamera.position).normalize(),4) + ); + + this.hermiteAngles = new Hermite.special.Polynom( + Tools.diff(this.target, this.position), + Tools.diff(otherCamera.target, otherCamera.position), + new THREE.Vector3() + ); +}