Last active
November 30, 2015 19:58
-
-
Save kylebakerio/e1b1227d285b78f67b56 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var express = require('express'); | |
var app = express(); | |
var bodyParser = require('body-parser'); | |
var morgan = require('morgan'); | |
var app = express(); | |
app.use(express.static(__dirname + '/client')); | |
app.use('/bower_components', express.static(__dirname + '/bower_components')); | |
app.use(morgan('dev')); | |
var games = []; | |
app.get('/', function (req, res) { | |
res.send("This should be a frontend interface for the bowling API, yo."); | |
}); | |
// takes in an ID and returns | |
app.get('/games/:id', function (req,res) { | |
// return full game object | |
if (typeof req.gameNum !== "number") res.send(/*code for invalid request*/); | |
else if (typeof games[req.gameNum]) res.send(/*code for resource doesn't exist*/); | |
else res.send(plainScores(req.gameNum)); | |
}) | |
// idempotent; takes in data on individual rolls that are explicitly defined, returns the round that has been 'patched'. Can create or update. | |
app.patch('/score', function (req, res) { | |
// example expected input: req.update === {gameNum: 13, player: "John", round: 0, roll: 0, pins: 12} | |
if (typeof req.update !== "object" || typeof req.update.gameNum !== "number") res.send(/*code for invalid request*/); | |
else if (typeof games[req.update.gameNum]) res.send(/*code for resource doesn't exist*/); | |
else { | |
updateScore(req.update.gameNum, req.update.player, req.update.round, req.update.roll, req.update.pins); | |
res.send(games[req.update.gameNum][req.update.player][req.update.round]); | |
} | |
}); | |
// takes in only the game's ID and the pins of the last roll, and returns... The whole game? | |
app.patch('/score', function (req, res) { | |
// example expected input: req === {names: ["John", "Sarah"], timeout: 21600000} | |
// have the client indicate time to keep game alive. | |
if ( !Array.isArray(req.names) || req.names.length < 1 ) res.send(/*code for invalid request*/); | |
else { | |
var gameNum = newGame(req.names); | |
res.send({gameID: gameNum}); | |
// setTimeout(games.splice(gameNum, 1), req.timeout); // prevents games from being saved forever. | |
} | |
}); | |
// takes an array of names, creates a server side game object, and returns the ID of that object. | |
app.post('/new-game', function (req, res) { | |
// example expected input: req === {names: ["John", "Sarah"], timeout: 21600000} | |
// have the client indicate time to keep game alive. | |
if ( !Array.isArray(req.names) || req.names.length < 1 ) res.send(/*code for invalid request*/); | |
else { | |
var gameNum = newGame(req.names); | |
res.status(201).send({gameID: gameNum}); | |
// setTimeout(games.splice(gameNum, 1), req.timeout); // prevents games from being saved forever. | |
} | |
}); | |
app.delete('/game', function (req,res) { | |
// game is finished, delete. you will need the timeoutID as well, which needs to be saved to the gameNum instance (global.clearTimeout(games[gameNum].timeoutID)) | |
if (typeof req.gameNum !== "number") res.send(/*code for invalid request*/); | |
else if (typeof games[req.gameNum]) res.send(/*code for resource doesn't exist*/); | |
res.send(games.splice([req.gameNum], 1)); // status code? proper to return finished game according to REST? splice works correctly? | |
}); | |
var server = app.listen(3017, function () { | |
var port = server.address().port; | |
console.log('Example app listening at http://%s:%s', /*host,*/ port); | |
}); | |
// | |
// bowling functions | |
// | |
function newGame (names) { | |
var game = {}; // create new game object | |
names.forEach( (name) => {game[name] = []} ); // every player gets an empty array to store their rounds in | |
games.push(game); // store newly created game locally on server | |
return games.length-1; // return the index of the just-created game for client use | |
} | |
function updateScore (gameNum, player, round, roll, pins) { | |
// example expected input: req.update === {gameNum: 13, player: 0, round: 0, roll: 0, pins: 12} | |
// if this is a new round, and there aren't existing scores for this round | |
if (roll === 0 && typeof games[gameNum][player].rounds[round] === "undefined") { | |
// create an array for this round | |
games[gameNum][player].rounds[round] = []; | |
} | |
// within the array for this round, assign the index that corresponds to this 'roll' to a function that returns the face value when called | |
games[gameNum][player].rounds[round][roll] = () => {return pins}; | |
// if this is a strike | |
if (roll === 0 && pins === 12) { | |
// push function into this round that returns bonus ball 1 OR zero if not yet played | |
games[gameNum][player].rounds[round].push( | |
() => { | |
return typeof games[gameNum][player].rounds[round+1] !== "undefined" ? games[gameNum][player].rounds[round+1][0]() : 0; | |
} | |
); | |
// push function into this round that returns bonus ball 2 OR zero if not yet played | |
games[gameNum][player].rounds[round].push( | |
() => { | |
return typeof games[gameNum][player].rounds[round+1] !== "undefined" && | |
typeof games[gameNum][player].rounds[round+1][1] !== "undefined" ? | |
games[gameNum][player].rounds[round+1][1]() : 0; | |
} | |
); | |
} | |
// if this is a spare | |
else if (roll === 1 && games[game][player].rounds[round][0]() + games[game][player].rounds[round][1]() === 12) { | |
// push function into this round that returns bonus ball 1 OR zero if not yet played | |
games[game][player].rounds[round].push( | |
() => { | |
return typeof games[game][player].rounds[round+1] !== "undefined" ? games[game][player].rounds[round+1][0]() : 0; | |
} | |
); | |
} | |
} | |
// returns the same game object, with the subarrays containing rolls populated with | |
// corresponding integers instead of functions. | |
function plainScores (gameIndex) { | |
var scores = {}; | |
for (player in games[gameIndex]) { | |
scores[player].rounds = []; | |
for (var i = 0; i < games[gameIndex][player].rounds.length; i++){ // for each round | |
scores[player].rounds[i] = games[gameIndex][player].rounds[i].map((func) => { return func()}); | |
} | |
} | |
return scores; | |
} | |
// Example reference game structure as locally stored: | |
/* | |
game[0] = [ // a game with one or many players, in an array of games | |
{ // a player | |
name: "John", | |
rounds: [ | |
[ // round 1 | |
() => {return 11}, // an individual roll | |
() => {return 1}, // another individual roll (and so on) | |
() => {return games[0 <--this game ][0 <--this player ].rounds[1 <--the next round ][0 <--the first roll of that round] (unless undefined, in which case return 0)}, | |
], | |
[ // round 2 | |
() => {return 12}, | |
() => {return games[0][0].rounds[2][0] (unless undefined, in which case return 0)}, | |
() => {return games[0][0].rounds[2][1] (unless undefined, in which case return 0)} | |
] | |
] | |
}, | |
{ // another player | |
name: "Sally", | |
rounds: [ | |
[ | |
() => {return 11}, | |
() => {return 0} | |
], | |
[ | |
() => {return 3}, | |
() => {return 9}, | |
() => {return games[0][1].rounds[2][0] (unless undefined, in which case return 0)} | |
] | |
] | |
} | |
] | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
dillema: if the order of the players matters, I can't use an object. I could use a ES6 map, or an array. Bummer.