* 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;
};
/**
- * Return `amatch` function.
+ * Expose `amatch` function.
*/
module.exports = function(allowederrors) {
return true;
}
- var splitted, trimmed;
-
// Ignore dots
- if (subject.match(/\./) &&
- checkDistance(subject.replace(/\./g, ""), guess, threshold)) {
- return true;
- }
- // Ignore commas
- if (subject.match(/,/) &&
- checkDistance(subject.replace(/,/g, ""), guess, threshold)) {
+ if (/\./.test(subject) &&
+ checkDistance(subject.replace(/\./g, ''), guess, threshold)) {
return true;
}
// Ignore dashes
- if (subject.match(/\-/) &&
- checkDistance(subject.replace(/\-/g, ""), guess, threshold)) {
+ if (/\-/.test(subject) &&
+ checkDistance(subject.replace(/\-/g, ''), guess, threshold)) {
return true;
}
// Allow to write "and" in place of "+"
- if (subject.match(/\+/) &&
- checkDistance(subject.replace(/\+/, "and"), guess, threshold)) {
+ 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 (subject.match(/^the /)) {
- var nothe = subject.replace(/^the /, "");
+ if (/^the /.test(subject)) {
+ var nothe = subject.replace(/^the /, '');
if (checkDistance(nothe, guess, threshold)) {
return true;
}
- if (nothe.match(/jimi hendrix experience/) &&
- checkDistance(nothe.replace(/ experience/, ""), guess, threshold)) {
+ if (/jimi hendrix experience/.test(nothe) &&
+ checkDistance(nothe.replace(/ experience/, ''), guess, threshold)) {
return true;
}
}
- // Split artist name on "&" (artist name can be composed by more names)
- splitted = subject.split("&");
+ // 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++) {
- trimmed = splitted[i].replace(/^ +/, "").replace(/ +$/, "");
- if (checkDistance(trimmed, guess, threshold)) {
+ if (checkDistance(splitted[i], guess, threshold)) {
return true;
}
- if (trimmed.match(/^the /) &&
- checkDistance(trimmed.replace(/^the /, ""), guess, threshold)) {
+ if (/^the /.test(splitted[i]) &&
+ checkDistance(splitted[i].replace(/^the /, ''), guess, threshold)) {
return true;
}
}
}
}
else {
- // Allow to write "and" in place of "&"
- if (subject.match(/ & /) && !subject.match(/\(/) &&
- checkDistance(subject.replace(/ & /, " and "), guess, threshold)) {
+ // Ignore commas
+ if (/,/.test(subject) &&
+ checkDistance(subject.replace(/,/g, ''), guess, threshold)) {
return true;
}
// Ignore additional info e.g. "(Love Theme from Titanic)"
- if (subject.match(/\(.+\)\??(?: \[.+\])?/)) {
- var normalized = subject.replace(/\(.+\)\??(?: \[.+\])?/, "")
- .replace(/^ +/, "").replace(/ +$/, "");
+ if (/\(.+\)\??(?: \[.+\])?/.test(subject)) {
+ var normalized = subject.replace(/\(.+\)\??(?: \[.+\])?/, '')
+ .replace(/^ +/, '').replace(/ +$/, '');
if (checkDistance(normalized, guess, threshold)) {
return true;
}
- if (normalized.match(/ & /) &&
- checkDistance(normalized.replace(/ & /, " and "), guess, threshold)) {
+ if (/ & /.test(normalized) &&
+ checkDistance(normalized.replace(/ & /, ' and '), guess, threshold)) {
return true;
}
}
- if (subject.match(/, [pP]t\. [0-9]$/) &&
- checkDistance(subject.replace(/, [pP]t\. [0-9]$/, ""), guess, threshold)) {
+ if (/, [pP]t\. [0-9]$/.test(subject) &&
+ checkDistance(subject.replace(/, [pP]t\. [0-9]$/, ''), guess, threshold)) {
return true;
}
}
/**
- * Return the `Room` class
+ * Expose the `Room` class.
*/
module.exports = function(params) {
function Room(roomname) {
var allowedguess = false
- , artistlcase
+ , 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
- , tracklcase
+ , title // Title in lowercase
, trackName
, trackscount = 0
, trackViewUrl
}
// Censor answers from chat
var msglcase = msg.toLowerCase();
- if (allowedguess && (amatch(artistlcase, msglcase, true) ||
- amatch(tracklcase, msglcase))) {
+ 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;
this.guess = function(socket, guess) {
if (allowedguess) {
if (!usersData[socket.nickname].matched) { // No track no artist
- if ((artistlcase === tracklcase) && amatch(tracklcase, guess, true)) {
+ if ((artist === title) && amatch(title, guess, true)) {
addPointsAndStats(socket.nickname, true);
socket.emit('bothmatched');
io.sockets.in(roomname).emit('updateusers', usersData);
}
- else if (amatch(artistlcase, guess, true)) {
+ else if (amatch(artist, guess, true) || (feat && amatch(feat, guess, true))) {
usersData[socket.nickname].roundpoints++;
usersData[socket.nickname].points++;
usersData[socket.nickname].matched = 'artist';
collectStats(socket.nickname, stats);
}
}
- else if (amatch(tracklcase, guess)) {
+ else if (amatch(title, guess)) {
usersData[socket.nickname].roundpoints++;
usersData[socket.nickname].points++;
usersData[socket.nickname].matched = 'title';
}
else if (usersData[socket.nickname].matched !== 'both') { // Track or artist
if (usersData[socket.nickname].matched === 'artist') {
- if (amatch(tracklcase, guess)) {
+ if (amatch(title, guess)) {
addPointsAndStats(socket.nickname, false);
socket.emit('bothmatched');
io.sockets.in(roomname).emit('updateusers', usersData);
}
}
else {
- if (amatch(artistlcase, guess, true)) {
+ if (amatch(artist, guess, true) || (feat && amatch(feat, guess, true))) {
addPointsAndStats(socket.nickname, false);
socket.emit('bothmatched');
io.sockets.in(roomname).emit('updateusers', usersData);
}
playedtracks.push(res);
songsdb.hmget('song:'+res, 'artistName', 'trackName', 'collectionName', 'previewUrl',
- 'artworkUrl60', 'trackViewUrl', function(e, replies) {
+ 'artworkUrl60', 'trackViewUrl', function(e, replies) {
artistName = replies[0];
- artistlcase = artistName.toLowerCase();
+ artist = artistName.toLowerCase();
trackName = replies[1];
- tracklcase = trackName.toLowerCase();
+ title = trackName.toLowerCase();
+ feat = /feat\. (.+?)[)\]]/.test(title) ? RegExp.$1 : null;
collectionName = replies[2];
previewUrl = replies[3];
artworkUrl = replies[4];