Monster commit : a lot of cleaning
- Removed the series of nested callback in controller/prototype/index.js. Now, there are dbrequests that gives functions to easily access results of SQL requests. - Cleaning in the views : removed if / else if / else if in prototype and replaced by template inheritance
This commit is contained in:
parent
ea56745b3f
commit
74eda889be
|
@ -0,0 +1,345 @@
|
|||
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.loadAll();
|
||||
});
|
||||
}
|
||||
|
||||
Info.prototype.loadAll = 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);
|
||||
}
|
||||
|
||||
Info.prototype.merge = function() {
|
||||
this.finalResult = [];
|
||||
|
||||
for (;;) {
|
||||
// Find next element
|
||||
var nextElement = null;
|
||||
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 &&
|
||||
(nextElement === null || this.results[i][0].time < nextElement.time)) {
|
||||
nextElement = this.results[i][0];
|
||||
nextIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no next element, we're done
|
||||
if (nextElement === 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 user_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 user_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 user_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 user_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 user_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 user_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 IdCreator = 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();
|
||||
});
|
||||
}
|
||||
|
||||
IdCreator.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();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
IdCreator.prototype.finish = function() {
|
||||
this.release();
|
||||
this.client = null;
|
||||
this.release = null;
|
||||
|
||||
this.finishAction(this.finalResult);
|
||||
}
|
||||
|
||||
var IdChecker = 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();
|
||||
});
|
||||
}
|
||||
|
||||
IdChecker.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();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
IdChecker.prototype.finish = function() {
|
||||
this.release();
|
||||
this.client = null;
|
||||
this.release = null;
|
||||
|
||||
this.finishAction(this.finalResult);
|
||||
}
|
||||
|
||||
var UserGetter = function(finishAction) {
|
||||
this.finishAction = finishAction;
|
||||
|
||||
var self = this;
|
||||
pg.connect(pgc.url, function(err, client, release) {
|
||||
self.client = client;
|
||||
self.release = release;
|
||||
self.execute();
|
||||
});
|
||||
}
|
||||
|
||||
UserGetter.prototype.execute = function() {
|
||||
var self = this;
|
||||
this.client.query(
|
||||
"SELECT id, name FROM users",
|
||||
[],
|
||||
function(err, result) {
|
||||
self.finalResult = result.rows;
|
||||
self.finish();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
UserGetter.prototype.finish = function() {
|
||||
this.release();
|
||||
this.client = null;
|
||||
this.release = null;
|
||||
|
||||
this.finishAction(this.finalResult);
|
||||
}
|
||||
|
||||
module.exports.getInfo = function(id, callback) { new Info(id, callback); };
|
||||
module.exports.createId = function(callback) { new IdCreator(callback); };
|
||||
module.exports.checkId = function(id, callback) { new IdChecker(id, callback); };
|
||||
module.exports.getAllUsers = function(callback) { new UserGetter(callback); };
|
|
@ -1,207 +1,7 @@
|
|||
var tools = require('../../my_modules/filterInt.js');
|
||||
var tools = require('../../my_modules/filterInt');
|
||||
var pg = require('pg');
|
||||
var pgc = require('../../private.js');
|
||||
|
||||
var createNewId = function(req, res, callback) {
|
||||
pg.connect(pgc.url, function(err, client, release) {
|
||||
client.query(
|
||||
"INSERT INTO users(name) VALUES('anonymous'); SELECT currval('users_id_seq');",
|
||||
[],
|
||||
function(err, result) {
|
||||
req.session.user_id = result.rows[0].currval;
|
||||
req.session.save();
|
||||
callback();
|
||||
release();
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
var checkId = function(req, res, next, callback, id) {
|
||||
pg.connect(pgc.url, function(err, client, release) {
|
||||
client.query(
|
||||
"SELECT id FROM users WHERE id = $1",
|
||||
[id],
|
||||
function(err, result) {
|
||||
if (result.rows.length > 0) {
|
||||
callback();
|
||||
} else {
|
||||
var error = new Error("Id not found");
|
||||
error.status = 404;
|
||||
next(error);
|
||||
}
|
||||
release();
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
var addCamerasFromId = function(client, req, res, callback, id) {
|
||||
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 user_id = $1 ORDER BY time;",
|
||||
[id],
|
||||
function(err, result) {
|
||||
res.locals.path = res.locals.path || [];
|
||||
for (var i in result.rows) {
|
||||
res.locals.path.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
|
||||
}
|
||||
);
|
||||
}
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var addCoinsFromId = function(client, req, res, callback, id) {
|
||||
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();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var addArrowsFromId = function(client, req, res, callback, id) {
|
||||
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
|
||||
}
|
||||
);
|
||||
}
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var addResetsFromId = function(client, req, res, callback, id) {
|
||||
client.query(
|
||||
"SELECT time FROM resetclicked 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: 'reset',
|
||||
time: result.rows[i].time
|
||||
}
|
||||
);
|
||||
}
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var addPreviousNextFromId = function(client, req, res, callback, id) {
|
||||
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 user_id = $1;",
|
||||
[id],
|
||||
function(err, result) {
|
||||
res.locals.path = res.locals.path || [];
|
||||
for (var i in result.rows) {
|
||||
res.locals.path.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
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var addHoveredFromId = function(client, req, res, callback, id) {
|
||||
client.query(
|
||||
"SELECT start, time, arrow_id FROM hovered 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: "hovered",
|
||||
time: result.rows[i].time,
|
||||
start: result.rows[i].start,
|
||||
id: result.rows[i].arrow_id
|
||||
}
|
||||
);
|
||||
}
|
||||
callback();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var getAllUsers = function(req, res, callback) {
|
||||
pg.connect(pgc.url, function(err, client, release) {
|
||||
client.query(
|
||||
"SELECT id, name FROM users;",
|
||||
[],
|
||||
function(err, result) {
|
||||
res.locals.ids = result.rows;
|
||||
callback();
|
||||
release();
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
var pgc = require('../../private');
|
||||
var db = require('./dbrequests');
|
||||
|
||||
module.exports.index = function(req, res) {
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
|
@ -211,41 +11,23 @@ module.exports.index = function(req, res) {
|
|||
});
|
||||
}
|
||||
|
||||
module.exports.arrows = function(req, res) {
|
||||
createNewId(req, res, function() {
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
var protoHelper = function(template) {
|
||||
return function(req, res) {
|
||||
db.createId(function(id) {
|
||||
req.session.user_id = id;
|
||||
req.session.save();
|
||||
|
||||
res.locals.cameraStyle = 'arrows';
|
||||
|
||||
res.render('prototype.jade', res.locals, function(err, result) {
|
||||
res.setHeader('Content-Type','text/html');
|
||||
res.render(template, res.locals, function(err, result) {
|
||||
res.send(result);
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
module.exports.viewports = function(req, res) {
|
||||
createNewId(req, res, function() {
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
|
||||
res.locals.cameraStyle = 'viewports';
|
||||
|
||||
res.render('prototype.jade', res.locals, function(err, result) {
|
||||
res.send(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.reverse = function(req, res) {
|
||||
createNewId(req, res, function() {
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
|
||||
res.locals.cameraStyle = 'reverse';
|
||||
|
||||
res.render('prototype.jade', res.locals, function(err, result) {
|
||||
res.send(result);
|
||||
});
|
||||
});
|
||||
}
|
||||
module.exports.arrows = protoHelper('prototype_arrows.jade');
|
||||
module.exports.viewports = protoHelper('prototype_viewports.jade');
|
||||
module.exports.reverse = protoHelper('prototype_reverse.jade');
|
||||
|
||||
module.exports.replay_info = function(req, res) {
|
||||
res.setHeader('Content-Type', 'text/plain');
|
||||
|
@ -253,46 +35,34 @@ module.exports.replay_info = function(req, res) {
|
|||
// Parse id
|
||||
var id = tools.filterInt(req.params.id);
|
||||
|
||||
pg.connect(pgc.url, function(err, client, release) {
|
||||
addCamerasFromId(client, req, res, function() {
|
||||
addCoinsFromId(client, req, res, function() {
|
||||
addArrowsFromId(client, req, res, function() {
|
||||
addResetsFromId(client, req, res, function() {
|
||||
addPreviousNextFromId(client, req, res, function() {
|
||||
addHoveredFromId(client, 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);
|
||||
}, id);
|
||||
}, id);
|
||||
}, id);
|
||||
release();
|
||||
db.getInfo(id, function(results) {
|
||||
res.send(JSON.stringify(results));
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.replay = function(req, res, next) {
|
||||
// Get id parameter
|
||||
res.locals.id = tools.filterInt(req.params.id);
|
||||
checkId(req,res, next, function() {
|
||||
|
||||
db.checkId(res.locals.id, function(idExist) {
|
||||
if (!idExist) {
|
||||
var err = new Error("This replay does not exist");
|
||||
err.status = 404;
|
||||
next(err);
|
||||
} else {
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
res.locals.cameraStyle = "replay";
|
||||
res.render('prototype.jade', res.locals, function(err, result) {
|
||||
res.render('prototype_replays.jade', res.locals, function(err, result) {
|
||||
res.send(result);
|
||||
});
|
||||
}, res.locals.id);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.replay_index = function(req, res, next) {
|
||||
getAllUsers(req, res, function() {
|
||||
db.getAllUsers(function(result) {
|
||||
res.locals.users = result;
|
||||
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
res.render("replay_index.jade", res.locals, function(err, result) {
|
||||
res.send(result);
|
||||
});
|
||||
|
|
|
@ -15,20 +15,8 @@ block extrajs
|
|||
script(src="/static/js/prototype/Coin.js")
|
||||
script(src="/static/js/Logger.js")
|
||||
|
||||
if cameraStyle == 'replay'
|
||||
script var params = params || {}; params.get = params.get || {}; params.get.id = #{id};
|
||||
script(src="/static/js/ReplayCamera.js")
|
||||
script(src="/static/js/prototype/replay.js")
|
||||
else
|
||||
if cameraStyle == 'arrows'
|
||||
script RecommendedCamera = FixedCamera;
|
||||
else if cameraStyle == 'viewports'
|
||||
script RecommendedCamera = OldFixedCamera;
|
||||
else if cameraStyle == 'reverse'
|
||||
script RecommendedCamera = ReverseCamera
|
||||
|
||||
script(src="/static/js/prototype/main.js")
|
||||
|
||||
block configjs
|
||||
block mainjs
|
||||
script document.getElementById('music').volume = 0.5;
|
||||
|
||||
block extrahead
|
||||
|
@ -36,75 +24,7 @@ block extrahead
|
|||
|
||||
block content
|
||||
#main-div.panel-group(style={'margin-top':'10px', 'margin-bottom':'10px'})
|
||||
if cameraStyle != 'replay'
|
||||
#instructions.panel.panel-default
|
||||
.panel-heading
|
||||
h4.panel-title
|
||||
a(href="#", data-target="#collapseInstructions", data-toggle="collapse",onclick="setTimeout(onWindowResize,500);") Instructions
|
||||
|
||||
.panel-collapse.collapse.in#collapseInstructions
|
||||
.panel-body
|
||||
p
|
||||
| This is the prototype of a 3D interface. You can move
|
||||
| the camera with the arrow keys of your keyboard (or
|
||||
| WASD if you like FPS-games, and by the way, if you
|
||||
| use azerty keyboard, you can also use ZQSD instead),
|
||||
| and change the angle of the camera by dragging and
|
||||
| dropping the scene around it (you can also use your
|
||||
| numpad, 2 to look lower, 8 to look higher, 4 to look
|
||||
| on the left and 6 to look on the right, but if you're
|
||||
| more comfortable with non-numpad keys, you can also
|
||||
| use i for up, j for left, k for down, and l for
|
||||
| right).
|
||||
|
||||
p
|
||||
| This is a re-creation of the Bob-omb Battlefield
|
||||
| level from Super Mario 64, and with its 8 red coins.
|
||||
| You can click on them to get them, and once you got
|
||||
| them all, you get... well you get nothing but the
|
||||
| sound of the star is played (but the star doesn't
|
||||
| appear... sorry guys)
|
||||
|
||||
p
|
||||
| It contains <em>recommended views</em> : 3D objects
|
||||
| here to guide you through this coin search.
|
||||
|
||||
if cameraStyle == 'arrows'
|
||||
|
||||
p
|
||||
| Recommended views are displayed with a
|
||||
| transparent blue arrow. They disappear when you
|
||||
| come closer to them, and shows the motion between
|
||||
| your current position and the recommendation.
|
||||
|
||||
else if cameraStyle == 'viewports'
|
||||
|
||||
p
|
||||
| Recommended views are displayed with a
|
||||
| transparent red rectangle and some lines.
|
||||
| Basically, it represents the position of a camera
|
||||
| (the point at the extramities of the lines
|
||||
| represents the optical center, and the red
|
||||
| rectangle represents the image plane).
|
||||
|
||||
else if cameraStyle == 'reverse'
|
||||
|
||||
p
|
||||
| Recommended views are displayed with a strange
|
||||
| blue object. Basically, the curve at the
|
||||
| begining of this weird object shows the motion
|
||||
| that starts from where you are and leads to the
|
||||
| recommended view, and the extremity is in fact an
|
||||
| object representing a camera.
|
||||
|
||||
p
|
||||
| You can click on a recommendation to move to the
|
||||
| recommended viewpoint. The recommendation will become
|
||||
| more and more transparent as you come closer, and
|
||||
| will disappear when you reach it.
|
||||
|
||||
p
|
||||
| You may now <a href="#" data-target="#collapseInstructions" data-toggle="collapse" onclick="setTimeout(onWindowResize,500);">hide this panel</a> and start playing !
|
||||
block description
|
||||
|
||||
button#full.btn.btn-primary(style={'margin-right': '10px', 'margin-bottom': '10px'}) Fullscreen
|
||||
button#reset.btn.btn-primary(style={'margin-right': '10px', 'margin-bottom':'10px'}) Reset camera
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
extends ./prototype_interactive
|
||||
|
||||
block title
|
||||
title #{title} - Prototype - Arrows
|
||||
|
||||
block configjs
|
||||
script RecommendedCamera = FixedCamera;
|
||||
|
||||
block preciseDescription
|
||||
p
|
||||
| Recommended views are displayed with a
|
||||
| transparent blue arrow. They disappear when you
|
||||
| come closer to them, and shows the motion between
|
||||
| your current position and the recommendation.
|
|
@ -0,0 +1,51 @@
|
|||
extends ./prototype
|
||||
|
||||
block title
|
||||
title #{title} - Prototype
|
||||
|
||||
block mainjs
|
||||
script(src="/static/js/prototype/main.js")
|
||||
|
||||
block description
|
||||
#instructions.panel.panel-default
|
||||
.panel-heading
|
||||
h4.panel-title
|
||||
a(href="#", data-target="#collapseInstructions", data-toggle="collapse",onclick="setTimeout(onWindowResize,500);") Instructions
|
||||
|
||||
.panel-collapse.collapse.in#collapseInstructions
|
||||
.panel-body
|
||||
p
|
||||
| This is the prototype of a 3D interface. You can move
|
||||
| the camera with the arrow keys of your keyboard (or
|
||||
| WASD if you like FPS-games, and by the way, if you
|
||||
| use azerty keyboard, you can also use ZQSD instead),
|
||||
| and change the angle of the camera by dragging and
|
||||
| dropping the scene around it (you can also use your
|
||||
| numpad, 2 to look lower, 8 to look higher, 4 to look
|
||||
| on the left and 6 to look on the right, but if you're
|
||||
| more comfortable with non-numpad keys, you can also
|
||||
| use i for up, j for left, k for down, and l for
|
||||
| right).
|
||||
|
||||
p
|
||||
| This is a re-creation of the Bob-omb Battlefield
|
||||
| level from Super Mario 64, and with its 8 red coins.
|
||||
| You can click on them to get them, and once you got
|
||||
| them all, you get... well you get nothing but the
|
||||
| sound of the star is played (but the star doesn't
|
||||
| appear... sorry guys)
|
||||
|
||||
p
|
||||
| It contains <em>recommended views</em> : 3D objects
|
||||
| here to guide you through this coin search.
|
||||
|
||||
block preciseDescription
|
||||
|
||||
p
|
||||
| You can click on a recommendation to move to the
|
||||
| recommended viewpoint. The recommendation will become
|
||||
| more and more transparent as you come closer, and
|
||||
| will disappear when you reach it.
|
||||
|
||||
p
|
||||
| You may now <a href="#" data-target="#collapseInstructions" data-toggle="collapse" onclick="setTimeout(onWindowResize,500);">hide this panel</a> and start playing !
|
|
@ -0,0 +1,12 @@
|
|||
extends ./prototype
|
||||
|
||||
block title
|
||||
title #{title} - Prototype - Replay
|
||||
|
||||
block configjs
|
||||
script RecommendedCamera = FixedCamera;
|
||||
script var params = params || {}; params.get = params.get || {}; params.get.id = #{id};
|
||||
script(src="/static/js/ReplayCamera.js")
|
||||
|
||||
block mainjs
|
||||
script(src="/static/js/prototype/replay.js")
|
|
@ -0,0 +1,17 @@
|
|||
extends ./prototype_interactive
|
||||
|
||||
block title
|
||||
title #{title} - Prototype - Reverse
|
||||
|
||||
block configjs
|
||||
script RecommendedCamera = ReverseCamera;
|
||||
|
||||
block preciseDescription
|
||||
p
|
||||
| Recommended views are displayed with a strange
|
||||
| blue object. Basically, the curve at the
|
||||
| begining of this weird object shows the motion
|
||||
| that starts from where you are and leads to the
|
||||
| recommended view, and the extremity is in fact an
|
||||
| object representing a camera.
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
extends ./prototype_interactive
|
||||
|
||||
block title
|
||||
title #{title} - Prototype - Viewports
|
||||
|
||||
block configjs
|
||||
script RecommendedCamera = OldFixedCamera;
|
||||
|
||||
block preciseDescription
|
||||
p
|
||||
| Recommended views are displayed with a
|
||||
| transparent red rectangle and some lines.
|
||||
| Basically, it represents the position of a camera
|
||||
| (the point at the extramities of the lines
|
||||
| represents the optical center, and the red
|
||||
| rectangle represents the image plane).
|
|
@ -5,9 +5,9 @@ block title
|
|||
|
||||
block content
|
||||
h2 Replays available
|
||||
if ids.length == 0
|
||||
if users.length == 0
|
||||
p Sorry, there are no replays available... try later or do an experiment !
|
||||
else
|
||||
ol
|
||||
each elt in ids
|
||||
each elt in users
|
||||
li <a href="/prototype/replay/#{elt.id}">#{elt.name}</a>
|
||||
|
|
Loading…
Reference in New Issue