Skip to content

Commit

Permalink
Way too much for one commit hashtag yolo
Browse files Browse the repository at this point in the history
  • Loading branch information
imakewebthings committed Dec 11, 2013
1 parent 75941d5 commit 7a8e470
Show file tree
Hide file tree
Showing 17 changed files with 262 additions and 15 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
*.swp
config.json
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: node index.js
4 changes: 3 additions & 1 deletion app/chatList.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ var ChatList = function() {
};

ChatList.prototype.push = function(chat) {
this.chats.push(chat);
if (chat.value.message) {
this.chats.push(chat);
}
if (this.chats.length > 200) {
this.chats.shift();
}
Expand Down
13 changes: 13 additions & 0 deletions app/chatStream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var socketClient = require('socket.io-client');

var ChatStream = function(chatList, nconf) {
this.chatList = chatList;
this.socket = socketClient.connect(nconf.get('SOCKET_URL'));
this.socket.on('message', this.handleMessage.bind(this));
};

ChatStream.prototype.handleMessage = function(data) {
this.chatList.push(data.chat);
};

module.exports = ChatStream;
35 changes: 35 additions & 0 deletions app/matchmaker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
var shuffle = require('knuth-shuffle').knuthShuffle;

var Matchmaker = function(chatList) {
this.chatList = chatList;
};

Matchmaker.prototype.generate = function() {
if (this.chatList.chats.length < 30) {
return null;
}
var randomIndices = [];
var match = {
answers: []
};

while(randomIndices.length < 5) {
var num = Math.floor(Math.random() * this.chatList.chats.length);
if (randomIndices.indexOf(num) === -1) {
randomIndices.push(num);
}
}
randomIndices.forEach(function(chatListIndex, randIndex) {
var chat = this.chatList.chats[chatListIndex];
match.answers.push(chat.value.message);
if (!randIndex) {
match.rightAnswer = chat.value.message;
match.gif = chat.value.media;
}
}.bind(this));

match.answers = shuffle(match.answers.slice(0));
return match;
};

module.exports = Matchmaker;
19 changes: 19 additions & 0 deletions app/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module.exports = function(app, matchmaker) {
app.get('/', function(req, res) {
var match = matchmaker.generate();
if (match) {
req.session.match = match;
res.render('index', { match: match });
}
else {
res.render('warming');
}
});

app.post('/', function(req, res) {
res.render('results', {
userAnswer: req.body.answer,
match: req.session.match
});
});
};
17 changes: 17 additions & 0 deletions app/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
var express = require('express');
var path = require('path');

module.exports = function(app, nconf) {
app.set('views', path.resolve(__dirname, '..', 'views'));
app.set('view engine', 'jade');
app.set('view options', { layout: false });
app.use(express.static(__dirname + '/public'));
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({
secret: nconf.get('COOKIE_SECRET'),
key: 'meatsess',
store: new express.session.MemoryStore()
}));
app.use(app.router);
};
3 changes: 3 additions & 0 deletions config.sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"PORT": 5000
}
13 changes: 13 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var express = require('express');
var app = express();
var nconf = require('nconf').argv().env().file('config.json');
var ChatList = require('./app/chatList');
var ChatStream = require('./app/chatStream');
var Matchmaker = require('./app/matchmaker');
var chatList = new ChatList();
var chatStream = new ChatStream(chatList, nconf);
var matchmaker = new Matchmaker(chatList);

require('./app/settings')(app, nconf);
require('./app/routes')(app, matchmaker);
app.listen(nconf.get('PORT'));
19 changes: 15 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,36 @@
"version": "0.0.0",
"description": "Matching meat gifs to messagses",
"main": "index.js",
"private": true,
"scripts": {
"tdd": "testem"
"tdd": "testem",
"start": "node index.js"
},
"repository": {
"type": "git",
"url": "git://github.com/kid-icarus/Meatmatch.git"
},
"keywords": [
"fun",
"stuff"
"meatspaces"
],
"author": "cool dudes",
"license": "BSD-2-Clause",
"license": "MIT",
"bugs": {
"url": "https://github.com/kid-icarus/Meatmatch/issues"
},
"devDependencies": {
"testem": "~0.5.12",
"chai": "~1.8.1",
"mocha": "~1.15.1"
"mocha": "~1.15.1",
"socket.io": "~0.9.16"
},
"dependencies": {
"express": "~3.4.6",
"nconf": "~0.6.9",
"socket.io-client": "~0.9.16",
"jade": "~0.35.0",
"connect": "~2.11.2",
"knuth-shuffle": "~1.0.0"
}
}
34 changes: 24 additions & 10 deletions test/chatList.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,61 @@
var ChatList = require('../app/chatList');
var should = require('chai').should();

var mockChat = function(message) {
return {
key: 'lorem',
value: {
message: message == null ? 'ipsum' : message,
media: 'dolor'
}
};
};

describe('Chat List', function() {
beforeEach(function() {
this.chatList = new ChatList();
});

describe('#push', function() {
beforeEach(function() {
this.chatList.push({'first': true});
var chat = mockChat();
chat.first = true;
this.chatList.push(chat);
});

it('should push a message into the chats array', function() {
it('pushes a message into the chats array', function() {
this.chatList.chats.should.have.length(1);
});

it('should pop the oldest chat off after 200 chats', function() {
it('pops the oldest chat off after 200 chats', function() {
for(var i = 0; i < 200; i++) {
this.chatList.push({});
this.chatList.push(mockChat());
}
this.chatList.chats[0].should.not.have.property('first');
});

it('rejects chats with blank messages', function() {
this.chatList.push(mockChat(''));
this.chatList.pop().should.have.property('first');
});
});

describe('#pop', function() {
beforeEach(function() {
this.chatList.push({});
this.chatList.push(mockChat());
this.chat = this.chatList.pop();
});

it('should return an object', function(){
it('returns a chat object', function(){
this.chat.should.be.an('object');
});

it('should pop off the chats array', function() {
it('pops off the chats array', function() {
this.chatList.chats.should.have.length(0);
});

it('should return undefined if chatList is empty', function() {
it('returns undefined if chatList is empty', function() {
should.not.exist(this.chatList.pop());
});

});
});

29 changes: 29 additions & 0 deletions test/chatStream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
var ChatStream = require('../app/chatStream');
var should = require('chai').should();
var io = require('socket.io').listen(8080, { log: false });
var nconf = require('nconf');
var ChatList = require('../app/chatList');

nconf.defaults({
SOCKET_URL: 'http://localhost:8080'
});

describe('Chat Streamer', function() {
before(function(done) {
io.sockets.on('connection', function(socket) {
this.socket = socket;
done();
}.bind(this));
this.chatList = new ChatList();
this.chatStream = new ChatStream(this.chatList, nconf);
});

it('pushes incoming messages to a ChatList', function(done) {
this.chatStream.socket.on('message', function() {
this.chatList.pop().should.exist;
done();
}.bind(this));
this.socket.emit('message', { chat: { value: { message: 'test' }}});
});
});

48 changes: 48 additions & 0 deletions test/matchmaker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
var should = require('chai').should();
var Matchmaker = require('../app/matchmaker');
var ChatList = require('../app/chatList');

var fillChatList = function(chatList, n) {
for(var i = 0; i < n; i++) {
chatList.push({
key: 'key-' + i,
value: {
message: 'message-' + i,
media: 'media-' + i
}
});
}
};

describe('Matchmaker', function() {
beforeEach(function() {
this.chatList = new ChatList();
this.matchmaker = new Matchmaker(this.chatList);
});

describe('#generate', function() {
describe('without minimum number of chats', function() {
beforeEach(function() {
fillChatList(this.chatList, 29);
this.match = this.matchmaker.generate();
});

it('returns undefined', function() {
should.equal(this.match, null);
});
});

describe('with a minimum number of chats', function() {
beforeEach(function() {
fillChatList(this.chatList, 30);
this.match = this.matchmaker.generate();
});

it('returns a match object', function() {
this.match.gif.should.exist;
this.match.rightAnswer.should.exist;
this.match.answers.should.be.an('array');
});
});
});
});
12 changes: 12 additions & 0 deletions views/index.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
extend layout

block content
img(src=match.gif, alt='')
form(method='post', action='/')
ul.answers
each answer in match.answers
li
label
input(type='radio', name='answer', value=answer)
= answer
input(type='submit', value='Final Answer')
12 changes: 12 additions & 0 deletions views/layout.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
!!!
html
head
title MeatMatch
meta(charset='utf8')
meta(name='viewport', content='width=device-width, initial-scale=1.0')
meta(name='apple-mobile-web-app-capable', content='yes')
link(rel='stylesheet', href='/stylesheets/main.css')
body
.page-wrapper
h1 MeatMatch
block content
13 changes: 13 additions & 0 deletions views/results.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
extend layout

block content
- var answerCorrect = userAnswer === match.rightAnswer;
img(src=match.gif, alt='')
ul.answers
each answer in match.answers
- var classes = []
- if (answer === userAnswer) classes.push('chosen')
- if (answer === match.rightAnswer) classes.push('correct')
li(class=classes.join(' '))= answer
h2= answerCorrect ? 'Correct' : 'Wrong'
a.more-meat(href='/') More Meat
4 changes: 4 additions & 0 deletions views/warming.jade
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
extend layout

block content
p.warming-message The meat is warming up. Check back in a few.

0 comments on commit 7a8e470

Please sign in to comment.