]> git.example.dev Git - binbsis50.git/commitdiff
splitted server code into multiple files to improve readability
authorLuigi Pinca <luigipinca@gmail.com>
Tue, 1 May 2012 15:30:22 +0000 (17:30 +0200)
committerLuigi Pinca <luigipinca@gmail.com>
Tue, 1 May 2012 15:30:22 +0000 (17:30 +0200)
15 files changed:
lib/captcha.js [new file with mode: 0644]
lib/match.js [new file with mode: 0644]
lib/room.js [new file with mode: 0644]
lib/stats.js [new file with mode: 0644]
package.json
public/static/css/style.css
server.js
views/feedback.jade [moved from views/uv.jade with 53% similarity]
views/footer.jade
views/header.jade
views/index.jade
views/login.jade
views/room.jade
views/signup.jade
views/user.jade

diff --git a/lib/captcha.js b/lib/captcha.js
new file mode 100644 (file)
index 0000000..6f4e605
--- /dev/null
@@ -0,0 +1,29 @@
+var canvas = require("canvas");
+
+module.exports = function(characters) {
+
+       function Captcha() {
+               var code = "";
+               while (code.length < 4) {
+                       code += characters[Math.floor(Math.random() * characters.length)];
+               }
+               var _canvas = new canvas(64, 26);
+               var ctx = _canvas.getContext('2d');
+               ctx.fillStyle = "#DDDDDD";
+               ctx.fillRect(0, 0, 64, 26);
+               ctx.font = "bold 20px Helvetica";
+               ctx.lineWidth = 1;
+               ctx.textAlign = "center";
+               ctx.strokeStyle = "#080";
+               ctx.strokeText(code, 31, 20);
+               ctx.save();
+               this.getCode = function() {
+                       return code;
+               };
+               this.toDataURL = function() {
+                       return _canvas.toDataURL();
+               };
+       }
+
+       return Captcha;
+};
diff --git a/lib/match.js b/lib/match.js
new file mode 100644 (file)
index 0000000..24a3b08
--- /dev/null
@@ -0,0 +1,120 @@
+module.exports = function(threshold) {
+
+       /*
+       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 algorithm 
+       in better than O(n*m).
+       We use only a diagonal stripe of width 2k+1 in the matrix.
+       See Algorithms on strings, trees, and sequences: computer science and computational biology.
+       Cambridge, UK: Cambridge University Press. pp 263-264. ISBN 0-521-58519-8.
+       */
+       var checkDistance = function(s1, s2, k) {
+               if (k === 0) {
+                       return s1 === s2;
+               }
+               if (Math.abs(s1.length - s2.length) > k) {
+                       return false;
+               }
+               var d = [];
+               for (var i=0; i <= s1.length; i++) {
+                       d[i] = []; // Now d is a matrix with s1.length + 1 rows
+                       d[i][0] = i;
+               }
+               for (var j=0; j <= s2.length; j++) {
+                       d[0][j] = j;
+               }
+               for (i=1; i <= s1.length; i++) {
+                       var l = ((i-k) < 1) ? 1 : i-k;
+                       var m = ((i+k) > s2.length) ? s2.length : i+k;
+                       for (j=l; j<=m; j++) {
+                               if (s1.charAt(i-1) === s2.charAt(j-1)) {
+                                       d[i][j] = d[i-1][j-1];
+                               }
+                               else {
+                                       if ((j === l) && (d[i][j-1] === undefined)) {
+                                               d[i][j] = Math.min(d[i-1][j-1]+1, d[i-1][j]+1);
+                                       }
+                                       else if ((j === m) && (d[i-1][j] === undefined)) {
+                                               d[i][j] = Math.min(d[i][j-1]+1, d[i-1][j-1]+1);
+                                       }
+                                       else {
+                                               d[i][j] = Math.min(d[i][j-1]+1, d[i-1][j-1]+1, d[i-1][j]+1);
+                                       }
+                               }
+                       }
+               }
+               return d[s1.length][s2.length] <= k;
+       };
+
+       var amatch = function(subject, guess, enableartistrules) {
+               if (checkDistance(subject, guess, threshold)) {
+                       return true;
+               }
+               var splitted, trimmed;
+               if (subject.match(/\./) && 
+                       checkDistance(subject.replace(/\./g, ""), guess, threshold)) {
+                       return true;
+               }
+               if (subject.match(/\-/) && 
+                       checkDistance(subject.replace(/\-/g, ""), guess, threshold)) {
+                       return true;
+               }
+               if (subject.match(/\+/) && 
+                       checkDistance(subject.replace(/\+/, "and"), guess, threshold)) {
+                       return true;
+               }
+               if (enableartistrules) {
+                       if (subject.match(/^the /)) {
+                               var nothe = subject.replace(/^the /, "");
+                               if (checkDistance(nothe, guess, threshold)) {
+                                       return true;
+                               }
+                               if (nothe.match(/jimi hendrix experience/) && 
+                                       checkDistance(nothe.replace(/ experience/, ""), guess, threshold)) {
+                                       return true;
+                               }
+                       }
+                       splitted = subject.split("&");
+                       if (splitted.length !== 1) {
+                               for (var i=0; i<splitted.length; i++) {
+                                       trimmed = splitted[i].replace(/^ +/, "").replace(/ +$/, "");
+                                       if (checkDistance(trimmed, guess, threshold)) {
+                                               return true;
+                                       }
+                                       if (trimmed.match(/^the /) && 
+                                               checkDistance(trimmed.replace(/^the /, ""), guess, threshold)) {
+                                               return true;
+                                       }
+                               }
+                       }
+               }
+               else {
+                       if (subject.match(/,/) && 
+                               checkDistance(subject.replace(/,/g, ""), guess, threshold)) {
+                               return true;
+                       }
+                       if (subject.match(/ & /) && !subject.match(/\(/) &&
+                               checkDistance(subject.replace(/ & /, " and "), guess, threshold)) {
+                               return true;
+                       }
+                       if (subject.match(/\(.+\)\??(?: \[.+\])?/)) {
+                               var normalized = subject.replace(/\(.+\)\??(?: \[.+\])?/, "")
+                                                                               .replace(/^ +/, "").replace(/ +$/, "");
+                               if (checkDistance(normalized, guess, threshold)) {
+                                       return true;
+                               }
+                               if (normalized.match(/ & /) && 
+                                       checkDistance(normalized.replace(/ & /, " and "), guess, threshold)) {
+                                       return true;
+                               }
+                       }
+                       if (subject.match(/, [pP]t\. [0-9]$/) && 
+                               checkDistance(subject.replace(/, [pP]t\. [0-9]$/, ""), guess, threshold)) {
+                               return true;
+                       }
+               }
+               return false;
+       };
+
+       return amatch;
+};
diff --git a/lib/room.js b/lib/room.js
new file mode 100644 (file)
index 0000000..5ffe820
--- /dev/null
@@ -0,0 +1,400 @@
+module.exports = function(params) {
+
+       var songsdb = params.songsdb;
+       var usersdb = params.usersdb;
+       var io = params.io;
+       var sockets = params.sockets;
+       var songsinarun = params.songsinarun;
+       var fifolength = params.fifolength;
+       var threshold = params.threshold;
+
+       var amatch = require('./match.js')(threshold);
+       var collectStats = require('./stats.js')(usersdb);
+
+       function Room(roomname) {
+
+               var roomname = roomname;
+               var totusers = 0;
+       
+               var usersData = Object.create(null);
+               var playedtracks = []; // The list of already played songs
+       
+               var artistName = null;
+               var artistlcase = null;
+               var trackName = null;
+               var tracklcase = null;
+               var collectionName = null;
+               var previewUrl = null;
+               var artworkUrl = null;
+               var trackViewUrl = null;
+               var finishline = 1;
+               var allowedguess = false;
+               var status = null;
+               var songtimeleft = null; // Milliseconds
+               var songcounter = 0;
+               var trackscount = 0;
+
+               this.getPopulation = function() {
+                       return totusers;
+               };
+
+               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,
+                               bestguesstime: 30000,
+                               golds: 0,
+                               silvers: 0,
+                               bronzes: 0
+                       };
+                       totusers = totusers + 1;
+                       io.sockets.in('home').emit('update', {room:roomname,players:totusers});
+                       // Broadcast new user event
+                       socket.emit('ready', {users:usersData,trackscount:trackscount,loggedin:loggedin});
+                       socket.broadcast.to(roomname).emit('newuser', {nickname:socket.nickname,users:usersData});
+               };
+
+               var removeUser = function(nickname) {
+                       // Delete the references
+                       delete sockets[nickname];
+                       delete usersData[nickname];
+                       totusers = totusers - 1;
+                       io.sockets.in('home').emit('update', {room:roomname,players:totusers});
+               };
+
+               var userExists = function(nickname) {
+                       var user = usersData[nickname];
+                       if (user) {
+                               return true;
+                       }
+                       return false;
+               };
+       
+               this.joinRoom = function(socket) {
+                       socket.roomname = roomname;
+                       socket.join(roomname);
+                       addUser(socket, true);
+               };
+       
+               // A user requested an invalid name
+               var invalidNickName = function(socket, feedback) {
+                       socket.emit('invalidnickname', feedback);
+               };
+
+               // A user is submitting a name
+               this.setNickName = function(socket, data) {
+                       var feedback = null;
+                       if (data.nickname.length > 15) {
+                               feedback = '<span class="label label-important">That name is too long.</span>';
+                       }
+                       else if (data.nickname === "binb") {
+                               feedback = '<span class="label label-important">That name is reserved.</span>';
+                       }
+                       else if (sockets[data.nickname]) {
+                               feedback = '<span class="label label-important">Name already taken.</span>';
+                       }
+                       if (feedback) {
+                               return invalidNickName(socket, feedback);
+                       }
+               
+                       var key = "user:"+data.nickname;
+                       usersdb.exists(key, function(err, resp) {
+                               if (resp === 1) { // User already exists
+                                       feedback = '<span class="label label-important">That name belongs ';
+                                       feedback += 'to a registered user.</span>';
+                                       return invalidNickName(socket, feedback);
+                               }
+                               else {
+                                       socket.nickname = data.nickname;
+                                       socket.roomname = roomname;
+                                       socket.join(roomname);
+                                       // Add user to the list of active users
+                                       addUser(socket, false);
+                               }
+                       });
+               };
+
+               // A user has left (DCed, etc.)
+               this.userLeft = function(nickname) {
+                       removeUser(nickname);
+                       io.sockets.in(roomname).emit('userleft', {nickname:nickname,users:usersData});
+               };
+       
+               this.sendChatMessage = function (socket, data) {
+                       if (typeof data === "string") {
+                               var datalcase = data.toLowerCase();
+                               if (allowedguess && (amatch(artistlcase, datalcase, true) || 
+                                                                       amatch(tracklcase, datalcase))) {
+                                       var msg = "You are probably right, but you have to use the box above.";
+                                       socket.emit('chatmsg', {from:"binb",to:socket.nickname,chatmsg:msg});
+                                       return;
+                               }
+                               io.sockets.in(roomname).emit('chatmsg', {from:socket.nickname,chatmsg:data});
+                       }
+                       else if (typeof data === "object" && typeof data.to === "string" && 
+                                               userExists(data.to) && typeof data.chatmsg === "string") {
+                               // Private message
+                               socket.emit('chatmsg', {from:socket.nickname,to:data.to,chatmsg:data.chatmsg});
+                               var recipient = sockets[data.to];
+                               recipient.emit('chatmsg', {from:socket.nickname,to:data.to,chatmsg:data.chatmsg});
+                       }
+               };
+
+               var addPoints = 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++;
+                       if (usersData[nickname].guesstime < usersData[nickname].bestguesstime) {
+                               usersData[nickname].bestguesstime = usersData[nickname].guesstime;
+                       }
+                       if (usersData[nickname].registered) {
+                               stats.userscore = usersData[nickname].points;
+                               stats.guesstime = usersData[nickname].guesstime;
+                               collectStats(nickname, stats);
+                       }
+               };
+       
+               this.guess = function(socket, guess) {
+                       if (allowedguess) {
+                               if (!usersData[socket.nickname].matched) { // No track no artist
+                                       if ((artistlcase === tracklcase) && amatch(tracklcase, guess, true)) {
+                                               addPoints(socket.nickname, true);
+                                               socket.emit('bothmatched');
+                                               io.sockets.in(roomname).emit('updateusers', {users:usersData});
+                                       }
+                                       else if (amatch(artistlcase, guess, true)) {
+                                               usersData[socket.nickname].roundpoints++;
+                                               usersData[socket.nickname].points++;
+                                               usersData[socket.nickname].matched = 'artist';
+                                               socket.emit('artistmatched');
+                                               io.sockets.in(roomname).emit('updateusers', {users:usersData});
+                                               if (usersData[socket.nickname].registered) {
+                                                       var stats = {points:1,userscore:usersData[socket.nickname].points};
+                                                       collectStats(socket.nickname, stats);
+                                               }
+                                       }
+                                       else if (amatch(tracklcase, guess)) {
+                                               usersData[socket.nickname].roundpoints++;
+                                               usersData[socket.nickname].points++;
+                                               usersData[socket.nickname].matched = 'title';
+                                               socket.emit('titlematched');
+                                               io.sockets.in(roomname).emit('updateusers', {users: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(tracklcase, guess)) {
+                                                       addPoints(socket.nickname, false);
+                                                       socket.emit('bothmatched');
+                                                       io.sockets.in(roomname).emit('updateusers', {users:usersData});
+                                               }
+                                               else {
+                                                       socket.emit('nomatch');
+                                               }
+                                       }
+                                       else {
+                                               if (amatch(artistlcase, guess, true)) {
+                                                       addPoints(socket.nickname, false);
+                                                       socket.emit('bothmatched');
+                                                       io.sockets.in(roomname).emit('updateusers', {users:usersData});
+                                               }
+                                               else {
+                                                       socket.emit('nomatch');
+                                               }
+                                       }
+                               }
+                               else { // The user has guessed both track and artist
+                                       socket.emit('stoptrying');
+                               }
+                       }
+                       else {
+                               socket.emit('noguesstime');
+                       }
+               };
+       
+               var resetPoints = function(roundonly) {
+                       for (var key in usersData) {
+                               if (!roundonly) {
+                                       usersData[key].points = 0;
+                                       usersData[key].guessed = 0;
+                                       usersData[key].bestguesstime = 30000;
+                                       usersData[key].golds = 0;
+                                       usersData[key].silvers = 0;
+                                       usersData[key].bronzes = 0;
+                               }
+                               usersData[key].roundpoints = 0;
+                               usersData[key].matched = null;
+                               usersData[key].guesstime = null;
+                       }
+               };
+
+               var sendLoadTrack = function() {
+                       songsdb.srandmember(roomname, function(err, res) {
+                               songsdb.hmget(res, "artistName", "trackName", "collectionName", "previewUrl",
+                                                               "artworkUrl60", "trackViewUrl", function(e, replies) {
+                                       if (playedtracks.indexOf(res) !== -1) {
+                                               return sendLoadTrack();
+                                       }
+                                       playedtracks.push(res);
+                                       artistName = replies[0];
+                                       artistlcase = artistName.toLowerCase();
+                                       trackName = replies[1];
+                                       tracklcase = trackName.toLowerCase();
+                                       collectionName = replies[2];
+                                       previewUrl = replies[3];
+                                       artworkUrl = replies[4];
+                                       trackViewUrl = replies[5];
+                                       io.sockets.in(roomname).emit('loadtrack', {previewUrl:previewUrl});
+                                       setTimeout(sendPlayTrack, 5000);
+                               });
+                       });
+                       status = 1; // Loading next song
+               };
+
+               var sendPlayTrack = function() {
+                       songcounter = songcounter + 1;
+                       status = 0; // Playing track
+                       io.sockets.in(roomname).emit('playtrack', {counter:songcounter,tot:songsinarun,
+                                                                                       users:usersData});
+                       songTimeLeft(Date.now()+30000, 50);
+                       allowedguess = true;
+                       setTimeout(sendTrackInfo, 30000);
+               };
+       
+               var songTimeLeft = function(end, delay) {
+                       songtimeleft = end - Date.now();
+                       if (songtimeleft < delay) {
+                               return;
+                       }
+                       setTimeout(songTimeLeft, delay, end, delay);
+               };
+       
+               var sendTrackInfo = function() {
+                       io.sockets.in(roomname).emit('trackinfo', {artworkUrl:artworkUrl,artistName:artistName,
+                                                                                       trackName:trackName,collectionName:collectionName,
+                                                                                       trackViewUrl:trackViewUrl});
+                       finishline = 1;
+                       allowedguess = false;
+                       if (songcounter < songsinarun) {
+                               resetPoints(true);
+                               sendLoadTrack();
+                       }
+                       else {
+                               status = 2; // Sending last track info
+                               setTimeout(gameOver, 5000);
+                       }
+               };
+
+               var gameOver = function() {
+                       status = 3; // Game over
+                       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', {users:podium});
+                       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);
+                       setTimeout(reset, 5000);
+               };
+
+               this.sendStatus = function(socket) {
+                       socket.emit('status', {status:status,timeleft:songtimeleft,previewUrl:previewUrl});
+               };
+
+               var reset = function() {
+                       songcounter = 0;
+                       if (playedtracks.length === fifolength) {
+                               playedtracks.splice(0, songsinarun);
+                       }
+                       sendLoadTrack();
+               };
+
+               // Start the room
+               this.start = function() {
+                       songsdb.scard(roomname, function(err, res) {
+                               trackscount = res;
+                       });
+                       sendLoadTrack();
+               };
+       }
+
+       return Room;
+};
diff --git a/lib/stats.js b/lib/stats.js
new file mode 100644 (file)
index 0000000..3f89aa7
--- /dev/null
@@ -0,0 +1,51 @@
+module.exports = function(db) {
+
+       var collectStats = function(username, stats) {
+               var key = "user:"+username;
+               if (stats.points) {
+                       db.hincrby(key, "totpoints", stats.points);
+               }
+               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) {
+                       db.hincrby(key, "golds", 1);
+               }
+               if (stats.silver) {
+                       db.hincrby(key, "silvers", 1);
+               }
+               if (stats.bronze) {
+                       db.hincrby(key, "bronzes", 1);
+               }
+               if (stats.guesstime) {
+                       db.hincrby(key, "guessed", 1);
+                       db.hincrby(key, "totguesstime", stats.guesstime);
+                       db.hget(key, "bestguesstime", function(err, res) {
+                               if (stats.guesstime < res) {
+                                       db.hset(key, "bestguesstime", stats.guesstime);
+                               }
+                       });
+                       db.hget(key, "worstguesstime", function(err, res) {
+                               if (stats.guesstime > res) {
+                                       db.hset(key, "worstguesstime", stats.guesstime);
+                               }
+                       });
+               }
+               if (stats.firstplace) {
+                       db.hincrby(key, "victories", 1);
+               }
+               if (stats.secondplace) {
+                       db.hincrby(key, "secondplaces", 1);
+               }
+               if (stats.thirdplace) {
+                       db.hincrby(key, "thirdplaces", 1);
+               }
+       };
+
+       return collectStats;
+};
index f6eb75c79cdc4fa35c5630facc71c3cfcf9fe78c..a140912c72e76c5cd29a1a042e6e705bb32374a7 100644 (file)
@@ -18,5 +18,5 @@
   "engines": {
     "node": "0.6.x"
   },
-  "version": "0.3.0-8"
+  "version": "0.3.0-9"
 }
\ No newline at end of file
index ed69b9b359213ef8f1445087109559dc058cfef5..2bf9180a68f7759f84a328c5ee7159052a6f00e9 100644 (file)
@@ -537,7 +537,7 @@ input {
        background: -ms-linear-gradient(center top , #FBFBFB, #F5F5F5);
        background: linear-gradient(center top , #FBFBFB, #F5F5F5);
 }
-.registered, #users .name, #users .points, .round-rank, .round-points, #users .guess-time, #tracks img.artwork, #tracks .info, #copy, #facebook-button, #twitter-button, #github-button {
+.registered, #users .name, #users .points, .round-rank, .round-points, #users .guess-time, #tracks img.artwork, #tracks .info, #copy, .fb-like, #twitter-button, #github-button {
        float:left;
 }
 #tracks img.artwork {
@@ -590,7 +590,7 @@ footer {
 #copy {
        margin: 0 20px 0 20px;
 }
-#facebook-button {
+.fb-like {
        width:90px;
        height:21px
 }
index 553e10539faa4f2ba2aae7a690385ef471b330b0..e008524d8352d392218332f52d077964ea594bf2 100644 (file)
--- a/server.js
+++ b/server.js
@@ -1,11 +1,14 @@
-var async = require("async");
-var crypto = require("crypto");
-var canvas = require("canvas");
-var express = require("express");
-var form = require("express-form");
+var async = require('async');
+var characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+var Captcha = require('./lib/captcha.js')(characters);
+var config = require('./config.js').configure();
+var crypto = require('crypto');
+var express = require('express');
+var form = require('express-form');
 var parseCookie = require('connect').utils.parseCookie;
 var redisstore = require('connect-redis')(express);
-var config = require("./config.js").configure();
+var rooms = Object.create(null); // The Object that contains all the room instances
+var sockets = Object.create(null); // Sockets of all rooms
 
 // Setting up Redis
 var songsdb = require("redis-url").createClient(config.songsdburl);
@@ -39,32 +42,6 @@ http.get("/", function(req, res) {
        res.render("index", {rooms:config.rooms});
 });
 
-// Captcha generator
-const CHARACTERS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
-
-var Captcha = function() {
-       var code = "";
-       while (code.length < 4) {
-               code += CHARACTERS[Math.floor(Math.random() * CHARACTERS.length)];
-       }
-       var _canvas = new canvas(64, 26);
-       var ctx = _canvas.getContext('2d');
-       ctx.fillStyle = "#DDDDDD";
-       ctx.fillRect(0, 0, 64, 26);
-       ctx.font = "bold 20px Helvetica";
-       ctx.lineWidth = 1;
-       ctx.textAlign = "center";
-       ctx.strokeStyle = "#080";
-       ctx.strokeText(code, 31, 20);
-       ctx.save();
-       this.getCode = function() {
-               return code;
-       };
-       this.toDataURL = function() {
-               return _canvas.toDataURL();
-       };
-};
-
 http.get("/signup", function(req, res) {
        var captcha = new Captcha();
        req.session.captchacode = captcha.getCode();
@@ -132,7 +109,7 @@ http.post("/signup",
                var mailkey = "email:"+req.form.email;
                var salt = "";
                while (salt.length < 8) {
-                       salt += CHARACTERS[Math.floor(Math.random() * CHARACTERS.length)];
+                       salt += characters[Math.floor(Math.random() * characters.length)];
                }
                var hash = crypto.createHash('sha256').update(salt+req.form.password).digest('hex');
                var date = new Date();
@@ -310,8 +287,8 @@ io.sockets.on('connection', function(socket) {
        var session = socket.handshake.session;
        socket.on('getoverview', function() {
                var data = Object.create(null);
-               for (var prop in Rooms) {
-                       data[prop] = Rooms[prop].getPopulation();
+               for (var prop in rooms) {
+                       data[prop] = rooms[prop].getPopulation();
                }
                socket.join('home');
                socket.emit('overview', data);
@@ -321,604 +298,59 @@ io.sockets.on('connection', function(socket) {
        });
        socket.on('joinroom', function(data) {
                if (session.user && typeof data === "string" && config.rooms.indexOf(data) !== -1) {
-                       if (getUserSocket(session.user)) { // User already in a room
+                       if (sockets[session.user]) { // User already in a room
                                socket.emit('alreadyinaroom');
                                return;
                        }
                        socket.nickname = session.user;
-                       Rooms[data].joinRoom(socket);
+                       rooms[data].joinRoom(socket);
                }
-       }); 
+       });
        socket.on('joinanonymously', function(data) {
                if (!socket.nickname && typeof data === "object" && typeof data.nickname === "string" &&
                        data.nickname !== "" && typeof data.roomname === "string" && 
                        config.rooms.indexOf(data.roomname) !== -1) {
-                       Rooms[data.roomname].setNickName(socket, data);
+                       rooms[data.roomname].setNickName(socket, data);
                }
        });
        socket.on('getstatus', function() {
                if (socket.roomname) {
-                       Rooms[socket.roomname].sendStatus(socket);
+                       rooms[socket.roomname].sendStatus(socket);
                }
        });
        socket.on('sendchatmsg', function(data) {
                if (socket.roomname) {
-                       Rooms[socket.roomname].sendChatMessage(socket, data);
+                       rooms[socket.roomname].sendChatMessage(socket, data);
                }
        });
        socket.on('guess', function(data) {
                if (socket.roomname && typeof data === "string") {
-                       Rooms[socket.roomname].guess(socket, data);
+                       rooms[socket.roomname].guess(socket, data);
                }
        });
        socket.on("disconnect", function() {
-               if (socket.roomname && socket.nickname) {
-                       Rooms[socket.roomname].userLeft(socket);
+               if (socket.roomname) {
+                       rooms[socket.roomname].userLeft(socket.nickname);
                }
        });
 });
 
-// Sockets of all rooms
-var sockets = Object.create(null);
-
-// Get the socket of a player
-var getUserSocket = function(nickname) {
-       return sockets[nickname];
-};
-
-/*
-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
-algorithm in better than O(n*m).
-We use only a diagonal stripe of width 2k+1 in the matrix.
-See Algorithms on strings, trees, and sequences: computer science and computational biology.
-Cambridge, UK: Cambridge University Press. pp 263-264. ISBN 0-521-58519-8.
-*/
-var checkDistance = function(s1, s2, k) {
-       if (k === 0) {
-               return s1 === s2;
-       }
-       if (Math.abs(s1.length - s2.length) > k) {
-               return false;
-       }
-       var d = [];
-       for (var i=0; i <= s1.length; i++) {
-               d[i] = []; // Now d is a matrix with s1.length + 1 rows
-               d[i][0] = i;
-       }
-       for (var j=0; j <= s2.length; j++) {
-               d[0][j] = j;
-       }
-       for (i=1; i <= s1.length; i++) {
-               var l = ((i-k) < 1) ? 1 : i-k;
-               var m = ((i+k) > s2.length) ? s2.length : i+k;
-               for (j=l; j<=m; j++) {
-                       if (s1.charAt(i-1) === s2.charAt(j-1)) {
-                               d[i][j] = d[i-1][j-1];
-                       }
-                       else {
-                               if ((j === l) && (d[i][j-1] === undefined)) {
-                                       d[i][j] = Math.min(d[i-1][j-1]+1, d[i-1][j]+1);
-                               }
-                               else if ((j === m) && (d[i-1][j] === undefined)) {
-                                       d[i][j] = Math.min(d[i][j-1]+1, d[i-1][j-1]+1);
-                               }
-                               else {
-                                       d[i][j] = Math.min(d[i][j-1]+1, d[i-1][j-1]+1, d[i-1][j]+1);
-                               }
-                       }
-               }
-       }
-       return d[s1.length][s2.length] <= k;
-};
-
-var amatch = function(subject, guess, enableartistrules) {
-       if (checkDistance(subject, guess, config.threshold)) {
-               return true;
-       }
-       var splitted, trimmed;
-       if (subject.match(/\./) && 
-               checkDistance(subject.replace(/\./g, ""), guess, config.threshold)) {
-               return true;
-       }
-       if (subject.match(/\-/) && 
-               checkDistance(subject.replace(/\-/g, ""), guess, config.threshold)) {
-               return true;
-       }
-       if (subject.match(/\+/) && 
-               checkDistance(subject.replace(/\+/, "and"), guess, config.threshold)) {
-               return true;
-       }
-       if (enableartistrules) {
-               if (subject.match(/^the /)) {
-                       var nothe = subject.replace(/^the /, "");
-                       if (checkDistance(nothe, guess, config.threshold)) {
-                               return true;
-                       }
-                       if (nothe.match(/jimi hendrix experience/) && 
-                               checkDistance(nothe.replace(/ experience/, ""), guess, config.threshold)) {
-                               return true;
-                       }
-               }
-               splitted = subject.split("&");
-               if (splitted.length !== 1) {
-                       for (var i=0; i<splitted.length; i++) {
-                               trimmed = splitted[i].replace(/^ +/, "").replace(/ +$/, "");
-                               if (checkDistance(trimmed, guess, config.threshold)) {
-                                       return true;
-                               }
-                               if (trimmed.match(/^the /) && 
-                                       checkDistance(trimmed.replace(/^the /, ""), guess, config.threshold)) {
-                                       return true;
-                               }
-                       }
-               }
-       }
-       else {
-               if (subject.match(/,/) && 
-                       checkDistance(subject.replace(/,/g, ""), guess, config.threshold)) {
-                       return true;
-               }
-               if (subject.match(/ & /) && !subject.match(/\(/) &&
-                       checkDistance(subject.replace(/ & /, " and "), guess, config.threshold)) {
-                       return true;
-               }
-               if (subject.match(/\(.+\)\??(?: \[.+\])?/)) {
-                       var normalized = subject.replace(/\(.+\)\??(?: \[.+\])?/, "")
-                                                                       .replace(/^ +/, "").replace(/ +$/, "");
-                       if (checkDistance(normalized, guess, config.threshold)) {
-                               return true;
-                       }
-                       if (normalized.match(/ & /) && 
-                               checkDistance(normalized.replace(/ & /, " and "), guess, config.threshold)) {
-                               return true;
-                       }
-               }
-               if (subject.match(/, [pP]t\. [0-9]$/) && 
-                       checkDistance(subject.replace(/, [pP]t\. [0-9]$/, ""), guess, config.threshold)) {
-                       return true;
-               }
-       }
-       return false;
-};
-
-var collectStats = function(username, stats) {
-       var key = "user:"+username;
-       if (stats.points) {
-               usersdb.hincrby(key, "totpoints", stats.points);
-       }
-       if (stats.userscore) {
-               // Set personal best
-               usersdb.hget(key, "bestscore", function(err, res) {
-                       if (res < stats.userscore) {
-                               usersdb.hset(key, "bestscore", stats.userscore);
-                       }
-               });
-       }
-       if (stats.gold) {
-               usersdb.hincrby(key, "golds", 1);
-       }
-       if (stats.silver) {
-               usersdb.hincrby(key, "silvers", 1);
-       }
-       if (stats.bronze) {
-               usersdb.hincrby(key, "bronzes", 1);
-       }
-       if (stats.guesstime) {
-               usersdb.hincrby(key, "guessed", 1);
-               usersdb.hincrby(key, "totguesstime", stats.guesstime);
-               usersdb.hget(key, "bestguesstime", function(err, res) {
-                       if (stats.guesstime < res) {
-                               usersdb.hset(key, "bestguesstime", stats.guesstime);
-                       }
-               });
-               usersdb.hget(key, "worstguesstime", function(err, res) {
-                       if (stats.guesstime > res) {
-                               usersdb.hset(key, "worstguesstime", stats.guesstime);
-                       }
-               });
-       }
-       if (stats.firstplace) {
-               usersdb.hincrby(key, "victories", 1);
-       }
-       if (stats.secondplace) {
-               usersdb.hincrby(key, "secondplaces", 1);
-       }
-       if (stats.thirdplace) {
-               usersdb.hincrby(key, "thirdplaces", 1);
-       }
+// Setting up the rooms
+var roomoptions = {
+       songsdb: songsdb,
+       usersdb: usersdb,
+       io: io,
+       sockets: sockets,
+       songsinarun: config.songsinarun,
+       fifolength: config.fifolength,
+       threshold: config.threshold
 };
 
-function Room(name) {
-
-       var roomname = name;
-       var totusers = 0;
-       
-       var usersData = Object.create(null);
-       var playedtracks = []; // The list of already played songs
-       
-       var artistName = null;
-       var artistlcase = null;
-       var trackName = null;
-       var tracklcase = null;
-       var collectionName = null;
-       var previewUrl = null;
-       var artworkUrl = null;
-       var trackViewUrl = null;
-       var finishline = 1;
-       var allowedguess = false;
-       var status = null;
-       var songtimeleft = null; // Milliseconds
-       var songcounter = 0;
-       var trackscount = 0;
-
-       this.getPopulation = function() {
-               return totusers;
-       };
-
-       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,
-                       bestguesstime: 30000,
-                       golds: 0,
-                       silvers: 0,
-                       bronzes: 0
-               };
-               totusers = totusers + 1;
-               io.sockets.in('home').emit('update', {room:roomname,players:totusers});
-               // Broadcast new user event
-               socket.emit('ready', {users:usersData,trackscount:trackscount,loggedin:loggedin});
-               socket.broadcast.to(roomname).emit('newuser', {nickname:socket.nickname,users:usersData});
-       };
-
-       var removeUser = function(socket) {
-               // Delete the references
-               delete sockets[socket.nickname];
-               delete usersData[socket.nickname];
-               totusers = totusers - 1;
-               io.sockets.in('home').emit('update', {room:roomname,players:totusers});
-       };
-
-       var userExists = function(nickname) {
-               var user = usersData[nickname];
-               if (user) {
-                       return true;
-               }
-               return false;
-       };
-       
-       this.joinRoom = function(socket) {
-               socket.roomname = roomname;
-               socket.join(roomname);
-               addUser(socket, true);
-       };
-       
-       // A user requested an invalid name
-       var invalidNickName = function(socket, feedback) {
-               socket.emit('invalidnickname', feedback);
-       };
-
-       // A user is submitting a name
-       this.setNickName = function(socket, data) {
-               var feedback = null;
-               if (data.nickname.length > 15) {
-                       feedback = '<span class="label label-important">That name is too long.</span>';
-               }
-               else if (data.nickname === "binb") {
-                       feedback = '<span class="label label-important">That name is reserved.</span>';
-               }
-               else if (getUserSocket(data.nickname)) {
-                       feedback = '<span class="label label-important">Name already taken.</span>';
-               }
-               if (feedback) {
-                       return invalidNickName(socket, feedback);
-               }
-               
-               var key = "user:"+data.nickname;
-               usersdb.exists(key, function(err, resp) {
-                       if (resp === 1) { // User already exists
-                               feedback = '<span class="label label-important">That name belongs ';
-                               feedback += 'to a registered user.</span>';
-                               return invalidNickName(socket, feedback);
-                       }
-                       else {
-                               socket.nickname = data.nickname;
-                               socket.roomname = roomname;
-                               socket.join(roomname);
-                               // Add user to the list of active users
-                               addUser(socket, false);
-                       }
-               });
-       };
-
-       // A user has left (DCed, etc.)
-       this.userLeft = function(socket) {
-               var leftname = socket.nickname;
-               removeUser(socket);
-               io.sockets.in(roomname).emit('userleft', {nickname:leftname,users:usersData});
-       };
-       
-       this.sendChatMessage = function (socket, data) {
-               if (typeof data === "string") {
-                       var datalcase = data.toLowerCase();
-                       if (allowedguess && (amatch(artistlcase, datalcase, true) || 
-                                                               amatch(tracklcase, datalcase))) {
-                               var msg = "You are probably right, but you have to use the box above.";
-                               socket.emit('chatmsg', {from:"binb",to:socket.nickname,chatmsg:msg});
-                               return;
-                       }
-                       io.sockets.in(roomname).emit('chatmsg', {from:socket.nickname,chatmsg:data});
-               }
-               else if (typeof data === "object" && typeof data.to === "string" && 
-                                       userExists(data.to) && typeof data.chatmsg === "string") {
-                       // Private message
-                       socket.emit('chatmsg', {from:socket.nickname,to:data.to,chatmsg:data.chatmsg});
-                       var recipient = getUserSocket(data.to);
-                       recipient.emit('chatmsg', {from:socket.nickname,to:data.to,chatmsg:data.chatmsg});
-               }
-       };
-
-       var addPoints = function(socket, allinone) {
-               usersData[socket.nickname].guesstime = 30000 - songtimeleft;
-               var stats = {};
-               switch (finishline) {
-                       case 1:
-                               finishline++;
-                               usersData[socket.nickname].roundpoints = 6;
-                               if (allinone) {
-                                       usersData[socket.nickname].points += 6;
-                                       stats.points = 6;
-                               }
-                               else {
-                                       usersData[socket.nickname].points += 5;
-                                       stats.points = 5;
-                               }
-                               usersData[socket.nickname].golds++;
-                               stats.gold = true;
-                               break;
-                       case 2:
-                               finishline++;
-                               usersData[socket.nickname].roundpoints = 5;
-                               if (allinone) {
-                                       usersData[socket.nickname].points += 5;
-                                       stats.points = 5;
-                               }
-                               else {
-                                       usersData[socket.nickname].points += 4;
-                                       stats.points = 4;
-                               }
-                               usersData[socket.nickname].silvers++;
-                               stats.silver = true;
-                               break;
-                       case 3:
-                               finishline++;
-                               usersData[socket.nickname].roundpoints = 4;
-                               if (allinone) {
-                                       usersData[socket.nickname].points += 4;
-                                       stats.points = 4;
-                               }
-                               else {
-                                       usersData[socket.nickname].points += 3;
-                                       stats.points = 3;
-                               }
-                               usersData[socket.nickname].bronzes++;
-                               stats.bronze = true;
-                               break;
-                       default:
-                               usersData[socket.nickname].roundpoints = 3;
-                               if (allinone) {
-                                       usersData[socket.nickname].points += 3;
-                                       stats.points = 3;
-                               }
-                               else {
-                                       usersData[socket.nickname].points += 2;
-                                       stats.points = 2;
-                               }
-               }
-               usersData[socket.nickname].matched = 'both';
-               usersData[socket.nickname].guessed++;
-               if (usersData[socket.nickname].guesstime < usersData[socket.nickname].bestguesstime) {
-                       usersData[socket.nickname].bestguesstime = usersData[socket.nickname].guesstime;
-               }
-               if (usersData[socket.nickname].registered) {
-                       stats.userscore = usersData[socket.nickname].points;
-                       stats.guesstime = usersData[socket.nickname].guesstime;
-                       collectStats(socket.nickname, stats);
-               }
-       };
-       
-       this.guess = function(socket, guess) {
-               if (allowedguess) {
-                       if (!usersData[socket.nickname].matched) { // No track no artist
-                               if ((artistlcase === tracklcase) && amatch(tracklcase, guess, true)) {
-                                       addPoints(socket, true);
-                                       socket.emit('bothmatched');
-                                       io.sockets.in(roomname).emit('updateusers', {users:usersData});
-                               }
-                               else if (amatch(artistlcase, guess, true)) {
-                                       usersData[socket.nickname].roundpoints++;
-                                       usersData[socket.nickname].points++;
-                                       usersData[socket.nickname].matched = 'artist';
-                                       socket.emit('artistmatched');
-                                       io.sockets.in(roomname).emit('updateusers', {users:usersData});
-                                       if (usersData[socket.nickname].registered) {
-                                               var stats = {points:1,userscore:usersData[socket.nickname].points};
-                                               collectStats(socket.nickname, stats);
-                                       }
-                               }
-                               else if (amatch(tracklcase, guess)) {
-                                       usersData[socket.nickname].roundpoints++;
-                                       usersData[socket.nickname].points++;
-                                       usersData[socket.nickname].matched = 'title';
-                                       socket.emit('titlematched');
-                                       io.sockets.in(roomname).emit('updateusers', {users: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(tracklcase, guess)) {
-                                               addPoints(socket, false);
-                                               socket.emit('bothmatched');
-                                               io.sockets.in(roomname).emit('updateusers', {users:usersData});
-                                       }
-                                       else {
-                                               socket.emit('nomatch');
-                                       }
-                               }
-                               else {
-                                       if (amatch(artistlcase, guess, true)) {
-                                               addPoints(socket, false);
-                                               socket.emit('bothmatched');
-                                               io.sockets.in(roomname).emit('updateusers', {users:usersData});
-                                       }
-                                       else {
-                                               socket.emit('nomatch');
-                                       }
-                               }
-                       }
-                       else { // The user has guessed both track and artist
-                               socket.emit('stoptrying');
-                       }
-               }
-               else {
-                       socket.emit('noguesstime');
-               }
-       };
-       
-       var resetPoints = function(roundonly) {
-               for (var key in usersData) {
-                       if (!roundonly) {
-                               usersData[key].points = 0;
-                               usersData[key].guessed = 0;
-                               usersData[key].bestguesstime = 30000;
-                               usersData[key].golds = 0;
-                               usersData[key].silvers = 0;
-                               usersData[key].bronzes = 0;
-                       }
-                       usersData[key].roundpoints = 0;
-                       usersData[key].matched = null;
-                       usersData[key].guesstime = null;
-               }
-       };
-
-       var sendLoadTrack = function() {
-               songsdb.srandmember(roomname, function(err, res) {
-                       songsdb.hmget(res, "artistName", "trackName", "collectionName", "previewUrl",
-                                                       "artworkUrl60", "trackViewUrl", function(e, replies) {
-                               if (playedtracks.indexOf(res) !== -1) {
-                                       return sendLoadTrack();
-                               }
-                               playedtracks.push(res);
-                               artistName = replies[0];
-                               artistlcase = artistName.toLowerCase();
-                               trackName = replies[1];
-                               tracklcase = trackName.toLowerCase();
-                               collectionName = replies[2];
-                               previewUrl = replies[3];
-                               artworkUrl = replies[4];
-                               trackViewUrl = replies[5];
-                               io.sockets.in(roomname).emit('loadtrack', {previewUrl:previewUrl});
-                               setTimeout(sendPlayTrack, 5000);
-                       });
-               });
-               status = 1; // Loading next song
-       };
-
-       var sendPlayTrack = function() {
-               songcounter = songcounter + 1;
-               status = 0; // Playing track
-               io.sockets.in(roomname).emit('playtrack', {counter:songcounter,tot:config.songsinarun,
-                                                                               users:usersData});
-               songTimeLeft(Date.now()+30000, 50);
-               allowedguess = true;
-               setTimeout(sendTrackInfo, 30000);
-       };
-       
-       var songTimeLeft = function(end, delay) {
-               songtimeleft = end - Date.now();
-               if (songtimeleft < delay) {
-                       return;
-               }
-               setTimeout(songTimeLeft, delay, end, delay);
-       };
-       
-       var sendTrackInfo = function() {
-               io.sockets.in(roomname).emit('trackinfo', {artworkUrl:artworkUrl,artistName:artistName,
-                                                                               trackName:trackName,collectionName:collectionName,
-                                                                               trackViewUrl:trackViewUrl});
-               finishline = 1;
-               allowedguess = false;
-               if (songcounter < config.songsinarun) {
-                       resetPoints(true);
-                       sendLoadTrack();
-               }
-               else {
-                       status = 2; // Sending last track info
-                       setTimeout(gameOver, 5000);
-               }
-       };
-
-       var gameOver = function() {
-               status = 3; // Game over
-               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', {users:podium});
-               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);
-               setTimeout(reset, 5000);
-       };
-
-       this.sendStatus = function(socket) {
-               socket.emit('status', {status:status,timeleft:songtimeleft,previewUrl:previewUrl});
-       };
-
-       var reset = function() {
-               songcounter = 0;
-               if (playedtracks.length === config.fifolength) {
-                       playedtracks.splice(0, config.songsinarun);
-               }
-               sendLoadTrack();
-       };
-
-       // Start the room
-       this.start = function() {
-               songsdb.scard(roomname, function(err, res) {
-                       trackscount = res;
-               });
-               sendLoadTrack();
-       };
-}
+var Room = require('./lib/room.js')(roomoptions);
 
-var Rooms = Object.create(null);
 for (var i=0; i<config.rooms.length; i++) {
-       Rooms[config.rooms[i]] = new Room(config.rooms[i]);
-       Rooms[config.rooms[i]].start();
+       rooms[config.rooms[i]] = new Room(config.rooms[i]);
+       rooms[config.rooms[i]].start();
 }
 
 console.log("binb started and listening on port "+config.port);
similarity index 53%
rename from views/uv.jade
rename to views/feedback.jade
index 2adbc49945611ce9362ec155d028a2497729bf18..3b882185138e34b27ef02938ab800b46d39343d0 100644 (file)
@@ -1,4 +1,13 @@
-script(type="text/javascript")
+#fb-root
+script
+       (function(d, s, id) {
+               var js, fjs = d.getElementsByTagName(s)[0];
+               if (d.getElementById(id)) return;
+               js = d.createElement(s); js.id = id;
+               js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
+               fjs.parentNode.insertBefore(js, fjs);
+       }(document, 'script', 'facebook-jssdk'));
+script
        var uvOptions = {};
        (function() {
                var uv = document.createElement('script');
index f881d3ede66292b574ce99cf205331d7831f8992..e67411bd6839533e27deefc9ee3cdabdec6ae844 100644 (file)
@@ -1,8 +1,8 @@
 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")
+               .fb-like(data-href="http://binb.nodejitsu.com", data-layout="button_count",
+                       data-send="false", data-show-faces="false")
                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", 
index c9fe1a0d47a753156cddee5c3750b6392f35a6f8..228891db6c222c7921e54fdf3e1318cad5547038 100644 (file)
@@ -8,7 +8,7 @@ head
        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="/static/js/jquery.min.js")
-       script(type="text/javascript")
+       script
                var _gaq = _gaq || [];
                _gaq.push(['_setAccount', 'UA-29865853-1']);
                _gaq.push(['_trackPageview']);
index aca79314ae4e12432106e03f935ed80d964ee8d2..bb9a4ce537a64e8506e1d3d49d2937275fa1f598 100644 (file)
@@ -6,7 +6,7 @@ html
                script(src="/static/js/bootstrap.min.js")
                script(src="/static/js/home.js")
        body
-               include uv.jade
+               include feedback.jade
                .navbar.navbar-fixed-top
                        .navbar-inner
                                .container
index 09bc95350c971777b94134992ea0180b68e9b5f2..9b75a422454f48d9fe958fef8b998ea78f993064 100644 (file)
@@ -4,7 +4,7 @@ html
                title binb :: login
                script(src="/static/js/bootstrap.min.js")
        body
-               include uv.jade
+               include feedback.jade
                .navbar.navbar-fixed-top
                        .navbar-inner
                                .container
index 1f4d5f6011d4b79f222047ff561b6e32b9c2b649..4023d06e92407ff348d404c5d3ee981a83609368 100644 (file)
@@ -9,7 +9,7 @@ html
                        var roomname = "#{roomname}";
                script(src="/static/js/room.js")
        body
-               include uv.jade
+               include feedback.jade
                .navbar.navbar-fixed-top
                        .navbar-inner
                                .container
index c82727fe30e923228208f894f68fe9311badcadd..5f5d28f8270cc339ea9595f0aca770fd3111af81 100644 (file)
@@ -4,7 +4,7 @@ html
                title binb :: sign up
                script(src="/static/js/bootstrap.min.js")
        body
-               include uv.jade
+               include feedback.jade
                .navbar.navbar-fixed-top
                        .navbar-inner
                                .container
index cbe03c68642453d3c7693ee8b73a87f72b75097f..ddea9f14884e072af376c15c906aa9b86113557a 100644 (file)
@@ -3,7 +3,7 @@ html
        include header
                title binb :: #{username} info
        body
-               include uv.jade
+               include feedback.jade
                .navbar.navbar-fixed-top
                        .navbar-inner
                                .container