Skip to content

Commit 12ba7e6

Browse files
committed
first commit
0 parents  commit 12ba7e6

23 files changed

+1002
-0
lines changed

.gitignore

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
lib-cov
2+
*.seed
3+
*.log
4+
*.csv
5+
*.dat
6+
*.out
7+
*.pid
8+
*.gz
9+
.DS_Store
10+
Thumbs.db
11+
database
12+
13+
pids
14+
logs
15+
results
16+
17+
npm-debug.log
18+
node_modules/

files/.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!.gitignore

game/data/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.json

game/game-verifier.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
var child = require('child_process');
2+
var game = require('./game');
3+
4+
var verify = function(file, callback) {
5+
var currentGame = game.get();
6+
var verifier = child.fork(__dirname + '/verifier');
7+
8+
verifier.send({
9+
file: file,
10+
input: currentGame.input,
11+
output: currentGame.output
12+
});
13+
14+
var timer = setTimeout(function() {
15+
verifier.kill();
16+
return callback({ valid: false, err: 'script took too long (5s)' });
17+
}, 5000);
18+
19+
verifier.on('message', function(result) {
20+
clearTimeout(timer);
21+
return callback({ valid: result.valid, err: result.err });
22+
});
23+
};
24+
25+
module.exports = {
26+
verify: verify
27+
};

game/game.js

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
var fs = require('fs');
2+
var path = require('path');
3+
var crypto = require('crypto');
4+
var _ = require('underscore');
5+
6+
var game;
7+
var savePath = __dirname + '/data/game.json';
8+
9+
var start = function(data) {
10+
if (game && game.title === data.title) {
11+
game.description = data.description;
12+
game.input = data.input;
13+
game.output = data.output;
14+
game.running = true;
15+
return save();
16+
}
17+
18+
game = {
19+
title: data.title,
20+
description: data.description,
21+
input: data.input,
22+
output: data.output,
23+
running: true,
24+
entries: []
25+
};
26+
27+
save();
28+
};
29+
30+
var stop = function() {
31+
if (game) game.running = false;
32+
save();
33+
};
34+
35+
var get = function() {
36+
return game;
37+
};
38+
39+
var addEntry = function(data) {
40+
var createKey = function() {
41+
return (Math.round(Math.random() * 100000000000)).toString(36);
42+
};
43+
44+
var getGravatarUrl = function(email) {
45+
var hash = crypto.createHash('md5').update(email).digest('hex');
46+
return 'http://www.gravatar.com/avatar/' + hash + '?s=130';
47+
};
48+
49+
var countStrokes = function(file) {
50+
if (fs.existsSync(file)) {
51+
var contents = fs.readFileSync(file, 'utf8').replace(/\s/g, '');
52+
return contents.length;
53+
}
54+
};
55+
56+
if (!game.running) return { err: 'Game is not running' };;
57+
58+
var entry = _.findWhere(game.entries, { email: data.email });
59+
60+
if (entry && entry.key !== data.key) {
61+
return { err: 'This email address is taken' };
62+
}
63+
64+
if (!entry) {
65+
if (!data.email) return { err: 'Enter an email address' };
66+
if (!data.team) return { err: 'Enter a team name' };
67+
if (!data.file) return { err: 'No file was selected' };
68+
69+
entry = {
70+
email: data.email,
71+
gravatar: getGravatarUrl(data.email),
72+
team: data.team,
73+
file: data.file,
74+
key: createKey(),
75+
strokes: countStrokes(data.file),
76+
updated: new Date
77+
};
78+
79+
game.entries.push(entry);
80+
save();
81+
return { entry: entry };
82+
}
83+
84+
if (entry && entry.key === data.key) {
85+
entry.updated = new Date;
86+
entry.file = data.file;
87+
entry.strokes = countStrokes(data.file);
88+
save();
89+
return { entry: entry };
90+
}
91+
};
92+
93+
var setValid = function(key, valid) {
94+
var entry = _.findWhere(game.entries, { key: key });
95+
96+
if (entry) {
97+
entry.valid = valid;
98+
save();
99+
}
100+
};
101+
102+
var save = function() {
103+
fs.writeFileSync(savePath, JSON.stringify(game));
104+
};
105+
106+
var load = function() {
107+
if (fs.existsSync(savePath)) {
108+
game = JSON.parse(fs.readFileSync(savePath, 'utf8'));
109+
}
110+
};
111+
112+
load();
113+
114+
module.exports = {
115+
addEntry: addEntry,
116+
setValid: setValid,
117+
start: start,
118+
stop: stop,
119+
get: get
120+
};

game/verifier.js

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
var fs = require('fs');
2+
var vm = require('vm');
3+
var _ = require('underscore');
4+
5+
var global = {};
6+
7+
var formatTypeAndValue = function(value) {
8+
var getType = function(value) {
9+
if (_.isArray(value)) return 'array';
10+
return typeof value;
11+
};
12+
13+
var type = getType(value);
14+
15+
if (type === 'array') return 'array [' + value.toString() + ']';
16+
if (type === 'string') return 'string "' + value + '"';
17+
if (type === 'undefined') return value;
18+
if (type === 'function') return type;
19+
return type + ' ' + value;
20+
};
21+
22+
process.on('message', function(entry) {
23+
var raiseError = function(expected, actual) {
24+
var expectedError = formatTypeAndValue(expected);
25+
var actualError = formatTypeAndValue(actual);
26+
throw new Error('expected ' + expectedError + ' but got ' + actualError);
27+
};
28+
29+
try {
30+
vm.runInNewContext(fs.readFileSync(entry.file, 'utf8'), global);
31+
32+
if (!global.play)
33+
throw new Error('no global play function defined');
34+
35+
var actualOutput = global.play(entry.input);
36+
var expectedOutput = eval(entry.output);
37+
38+
if (_.isArray(actualOutput) && _.isArray(expectedOutput)) {
39+
if (actualOutput.toString() !== expectedOutput.toString()) {
40+
raiseError(expectedOutput, actualOutput);
41+
}
42+
} else if (actualOutput !== expectedOutput) {
43+
raiseError(expectedOutput, actualOutput);
44+
}
45+
46+
process.send({ valid: true });
47+
} catch (err) {
48+
process.send({ valid: false, err: err.toString() });
49+
}
50+
});

mancjs-golf.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
var http = require('http');
2+
var express = require('express');
3+
var mustachex = require('mustachex');
4+
5+
var app = express();
6+
7+
app.configure(function() {
8+
app.engine('html', mustachex.express);
9+
app.set('view engine', 'html');
10+
app.set('views', __dirname + '/views');
11+
app.use(express.limit('50kb'));
12+
app.use(express.bodyParser({ uploadDir: __dirname + '/files' }));
13+
app.use(express.static(__dirname + '/public'));
14+
app.use(app.router);
15+
});
16+
17+
require('./routes/play')(app);
18+
require('./routes/admin')(app);
19+
20+
http.createServer(app).listen(1122);

package.json

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "mancjs-golf",
3+
"version": "0.0.0",
4+
"description": "The MancJS code golf server",
5+
"main": "mancjs-golf.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "Martin Rue",
10+
"license": "BSD-2-Clause",
11+
"dependencies": {
12+
"express": "~3.4.0",
13+
"mustachex": "0.0.2",
14+
"underscore": "~1.5.2",
15+
"moment": "~2.2.1"
16+
}
17+
}

0 commit comments

Comments
 (0)