io.sockets.on('connection', function(socket) {
var session = socket.handshake.session;
- socket.on('getoverview', function() {
+ socket.on('disconnect', function() {
+ if (socket.roomname) {
+ rooms[socket.roomname].removeUser(socket.nickname);
+ }
+ });
+ socket.on('getoverview', function(callback) {
+ if (typeof callback !== 'function') {
+ return;
+ }
var data = Object.create(null);
for (var prop in rooms) {
data[prop] = rooms[prop].getPopulation();
}
- socket.join('home');
- socket.emit('overview', data);
+ callback(data);
});
- socket.on('loggedin', function(fn) {
- return (session.user) ? fn(session.user) : fn(false);
+ socket.on('getstatus', function(callback) {
+ if (socket.roomname && typeof callback === 'function') {
+ rooms[socket.roomname].sendStatus(callback);
+ }
+ });
+ socket.on('guess', function(guess) {
+ if (socket.roomname && typeof guess === 'string') {
+ rooms[socket.roomname].guess(socket, guess);
+ }
+ });
+ socket.on('ignore', function(baduser, callback) {
+ if (socket.roomname && typeof baduser === 'string' && typeof callback === 'function') {
+ rooms[socket.roomname].ignore(baduser, socket.nickname, callback);
+ }
+ });
+ socket.on('joinanonymously', function(nickname, roomname) {
+ if (!socket.nickname && typeof nickname === 'string' && nickname !== '' &&
+ config.rooms.indexOf(roomname) !== -1) {
+ rooms[roomname].setNickName(socket, nickname);
+ }
});
socket.on('joinroom', function(room) {
- if (session.user && typeof room === 'string' && config.rooms.indexOf(room) !== -1) {
+ if (session.user && config.rooms.indexOf(room) !== -1) {
if (sockets[session.user]) { // User already in a room
socket.emit('alreadyinaroom');
return;
rooms[room].joinRoom(socket);
}
});
- socket.on('joinanonymously', function(nickname, roomname) {
- if (!socket.nickname && typeof nickname === 'string' && nickname !== '' &&
- typeof roomname === 'string' && config.rooms.indexOf(roomname) !== -1) {
- rooms[roomname].setNickName(socket, nickname);
- }
- });
- socket.on('getstatus', function() {
- if (socket.roomname) {
- rooms[socket.roomname].sendStatus(socket);
+ socket.on('loggedin', function(callback) {
+ if (typeof callback !== 'function') {
+ return;
}
+ return (session.user) ? callback(session.user) : callback(false);
});
socket.on('sendchatmsg', function(msg, to) {
if (socket.roomname && typeof msg === 'string') {
rooms[socket.roomname].sendChatMessage(msg, socket, to);
}
});
- socket.on('guess', function(guess) {
- if (socket.roomname && typeof guess === 'string') {
- rooms[socket.roomname].guess(socket, guess);
- }
- });
- socket.on('disconnect', function() {
- if (socket.roomname) {
- rooms[socket.roomname].removeUser(socket.nickname);
+ socket.on('unignore', function(baduser) {
+ if (socket.roomname && typeof baduser === 'string') {
+ rooms[socket.roomname].unignore(baduser, socket.nickname);
}
});
});
, totusers = 0
, usersData = Object.create(null);
- // 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.in('home').emit('update', roomname, totusers);
- socket.emit('ready', usersData, trackscount, loggedin);
- socket.broadcast.to(roomname).emit('newuser', socket.nickname, usersData);
- };
-
- // 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.in('home').emit('update', roomname, totusers);
- io.sockets.in(roomname).emit('userleft', nickname, usersData);
- };
-
- // Return the number of users in the room.
- this.getPopulation = function() {
- return totusers;
- };
-
- 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, 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 invalidNickName(socket, 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 invalidNickName(socket, feedback);
- }
- socket.nickname = nickname;
- socket.roomname = roomname;
- socket.join(roomname);
- addUser(socket, false);
- });
- };
-
- // 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;
- }
- io.sockets.in(roomname).emit('chatmsg', msg, socket.nickname);
- };
-
// User points and statistics
var addPointsAndStats = function(nickname, allinone) {
usersData[nickname].guesstime = 30000 - songtimeleft;
}
};
+ // 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
+
+ // 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, 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) {
}
};
+ 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);
+ };
+
+ // 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) {
}
};
+ // 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;
+ }
+ 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) {
status = 1; // Loading next song
};
- // Timer for the playing song
- var songTimeLeft = function(end, delay) {
- songtimeleft = end - Date.now();
- if (songtimeleft < delay) {
- return;
- }
- setTimeout(songTimeLeft, delay, end, delay);
- };
-
var sendPlayTrack = function() {
songcounter++;
status = 0; // Playing track
var data = {
- counter:songcounter,
- tot:songsinarun,
- users:usersData
+ counter: songcounter,
+ tot: songsinarun,
+ users: usersData
};
io.sockets.in(roomname).emit('playtrack', data);
songTimeLeft(Date.now() + 30000, 50);
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
+ artworkUrl: artworkUrl,
+ artistName: artistName,
+ trackName: trackName,
+ trackViewUrl: trackViewUrl,
+ collectionName: collectionName
};
io.sockets.in(roomname).emit('trackinfo', trackinfo);
finishline = 1;
setTimeout(gameOver, 5000);
};
- 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);
+ // A user is submitting a name
+ this.setNickName = function(socket, nickname) {
+ var feedback = null;
- // Collect podium stats
- if (podium[0] && podium[0].registered) {
- collectStats(podium[0].nickname, {firstplace:true});
+ if (nickname.length > 15) {
+ feedback = '<span class="label label-important">That name is too long.</span>';
}
- if (podium[1] && podium[1].registered) {
- collectStats(podium[1].nickname, {secondplace:true});
+ else if (nickname === 'binb') {
+ feedback = '<span class="label label-important">That name is reserved.</span>';
}
- if (podium[2] && podium[2].registered) {
- collectStats(podium[2].nickname, {thirdplace:true});
+ else if (sockets[nickname]) {
+ feedback = '<span class="label label-important">Name already taken.</span>';
}
- resetPoints(false);
- songcounter = 0;
- // Check if FIFO is full
- if (playedtracks.length === fifolength) {
- playedtracks.splice(0, songsinarun);
+ if (feedback) {
+ return socket.emit('invalidnickname', feedback);
}
- // Start a new game
- setTimeout(sendLoadTrack, 5000);
+ // 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);
+ });
};
- // Send the room status
- this.sendStatus = function(socket) {
- var data = {
- status:status,
- timeleft:songtimeleft,
- previewUrl:previewUrl
- };
- socket.emit('status', data);
+ // 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
});
sendLoadTrack();
};
+
+ this.unignore = function(baduser, executor) {
+ if (usersData[baduser]) {
+ // Inform the wicked player that he/she is no longer ignored
+ var recipient = sockets[baduser];
+ var notice = executor+' has stopped ignoring you.';
+ recipient.emit('chatmsg', notice, 'binb', baduser);
+ }
+ };
}
return Room;
, DOM = {}
, historycursor = 0
, historyvalues = []
+ , ignoredplayers = {}
, jplayer
, nickname
, pvtmsgto
, socket
, stopanimation = false
, touchplay
- , urlregex = /(https?:\/\/[-A-Za-z0-9+&@#/%?=~_()|!:,.;]*[-A-Za-z0-9+&@#/%=~_()|])/;
+ , urlregex = /(https?:\/\/[\-A-Za-z0-9+&@#\/%?=~_()|!:,.;]*[\-A-Za-z0-9+&@#\/%=~_()|])/;
var amstrings = [
'Yes, that\'s the artist. What about the title?'
html += '<th><div class="icons cups stand2"></div></th>';
html += '<th><div class="icons cups stand3"></div></th><th>Guessed</th><th>Mean time</th>';
html += '</thead><tbody>';
-
+
for(var i=0;i<3;i++) {
if (podium[i]) {
var playername = podium[i].nickname.encodeEntities();
// Receive a chat message
var getChatMessage = function(chatmsg, from, to) {
+ if (ignoredplayers[from]) {
+ return;
+ }
var prefix = from;
var msgspan = $('<span class="message"></span>');
if (to) {
DOM.togglechat.click(showChat);
};
+ // Put a player in the ignore list
+ var ignore = function(baduser, outcome) {
+ socket.emit('ignore', baduser, function(player) {
+ if (player) {
+ ignoredplayers[player] = true;
+ outcome.text('(From binb): '+player+' is now ignored.');
+ return addChatEntry(outcome);
+ }
+ outcome.append('player not found.');
+ addChatEntry(outcome);
+ });
+ };
+
// Submitted name was invalid
var invalidNickName = function(feedback) {
joinAnonymously(feedback+'<br/>Try with another one:');
if (!loggedin && !/nickname\s*\=/.test(document.cookie)) {
document.cookie = 'nickname='+encodeURIComponent(nickname)+';path=/;';
}
-
+
DOM.modal.modal('hide').empty();
$('#total-tracks span').text(trackscount);
var msg = nickname+' joined the game';
if (pvtmsgto) {
socket.emit('sendchatmsg', val, pvtmsgto);
}
+ else if (/^\/[^ ]/.test(val)) {
+ slashCommandHandler(val);
+ }
else {
socket.emit('sendchatmsg', val);
}
addFeedback(nmstrings[Math.floor(Math.random()*nmstrings.length)], 'wrong');
});
socket.on('playtrack', playTrack);
- socket.on('status', setStatus);
socket.on('stoptrying', function() {
addFeedback('You guessed both artist and title. Please wait...');
});
socket.on('trackinfo', addTrackInfo);
socket.on('updateusers', updateUsers);
socket.on('userleft', userLeft);
- socket.emit('getstatus');
+ socket.emit('getstatus', setStatus);
};
// Show the number of players inside each room
DOM.togglechat.click(hideChat);
};
+ var slashCommandHandler = function(line) {
+ var matches = line.match(/^(\/[^ ]+) ?(.*)/)
+ , argument = matches[2]
+ , command = matches[1]
+ , outcome = $('<span class="message private">(From binb): </span>');
+
+ if (/^\/(?:(?:un)?ignore|kick)$/.test(command)) {
+ if (!argument) {
+ outcome.append('usage: '+command+' <player name>');
+ return addChatEntry(outcome);
+ }
+ if (argument === nickname) {
+ outcome.append('you can\'t '+command.replace(/^\//, '')+' yourself.');
+ return addChatEntry(outcome);
+ }
+ switch (command) {
+ case '/ignore':
+ if (!ignoredplayers[argument]) {
+ return ignore(argument, outcome);
+ }
+ outcome.text('(From binb): '+argument+' is already ignored.');
+ break;
+ case '/kick':
+ // TO DO
+ break;
+ case '/unignore':
+ if (ignoredplayers[argument]) {
+ delete ignoredplayers[argument];
+ socket.emit('unignore', argument);
+ outcome.text('(From binb): '+argument+' is no longer ignored.');
+ }
+ else {
+ outcome.text('(From binb): you have not ignored '+argument+'.');
+ }
+ }
+ }
+ else {
+ outcome.append('unknown command '+command+'.');
+ }
+ addChatEntry(outcome);
+ };
+
// Update the list of players
var updateUsers = function(usersData) {
DOM.users.empty();
-
+
var users = [];
for (var key in usersData) {
users.push(usersData[key]);
}
users.sort(function(a, b) {return b.points - a.points;});
-
+
// Flag to test if our private recipient is in the list of active users
var found = false;
for (var i=0; i<users.length; i++) {
pvt.after('<a class="icons registered" target="_blank" '+href+'></a>');
}
DOM.users.append(li);
-
+
if (pvtmsgto === user.nickname) {
pvt.show();
username.click(clearPrivate);
addPrivate($(this).text());
});
}
-
+
if (nickname === user.nickname) {
username.addClass('you');
roundpoints = user.roundpoints;
DOM.rank.text(i+1);
DOM.points.text(user.points);
}
-
+
if (user.roundpoints > 0) {
roundpointsel.text('+'+user.roundpoints);
if (user.roundpoints === 1) {
}
}
}
-
+
if (!found && pvtmsgto) {
var width = DOM.recipient.outerWidth(true) + 1;
DOM.recipient.css('margin-right', '0');
// A new player has joined the game
var userJoin = function(username, usersData) {
- var msg = username+' joined the game';
+ var joinmsg = username+' joined the game';
var joinspan = $('<span class="join"></span>');
- joinspan.text(msg);
+ joinspan.text(joinmsg);
addChatEntry(joinspan);
updateUsers(usersData);
};
socket.on('alreadyinaroom', alreadyInARoom);
socket.on('disconnect', disconnect);
socket.on('invalidnickname', invalidNickName);
- socket.on('overview', roomsOverview);
socket.on('ready', ready);
- socket.on('update', updateRoomsOverview);
- socket.emit('getoverview');
+ socket.on('updateoverview', updateRoomsOverview);
+ socket.emit('getoverview', roomsOverview);
});
});