]> git.example.dev Git - binbsis50.git/commitdiff
refactoring
authorLuigi Pinca <luigipinca@gmail.com>
Sat, 3 Nov 2012 14:29:50 +0000 (15:29 +0100)
committerLuigi Pinca <luigipinca@gmail.com>
Sat, 3 Nov 2012 14:29:50 +0000 (15:29 +0100)
41 files changed:
app.js
lib/captcha.js
lib/match.js
lib/redis-clients.js [new file with mode: 0644]
lib/room.js
lib/stats.js
lib/user.js
lib/utils.js [new file with mode: 0644]
package.json
public/css/bootstrap.min.css [moved from public/static/css/bootstrap.min.css with 99% similarity]
public/css/style.css [moved from public/static/css/style.css with 97% similarity]
public/fonts/comesinhandy-webfont.eot [moved from public/static/css/comesinhandy-webfont.eot with 100% similarity]
public/fonts/comesinhandy-webfont.ttf [moved from public/static/css/comesinhandy-webfont.ttf with 100% similarity]
public/fonts/comesinhandy-webfont.woff [moved from public/static/css/comesinhandy-webfont.woff with 100% similarity]
public/img/bg.jpg [moved from public/static/images/bg.jpg with 100% similarity]
public/img/cassette.png [moved from public/static/images/cassette.png with 100% similarity]
public/img/favicon.ico [moved from public/static/images/favicon.ico with 100% similarity]
public/img/glyphicons-halflings-white.png [moved from public/static/images/glyphicons-halflings-white.png with 100% similarity]
public/img/glyphicons-halflings.png [moved from public/static/images/glyphicons-halflings.png with 100% similarity]
public/img/sprites.png [moved from public/static/images/sprites.png with 100% similarity]
public/js/app.js [moved from public/static/js/room.js with 96% similarity]
public/js/bootstrap.min.js [moved from public/static/js/bootstrap.min.js with 100% similarity]
public/js/home.js [moved from public/static/js/home.js with 97% similarity]
public/js/jquery.jplayer.min.js [moved from public/static/js/jquery.jplayer.min.js with 100% similarity]
public/swf/Jplayer.swf [moved from public/static/swf/Jplayer.swf with 100% similarity]
routes/site.js
routes/user.js
views/changepasswd.jade
views/footer.jade [deleted file]
views/header.jade [deleted file]
views/home.jade [new file with mode: 0644]
views/index.jade [deleted file]
views/layout.jade [new file with mode: 0644]
views/leaderboards.jade
views/login.jade
views/recoverpasswd.jade
views/resetpasswd.jade
views/room.jade
views/signup.jade
views/user.jade
views/uv.jade [deleted file]

diff --git a/app.js b/app.js
index 271c0aabed3d974da5711aa01745f53e8e20d12d..6ca2d835e78ed5a49a599f5441c4e1681b260bdd 100644 (file)
--- a/app.js
+++ b/app.js
@@ -8,70 +8,41 @@ var config = require('./config')
     , parseCookie = require('express/node_modules/cookie').parse
     , parseSignedCookies = require('express/node_modules/connect').utils.parseSignedCookies
     , redisstore = require('connect-redis')(express)
-    , redisurl = require('redis-url')
     , site = require('./routes/site')
-    , user = require('./routes/user');
-
-/**
- * Setting up redis.
- */
-
-var songsdb = redisurl.createClient(process.env.SONGS_DB_URL)
-    , usersdb = redisurl.createClient(process.env.USERS_DB_URL);
-
-songsdb.on('error', function(err) {
-    console.log(err.message);
-});
-
-usersdb.on('error', function(err) {
-    console.log(err.message);
-});
+    , user = require('./routes/user')
+    , usersdb = require('./lib/redis-clients').users;
 
 /**
  * Setting up Express.
  */
 
 var app = express()
-    , sessionstore = new redisstore({client:usersdb});
+    , pub = __dirname + '/public' // Path to public directory
+    , sessionstore = new redisstore({client: usersdb});
 
 // Configuration
-app.use(express.static(__dirname + '/public'), {maxAge: 2592000000});
-app.use(express.favicon(__dirname + '/public/static/images/favicon.ico', {maxAge: 2592000000}));
+app.set('view engine', 'jade');
+app.use(express.compress());
+app.use('/static', express.static(pub, {maxAge: 2419200000})); // 4 weeks = 2419200000 ms
+app.use(express.favicon(pub + '/img/favicon.ico', {maxAge: 2419200000}));
 app.use(express.bodyParser());
 app.use(express.cookieParser(process.env.SITE_SECRET));
-app.use(express.session({store:sessionstore}));
-app.set('view engine', 'jade');
-
-// Middleware to report errors during form submission
-app.use(function(req, res, next) {
-    if (req.session.errors) {
-        res.locals.errors = req.session.errors;
-        delete req.session.errors;
-    }
-    if (req.session.oldvalues) {
-        res.locals.oldvalues = req.session.oldvalues;
-        delete req.session.oldvalues;
-    }
-    next();
-});
+app.use(express.session({store: sessionstore}));
 
 // Routes
-site.use({db:songsdb,rooms:config.rooms});
-user.use({db:usersdb,rooms:config.rooms});
-
-app.get('/', site.index);
+app.get('/', site.home);
 app.get('/artworks', site.artworks);
-app.get('/changepasswd', site.changePasswd);
+app.get('/changepasswd', site.validationErrors, site.changePasswd);
 app.post('/changepasswd', user.validateChangePasswd, user.checkOldPasswd, user.changePasswd);
 app.get('/leaderboards', user.leaderboards);
-app.get('/login', site.login);
+app.get('/login', site.validationErrors, site.login);
 app.post('/login', user.validateLogin, user.checkUser, user.authenticate);
 app.get('/logout', user.logout);
-app.get('/signup', site.signup);
+app.get('/signup', site.validationErrors, site.signup);
 app.post('/signup', user.validateSignUp, user.userExists, user.emailExists, user.createAccount);
-app.get('/recoverpasswd', site.recoverPasswd);
+app.get('/recoverpasswd', site.validationErrors, site.recoverPasswd);
 app.post('/recoverpasswd', user.validateRecoverPasswd, user.sendEmail);
-app.get('/resetpasswd', site.resetPasswd);
+app.get('/resetpasswd', site.validationErrors, site.resetPasswd);
 app.post('/resetpasswd', user.resetPasswd);
 app.get('/:room', site.room);
 app.get('/user/*', user.profile);
@@ -103,7 +74,7 @@ io.set('authorization', function(data, accept) {
     if(!data.headers.cookie) {
         return accept('no cookie transmitted', false);
     }
-    var signedcookie = parseCookie(decodeURIComponent(data.headers.cookie));
+    var signedcookie = parseCookie(data.headers.cookie);
     var cookie = parseSignedCookies(signedcookie, process.env.SITE_SECRET);
     sessionstore.get(cookie['connect.sid'], function(err, session) {
         if (err) {
@@ -157,12 +128,12 @@ io.sockets.on('connection', function(socket) {
     });
     socket.on('joinanonymously', function(nickname, roomname) {
         if (!socket.nickname && typeof nickname === 'string' && nickname !== '' &&
-            config.rooms.indexOf(roomname) !== -1) {
+            ~config.rooms.indexOf(roomname)) {
             rooms[roomname].setNickName(socket, nickname);
         }
     });
     socket.on('joinroom', function(room) {
-        if (session.user && config.rooms.indexOf(room) !== -1) {
+        if (session.user && ~config.rooms.indexOf(room)) {
             if (sockets[session.user]) { // User already in a room
                 socket.emit('alreadyinaroom');
                 return;
@@ -198,17 +169,7 @@ io.sockets.on('connection', function(socket) {
  * Setting up the rooms.
  */
 
-var roomoptions = {
-    songsdb: songsdb,
-    usersdb: usersdb,
-    io: io,
-    sockets: sockets,
-    songsinarun: config.songsinarun,
-    fifolength: config.songsinarun * config.gameswithnorepeats,
-    threshold: config.allowederrors
-};
-
-var Room = require('./lib/room')(roomoptions)
+var Room = require('./lib/room')({io: io, sockets: sockets})
     , rooms = Object.create(null); // The Object that contains all the room instances
 
 for (var i=0; i<config.rooms.length; i++) {
index fcf5f665f45152cf71300938fc7a5bf1e0cb3246..08065e236f7760625404744f234bdb8ef0855e3f 100644 (file)
@@ -6,7 +6,7 @@ var canvas = require('canvas')
     , characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
 
 /**
- * Export the class.
+ * Expose the constructor.
  */
 
 module.exports = function() {
index a827441d5939b1b9b66bf7a6aad307fd1ee38c7e..8fef54a9080b37d33b47d2dd6ab10409e7fe3254 100644 (file)
@@ -1,3 +1,9 @@
+/**
+ * Module dependencies.
+ */
+
+var threshold = require('../config').allowederrors;
+
 /**
  * Check if the edit distance between two strings is smaller than a threshold k.
  * We dont need to trace back the optimal alignment, so we can run the Levenshtein distance 
@@ -46,95 +52,83 @@ var checkDistance = function(s1, s2, k) {
 };
 
 /**
- * Expose `amatch` function.
+ * Expose a function to check if the user answer is acceptable.
  */
 
-module.exports = function(allowederrors) {
-
-    /**
-     * Edit distance threshold.
-     */
-
-    var threshold = allowederrors;
+module.exports = function(subject, guess, enableartistrules) {
+    if (checkDistance(subject, guess, threshold)) {
+        return true;
+    }
 
-    var amatch = function(subject, guess, enableartistrules) {
-        if (checkDistance(subject, guess, threshold)) {
-            return true;
-        }
+    // Ignore dots
+    if (/\./.test(subject) && 
+        checkDistance(subject.replace(/\./g, ''), guess, threshold)) {
+        return true;
+    }
+    // Ignore dashes
+    if (/\-/.test(subject) && 
+        checkDistance(subject.replace(/\-/g, ''), guess, threshold)) {
+        return true;
+    }
+    // Allow to write "and" in place of "+"
+    if (/\+/.test(subject) && 
+        checkDistance(subject.replace(/\+/, 'and'), guess, threshold)) {
+        return true;
+    }
+    // Allow to write "and" in place of " & "
+    if (/ & /.test(subject) && !/\(/.test(subject) &&
+        checkDistance(subject.replace(/ & /, ' and '), guess, threshold)) {
+        return true;
+    }
 
-        // Ignore dots
-        if (/\./.test(subject) && 
-            checkDistance(subject.replace(/\./g, ''), guess, threshold)) {
-            return true;
-        }
-        // Ignore dashes
-        if (/\-/.test(subject) && 
-            checkDistance(subject.replace(/\-/g, ''), guess, threshold)) {
-            return true;
-        }
-        // Allow to write "and" in place of "+"
-        if (/\+/.test(subject) && 
-            checkDistance(subject.replace(/\+/, 'and'), guess, threshold)) {
-            return true;
-        }
-        // Allow to write "and" in place of " & "
-        if (/ & /.test(subject) && !/\(/.test(subject) &&
-            checkDistance(subject.replace(/ & /, ' and '), guess, threshold)) {
-            return true;
+    if (enableartistrules) {
+        // Ignore "the" at the beginning of artist name
+        if (/^the /.test(subject)) {
+            var nothe = subject.replace(/^the /, '');
+            if (checkDistance(nothe, guess, threshold)) {
+                return true;
+            }
+            if (/jimi hendrix experience/.test(nothe) && 
+                checkDistance(nothe.replace(/ experience/, ''), guess, threshold)) {
+                return true;
+            }
         }
-
-        if (enableartistrules) {
-            // Ignore "the" at the beginning of artist name
-            if (/^the /.test(subject)) {
-                var nothe = subject.replace(/^the /, '');
-                if (checkDistance(nothe, guess, threshold)) {
+        // Split artist name on " & " and ", " (artist name can be composed by more names)
+        var splitted = subject.split(/ & |, /);
+        if (splitted.length !== 1) {
+            for (var i=0; i<splitted.length; i++) {
+                if (checkDistance(splitted[i], guess, threshold)) {
                     return true;
                 }
-                if (/jimi hendrix experience/.test(nothe) && 
-                    checkDistance(nothe.replace(/ experience/, ''), guess, threshold)) {
+                if (/^the /.test(splitted[i]) && 
+                    checkDistance(splitted[i].replace(/^the /, ''), guess, threshold)) {
                     return true;
                 }
             }
-            // Split artist name on " & " and ", " (artist name can be composed by more names)
-            var splitted = subject.split(/ & |, /);
-            if (splitted.length !== 1) {
-                for (var i=0; i<splitted.length; i++) {
-                    if (checkDistance(splitted[i], guess, threshold)) {
-                        return true;
-                    }
-                    if (/^the /.test(splitted[i]) && 
-                        checkDistance(splitted[i].replace(/^the /, ''), guess, threshold)) {
-                        return true;
-                    }
-                }
-            }
         }
-        else {
-            // Ignore commas
-            if (/,/.test(subject) && 
-                checkDistance(subject.replace(/,/g, ''), guess, threshold)) {
+    }
+    else {
+        // Ignore commas
+        if (/,/.test(subject) && 
+            checkDistance(subject.replace(/,/g, ''), guess, threshold)) {
+            return true;
+        }
+        // Ignore additional info e.g. "(Love Theme from Titanic)"
+        if (/\(.+\)\??(?: \[.+\])?/.test(subject)) {
+            var normalized = subject.replace(/\(.+\)\??(?: \[.+\])?/, '').trim();
+            if (checkDistance(normalized, guess, threshold)) {
                 return true;
             }
-            // Ignore additional info e.g. "(Love Theme from Titanic)"
-            if (/\(.+\)\??(?: \[.+\])?/.test(subject)) {
-                var normalized = subject.replace(/\(.+\)\??(?: \[.+\])?/, '')
-                                        .replace(/^ +/, '').replace(/ +$/, '');
-                if (checkDistance(normalized, guess, threshold)) {
-                    return true;
-                }
-                if (/ & /.test(normalized) && 
-                    checkDistance(normalized.replace(/ & /, ' and '), guess, threshold)) {
-                    return true;
-                }
-            }
-            if (/, [pP]t\. [0-9]$/.test(subject) && 
-                checkDistance(subject.replace(/, [pP]t\. [0-9]$/, ''), guess, threshold)) {
+            if (/ & /.test(normalized) && 
+                checkDistance(normalized.replace(/ & /, ' and '), guess, threshold)) {
                 return true;
             }
         }
+        if (/, [pP]t\. [0-9]$/.test(subject) && 
+            checkDistance(subject.replace(/, [pP]t\. [0-9]$/, ''), guess, threshold)) {
+            return true;
+        }
+    }
 
-        return false;
-    };
-
-    return amatch;
+    return false;
 };
diff --git a/lib/redis-clients.js b/lib/redis-clients.js
new file mode 100644 (file)
index 0000000..81ccd8a
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * Module dependencies.
+ */
+
+var redisurl = require('redis-url');
+
+/**
+ * Setting up redis clients.
+ */
+
+var songsclient = redisurl.createClient(process.env.SONGS_DB_URL)
+    , usersclient = redisurl.createClient(process.env.USERS_DB_URL);
+
+songsclient.on('error', function(err) {
+    console.log(err.message);
+});
+
+usersclient.on('error', function(err) {
+    console.log(err.message);
+});
+
+/**
+ * Expose the clients
+ */
+
+exports.songs = songsclient;
+exports.users = usersclient;
index da3861921f1a41ee0f91873c6583f639aa345695..ef606a441f34e26eef65338584c082ac17ec1209 100644 (file)
 /**
- * Expose the `Room` class.
+ * Module dependencies.
  */
 
-module.exports = function(params) {
-
-    /**
-     * Room dependencies.
-     */
-
-    var amatch = require('./match')(params.threshold)
-        , collectStats = require('./stats')(params.usersdb)
-        , fifolength = params.fifolength
-        , io = params.io
-        , sockets = params.sockets
-        , songsdb = params.songsdb
-        , songsinarun = params.songsinarun
-        , usersdb = params.usersdb;
-
-    /**
-     * Room class.
-     */
-
-    function Room(roomname) {
-
-        var allowedguess = false
-            , artist // Artists in lowercase
-            , artistName
-            , artworkUrl
-            , collectionName
-            , feat // Featured artists
-            , finishline = 1
-            , playedtracks = [] // The list of already played songs
-            , previewUrl
-            , songcounter = 0
-            , songtimeleft // Milliseconds
-            , status
-            , title // Title in lowercase
-            , trackName
-            , trackscount = 0
-            , trackViewUrl
-            , totusers = 0
-            , usersData = Object.create(null);
-
-        // User points and statistics
-        var addPointsAndStats = function(nickname, allinone) {
-            usersData[nickname].guesstime = 30000 - songtimeleft;
-            var stats = {};
-            switch (finishline) {
-                case 1:
-                    finishline++;
-                    usersData[nickname].roundpoints = 6;
-                    if (allinone) {
-                        usersData[nickname].points += 6;
-                        stats.points = 6;
-                    }
-                    else {
-                        usersData[nickname].points += 5;
-                        stats.points = 5;
-                    }
-                    usersData[nickname].golds++;
-                    stats.gold = true;
-                    break;
-                case 2:
-                    finishline++;
-                    usersData[nickname].roundpoints = 5;
-                    if (allinone) {
-                        usersData[nickname].points += 5;
-                        stats.points = 5;
-                    }
-                    else {
-                        usersData[nickname].points += 4;
-                        stats.points = 4;
-                    }
-                    usersData[nickname].silvers++;
-                    stats.silver = true;
-                    break;
-                case 3:
-                    finishline++;
-                    usersData[nickname].roundpoints = 4;
-                    if (allinone) {
-                        usersData[nickname].points += 4;
-                        stats.points = 4;
-                    }
-                    else {
-                        usersData[nickname].points += 3;
-                        stats.points = 3;
-                    }
-                    usersData[nickname].bronzes++;
-                    stats.bronze = true;
-                    break;
-                default:
-                    usersData[nickname].roundpoints = 3;
-                    if (allinone) {
-                        usersData[nickname].points += 3;
-                        stats.points = 3;
-                    }
-                    else {
-                        usersData[nickname].points += 2;
-                        stats.points = 2;
-                    }
-            }
-            usersData[nickname].matched = 'both';
-            usersData[nickname].guessed++;
-            usersData[nickname].totguesstime += usersData[nickname].guesstime;
-
-            if (usersData[nickname].registered) {
-                stats.userscore = usersData[nickname].points;
-                stats.guesstime = usersData[nickname].guesstime;
-                collectStats(nickname, stats);
-            }
-        };
-
-        // Add a new user in the room
-        var addUser = function(socket, loggedin) {
-            sockets[socket.nickname] = socket;
-            usersData[socket.nickname] = {
-                nickname: socket.nickname,
-                registered: loggedin,
-                points: 0,
-                roundpoints: 0,
-                matched: null,
-                guessed: 0,
-                guesstime: null,
-                totguesstime: 0,
-                golds: 0,
-                silvers: 0,
-                bronzes: 0
-            };
-            totusers++;
-            // Broadcast new user event
-            io.sockets.emit('updateoverview', roomname, totusers);
-            socket.emit('ready', usersData, trackscount, loggedin);
-            socket.broadcast.to(roomname).emit('newuser', socket.nickname, usersData);
-        };
-
-        var gameOver = function() {
-            status = 3; // Game over
+var amatch = require('./match')
+    , clients = require('./redis-clients')
+    , collectStats = require('./stats')
+    , config = require('../config')
+    , fifolength = config.songsinarun * config.gameswithnorepeats
+    , io
+    , sockets
+    , songsdb = clients.songs
+    , usersdb = clients.users;
 
-            // Build podium
-            var users = [];
-            for (var key in usersData) {
-                users.push(usersData[key]);
-            }
-            users.sort(function(a, b) {return b.points - a.points;});
-            var podium = users.slice(0,3);
-            io.sockets.in(roomname).emit('gameover', podium);
-
-            // Collect podium stats
-            if (podium[0] && podium[0].registered) {
-                collectStats(podium[0].nickname, {firstplace:true});
-            }
-            if (podium[1] && podium[1].registered) {
-                collectStats(podium[1].nickname, {secondplace:true});
-            }
-            if (podium[2] && podium[2].registered) {
-                collectStats(podium[2].nickname, {thirdplace:true});
-            }
+/**
+ * Expose the constructor.
+ */
 
-            resetPoints(false);
-            songcounter = 0;
-            // Check if FIFO is full
-            if (playedtracks.length === fifolength) {
-                playedtracks.splice(0, songsinarun);
-            }
+module.exports = function(options) {
+    io = options.io;
+    sockets = options.sockets;
+    return Room;
+};
 
-            // Start a new game
-            setTimeout(sendLoadTrack, 5000);
-        };
+/**
+ * Room constructor.
+ */
 
-        // Return the number of users in the room
-        this.getPopulation = function() {
-            return totusers;
+function Room(roomname) {
+
+    var allowedguess = false
+        , artist // Artists in lowercase
+        , artistName
+        , artworkUrl
+        , collectionName
+        , feat // Featured artists
+        , finishline = 1
+        , playedtracks = [] // The list of already played songs
+        , previewUrl
+        , songcounter = 0
+        , songtimeleft // Milliseconds
+        , status
+        , title // Title in lowercase
+        , trackName
+        , trackscount = 0
+        , trackViewUrl
+        , totusers = 0
+        , usersData = Object.create(null);
+
+    // User points and statistics
+    var addPointsAndStats = function(nickname, allinone) {
+        usersData[nickname].guesstime = 30000 - songtimeleft;
+        var stats = {};
+        switch (finishline) {
+            case 1:
+                finishline++;
+                usersData[nickname].roundpoints = 6;
+                if (allinone) {
+                    usersData[nickname].points += 6;
+                    stats.points = 6;
+                }
+                else {
+                    usersData[nickname].points += 5;
+                    stats.points = 5;
+                }
+                usersData[nickname].golds++;
+                stats.gold = true;
+                break;
+            case 2:
+                finishline++;
+                usersData[nickname].roundpoints = 5;
+                if (allinone) {
+                    usersData[nickname].points += 5;
+                    stats.points = 5;
+                }
+                else {
+                    usersData[nickname].points += 4;
+                    stats.points = 4;
+                }
+                usersData[nickname].silvers++;
+                stats.silver = true;
+                break;
+            case 3:
+                finishline++;
+                usersData[nickname].roundpoints = 4;
+                if (allinone) {
+                    usersData[nickname].points += 4;
+                    stats.points = 4;
+                }
+                else {
+                    usersData[nickname].points += 3;
+                    stats.points = 3;
+                }
+                usersData[nickname].bronzes++;
+                stats.bronze = true;
+                break;
+            default:
+                usersData[nickname].roundpoints = 3;
+                if (allinone) {
+                    usersData[nickname].points += 3;
+                    stats.points = 3;
+                }
+                else {
+                    usersData[nickname].points += 2;
+                    stats.points = 2;
+                }
+        }
+        usersData[nickname].matched = 'both';
+        usersData[nickname].guessed++;
+        usersData[nickname].totguesstime += usersData[nickname].guesstime;
+
+        if (usersData[nickname].registered) {
+            stats.userscore = usersData[nickname].points;
+            stats.guesstime = usersData[nickname].guesstime;
+            collectStats(nickname, stats);
+        }
+    };
+
+    // Add a new user in the room
+    var addUser = function(socket, loggedin) {
+        sockets[socket.nickname] = socket;
+        usersData[socket.nickname] = {
+            nickname: socket.nickname,
+            registered: loggedin,
+            points: 0,
+            roundpoints: 0,
+            matched: null,
+            guessed: 0,
+            guesstime: null,
+            totguesstime: 0,
+            golds: 0,
+            silvers: 0,
+            bronzes: 0
         };
-
-        // A user is sending a guess
-        this.guess = function(socket, guess) {
-            if (allowedguess) {
-                if (!usersData[socket.nickname].matched) { // No track no artist
-                    if ((artist === title) && amatch(title, guess, true)) {
-                        addPointsAndStats(socket.nickname, true);
-                        socket.emit('bothmatched');
-                        io.sockets.in(roomname).emit('updateusers', usersData);
+        totusers++;
+        // Broadcast new user event
+        io.sockets.emit('updateoverview', roomname, totusers);
+        socket.emit('ready', usersData, trackscount, loggedin);
+        socket.broadcast.to(roomname).emit('newuser', socket.nickname, usersData);
+    };
+
+    var gameOver = function() {
+        status = 3; // Game over
+
+        // Build podium
+        var users = [];
+        for (var key in usersData) {
+            users.push(usersData[key]);
+        }
+        users.sort(function(a, b) {return b.points - a.points;});
+        var podium = users.slice(0,3);
+        io.sockets.in(roomname).emit('gameover', podium);
+
+        // Collect podium stats
+        if (podium[0] && podium[0].registered) {
+            collectStats(podium[0].nickname, {firstplace:true});
+        }
+        if (podium[1] && podium[1].registered) {
+            collectStats(podium[1].nickname, {secondplace:true});
+        }
+        if (podium[2] && podium[2].registered) {
+            collectStats(podium[2].nickname, {thirdplace:true});
+        }
+
+        resetPoints(false);
+        songcounter = 0;
+        // Check if FIFO is full
+        if (playedtracks.length === fifolength) {
+            playedtracks.splice(0, config.songsinarun);
+        }
+
+        // Start a new game
+        setTimeout(sendLoadTrack, 5000);
+    };
+
+    // Return the number of users in the room
+    this.getPopulation = function() {
+        return totusers;
+    };
+
+    // A user is sending a guess
+    this.guess = function(socket, guess) {
+        if (allowedguess) {
+            if (!usersData[socket.nickname].matched) { // No track no artist
+                if ((artist === title) && amatch(title, guess, true)) {
+                    addPointsAndStats(socket.nickname, true);
+                    socket.emit('bothmatched');
+                    io.sockets.in(roomname).emit('updateusers', usersData);
+                }
+                else if (amatch(artist, guess, true) || (feat && amatch(feat, guess, true))) {
+                    usersData[socket.nickname].roundpoints++;
+                    usersData[socket.nickname].points++;
+                    usersData[socket.nickname].matched = 'artist';
+                    socket.emit('artistmatched');
+                    io.sockets.in(roomname).emit('updateusers', usersData);
+                    if (usersData[socket.nickname].registered) {
+                        var stats = {points:1,userscore:usersData[socket.nickname].points};
+                        collectStats(socket.nickname, stats);
                     }
-                    else if (amatch(artist, guess, true) || (feat && amatch(feat, guess, true))) {
-                        usersData[socket.nickname].roundpoints++;
-                        usersData[socket.nickname].points++;
-                        usersData[socket.nickname].matched = 'artist';
-                        socket.emit('artistmatched');
-                        io.sockets.in(roomname).emit('updateusers', usersData);
-                        if (usersData[socket.nickname].registered) {
-                            var stats = {points:1,userscore:usersData[socket.nickname].points};
-                            collectStats(socket.nickname, stats);
-                        }
+                }
+                else if (amatch(title, guess)) {
+                    usersData[socket.nickname].roundpoints++;
+                    usersData[socket.nickname].points++;
+                    usersData[socket.nickname].matched = 'title';
+                    socket.emit('titlematched');
+                    io.sockets.in(roomname).emit('updateusers', usersData);
+                    if (usersData[socket.nickname].registered) {
+                        var stats = {points:1,userscore:usersData[socket.nickname].points};
+                        collectStats(socket.nickname, stats);
                     }
-                    else if (amatch(title, guess)) {
-                        usersData[socket.nickname].roundpoints++;
-                        usersData[socket.nickname].points++;
-                        usersData[socket.nickname].matched = 'title';
-                        socket.emit('titlematched');
+                }
+                else {
+                    socket.emit('nomatch');
+                }
+            }
+            else if (usersData[socket.nickname].matched !== 'both') { // Track or artist
+                if (usersData[socket.nickname].matched === 'artist') {
+                    if (amatch(title, guess)) {
+                        addPointsAndStats(socket.nickname, false);
+                        socket.emit('bothmatched');
                         io.sockets.in(roomname).emit('updateusers', usersData);
-                        if (usersData[socket.nickname].registered) {
-                            var stats = {points:1,userscore:usersData[socket.nickname].points};
-                            collectStats(socket.nickname, stats);
-                        }
                     }
                     else {
                         socket.emit('nomatch');
                     }
                 }
-                else if (usersData[socket.nickname].matched !== 'both') { // Track or artist
-                    if (usersData[socket.nickname].matched === 'artist') {
-                        if (amatch(title, guess)) {
-                            addPointsAndStats(socket.nickname, false);
-                            socket.emit('bothmatched');
-                            io.sockets.in(roomname).emit('updateusers', usersData);
-                        }
-                        else {
-                            socket.emit('nomatch');
-                        }
+                else {
+                    if (amatch(artist, guess, true) || (feat && amatch(feat, guess, true))) {
+                        addPointsAndStats(socket.nickname, false);
+                        socket.emit('bothmatched');
+                        io.sockets.in(roomname).emit('updateusers', usersData);
                     }
                     else {
-                        if (amatch(artist, guess, true) || (feat && amatch(feat, guess, true))) {
-                            addPointsAndStats(socket.nickname, false);
-                            socket.emit('bothmatched');
-                            io.sockets.in(roomname).emit('updateusers', usersData);
-                        }
-                        else {
-                            socket.emit('nomatch');
-                        }
-                    }
-                }
-                else { // The user has guessed both track and artist
-                    socket.emit('stoptrying');
-                }
-            }
-            else {
-                socket.emit('noguesstime');
-            }
-        };
-
-        this.ignore = function(baduser, executor, callback) {
-            // Check if the player to be ignored is in the room
-            if (usersData[baduser]) {
-                // Inform the bad player that he/she is being ignored
-                var recipient = sockets[baduser];
-                recipient.emit('chatmsg', executor+' is ignoring you.', 'binb', baduser);
-                return callback(baduser);
-            }
-            callback(false);
-        };
-
-        this.joinRoom = function(socket) {
-            socket.roomname = roomname;
-            socket.join(roomname);
-            addUser(socket, true);
-        };
-
-        // Kick a user
-        this.kick = function(baduser, executor, callback) {
-            usersdb.hget('user:'+executor, 'role', function (err, role) {
-                if (role > 0) { // Check role
-                    if (usersData[baduser]) {
-                        var notice = 'you have been kicked by '+executor+'.';
-                        var recipient = sockets[baduser];
-                        recipient.emit('chatmsg', notice, 'binb', baduser);
-                        recipient.disconnect();
+                        socket.emit('nomatch');
                     }
-                    return;
-                }
-                callback();
-            });
-        };
-
-        // A user has left (DCed, etc.)
-        this.removeUser = function(nickname) {
-            // Delete the references
-            delete sockets[nickname];
-            delete usersData[nickname];
-            totusers--;
-            // Broadcast the event
-            io.sockets.emit('updateoverview', roomname, totusers);
-            io.sockets.in(roomname).emit('userleft', nickname, usersData);
-        };
-
-        var resetPoints = function(roundonly) {
-            for (var key in usersData) {
-                if (!roundonly) {
-                    usersData[key].points = 0;
-                    usersData[key].guessed = 0;
-                    usersData[key].totguesstime = 0;
-                    usersData[key].golds = 0;
-                    usersData[key].silvers = 0;
-                    usersData[key].bronzes = 0;
-                }
-                usersData[key].roundpoints = 0;
-                usersData[key].matched = null;
-                usersData[key].guesstime = null;
-            }
-        };
-
-        // A user is sending a chat message
-        this.sendChatMessage = function(msg, socket, to) {
-            if (typeof to === 'string') {
-                // Check if the recipient is in the room
-                if (usersData[to]) {
-                    socket.emit('chatmsg', msg, socket.nickname, to);
-                    var recipient = sockets[to];
-                    recipient.emit('chatmsg', msg, socket.nickname, to);
                 }
-                return;
             }
-            // Censor answers from chat
-            var msglcase = msg.toLowerCase();
-            if (allowedguess && (amatch(artist, msglcase, true) ||
-                    (feat && amatch(feat, msglcase, true)) || amatch(title, msglcase))) {
-                var notice = 'You are probably right, but you have to use the box above.';
-                socket.emit('chatmsg', notice, 'binb', socket.nickname);
-                return;
+            else { // The user has guessed both track and artist
+                socket.emit('stoptrying');
             }
-            io.sockets.in(roomname).emit('chatmsg', msg, socket.nickname);
-        };
-
-        // Extract a random track from the database and send the load event
-        var sendLoadTrack = function() {
-            songsdb.srandmember(roomname, function(err, res) {
-                // Check if extracted track is in the list of already played tracks
-                if (playedtracks.indexOf(res) !== -1) {
-                    return sendLoadTrack();
+        }
+        else {
+            socket.emit('noguesstime');
+        }
+    };
+
+    this.ignore = function(baduser, executor, callback) {
+        // Check if the player to be ignored is in the room
+        if (usersData[baduser]) {
+            // Inform the bad player that he/she is being ignored
+            var recipient = sockets[baduser];
+            recipient.emit('chatmsg', executor+' is ignoring you.', 'binb', baduser);
+            return callback(baduser);
+        }
+        callback(false);
+    };
+
+    this.joinRoom = function(socket) {
+        socket.roomname = roomname;
+        socket.join(roomname);
+        addUser(socket, true);
+    };
+
+    // Kick a user
+    this.kick = function(baduser, executor, callback) {
+        usersdb.hget('user:'+executor, 'role', function (err, role) {
+            if (role > 0) { // Check role
+                if (usersData[baduser]) {
+                    var notice = 'you have been kicked by '+executor+'.';
+                    var recipient = sockets[baduser];
+                    recipient.emit('chatmsg', notice, 'binb', baduser);
+                    recipient.disconnect();
                 }
-                playedtracks.push(res);
-                songsdb.hmget('song:'+res, 'artistName', 'trackName', 'collectionName',
-                        'previewUrl', 'artworkUrl60', 'trackViewUrl', function(e, replies) {
-                    artistName = replies[0];
-                    artist = artistName.toLowerCase();
-                    trackName = replies[1];
-                    title = trackName.toLowerCase();
-                    feat = /feat\. (.+?)[)\]]/.test(title) ? RegExp.$1 : null;
-                    collectionName = replies[2];
-                    previewUrl = replies[3];
-                    artworkUrl = replies[4];
-                    trackViewUrl = replies[5];
-                    io.sockets.in(roomname).emit('loadtrack', previewUrl);
-                    setTimeout(sendPlayTrack, 5000);
-                });
-            });
-            status = 1; // Loading next song
-        };
-
-        var sendPlayTrack = function() {
-            songcounter++;
-            status = 0; // Playing track
-            var data = {
-                counter: songcounter,
-                tot: songsinarun,
-                users: usersData
-            };
-            io.sockets.in(roomname).emit('playtrack', data);
-            songTimeLeft(Date.now() + 30000, 50);
-            allowedguess = true;
-            setTimeout(sendTrackInfo, 30000);
-        };
-
-        // Send the room status
-        this.sendStatus = function(callback) {
-            var data = {
-                status: status,
-                timeleft: songtimeleft,
-                previewUrl: previewUrl
-            };
-            callback(data);
-        };
-
-        var sendTrackInfo = function() {
-            var trackinfo = {
-                artworkUrl: artworkUrl,
-                artistName: artistName,
-                trackName: trackName,
-                trackViewUrl: trackViewUrl,
-                collectionName: collectionName
-            };
-            io.sockets.in(roomname).emit('trackinfo', trackinfo);
-            finishline = 1;
-            allowedguess = false;
-
-            if (songcounter < songsinarun) {
-                resetPoints(true);
-                sendLoadTrack();
                 return;
             }
-
-            status = 2; // Sending last track info
-            setTimeout(gameOver, 5000);
-        };
-
-        // A user is submitting a name
-        this.setNickName = function(socket, nickname) {
-            var feedback = null;
-
-            if (nickname.length > 15) {
-                feedback = '<span class="label label-important">That name is too long.</span>';
-            }
-            else if (nickname === 'binb') {
-                feedback = '<span class="label label-important">That name is reserved.</span>';
+            callback();
+        });
+    };
+
+    // A user has left (DCed, etc.)
+    this.removeUser = function(nickname) {
+        // Delete the references
+        delete sockets[nickname];
+        delete usersData[nickname];
+        totusers--;
+        // Broadcast the event
+        io.sockets.emit('updateoverview', roomname, totusers);
+        io.sockets.in(roomname).emit('userleft', nickname, usersData);
+    };
+
+    var resetPoints = function(roundonly) {
+        for (var key in usersData) {
+            if (!roundonly) {
+                usersData[key].points = 0;
+                usersData[key].guessed = 0;
+                usersData[key].totguesstime = 0;
+                usersData[key].golds = 0;
+                usersData[key].silvers = 0;
+                usersData[key].bronzes = 0;
             }
-            else if (sockets[nickname]) {
-                feedback = '<span class="label label-important">Name already taken.</span>';
+            usersData[key].roundpoints = 0;
+            usersData[key].matched = null;
+            usersData[key].guesstime = null;
+        }
+    };
+
+    // A user is sending a chat message
+    this.sendChatMessage = function(msg, socket, to) {
+        if (typeof to === 'string') {
+            // Check if the recipient is in the room
+            if (usersData[to]) {
+                socket.emit('chatmsg', msg, socket.nickname, to);
+                var recipient = sockets[to];
+                recipient.emit('chatmsg', msg, socket.nickname, to);
             }
-
-            if (feedback) {
-                return socket.emit('invalidnickname', feedback);
+            return;
+        }
+        // Censor answers from chat
+        var msglcase = msg.toLowerCase();
+        if (allowedguess && (amatch(artist, msglcase, true) ||
+                (feat && amatch(feat, msglcase, true)) || amatch(title, msglcase))) {
+            var notice = 'You are probably right, but you have to use the box above.';
+            socket.emit('chatmsg', notice, 'binb', socket.nickname);
+            return;
+        }
+        io.sockets.in(roomname).emit('chatmsg', msg, socket.nickname);
+    };
+
+    // Extract a random track from the database and send the load event
+    var sendLoadTrack = function() {
+        songsdb.srandmember(roomname, function(err, res) {
+            // Check if extracted track is in the list of already played tracks
+            if (~playedtracks.indexOf(res)) {
+                return sendLoadTrack();
             }
-
-            // Check if requested nickname belong to a registered user
-            var key = 'user:'+nickname;
-            usersdb.exists(key, function(err, resp) {
-                if (resp === 1) {
-                    feedback = '<span class="label label-important">That name belongs ';
-                    feedback += 'to a registered user.</span>';
-                    return socket.emit('invalidnickname', feedback);
-                }
-                socket.nickname = nickname;
-                socket.roomname = roomname;
-                socket.join(roomname);
-                addUser(socket, false);
+            playedtracks.push(res);
+            songsdb.hmget('song:'+res, 'artistName', 'trackName', 'collectionName',
+                    'previewUrl', 'artworkUrl60', 'trackViewUrl', function(e, replies) {
+                artistName = replies[0];
+                artist = artistName.toLowerCase();
+                trackName = replies[1];
+                title = trackName.toLowerCase();
+                feat = /feat\. (.+?)[)\]]/.test(title) ? RegExp.$1 : null;
+                collectionName = replies[2];
+                previewUrl = replies[3];
+                artworkUrl = replies[4];
+                trackViewUrl = replies[5];
+                io.sockets.in(roomname).emit('loadtrack', previewUrl);
+                setTimeout(sendPlayTrack, 5000);
             });
+        });
+        status = 1; // Loading next song
+    };
+
+    var sendPlayTrack = function() {
+        songcounter++;
+        status = 0; // Playing track
+        var data = {
+            counter: songcounter,
+            tot: config.songsinarun,
+            users: usersData
         };
-
-        // Timer for the playing song
-        var songTimeLeft = function(end, delay) {
-            songtimeleft = end - Date.now();
-            if (songtimeleft < delay) {
-                return;
-            }
-            setTimeout(songTimeLeft, delay, end, delay);
+        io.sockets.in(roomname).emit('playtrack', data);
+        songTimeLeft(Date.now() + 30000, 50);
+        allowedguess = true;
+        setTimeout(sendTrackInfo, 30000);
+    };
+
+    // Send the room status
+    this.sendStatus = function(callback) {
+        var data = {
+            status: status,
+            timeleft: songtimeleft,
+            previewUrl: previewUrl
         };
-
-        // Start the room
-        this.start = function() {
-            songsdb.scard(roomname, function(err, res) {
-                trackscount = res;
-            });
-            sendLoadTrack();
+        callback(data);
+    };
+
+    var sendTrackInfo = function() {
+        var trackinfo = {
+            artworkUrl: artworkUrl,
+            artistName: artistName,
+            trackName: trackName,
+            trackViewUrl: trackViewUrl,
+            collectionName: collectionName
         };
+        io.sockets.in(roomname).emit('trackinfo', trackinfo);
+        finishline = 1;
+        allowedguess = false;
 
-        this.unignore = function(baduser, executor) {
-            if (usersData[baduser]) {
-                // Inform the bad player that he/she is no longer ignored
-                var notice = executor+' has stopped ignoring you.';
-                var recipient = sockets[baduser];
-                recipient.emit('chatmsg', notice, 'binb', baduser);
+        if (songcounter < config.songsinarun) {
+            resetPoints(true);
+            sendLoadTrack();
+            return;
+        }
+
+        status = 2; // Sending last track info
+        setTimeout(gameOver, 5000);
+    };
+
+    // A user is submitting a name
+    this.setNickName = function(socket, nickname) {
+        var feedback = null;
+
+        if (nickname.length > 15) {
+            feedback = '<span class="label label-important">That name is too long.</span>';
+        }
+        else if (nickname === 'binb') {
+            feedback = '<span class="label label-important">That name is reserved.</span>';
+        }
+        else if (sockets[nickname]) {
+            feedback = '<span class="label label-important">Name already taken.</span>';
+        }
+
+        if (feedback) {
+            return socket.emit('invalidnickname', feedback);
+        }
+
+        // Check if requested nickname belong to a registered user
+        var key = 'user:'+nickname;
+        usersdb.exists(key, function(err, resp) {
+            if (resp === 1) {
+                feedback = '<span class="label label-important">That name belongs ';
+                feedback += 'to a registered user.</span>';
+                return socket.emit('invalidnickname', feedback);
             }
-        };
-    }
-
-    return Room;
-};
+            socket.nickname = nickname;
+            socket.roomname = roomname;
+            socket.join(roomname);
+            addUser(socket, false);
+        });
+    };
+
+    // Timer for the playing song
+    var songTimeLeft = function(end, delay) {
+        songtimeleft = end - Date.now();
+        if (songtimeleft < delay) {
+            return;
+        }
+        setTimeout(songTimeLeft, delay, end, delay);
+    };
+
+    // Start the room
+    this.start = function() {
+        songsdb.scard(roomname, function(err, res) {
+            trackscount = res;
+        });
+        sendLoadTrack();
+    };
+
+    this.unignore = function(baduser, executor) {
+        if (usersData[baduser]) {
+            // Inform the bad player that he/she is no longer ignored
+            var notice = executor+' has stopped ignoring you.';
+            var recipient = sockets[baduser];
+            recipient.emit('chatmsg', notice, 'binb', baduser);
+        }
+    };
+}
index a4020057e0c748a1c9fe4a0664dd3512c29f7c3d..b4c4ee85784bd7f3c32a9f89be5602c9d4f38afd 100644 (file)
@@ -1,64 +1,65 @@
 /**
- * Return `collectStats` function.
+ * Module dependencies.
  */
 
-module.exports = function(db) {
+var db = require('./redis-clients').users;
 
-    var collectStats = function(username, stats) {
-        var key = 'user:'+username;
-        if (stats.points) {
-            // Update total points
-            db.hincrby(key, 'totpoints', stats.points);
-            // Update the score of the member in the sorted set
-            db.zincrby('users', stats.points, username);
-        }
-        if (stats.userscore) {
-            // Set personal best
-            db.hget(key, 'bestscore', function(err, res) {
-                if (res < stats.userscore) {
-                    db.hset(key, 'bestscore', stats.userscore);
-                }
-            });
-        }
-        if (stats.gold) {
-            // Update the number of golds
-            db.hincrby(key, 'golds', 1);
-        }
-        if (stats.silver) {
-            db.hincrby(key, 'silvers', 1);
-        }
-        if (stats.bronze) {
-            db.hincrby(key, 'bronzes', 1);
-        }
-        if (stats.guesstime) {
-            // Update the number of guessed tracks
-            db.hincrby(key, 'guessed', 1);
-            // Update total guess time
-            db.hincrby(key, 'totguesstime', stats.guesstime);
-            // Set best answer time
-            db.hget(key, 'bestguesstime', function(err, res) {
-                if (stats.guesstime < res) {
-                    db.hset(key, 'bestguesstime', stats.guesstime);
-                }
-            });
-            // Set worst answer time
-            db.hget(key, 'worstguesstime', function(err, res) {
-                if (stats.guesstime > res) {
-                    db.hset(key, 'worstguesstime', stats.guesstime);
-                }
-            });
-        }
-        if (stats.firstplace) {
-            // Update the number of first places
-            db.hincrby(key, 'victories', 1);
-        }
-        if (stats.secondplace) {
-            db.hincrby(key, 'secondplaces', 1);
-        }
-        if (stats.thirdplace) {
-            db.hincrby(key, 'thirdplaces', 1);
-        }
-    };
+/**
+ * Expose a function to collect user statistics.
+ */
 
-    return collectStats;
+module.exports = function(username, stats) {
+    var key = 'user:'+username;
+    if (stats.points) {
+        // Update total points
+        db.hincrby(key, 'totpoints', stats.points);
+        // Update the score of the member in the sorted set
+        db.zincrby('users', stats.points, username);
+    }
+    if (stats.userscore) {
+        // Set personal best
+        db.hget(key, 'bestscore', function(err, res) {
+            if (res < stats.userscore) {
+                db.hset(key, 'bestscore', stats.userscore);
+            }
+        });
+    }
+    if (stats.gold) {
+        // Update the number of golds
+        db.hincrby(key, 'golds', 1);
+    }
+    if (stats.silver) {
+        db.hincrby(key, 'silvers', 1);
+    }
+    if (stats.bronze) {
+        db.hincrby(key, 'bronzes', 1);
+    }
+    if (stats.guesstime) {
+        // Update the number of guessed tracks
+        db.hincrby(key, 'guessed', 1);
+        // Update total guess time
+        db.hincrby(key, 'totguesstime', stats.guesstime);
+        // Set best answer time
+        db.hget(key, 'bestguesstime', function(err, res) {
+            if (stats.guesstime < res) {
+                db.hset(key, 'bestguesstime', stats.guesstime);
+            }
+        });
+        // Set worst answer time
+        db.hget(key, 'worstguesstime', function(err, res) {
+            if (stats.guesstime > res) {
+                db.hset(key, 'worstguesstime', stats.guesstime);
+            }
+        });
+    }
+    if (stats.firstplace) {
+        // Update the number of first places
+        db.hincrby(key, 'victories', 1);
+    }
+    if (stats.secondplace) {
+        db.hincrby(key, 'secondplaces', 1);
+    }
+    if (stats.thirdplace) {
+        db.hincrby(key, 'thirdplaces', 1);
+    }
 };
index 3b88b5f66c39dd83b809bad80919ec3dab6cdc83..675c76e6ae93213cb70a5aa17b5fdb923c74bd0f 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Export the class.
+ * Expose the constructor.
  */
 
 module.exports = function(username, email, salt, hash, joindate) {
diff --git a/lib/utils.js b/lib/utils.js
new file mode 100644 (file)
index 0000000..84b1127
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * Get a random slogan.
+ */
+
+exports.randomSlogan = function() {
+       var slogans = [
+        'guess the song.'
+        , 'name that tune.'
+        , 'i know this track.'
+    ];
+       return slogans[Math.floor(Math.random() * slogans.length)];
+};
+
+/**
+ * Check if the provided string is a valid email address.
+ */
+
+exports.isEmail = function(str) {
+       // Simple filter, but it covers most of the use cases.
+       var filter = /^[+a-zA-Z0-9_.\-]+@([a-zA-Z0-9\-]+\.)+[a-zA-Z0-9]{2,6}$/;
+       return filter.test(str);
+};
+
+/**
+ * Helper function used to build leaderboards.
+ * Rearrange database results in an object.
+ */
+
+exports.buildLeaderboards = function(pointsresults, timesresults) {
+    var obj = {
+        pointsleaderboard: [],
+        timesleaderboard: []
+    };
+    for (var i=0; i<pointsresults.length; i+=2) {
+        obj.pointsleaderboard.push({
+            username: pointsresults[i],
+            totpoints: pointsresults[i+1]
+        });
+        obj.timesleaderboard.push({
+            username: timesresults[i],
+            bestguesstime: (timesresults[i+1] / 1000).toFixed(2)
+        });
+    }
+    return obj;
+};
index 013168eaef63da871b7aea35972576db3dad8af0..d5b31574bed765a7d99ffbe5a9d8a0bde081873f 100644 (file)
@@ -21,5 +21,5 @@
     "start": "app.js"
   },
   "subdomain": "binb",
-  "version": "0.3.4-3"
+  "version": "0.3.4-6"
 }
\ No newline at end of file
similarity index 99%
rename from public/static/css/bootstrap.min.css
rename to public/css/bootstrap.min.css
index c0afd92e38b94e7b09db540ff69eef4823b78d83..38226a8c52b74e6ade393b7f07b0f65794c1274a 100644 (file)
@@ -368,8 +368,8 @@ button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-
 .btn-link,.btn-link:active{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
 .btn-link{border-color:transparent;cursor:pointer;color:#0088cc;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
 .btn-link:hover{color:#005580;text-decoration:underline;background-color:transparent;}
-[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../images/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat;margin-top:1px;}
-.icon-white,.nav>.active>a>[class^="icon-"],.nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"]{background-image:url("../images/glyphicons-halflings-white.png");}
+[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat;margin-top:1px;}
+.icon-white,.nav>.active>a>[class^="icon-"],.nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png");}
 .icon-glass{background-position:0 0;}
 .icon-music{background-position:-24px 0;}
 .icon-search{background-position:-48px 0;}
similarity index 97%
rename from public/static/css/style.css
rename to public/css/style.css
index ac8e655f300281f7c4337ccf2f50c1d1ff680eaf..be5ead87ab8e2fcd30f3ded30547ab3bec3253ed 100644 (file)
@@ -1,14 +1,14 @@
 @font-face {
     font-family: 'ChristopherhandRegular';
-    src: url('comesinhandy-webfont.eot');
-    src: url('comesinhandy-webfont.eot?#iefix') format('embedded-opentype'),
-         url('comesinhandy-webfont.woff') format('woff'),
-         url('comesinhandy-webfont.ttf') format('truetype');
+    src: url('/static/fonts/comesinhandy-webfont.eot');
+    src: url('/static/fonts/comesinhandy-webfont.eot?#iefix') format('embedded-opentype'),
+         url('/static/fonts/comesinhandy-webfont.woff') format('woff'),
+         url('/static/fonts/comesinhandy-webfont.ttf') format('truetype');
     font-weight: normal;
     font-style: normal;
 }
 body {
-    background: url('/static/images/bg.jpg') repeat-x scroll 0 0 #F5F6F7;
+    background: url('/static/img/bg.jpg') repeat-x scroll 0 0 #F5F6F7;
     padding-top: 45px;
 }
 section {
@@ -44,7 +44,7 @@ h6 {
     text-transform: uppercase;
 }
 .icons {
-    background: url('/static/images/sprites.png') no-repeat;
+    background: url('/static/img/sprites.png') no-repeat;
 }
 .align-left {
     text-align: left;
@@ -279,7 +279,7 @@ form .clearfix {
 #cassette {
     margin-top: 22px;
     height: 137px;
-    background: url('/static/images/cassette.png') no-repeat 0 0;
+    background: url('/static/img/cassette.png') no-repeat 0 0;
 }
 #countdown {
     position: absolute;
similarity index 96%
rename from public/static/js/room.js
rename to public/js/app.js
index e18b6bce8c5244c64b1a2bd2aa20f8c83764fb7d..526814a4436dd28417c91c66a092135596c493e6 100644 (file)
@@ -1,5 +1,5 @@
 (function() {
-
+    
     var elapsedtime = 0
         , DOM = {}
         , historycursor = 0
         , pvtmsgto
         , subscriber = false
         , roundpoints = 0
+        , roomname = window.location.pathname.replace('/', '')
         , socket
         , stopanimation = false
         , touchplay
-        , urlregex = /(https?:\/\/[\-A-Za-z0-9+&@#\/%?=~_()|!:,.;]*[\-A-Za-z0-9+&@#\/%=~_()|])/;
+        , urlregex = /(https?:\/\/[\-A-Za-z0-9+&@#\/%?=~_()|!:,.;]*[\-A-Za-z0-9+&@#\/%=~_()|])/
+        , uri = window.location.protocol+'//'+window.location.host; // Socket.IO server URI
 
     var amstrings = [
         'Yes, that\'s the artist. What about the title?'
         updateUsers(usersData);
     };
 
-    // Set up the room.
-    $(function() {
-        setVariables();
-        DOM.modal.modal({keyboard:false, show:false, backdrop:'static'});
-        DOM.togglechat.click(hideChat);
-        if ($.browser.mozilla) {
-            // Block ESC button in firefox (breaks socket connections).
-            $(document).keypress(function(event) {
-                if(event.keyCode === 27) {
-                    return false;
-                }
-            });
-        }
-        var uri = window.location.protocol+'//'+window.location.host;
-        socket = io.connect(uri, {'reconnect':false});
-        socket.on('connect', function() {
-            jplayer = $('#player').jPlayer({
-                ready: jplayerReady,
-                swfPath: '/static/swf/',
-                supplied: 'm4a',
-                preload: 'auto',
-                volume: 1
-            });
-            socket.on('alreadyinaroom', alreadyInARoom);
-            socket.on('disconnect', disconnect);
-            socket.on('invalidnickname', invalidNickName);
-            socket.on('ready', ready);
-            socket.on('updateoverview', updateRoomsOverview);
-            socket.emit('getoverview', roomsOverview);
+    // Set up the app.
+    setVariables();
+    DOM.modal.modal({keyboard:false, show:false, backdrop:'static'});
+    DOM.togglechat.click(hideChat);
+    if ($.browser.mozilla) {
+        // Block ESC button in firefox (breaks socket connections).
+        $(document).keypress(function(event) {
+            if(event.keyCode === 27) {
+                return false;
+            }
+        });
+    }
+    socket = io.connect(uri, {'reconnect':false});
+    socket.on('connect', function() {
+        jplayer = $('#player').jPlayer({
+            ready: jplayerReady,
+            swfPath: '/static/swf/',
+            supplied: 'm4a',
+            preload: 'auto',
+            volume: 1
         });
+        socket.on('alreadyinaroom', alreadyInARoom);
+        socket.on('disconnect', disconnect);
+        socket.on('invalidnickname', invalidNickName);
+        socket.on('ready', ready);
+        socket.on('updateoverview', updateRoomsOverview);
+        socket.emit('getoverview', roomsOverview);
     });
 
 })();
similarity index 97%
rename from public/static/js/home.js
rename to public/js/home.js
index f23c6204f6f8e4cbbe05261264dd7a1eaf5a3c0e..5c0ec62ea0332b2fed57cc35fc2a3e6eeb496e7e 100644 (file)
@@ -1,4 +1,4 @@
-$(function() {
+(function() {
     if ($.browser.mozilla) {
         // Block ESC button in firefox (breaks socket connections).
         $(document).keypress(function(event) {
@@ -28,4 +28,4 @@ $(function() {
             $('#'+room).text(players);
         });
     });
-});
+})();
index 19abf3dd22bf893152400014a5677afebbe99488..d690964a6065e885fe4a65de0f48776c5c40f202 100644 (file)
@@ -4,11 +4,12 @@
 
 var async = require('async')
     , Captcha = require('../lib/captcha')
-    , db
-    , rooms;
+    , db = require('../lib/redis-clients').songs
+    , randomSlogan = require('../lib/utils').randomSlogan
+    , rooms = require('../config').rooms;
 
 /**
- * Generate a task for async.
+ * Generate a task.
  */
 
 var task = function(genre) {
@@ -19,15 +20,6 @@ var task = function(genre) {
     };
 };
 
-/**
- * Initialize dependencies.
- */
-
-exports.use = function(options) {
-    db = options.db;
-    rooms = options.rooms;
-};
-
 /**
  * Extract at random in each room, some album covers and return the result as a JSON.
  */
@@ -52,38 +44,75 @@ exports.changePasswd = function(req, res) {
     if (!req.session.user) {
         return res.redirect('/login?followup=/changepasswd');
     }
-    res.render('changepasswd', {followup:req.query.followup,loggedin:req.session.user});
+    res.render('changepasswd', {
+        followup: req.query.followup || '/',
+        loggedin: req.session.user,
+        slogan: randomSlogan()
+    });
 };
 
-exports.index = function(req, res) {
-    res.render('index', {loggedin:req.session.user,rooms:rooms});
+exports.home = function(req, res) {
+    res.render('home', {
+        loggedin: req.session.user,
+        rooms: rooms,
+        slogan: randomSlogan()
+    });
 };
 
 exports.login = function(req, res) {
-    res.render('login', {followup:req.query.followup});
+    res.render('login', {
+        followup: req.query.followup || '/',
+        slogan: randomSlogan()
+    });
 };
 
 exports.recoverPasswd = function(req, res) {
     var captcha = new Captcha();
     req.session.captchacode = captcha.getCode();
-    res.render('recoverpasswd', {captchaurl:captcha.toDataURL(),followup:req.query.followup});
+    res.render('recoverpasswd', {
+        captchaurl: captcha.toDataURL(),
+        followup: req.query.followup || '/',
+        slogan: randomSlogan()
+    });
 };
 
 exports.resetPasswd = function(req, res) {
-    res.render('resetpasswd', {token:req.query.token});
+    res.render('resetpasswd', {
+        slogan: randomSlogan(),
+        token: req.query.token || ''
+    });
 };
 
 exports.room = function(req, res) {
-    if (rooms.indexOf(req.params.room) !== -1) {
-        res.render('room', {loggedin:req.session.user,roomname:req.params.room,rooms:rooms});
-    }
-    else {
-        res.send(404);
+    if (~rooms.indexOf(req.params.room)) {
+        return res.render('room', {
+            loggedin: req.session.user,
+            roomname: req.params.room,
+            rooms: rooms,
+            slogan: randomSlogan()
+        });
     }
+    res.send(404);
 };
 
 exports.signup = function(req, res) {
     var captcha = new Captcha();
     req.session.captchacode = captcha.getCode();
-    res.render('signup', {captchaurl:captcha.toDataURL(),followup:req.query.followup});
+    res.render('signup', {
+        captchaurl: captcha.toDataURL(),
+        followup: req.query.followup || '/',
+        slogan: randomSlogan()
+    });
+};
+
+/**
+ * Report errors during form submission.
+ */
+
+exports.validationErrors = function(req, res, next) {
+    res.locals.errors = req.session.errors;
+    res.locals.oldvalues = req.session.oldvalues;
+    delete req.session.errors;
+    delete req.session.oldvalues;
+    next();
 };
index 2ec5df6317bc24b44508f5a713ca73c07af44818..38bf82aed833f163c06d6a6f45bafa43c85f5337 100644 (file)
@@ -3,88 +3,20 @@
  */
 
 var crypto = require('crypto')
-    , db
-    , followupurls = []
+    , db = require('../lib/redis-clients').users
     , mailer = require('../lib/email/mailer')
-    , User = require('../lib/user');
-    
-/**
- * Extend String with custom methods for input validation.
- */
-
-String.prototype.trim = function() {
-    return this.replace(/^[\r\n\t\s]+|[\r\n\t\s]+$/g, '');
-};
-
-String.prototype.isEmail = function() {
-    return this.match(/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/);
-};
-
-/**
- * Check if a URL is in the whitelist of follow-up URLs.
- */
-
-var safeFollowup = function(url) {
-    if (followupurls.indexOf(url) !== -1) {
-        return true;
-    }
-    return false;
-};
+    , rooms = require('../config').rooms
+    , User = require('../lib/user')
+    , utils = require('../lib/utils');
 
 /**
- * Parameters to get users ordered by best guess time.
+ * Populate the whitelist of follow-up URLs.
  */
 
-var sortparams = [
-    'users'
-    , 'by'
-    , 'user:*->bestguesstime'
-    , 'get'
-    , '#'
-    , 'get'
-    , 'user:*->bestguesstime'
-    , 'limit'
-    , '0'
-    , '30'
-];
-
-/**
- * Helper function used to build leaderboards.
- * Rearrange database results in an object.
- */
-
-var buildLeaderboards = function(pointsresults, timesresults) {
-    var obj = {
-        pointsleaderboard: [],
-        timesleaderboard: []
-    };
-    for (var i=0; i<pointsresults.length; i+=2) {
-        obj.pointsleaderboard.push({
-            username: pointsresults[i],
-            totpoints: pointsresults[i+1]
-        });
-        obj.timesleaderboard.push({
-            username: timesresults[i],
-            bestguesstime: (timesresults[i+1] / 1000).toFixed(2)
-        });
-    }
-    return obj;
-};
-
-/**
- * Initialize dependencies.
- */
-
-exports.use = function(options) {
-    db = options.db;
-    var rooms = options.rooms;
-    // Populate the whitelist of follow-up URLs
-    followupurls.push('/');
-    followupurls.push('/changepasswd');
-    for (var i=0; i<rooms.length; i++) {
-        followupurls.push('/'+rooms[i]);
-    }
-};
+var safeurls = ['/', '/changepasswd'];
+for (var i=0; i<rooms.length; i++) {
+    safeurls.push('/'+rooms[i]);
+}
 
 /**
  * Show two lists of users, one ordered by points and one by best guess time (limit set to 30).
@@ -92,8 +24,21 @@ exports.use = function(options) {
 
 exports.leaderboards = function(req, res) {
     db.zrevrange('users', 0, 29, 'withscores', function(err, pointsresults) {
+        var sortparams = [
+            'users'
+            , 'by'
+            , 'user:*->bestguesstime'
+            , 'get'
+            , '#'
+            , 'get'
+            , 'user:*->bestguesstime'
+            , 'limit'
+            , '0'
+            , '30'
+        ];
         db.sort(sortparams, function (e, timesresults) {
-            var leaderboards = buildLeaderboards(pointsresults, timesresults);
+            var leaderboards = utils.buildLeaderboards(pointsresults, timesresults);
+            res.locals.slogan = utils.randomSlogan();
             res.render('leaderboards', leaderboards);
         });
     });
@@ -143,7 +88,7 @@ exports.checkOldPasswd = function(req, res, next) {
 };
 
 exports.changePasswd = function(req, res) {
-    var followup = (safeFollowup(req.query.followup)) ? req.query.followup : '/'
+    var followup = ~safeurls.indexOf(req.query.followup) ? req.query.followup : '/'
         , user = req.session.user
         , key = 'user:'+user
         , salt = crypto.randomBytes(6).toString('base64')
@@ -203,7 +148,7 @@ exports.authenticate = function(req, res) {
     db.hmget(key, 'salt', 'password', function(err, data) {
         var hash = crypto.createHash('sha256').update(data[0]+req.body.password).digest('hex');
         if (hash === data[1]) {
-            var followup = (safeFollowup(req.query.followup)) ? req.query.followup : '/';
+            var followup = ~safeurls.indexOf(req.query.followup) ? req.query.followup : '/';
             // Authentication succeeded, regenerate the session
             req.session.regenerate(function() {
                 req.session.cookie.maxAge = 604800000; // One week
@@ -247,7 +192,7 @@ exports.validateSignUp = function(req, res, next) {
     else if (!req.body.username.match(/^[^\x00-\x1F\x7F]{1,15}$/)) {
         errors.username = '1 to 15 characters required';
     }
-    if (!req.body.email.isEmail()) {
+    if (!utils.isEmail(req.body.email)) {
         errors.email = 'is not an email address';
     }
     if (!req.body.password.match(/^[A-Za-z0-9]{6,15}$/)) {
@@ -320,8 +265,11 @@ exports.createAccount = function(req, res) {
     db.sadd('emails', req.body.email);
     // Delete old fields values
     delete req.session.oldvalues;
-    var msg = 'You successfully created your account. You are now ready to login.';
-    res.render('login', {followup:req.query.followup,success:msg});
+    res.render('login', {
+        followup: req.query.followup || '/',
+        slogan: utils.randomSlogan(),
+        success: 'You successfully created your account. You are now ready to login.'
+    });
 };
 
 /**
@@ -335,7 +283,7 @@ exports.validateRecoverPasswd = function(req, res, next) {
 
     var errors = {};
     
-    if (!req.body.email.isEmail()) {
+    if (!utils.isEmail(req.body.email)) {
         errors.email = 'is not an email address';
     }
     if (req.body.captcha !== req.session.captchacode) {
@@ -363,12 +311,16 @@ exports.sendEmail = function(req, res) {
             db.setex('token:'+token, 14400, data, function(err, reply) {
                 mailer.sendEmail(req.body.email, token, function(err, response) {
                     if (err) {
-                        console.log('reset password error: '+err.message);
+                        console.log('error sending email: '+err.message);
                     }
                 });
             });
             delete req.session.oldvalues;
-            return res.render('recoverpasswd', {followup:req.query.followup,success:true});
+            return res.render('recoverpasswd', {
+                followup: req.query.followup || '/',
+                slogan: utils.randomSlogan(),
+                success: true
+            });
         }
         req.session.errors = {alert: 'The email address you specified could not be found'};
         res.redirect(req.url);
@@ -409,7 +361,11 @@ exports.resetPasswd = function(req, res) {
             var salt = crypto.randomBytes(6).toString('base64');
             var password = crypto.createHash('sha256').update(salt+req.body.password).digest('hex');
             db.hmset(user, 'salt', salt, 'password', password, function(err, data) {
-                res.render('login', {success:'You can now login with your new password.'});
+                res.render('login', {
+                    followup: '/',
+                    slogan: utils.randomSlogan(),
+                    success: 'You can now login with your new password.'
+                });
             });
             return;
         }
@@ -436,6 +392,7 @@ exports.profile = function(req, res) {
                 delete obj.password;
                 delete obj.salt;
                 delete obj.totguesstime;
+                res.locals.slogan = utils.randomSlogan();
                 res.render('user', obj);
             });
             return;
index 8f60a5c93a8d889bca99f9b4b6030fe0463e3ddb..fac6e99631984ac281d49bb39663d6be06605848 100644 (file)
@@ -1,72 +1,65 @@
-followup = (typeof(followup) !== "undefined") ? '?followup='+followup : '?followup=/'
-doctype html
-html
-    include header
-        title binb :: Change password
-        script(src="/static/js/bootstrap.min.js")
-    body
-        include uv.jade
-        .navbar.navbar-inverse.navbar-fixed-top
-            .navbar-inner
-                .container
-                    a.brand(href="/")
-                        .icons.logo #{motto}
-                    ul.nav.pull-right
-                        li
-                            a(href="/") Home
-                        li.dropdown
-                            a.dropdown-toggle(data-toggle="dropdown",
-                                href="#") Logged in as #{loggedin.replace(/&/g, '&amp;')} 
-                                span.caret
-                            ul.dropdown-menu
-                                li
-                                    a(href="/user/#{encodeURIComponent(loggedin)}",
-                                        target="_blank") Profile
-                                li
-                                    a(href="/logout") Logout
-        .container
-            section
-                .row
-                    .span12.offset2
-                        form.form-horizontal.well(method="post",action="/changepasswd#{followup}")
-                            fieldset
-                                if (typeof(errors) !== "undefined")
-                                    if (typeof(errors.oldpassword) !== "undefined")
-                                        .control-group.error
-                                            label.control-label(for="oldpassword") Old password
-                                            .controls
-                                                input#oldpassword(type="password",name="oldpassword")
-                                                span.help-inline #{errors.oldpassword}
-                                    else
-                                        .control-group
-                                            label.control-label(for="oldpassword") Old password
-                                            .controls
-                                                input#username(type="password",name="oldpassword",
-                                                    placeholder="enter your current password...")
-                                    if (typeof(errors.newpassword) !== 'undefined')
-                                        .control-group.error
-                                            label.control-label(for="newpassword") New password
-                                            .controls
-                                                input#password(type="password",name="newpassword")
-                                                span.help-inline #{errors.newpassword}
-                                    else
-                                        .control-group
-                                            label.control-label(for="newpassword") New password
-                                            .controls
-                                                input#password(type="password",name="newpassword",
-                                                    placeholder="enter your new password...")
-                                else
-                                    .control-group
-                                        label.control-label(for="oldpassword") Old password
-                                        .controls
-                                            input#username(type="password",name="oldpassword",
-                                                placeholder="enter your current password...")
-                                    .control-group
-                                        label.control-label(for="password") New password
-                                        .controls
-                                            input#password(type="password",name="newpassword",
-                                                placeholder="enter your new password...")
-                                button.submit-button.btn.btn-primary(type="submit")
-                                    i.icon-edit.icon-white
-                                    |  Update
-            include footer
+extends layout
+
+block title
+    title binb :: Change password
+
+block nav
+    ul.nav.pull-right
+        li
+            a(href="/") Home
+        li.dropdown
+            a.dropdown-toggle(data-toggle="dropdown", href="#")
+                | Logged in as #{loggedin.replace(/&/g, '&amp;')} 
+                span.caret
+            ul.dropdown-menu
+                li
+                    a(href="/user/#{encodeURIComponent(loggedin)}", target="_blank") Profile
+                li
+                    a(href="/logout") Logout
+
+block sections
+    section
+        .row
+            .span12.offset2
+                form.form-horizontal.well(method="post",
+                    action="/changepasswd?followup=#{followup}")
+                    fieldset
+                        - if (locals.errors)
+                            - if (errors.oldpassword)
+                                .control-group.error
+                                    label.control-label(for="oldpassword") Old password
+                                    .controls
+                                        input#oldpassword(type="password", name="oldpassword")
+                                        span.help-inline #{errors.oldpassword}
+                            - else
+                                .control-group
+                                    label.control-label(for="oldpassword") Old password
+                                    .controls
+                                        input#username(type="password", name="oldpassword",
+                                            placeholder="enter your current password...")
+                            - if (errors.newpassword)
+                                .control-group.error
+                                    label.control-label(for="newpassword") New password
+                                    .controls
+                                        input#password(type="password", name="newpassword")
+                                        span.help-inline #{errors.newpassword}
+                            - else
+                                .control-group
+                                    label.control-label(for="newpassword") New password
+                                    .controls
+                                        input#password(type="password", name="newpassword",
+                                            placeholder="enter your new password...")
+                        - else
+                            .control-group
+                                label.control-label(for="oldpassword") Old password
+                                .controls
+                                    input#username(type="password", name="oldpassword",
+                                        placeholder="enter your current password...")
+                            .control-group
+                                label.control-label(for="password") New password
+                                .controls
+                                    input#password(type="password", name="newpassword",
+                                        placeholder="enter your new password...")
+                        button.submit-button.btn.btn-primary(type="submit")
+                            i.icon-edit.icon-white
+                            |  Update
diff --git a/views/footer.jade b/views/footer.jade
deleted file mode 100644 (file)
index b49d4c2..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-footer
-    #footer-inner
-        #copy &copy; 2012 Luigi Pinca
-        iframe#facebook-button(allowTransparency="true", frameborder="0",
-            scrolling="no", src="//www.facebook.com/plugins/like.php?href=http%3A%2F%2Fbinb.nodejitsu.com&amp;send=false&amp;layout=button_count&amp;show_faces=false&amp;action=like&amp;colorscheme=light&amp;locale=en_US")
-        iframe#twitter-button(allowtransparency="true", frameborder="0",
-            scrolling="no", src="//platform.twitter.com/widgets/tweet_button.html?url=http%3A%2F%2Fbinb.nodejitsu.com")
-        iframe#github-button(allowtransparency="true", frameborder="0", scrolling="0", 
-            src="http://ghbtns.com/github-btn.html?user=lpinca&repo=binb&type=watch&count=true")
-        span.footer-info . Optimized for Google Chrome.
-        a#nodejitsu-logo.icons(target="_blank", href="http://nodejitsu.com/")
-        span.footer-info Powered by 
diff --git a/views/header.jade b/views/header.jade
deleted file mode 100644 (file)
index 75762e3..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-mottos = ['guess the song.', 'name that tune.', 'i know this track.']
-motto = mottos[Math.floor(Math.random()*mottos.length)]
-head
-    link(href="/static/css/bootstrap.min.css", rel="stylesheet")
-    link(href="/static/css/style.css", rel="stylesheet")
-    meta(charset="UTF-8")
-    meta(name="keywords", content="iTunes, music, quiz, binb, beatquest, realtime, multiplayer, listening, game")
-    meta(name="description", content="Simple, realtime, multiplayer, competitive music listening game. Guess the song and prove your music knowledge!")
-    meta(name="author", content="Luigi Pinca")
-    script(src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js")
-    script
-        var _gaq = _gaq || [];
-        _gaq.push(['_setAccount', 'UA-29865853-1']);
-        _gaq.push(['_trackPageview']);
-        (function() {
-            var ga = document.createElement('script');
-            ga.type = 'text/javascript'; ga.async = true;
-            ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') +
-                '.google-analytics.com/ga.js';
-            var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
-        })();
diff --git a/views/home.jade b/views/home.jade
new file mode 100644 (file)
index 0000000..1a061fd
--- /dev/null
@@ -0,0 +1,61 @@
+extends layout
+
+block title
+    title binb
+
+block nav
+    ul.nav.pull-right
+        li.active
+            a(href="/") Home
+        li
+            a(target="_blank", href="/leaderboards")
+                i.icon-list-alt.icon-white
+                |  Leaderboards
+        - if (locals.loggedin)
+            li.dropdown
+                a.dropdown-toggle(data-toggle="dropdown", href="#")
+                    | Logged in as #{loggedin.replace(/&/g, '&amp;')} 
+                    span.caret
+                ul.dropdown-menu
+                    li
+                        a(href="/user/#{encodeURIComponent(loggedin)}", target="_blank") Profile
+                    li
+                        a(href="/changepasswd") Change password
+                    li
+                        a(href="/logout") Logout
+        - else
+            li
+                a(href="/signup") Sign up
+            li
+                a(href="/login") Login
+
+block sections
+    section
+        .row
+            .span7
+                h3 What's this?
+                p binb is a realtime, multiplayer, competitive music listening game.
+            .span9
+                h3 How to play?
+                p All you have to do is to guess the song that is playing. A fixed number 
+                    | of songs will run and for each one correctly guessed you will earn an 
+                    | amount of points. That amount depends on the number of correct guesses 
+                    | (artist and/or title of the song) and on how fast you will be on 
+                    | answering compared to other players. At the end a scoreboard will 
+                    | report the best three players of the match. If you have read this 
+                    | far, what are you waiting? Click on a room below and prove your 
+                    | music knowledge!
+    section
+        .row
+            .span16
+                ul.thumbnails
+                    - each item in rooms
+                        li.span4
+                            a.thumbnail.relative(href=item)
+                                .room #{item} - 
+                                    span(id=item)
+                                    |  Players
+
+append scripts    
+    script(src="/socket.io/socket.io.js")
+    script(src="/static/js/home.js")
diff --git a/views/index.jade b/views/index.jade
deleted file mode 100644 (file)
index fe16563..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-doctype html
-html
-    include header
-        title binb
-        script(src="/socket.io/socket.io.js")
-        script(src="/static/js/bootstrap.min.js")
-        script(src="/static/js/home.js")
-    body
-        include uv.jade
-        .navbar.navbar-inverse.navbar-fixed-top
-            .navbar-inner
-                .container
-                    a.brand(href="/")
-                        .icons.logo #{motto}
-                    ul.nav.pull-right
-                        li.active
-                            a(href="/") Home
-                        li
-                            a(target="_blank", href="/leaderboards")
-                                i.icon-list-alt.icon-white
-                                |  Leaderboards
-                        if (typeof(loggedin) !== "undefined")
-                            li.dropdown
-                                a.dropdown-toggle(data-toggle="dropdown",
-                                    href="#") Logged in as #{loggedin.replace(/&/g, '&amp;')} 
-                                    span.caret
-                                ul.dropdown-menu
-                                    li
-                                        a(href="/user/#{encodeURIComponent(loggedin)}",
-                                            target="_blank") Profile
-                                    li
-                                        a(href="/changepasswd") Change password
-                                    li
-                                        a(href="/logout") Logout
-                        else
-                            li
-                                a(href="/signup") Sign up
-                            li
-                                a(href="/login") Login
-        .container
-            section
-                .row
-                    .span7
-                        h3 What's this?
-                        p binb is a realtime, multiplayer, competitive music listening game.
-                    .span9
-                        h3 How to play?
-                        p All you have to do is to guess the song that is playing. A fixed number 
-                            | of songs will run and for each one correctly guessed you will earn an 
-                            | amount of points. That amount depends on the number of correct guesses 
-                            | (artist and/or title of the song) and on how fast you will be on 
-                            | answering compared to other players. At the end a scoreboard will 
-                            | report the best three players of the match. If you have read this 
-                            | far, what are you waiting? Click on a room below and prove your 
-                            | music knowledge!
-            section
-                .row
-                    .span16
-                        ul.thumbnails
-                            each item in rooms
-                                li.span4
-                                    a.thumbnail.relative(href=item)
-                                        .room #{item} - 
-                                            span(id=item)
-                                            |  Players
-            include footer
diff --git a/views/layout.jade b/views/layout.jade
new file mode 100644 (file)
index 0000000..07126dd
--- /dev/null
@@ -0,0 +1,57 @@
+doctype html
+html
+    head
+        meta(charset="utf-8")
+        block title
+        meta(name="author", content="Luigi Pinca")
+        meta(name="description", content="Simple, realtime, multiplayer, competitive music listening game. Guess the song and prove your music knowledge!")
+        link(href="/static/css/bootstrap.min.css", rel="stylesheet")
+        link(href="/static/css/style.css", rel="stylesheet")
+        script
+            var _gaq = _gaq || [];
+            _gaq.push(['_setAccount', 'UA-29865853-1']);
+            _gaq.push(['_trackPageview']);
+            (function() {
+                var ga = document.createElement('script');
+                ga.type = 'text/javascript'; ga.async = true;
+                ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') +
+                    '.google-analytics.com/ga.js';
+                var s = document.getElementsByTagName('script')[0];
+                s.parentNode.insertBefore(ga, s);
+            })();
+    body
+        .navbar.navbar-inverse.navbar-fixed-top
+            .navbar-inner
+                .container
+                    block brand
+                        a.brand(href="/")
+                            .icons.logo #{slogan}
+                    block nav
+        .container
+            block sections
+            footer
+                #footer-inner
+                    #copy &copy; 2012 Luigi Pinca
+                    iframe#facebook-button(allowTransparency="true", frameborder="0", scrolling="no",
+                        src="//www.facebook.com/plugins/like.php?href=http%3A%2F%2Fbinb.nodejitsu.com&amp;send=false&amp;layout=button_count&amp;show_faces=false&amp;action=like&amp;colorscheme=light&amp;locale=en_US")
+                    iframe#twitter-button(allowtransparency="true", frameborder="0", scrolling="no",
+                        src="//platform.twitter.com/widgets/tweet_button.html?url=http%3A%2F%2Fbinb.nodejitsu.com")
+                    iframe#github-button(allowtransparency="true", frameborder="0", scrolling="0", 
+                        src="http://ghbtns.com/github-btn.html?user=lpinca&repo=binb&type=watch&count=true")
+                    span.footer-info . Optimized for Google Chrome.
+                    a#nodejitsu-logo.icons(target="_blank", href="http://nodejitsu.com/")
+                    span.footer-info Powered by 
+        block media
+        block scripts
+            script(src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js")
+            script(src="/static/js/bootstrap.min.js")
+        script
+            var uvOptions = {};
+            (function() {
+                var uv = document.createElement('script');
+                uv.type = 'text/javascript'; uv.async = true;
+                uv.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 
+                    'widget.uservoice.com/LSMjFAQRifhD6BjOG2KWw.js';
+                var s = document.getElementsByTagName('script')[0];
+                s.parentNode.insertBefore(uv, s);
+            })();
index b4a6a6d55eac1d1ebc7690f54dd869b6c5385ee2..800a64c9be7934d967179e3ec8200e2904c3e889 100644 (file)
@@ -1,46 +1,45 @@
-doctype html
-html
-    include header
-        title binb :: Leaderboards
-    body
-        include uv.jade
-        .navbar.navbar-inverse.navbar-fixed-top
-            .navbar-inner
-                .container
-                    a.brand(href="#")
-                        .icons.logo #{motto}
-        .container
-            section
-                .row
-                    .span7.offset1
-                        .highscores High Scores
-                            .icons.img
-            section
-                .row
-                    .span7.offset1
-                        h4 Points
-                        div.leaderboard-wrapper
-                            table.table.table-striped.table-bordered.leaderboard
-                                tbody
-                                each user, i in pointsleaderboard
-                                    tr
-                                        td #{i+1}
-                                        td
-                                            a(href="/user/#{encodeURIComponent(user.username)}")
-                                                | #{user.username.replace(/&/g, '&amp;')}
-                                        td #{user.totpoints}
-                    .span7
-                        h4 Times
-                        div.leaderboard-wrapper
-                            table.table.table-striped.table-bordered.leaderboard
-                                tbody
-                                each user, i in timesleaderboard
-                                    tr
-                                        td #{i+1}
-                                        td
-                                            a(href="/user/#{encodeURIComponent(user.username)}")
-                                                | #{user.username.replace(/&/g, '&amp;')}
-                                        td 
-                                            i.icon-time
-                                            |  #{user.bestguesstime} sec
-            include footer
+extends layout
+
+block title
+    title binb :: Leaderboards
+
+block brand
+    a.brand(href="#")
+        .icons.logo #{slogan}
+
+block sections
+    section
+        .row
+            .span7.offset1
+                .highscores High Scores
+                    .icons.img
+    section
+        .row
+            .span7.offset1
+                h4 Points
+                div.leaderboard-wrapper
+                    table.table.table-striped.table-bordered.leaderboard
+                        tbody
+                        - each user, i in pointsleaderboard
+                            tr
+                                td #{i+1}
+                                td
+                                    a(href="/user/#{encodeURIComponent(user.username)}")
+                                        | #{user.username.replace(/&/g, '&amp;')}
+                                td #{user.totpoints}
+            .span7
+                h4 Times
+                div.leaderboard-wrapper
+                    table.table.table-striped.table-bordered.leaderboard
+                        tbody
+                        - each user, i in timesleaderboard
+                            tr
+                                td #{i+1}
+                                td
+                                    a(href="/user/#{encodeURIComponent(user.username)}")
+                                        | #{user.username.replace(/&/g, '&amp;')}
+                                td 
+                                    i.icon-time
+                                    |  #{user.bestguesstime} sec
+
+block scripts
index 23e52da40f2afba6ce79509905a9882904028d0c..ea3184fe1e91714f1aa516517daecd9fb415c4ad 100644 (file)
@@ -1,82 +1,75 @@
-followup = (typeof(followup) !== "undefined") ? '?followup='+followup : '?followup=/'
-doctype html
-html
-    include header
-        title binb :: login
-        script(src="/static/js/bootstrap.min.js")
-    body
-        include uv.jade
-        .navbar.navbar-inverse.navbar-fixed-top
-            .navbar-inner
-                .container
-                    a.brand(href="/")
-                        .icons.logo #{motto}
-                    ul.nav.pull-right
-                        li
-                            a(href="/") Home
-                        li
-                            a(href="/signup#{followup}") Sign up
-                        li.active
-                            a(href="/login#{followup}") Login
-        .container
-            section
-                .row
-                    .span3
-                        h3 New user?
-                        a(href="/signup#{followup}") Click here to create an account.
-                    .span13
-                        if ((typeof(errors) !== "undefined") && (typeof(errors.alert) !== "undefined"))
-                            .alert.alert-error
-                                a.close(data-dismiss="alert") &times;
-                                strong Oh snap!
-                                |  #{errors.alert}
-                        else if (typeof(success) !== "undefined")
-                            .alert.alert-success
-                                a.close(data-dismiss="alert") &times;
-                                strong Well done!
-                                |  #{success}
-                        form.form-horizontal.well(method="post",action="/login#{followup}")
-                            fieldset
-                                if (typeof(errors) !== "undefined")
-                                    if (typeof(errors.username) !== "undefined")
-                                        .control-group.error
-                                            label.control-label(for="username") Name
-                                            .controls
-                                                input#username(type="text",name="username",
-                                                    value=oldvalues.username)
-                                                span.help-inline #{errors.username}
-                                    else
-                                        .control-group
-                                            label.control-label(for="username") Name
-                                            .controls
-                                                input#username(type="text",name="username",
-                                                    value=oldvalues.username)
-                                    if (typeof(errors.password) !== 'undefined')
-                                        .control-group.error
-                                            label.control-label(for="password") Password
-                                            .controls
-                                                input#password(type="password",name="password")
-                                                span.help-inline #{errors.password}
-                                    else
-                                        .control-group
-                                            label.control-label(for="password") Password
-                                            .controls
-                                                input#password(type="password",name="password",
-                                                    placeholder="enter your password...")
-                                else
-                                    .control-group
-                                        label.control-label(for="username") Name
-                                        .controls
-                                            input#username(type="text",name="username",
-                                                placeholder="enter your nickname...")
-                                    .control-group
-                                        label.control-label(for="password") Password
-                                        .controls
-                                            input#password(type="password",name="password",
-                                                placeholder="enter your password...")
-                                button.submit-button.btn.btn-primary(type="submit")
-                                    i.icon-lock.icon-white
-                                    |  Login
-                                a.forgot-passwd(href="/recoverpasswd#{followup}")
-                                    | Forgot your password?
-            include footer
+extends layout
+
+block title
+    title binb :: login
+        
+block nav
+    ul.nav.pull-right
+        li
+            a(href="/") Home
+        li
+            a(href="/signup?followup=#{followup}") Sign up
+        li.active
+            a(href="/login?followup=#{followup}") Login
+
+block sections
+    section
+        .row
+            .span3
+                h3 New user?
+                a(href="/signup?followup=#{followup}") Click here to create an account.
+            .span13
+                - if (locals.errors && errors.alert)
+                    .alert.alert-error
+                        a.close(data-dismiss="alert") &times;
+                        strong Oh snap!
+                        |  #{errors.alert}
+                - else if (locals.success)
+                    .alert.alert-success
+                        a.close(data-dismiss="alert") &times;
+                        strong Well done!
+                        |  #{success}
+                form.form-horizontal.well(method="post", action="/login?followup=#{followup}")
+                    fieldset
+                        - if (locals.errors)
+                            - if (errors.username)
+                                .control-group.error
+                                    label.control-label(for="username") Name
+                                    .controls
+                                        input#username(type="text", name="username",
+                                            value=oldvalues.username)
+                                        span.help-inline #{errors.username}
+                            - else
+                                .control-group
+                                    label.control-label(for="username") Name
+                                    .controls
+                                        input#username(type="text", name="username",
+                                            value=oldvalues.username)
+                            - if (errors.password)
+                                .control-group.error
+                                    label.control-label(for="password") Password
+                                    .controls
+                                        input#password(type="password", name="password")
+                                        span.help-inline #{errors.password}
+                            - else
+                                .control-group
+                                    label.control-label(for="password") Password
+                                    .controls
+                                        input#password(type="password", name="password",
+                                            placeholder="enter your password...")
+                        - else
+                            .control-group
+                                label.control-label(for="username") Name
+                                .controls
+                                    input#username(type="text", name="username",
+                                        placeholder="enter your nickname...")
+                            .control-group
+                                label.control-label(for="password") Password
+                                .controls
+                                    input#password(type="password", name="password",
+                                        placeholder="enter your password...")
+                        button.submit-button.btn.btn-primary(type="submit")
+                            i.icon-lock.icon-white
+                            |  Login
+                        a.forgot-passwd(href="/recoverpasswd?followup=#{followup}")
+                            | Forgot your password?
index 829dfe34900f883d9723534c3ff9116e286097fb..d52343bf264840465afaa7d58579cd7649faa519 100644 (file)
@@ -1,86 +1,77 @@
-followup = (typeof(followup) !== "undefined") ? '?followup='+followup : '?followup=/'
-doctype html
-html
-    include header
-        title binb :: Recover password
-        script(src="/static/js/bootstrap.min.js")
-    body
-        include uv.jade
-        .navbar.navbar-inverse.navbar-fixed-top
-            .navbar-inner
-                .container
-                    a.brand(href="/")
-                        .icons.logo #{motto}
-                    ul.nav.pull-right
-                        li
-                            a(href="/") Home
-                        li
-                            a(href="/signup#{followup}") Sign up
-                        li
-                            a(href="/login#{followup}") Login
-        .container
-            section
-                .row
-                    .span12.offset2
-                        if (typeof(success) !== "undefined")
-                            .alert.alert-block.alert-success
-                                h4.alert-heading Success!
-                                | An email has been sent to you.<br>To start the password reset 
-                                | process, open this email and follow the given instructions.<br>
-                                | If you don't receive it in a reasonable amount of time, please 
-                                | use the support form on the left.
-                        else
-                            if ((typeof(errors) !== "undefined") && (typeof(errors.alert) !== "undefined"))
-                                .alert.alert-error
-                                    a.close(data-dismiss="alert") &times;
-                                    strong Oh snap!
-                                    |  #{errors.alert}
-                            form.form-horizontal.well(method="post",
-                                action="/recoverpasswd#{followup}")
-                                fieldset
-                                    if (typeof(errors) !== "undefined")
-                                        if (typeof(errors.email) !== "undefined")
-                                            .control-group.error
-                                                label.control-label(for="email") Email
-                                                .controls
-                                                    input#oldpassword(type="text",name="email",
-                                                        value=oldvalues.email)
-                                                    span.help-inline #{errors.email}
-                                        else
-                                            .control-group
-                                                label.control-label(for="email") Email
-                                                .controls
-                                                    input#username(type="text",name="email",
-                                                        value=oldvalues.email)
-                                        if (typeof(errors.captcha) !== 'undefined')
-                                            .control-group.error
-                                                label.control-label(for="captcha-input")
-                                                    | Are you human?
-                                                .controls
-                                                    img#captcha(src=captchaurl)
-                                                    input#captcha-input(type="text",name="captcha")
-                                                    span.help-inline #{errors.captcha}
-                                        else
-                                            .control-group
-                                                label.control-label(for="captcha-input")
-                                                    | Are you human?
-                                                .controls
-                                                    img#captcha(src=captchaurl)
-                                                    input#captcha-input(type="text",name="captcha",
-                                                        placeholder="type what you see...")
-                                    else
-                                        .control-group
-                                            label.control-label(for="email") Email
-                                            .controls
-                                                input#email(type="text",name="email",
-                                                    placeholder="type the email you used to sign up...")
-                                        .control-group
-                                            label.control-label(for="captcha-input") Are you human?
-                                            .controls
-                                                img#captcha(src=captchaurl)
-                                                input#captcha-input(type="text",name="captcha",
-                                                    placeholder="type what you see...")
-                                    button.submit-button.btn.btn-primary(type="submit")
-                                        i.icon-envelope.icon-white
-                                        |  Send password reset link
-            include footer
+extends layout
+
+block title
+    title binb :: Recover password
+
+block nav
+    ul.nav.pull-right
+        li
+            a(href="/") Home
+        li
+            a(href="/signup?followup=#{followup}") Sign up
+        li
+            a(href="/login?followup=#{followup}") Login
+
+block sections
+    section
+        .row
+            .span12.offset2
+                - if (locals.success)
+                    .alert.alert-block.alert-success
+                        h4.alert-heading Success!
+                        | An email has been sent to you.<br>To start the password reset 
+                        | process, open this email and follow the given instructions.<br>
+                        | If you don't receive it in a reasonable amount of time, please 
+                        | use the support form on the left.
+                - else
+                    - if (locals.errors && errors.alert)
+                        .alert.alert-error
+                            a.close(data-dismiss="alert") &times;
+                            strong Oh snap!
+                            |  #{errors.alert}
+                    form.form-horizontal.well(method="post",
+                        action="/recoverpasswd?followup=#{followup}")
+                        fieldset
+                            - if (locals.errors)
+                                - if (errors.email)
+                                    .control-group.error
+                                        label.control-label(for="email") Email
+                                        .controls
+                                            input#oldpassword(type="text", name="email",
+                                                value=oldvalues.email)
+                                            span.help-inline #{errors.email}
+                                - else
+                                    .control-group
+                                        label.control-label(for="email") Email
+                                        .controls
+                                            input#username(type="text", name="email",
+                                                value=oldvalues.email)
+                                - if (errors.captcha)
+                                    .control-group.error
+                                        label.control-label(for="captcha-input") Are you human?
+                                        .controls
+                                            img#captcha(src=captchaurl)
+                                            input#captcha-input(type="text", name="captcha")
+                                            span.help-inline #{errors.captcha}
+                                - else
+                                    .control-group
+                                        label.control-label(for="captcha-input") Are you human?
+                                        .controls
+                                            img#captcha(src=captchaurl)
+                                            input#captcha-input(type="text", name="captcha",
+                                                placeholder="type what you see...")
+                            - else
+                                .control-group
+                                    label.control-label(for="email") Email
+                                    .controls
+                                        input#email(type="text", name="email",
+                                            placeholder="type the email you used to sign up...")
+                                .control-group
+                                    label.control-label(for="captcha-input") Are you human?
+                                    .controls
+                                        img#captcha(src=captchaurl)
+                                        input#captcha-input(type="text", name="captcha",
+                                            placeholder="type what you see...")
+                            button.submit-button.btn.btn-primary(type="submit")
+                                i.icon-envelope.icon-white
+                                |  Send password reset link
index f289aa1f5b7ec96efdd5231dea1826c049b880f3..2aec8063ebfc10e0751c66a4e55db533bbe249a2 100644 (file)
@@ -1,47 +1,42 @@
-token = (typeof(token) !== "undefined") ? '?token='+token : ''
-doctype html
-html
-    include header
-        title binb :: Reset password
-        script(src="/static/js/bootstrap.min.js")
-    body
-        include uv.jade
-        .navbar.navbar-inverse.navbar-fixed-top
-            .navbar-inner
-                .container
-                    a.brand(href="#")
-                        .icons.logo #{motto}
-        .container
-            section
-                .row
-                    .span12.offset2
-                        if ((typeof(errors) !== "undefined") && (typeof(errors.alert) !== "undefined"))
-                            .alert.alert-error
-                                a.close(data-dismiss="alert") &times;
-                                strong Oh snap!
-                                |  #{errors.alert}
-                        form.form-horizontal.well(method="post",action="/resetpasswd#{token}")
-                            fieldset
-                                if (typeof(errors) !== "undefined")
-                                    if (typeof(errors.password) !== "undefined")
-                                        .control-group.error
-                                            label.control-label(for="password") New password
-                                            .controls
-                                                input#oldpassword(type="password",name="password")
-                                                span.help-inline #{errors.password}
-                                    else
-                                        .control-group
-                                            label.control-label(for="password") New password
-                                            .controls
-                                                input#username(type="password",name="password",
-                                                    placeholder="enter your new password...")
-                                else
-                                    .control-group
-                                        label.control-label(for="oldpassword") New password
-                                        .controls
-                                            input#username(type="password",name="password",
-                                                placeholder="enter your new password...")
-                                button.submit-button.btn.btn-primary(type="submit")
-                                    i.icon-edit.icon-white
-                                    |  Update
-            include footer
+extends layout
+
+block title
+    title binb :: Reset password
+
+block brand
+    a.brand(href="#")
+        .icons.logo #{slogan}
+
+block sections
+    section
+        .row
+            .span12.offset2
+                - if (locals.errors && errors.alert)
+                    .alert.alert-error
+                        a.close(data-dismiss="alert") &times;
+                        strong Oh snap!
+                        |  #{errors.alert}
+                form.form-horizontal.well(method="post", action="/resetpasswd?token=#{token}")
+                    fieldset
+                        - if (locals.errors)
+                            - if (errors.password)
+                                .control-group.error
+                                    label.control-label(for="password") New password
+                                    .controls
+                                        input#oldpassword(type="password", name="password")
+                                        span.help-inline #{errors.password}
+                            - else
+                                .control-group
+                                    label.control-label(for="password") New password
+                                    .controls
+                                        input#username(type="password", name="password",
+                                            placeholder="enter your new password...")
+                        - else
+                            .control-group
+                                label.control-label(for="oldpassword") New password
+                                .controls
+                                    input#username(type="password", name="password",
+                                        placeholder="enter your new password...")
+                        button.submit-button.btn.btn-primary(type="submit")
+                            i.icon-edit.icon-white
+                            |  Update
index ea35a6d74b4ad6aa4601b0877c81e3ff864fe513..6b27c1c1d59cd35e643a33a0b6b49dad190c6b22 100644 (file)
-doctype html
-html
-    include header
-        title binb :: #{roomname}
-        script(src="/socket.io/socket.io.js")
-        script(src="/static/js/bootstrap.min.js")
-        script(src="/static/js/jquery.jplayer.min.js")
-        script(type='text/javascript')
-            var roomname = "#{roomname}";
-        script(src="/static/js/room.js")
-    body
-        include uv.jade
-        .navbar.navbar-inverse.navbar-fixed-top
-            .navbar-inner
-                .container
-                    ul.nav.pull-right
+extends layout
+
+block title
+    title binb :: #{roomname}
+        
+block nav
+    ul.nav.pull-right
+        li
+            a(href="/") Home
+        li
+            a(target="_blank", href="/leaderboards")
+                i.icon-list-alt.icon-white
+                |  Leaderboards
+        li.active.dropdown
+            a.dropdown-toggle(data-toggle="dropdown",href="#") #{roomname} 
+                b.caret
+            ul.dropdown-menu
+                - each item in rooms
+                    - if (item !== roomname)
                         li
-                            a(href="/") Home
-                        li
-                            a(target="_blank", href="/leaderboards")
-                                i.icon-list-alt.icon-white
-                                |  Leaderboards
-                        li.active.dropdown
-                            a.dropdown-toggle(data-toggle="dropdown",href="#") #{roomname} 
-                                b.caret
-                            ul.dropdown-menu
-                                each item in rooms
-                                    if item != roomname
-                                        li
-                                            a(href=item)
-                                                span.room-name #{item}
-                                                i.icon-user.pull-right
-                                                span.users-counter
-                        if (typeof(loggedin) !== "undefined")
-                            li.dropdown
-                                a.dropdown-toggle(data-toggle="dropdown",
-                                    href="#") Logged in as #{loggedin.replace(/&/g, '&amp;')} 
-                                    span.caret
-                                ul.dropdown-menu
-                                    li
-                                        a(href="/user/#{encodeURIComponent(loggedin)}",
-                                            target="_blank") Profile
-                                    li
-                                        a(href="/changepasswd?followup=/#{roomname}")
-                                            | Change password
-                                    li
-                                        a(href="/logout") Logout
-                        else
-                            li
-                                a(href="/signup?followup=/#{roomname}") Sign up
-                            li
-                                a(href="/login?followup=/#{roomname}") Login
-        #player
-        #modal.modal.fade
-        .container
-            section
-                .row
-                    .span4.offset1
-                        #cassette.relative
-                            #wheel-left.icons.wheel
-                            #tape-left
-                            #tape-right
-                            #wheel-right.icons.wheel
-                            #progress-bar
-                                #progress
-                            #countdown
+                            a(href=item)
+                                span.room-name #{item}
+                                i.icon-user.pull-right
+                                span.users-counter
+        - if (locals.loggedin)
+            li.dropdown
+                a.dropdown-toggle(data-toggle="dropdown", href="#")
+                    | Logged in as #{loggedin.replace(/&/g, '&amp;')} 
+                    span.caret
+                ul.dropdown-menu
+                    li
+                        a(href="/user/#{encodeURIComponent(loggedin)}", target="_blank") Profile
+                    li
+                        a(href="/changepasswd?followup=/#{roomname}") Change password
+                    li
+                        a(href="/logout") Logout
+        - else
+            li
+                a(href="/signup?followup=/#{roomname}") Sign up
+            li
+                a(href="/login?followup=/#{roomname}") Login
+
+block sections
+    section
+        .row
+            .span4.offset1
+                #cassette.relative
+                    #wheel-left.icons.wheel
+                    #tape-left
+                    #tape-right
+                    #wheel-right.icons.wheel
+                    #progress-bar
+                        #progress
+                    #countdown
+            .span2
+                #volume.relative
+            .span8
+                .page-header
+                    .icons.logo #{slogan}
+                    #total-tracks
+                        span
+                        |  tracks.
+                #summary.row
+                    .span2
+                        .title Rank
+                        .rank
+                    .span4
+                        .title Points
+                        .points
                     .span2
-                        #volume.relative
-                    .span8
-                        .page-header
-                            .icons.logo #{motto}
-                            #total-tracks <span></span> tracks.
-                        #summary.row
-                            .span2
-                                .title Rank
-                                .rank
-                            .span4
-                                .title Points
-                                .points
-                            .span2
-                                .title Track
-                                .track
-                        p#feedback Waiting for connection...
-                        input#guess.span8(type="text",tabindex="1",
-                            placeholder="guess the artist and/or title here")
-            section.relative
-                .row
-                    #users-wrapper.span5.offset2
-                        ul#users.unstyled
-                    .span8
-                        a#toggle-chat Hide chat
-                        #chat-outer-wrapper
-                            #chat-wrapper.bordered
-                                ul#chat.unstyled
-                            #message-wrapper
-                                span#recipient
-                                input#message.span8(type="text",tabindex="2")
-                        ul#tracks.unstyled
-                #disclaimer
-                    div I do not own any right on the songs that are played here.
-                    div Tracks are played using iTunes api preview.
-                    div Original idea from 
-                        a(target="_blank", href="http://beatquest.fm/") beatquest.fm
-                        |.
-            include footer
+                        .title Track
+                        .track
+                p#feedback Waiting for connection...
+                input#guess.span8(type="text", tabindex="1",
+                    placeholder="guess the artist and/or title here")
+    section.relative
+        .row
+            #users-wrapper.span5.offset2
+                ul#users.unstyled
+            .span8
+                a#toggle-chat Hide chat
+                #chat-outer-wrapper
+                    #chat-wrapper.bordered
+                        ul#chat.unstyled
+                    #message-wrapper
+                        span#recipient
+                        input#message.span8(type="text", tabindex="2")
+                ul#tracks.unstyled
+        #disclaimer
+            div I do not own any right on the songs that are played here.
+            div Tracks are played using iTunes api preview.
+            div Original idea from 
+                a(target="_blank", href="http://beatquest.fm/") beatquest.fm
+                | .
+
+block media
+    #modal.modal.fade
+    #player
+
+append scripts
+    script(src="/static/js/jquery.jplayer.min.js")
+    script(src="/socket.io/socket.io.js")
+    script(src="/static/js/app.js")
index 2419d834bc65223747ce41516067c0b4564572b7..1e58dcecaec01670594f20b4f16f8ec07f6ae522 100644 (file)
-followup = (typeof(followup) !== "undefined") ? '?followup='+followup : '?followup=/'
-doctype html
-html
-    include header
-        title binb :: sign up
-        script(src="/static/js/bootstrap.min.js")
-    body
-        include uv.jade
-        .navbar.navbar-inverse.navbar-fixed-top
-            .navbar-inner
-                .container
-                    a.brand(href="/")
-                        .icons.logo #{motto}
-                    ul.nav.pull-right
-                        li
-                            a(href="/") Home
-                        li.active
-                            a(href="/signup#{followup}") Sign up
-                        li
-                            a(href="/login#{followup}") Login
-        .container
-            section
-                .row
-                    .span3
-                        h3 Not a new user?
-                        a(href="/login#{followup}") Click here to log in.
-                    .span13
-                        h3 Why sign up?
-                        p Registration is optional, but if you are a regular user consider creating 
-                            | an account. This will provide the following advantages:
-                        ul
-                            li You will be the one and only owner of your nickname (no one can use 
-                                | your nickname in your place).
-                            li Some simple stats related to your account will be collected.
-                        if ((typeof(errors) !== "undefined") && (typeof(errors.alert) !== "undefined"))
-                            .alert.alert-error
-                                a.close(data-dismiss="alert") &times;
-                                strong Oh snap!
-                                |  #{errors.alert}
-                        form.form-horizontal.well(method="post",action="/signup#{followup}")
-                            fieldset
-                                if (typeof(errors) !== "undefined")
-                                    if (typeof(errors.username) !== "undefined")
-                                        .control-group.error
-                                            label.control-label(for="username") Name
-                                            .controls
-                                                input#username(type="text",name="username",
-                                                    value=oldvalues.username)
-                                                span.help-inline #{errors.username}
-                                    else
-                                        .control-group
-                                            label.control-label(for="username") Name
-                                            .controls
-                                                input#username(type="text",name="username",
-                                                    value=oldvalues.username)
-                                    if (typeof(errors.email) !== 'undefined')
-                                        .control-group.error
-                                            label.control-label(for="email") Email
-                                            .controls
-                                                input#email(type="text",name="email",
-                                                    value=oldvalues.email)
-                                                span.help-inline #{errors.email}
-                                    else
-                                        .control-group
-                                            label.control-label(for="email") Email
-                                            .controls
-                                                input#email(type="text",name="email",
-                                                    value=oldvalues.email)
-                                    if (typeof(errors.password) !== 'undefined')
-                                        .control-group.error
-                                            label.control-label(for="password") Password
-                                            .controls
-                                                input#password(type="password",name="password")
-                                                span.help-inline #{errors.password}
-                                    else
-                                        .control-group
-                                            label.control-label(for="password") Password
-                                            .controls
-                                                input#password(type="password",name="password",
-                                                    placeholder="enter a password...")
-                                    if (typeof(errors.captcha) !== 'undefined')
-                                        .control-group.error
-                                            label.control-label(for="captcha-input") Are you human?
-                                            .controls
-                                                img#captcha(src=captchaurl)
-                                                input#captcha-input(type="text",name="captcha")
-                                                span.help-inline #{errors.captcha}
-                                    else
-                                        .control-group
-                                            label.control-label(for="captcha-input") Are you human?
-                                            .controls
-                                                img#captcha(src=captchaurl)
-                                                input#captcha-input(type="text",name="captcha",
-                                                    placeholder="type what you see...")
-                                else
-                                    .control-group
-                                        label.control-label(for="username") Name
-                                        .controls
-                                            input#username(type="text",name="username",
-                                                placeholder="enter a nickname...")
-                                    .control-group
-                                        label.control-label(for="email") Email
-                                        .controls
-                                            input#email(type="text",name="email",
-                                                placeholder="enter a valid email...")
-                                    .control-group
-                                        label.control-label(for="password") Password
-                                        .controls
-                                            input#password(type="password",name="password",
-                                                placeholder="enter a password...")
-                                    .control-group
-                                        label.control-label(for="captcha-input") Are you human?
-                                        .controls
-                                            img#captcha(src=captchaurl)
-                                            input#captcha-input(type="text",name="captcha",
-                                                placeholder="type what you see...")
-                                button.submit-button.btn.btn-success(type="submit")
-                                    i.icon-user.icon-white
-                                    |  Sign up!
-            include footer
+extends layout
+
+block title
+    title binb :: sign up
+
+block nav
+    ul.nav.pull-right
+        li
+            a(href="/") Home
+        li.active
+            a(href="/signup?followup=#{followup}") Sign up
+        li
+            a(href="/login?followup=#{followup}") Login
+
+block sections
+    section
+        .row
+            .span3
+                h3 Not a new user?
+                a(href="/login?followup=#{followup}") Click here to log in.
+            .span13
+                h3 Why sign up?
+                p Registration is optional, but if you are a regular user consider creating 
+                    | an account. This will provide the following advantages:
+                ul
+                    li You will be the one and only owner of your nickname (no one can use 
+                        | your nickname in your place).
+                    li Some simple stats related to your account will be collected.
+                - if (locals.errors && errors.alert)
+                    .alert.alert-error
+                        a.close(data-dismiss="alert") &times;
+                        strong Oh snap!
+                        |  #{errors.alert}
+                form.form-horizontal.well(method="post",action="/signup?followup=#{followup}")
+                    fieldset
+                        - if (locals.errors)
+                            - if (errors.username)
+                                .control-group.error
+                                    label.control-label(for="username") Name
+                                    .controls
+                                        input#username(type="text", name="username",
+                                            value=oldvalues.username)
+                                        span.help-inline #{errors.username}
+                            - else
+                                .control-group
+                                    label.control-label(for="username") Name
+                                    .controls
+                                        input#username(type="text", name="username",
+                                            value=oldvalues.username)
+                            - if (errors.email)
+                                .control-group.error
+                                    label.control-label(for="email") Email
+                                    .controls
+                                        input#email(type="text", name="email",
+                                            value=oldvalues.email)
+                                        span.help-inline #{errors.email}
+                            - else
+                                .control-group
+                                    label.control-label(for="email") Email
+                                    .controls
+                                        input#email(type="text", name="email",
+                                            value=oldvalues.email)
+                            - if (errors.password)
+                                .control-group.error
+                                    label.control-label(for="password") Password
+                                    .controls
+                                        input#password(type="password", name="password")
+                                        span.help-inline #{errors.password}
+                            - else
+                                .control-group
+                                    label.control-label(for="password") Password
+                                    .controls
+                                        input#password(type="password", name="password",
+                                            placeholder="enter a password...")
+                            - if (errors.captcha)
+                                .control-group.error
+                                    label.control-label(for="captcha-input") Are you human?
+                                    .controls
+                                        img#captcha(src=captchaurl)
+                                        input#captcha-input(type="text", name="captcha")
+                                        span.help-inline #{errors.captcha}
+                            - else
+                                .control-group
+                                    label.control-label(for="captcha-input") Are you human?
+                                    .controls
+                                        img#captcha(src=captchaurl)
+                                        input#captcha-input(type="text", name="captcha",
+                                            placeholder="type what you see...")
+                        - else
+                            .control-group
+                                label.control-label(for="username") Name
+                                .controls
+                                    input#username(type="text", name="username",
+                                        placeholder="enter a nickname...")
+                            .control-group
+                                label.control-label(for="email") Email
+                                .controls
+                                    input#email(type="text", name="email",
+                                        placeholder="enter a valid email...")
+                            .control-group
+                                label.control-label(for="password") Password
+                                .controls
+                                    input#password(type="password", name="password",
+                                        placeholder="enter a password...")
+                            .control-group
+                                label.control-label(for="captcha-input") Are you human?
+                                .controls
+                                    img#captcha(src=captchaurl)
+                                    input#captcha-input(type="text", name="captcha",
+                                        placeholder="type what you see...")
+                        button.submit-button.btn.btn-success(type="submit")
+                            i.icon-user.icon-white
+                            |  Sign up!
index 8b7a6790f92be347ee798200adbfa97a7477e30d..38b2b6df08bf47f446a24c438e17123962bc3b92 100644 (file)
@@ -1,89 +1,88 @@
-doctype html
-html
-    include header
-        title binb :: #{username.replace(/&/g, '&amp;')} info
-    body
-        include uv.jade
-        .navbar.navbar-inverse.navbar-fixed-top
-            .navbar-inner
-                .container
-                    a.brand(href="#")
-                        .icons.logo #{motto}
-        .container
-            section
-                .row
-                    .span7.offset1
-                        .profile #{username.replace(/&/g, '&amp;')}
-                            .icons.img
-                        div member since #{joindate}
-            section
-                .row
-                    .span7.offset1
-                        h4 Points
-                        table.table.table-striped.table-bordered.stats
-                            tbody
-                                tr
-                                    td Total
-                                    td #{totpoints}
-                                tr
-                                    td Best score
-                                    td #{bestscore}
-                                tr
-                                    td Guessed songs
-                                    td #{guessed}
-                        h4 Times
-                        table.table.table-striped.table-bordered.stats
-                            tbody
-                                tr
-                                    td Best guess time
-                                    if (bestguesstime !== "30.0")
-                                        td #{bestguesstime} sec
-                                    else
-                                        td N/A
-                                tr
-                                    td Worst guess time
-                                    if (worstguesstime !== "0.0")
-                                        td #{worstguesstime} sec
-                                    else
-                                        td N/A
-                                tr
-                                    td Mean guess time
-                                    if (typeof meanguesstime !== "undefined")
-                                        td #{meanguesstime} sec
-                                    else
-                                        td N/A
-                    .span7
-                        h4 Awards
-                        table.table.table-striped.table-bordered.stats
-                            tbody
-                                tr
-                                    td Gold cups
-                                    td
-                                        .icons.cups.stand1
-                                    td #{golds}
-                                tr
-                                    td Silver cups
-                                    td
-                                        .icons.cups.stand2
-                                    td #{silvers}
-                                tr
-                                    td Bronze cups
-                                    td
-                                        .icons.cups.stand3
-                                    td #{bronzes}
-                                tr
-                                    td Victories
-                                    td
-                                        .icons.medals.rank1
-                                    td #{victories}
-                                tr
-                                    td Second places
-                                    td
-                                        .icons.medals.rank2
-                                    td #{secondplaces}
-                                tr
-                                    td Third places
-                                    td
-                                        .icons.medals.rank3
-                                    td #{thirdplaces}
-            include footer
+extends layout
+
+block title
+    title binb :: #{username.replace(/&/g, '&amp;')} info
+    
+block brand
+    a.brand(href="#")
+        .icons.logo #{slogan}
+
+block sections
+    section
+        .row
+            .span7.offset1
+                .profile #{username.replace(/&/g, '&amp;')}
+                    .icons.img
+                div member since #{joindate}
+    section
+        .row
+            .span7.offset1
+                h4 Points
+                table.table.table-striped.table-bordered.stats
+                    tbody
+                        tr
+                            td Total
+                            td #{totpoints}
+                        tr
+                            td Best score
+                            td #{bestscore}
+                        tr
+                            td Guessed songs
+                            td #{guessed}
+                h4 Times
+                table.table.table-striped.table-bordered.stats
+                    tbody
+                        tr
+                            td Best guess time
+                            - if (bestguesstime !== "30.0")
+                                td #{bestguesstime} sec
+                            - else
+                                td N/A
+                        tr
+                            td Worst guess time
+                            - if (worstguesstime !== "0.0")
+                                td #{worstguesstime} sec
+                            - else
+                                td N/A
+                        tr
+                            td Mean guess time
+                            - if (typeof meanguesstime !== 'undefined')
+                                td #{meanguesstime} sec
+                            - else
+                                td N/A
+            .span7
+                h4 Awards
+                table.table.table-striped.table-bordered.stats
+                    tbody
+                        tr
+                            td Gold cups
+                            td
+                                .icons.cups.stand1
+                            td #{golds}
+                        tr
+                            td Silver cups
+                            td
+                                .icons.cups.stand2
+                            td #{silvers}
+                        tr
+                            td Bronze cups
+                            td
+                                .icons.cups.stand3
+                            td #{bronzes}
+                        tr
+                            td Victories
+                            td
+                                .icons.medals.rank1
+                            td #{victories}
+                        tr
+                            td Second places
+                            td
+                                .icons.medals.rank2
+                            td #{secondplaces}
+                        tr
+                            td Third places
+                            td
+                                .icons.medals.rank3
+                            td #{thirdplaces}
+
+block scripts
diff --git a/views/uv.jade b/views/uv.jade
deleted file mode 100644 (file)
index 4b29b34..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-script
-    var uvOptions = {};
-    (function() {
-        var uv = document.createElement('script');
-        uv.type = 'text/javascript';
-        uv.async = true;
-        uv.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 
-            'widget.uservoice.com/LSMjFAQRifhD6BjOG2KWw.js';
-        var s = document.getElementsByTagName('script')[0];
-        s.parentNode.insertBefore(uv, s);
-    })();