diff options
Diffstat (limited to 'src/quiz-bunny/server.js')
-rw-r--r-- | src/quiz-bunny/server.js | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/src/quiz-bunny/server.js b/src/quiz-bunny/server.js new file mode 100644 index 0000000..12a0090 --- /dev/null +++ b/src/quiz-bunny/server.js @@ -0,0 +1,312 @@ +const uuidv4 = require('uuid/v4'); +const words = require('./words').words; + +function setUpRoutes(server, models, jwtFunctions, database) { + // simple send files + server.get('/quiz-bunny', (req, res) => res.sendFile(__dirname + "/index.html")) + server.get('/quiz-bunny/main.js', (req, res) => res.sendFile(__dirname + "/static/main.js")) + server.get('/quiz-bunny/styles.css', (req, res) => res.sendFile(__dirname + "/static/styles.css")) + + // a list of games + var games = [] + let STATES = { + TYPING: 0, + VOTING: 1, + OVER: 2, + WAITING: 3, + } + setInterval(function(){ + console.log(games) + }, 3000) + + // generates a game code + function generateGameCode() { + // let words = ["cat", "dog"]; + var index = Math.floor(Math.random() * words.length) + // ensure no duplicate game code + while (games.find(el => el.gameCode == words[index].toLowerCase())) { + var index = Math.floor(Math.random() * words.length) + } + return words[index].toLowerCase() + } + // gets a new game object + function getNewGame(hostCookie, hostName) { + let gameCode = generateGameCode(); + return { + host: hostCookie, + players: [{ cookie: hostCookie, name: hostName }], + gameCode: gameCode + } + } + // adds a player to a game object + function addToGame(gameCode, playerCookie, playerName) { + let game = games.find(el => el.gameCode == gameCode) + if (game) { + game.players.push({ cookie: playerCookie, name: playerName }) + return true + } + return false + } + function findGameByCookie(cookie) { + return games.find(el => el.players.some(player => player.cookie == cookie)) + } + function findPlayerByCookie(game, cookie) { + return game.players.find(player => player.cookie == cookie) + } + function getPlayerNames(players) { + return players.map(player => player.name) + } + // Turn the game into a public game object (no cookies, etc.) + function getPublicGame(cookie) { + var game = findGameByCookie(cookie) + if (!game) { + return { message: "no game active" } + } else { + let isHost = cookie == game.host + let username = game.players.find(player => player.cookie == cookie).name + let players = getPlayerNames(game.players) + var newGame = { + host: isHost, + players: players, + name: username, + gameCode: game.gameCode, + gameStarted: game.gameStarted, + state: game.state + } + if (game.state == STATES.TYPING) { + newGame.submitted = game.answers.some(answer => answer.cookie == cookie) + newGame.prompt = game.prompts[game.round] + } else if (game.state == STATES.VOTING) { + newGame.answers = game.answers.map(answer => answer.text) + newGame.prompt = game.prompts[game.round] + var game = findGameByCookie(cookie) + var player = findPlayerByCookie(game, cookie) + newGame.voted = player.voted + } else if (game.state == STATES.WAITING) { + newGame.answers = game.answers.map(answer => { + return { text: answer.text, voteCount: answer.votes.length } + }) + newGame.prompt = game.prompts[game.round] + var game = findGameByCookie(cookie) + var player = findPlayerByCookie(game, cookie) + newGame.ready = player.ready + } else if (game.state == STATES.OVER) { + var scores = game.players.map(player => { + return { name: player.name, score: player.score } + }) + // sort + scores.sort((a,b) => b.score - a.score); + newGame.scores = scores + } + + return newGame + } + } + // gets a game prompt + function getPrompts(players) { + // temporary hard coded 2 rounds + return [`What would ${players[0]} eat for breakfast?`, `What would ${players[1]} be famous for?`] + } + // marks the game as started + function startGame(cookie) { + let game = games.find(el => el.host == cookie) + if (game) { + game.gameStarted = true + game.prompts = getPrompts(getPlayerNames(game.players)) + game.round = 0; + game.players.forEach(player => { + player.score = 0 + }) + game.state = STATES.TYPING + startRound(game); + return true + } else { + return false + } + } + function startRound(game) { + // keep track of votes + game.players.forEach(player => { + player.voted = false + }) + game.answers = [] + game.state = STATES.TYPING + } + function submitAnswer(cookie, text) { + let game = findGameByCookie(cookie) + if (!game.answers.some(answer => answer.cookie == cookie)) { + game.answers.push({ text: text, cookie: cookie }) + } + if (game.answers.length == game.players.length) { + startVoting(game) + } + } + function startVoting(game) { + game.state = STATES.VOTING + game.answers.forEach(answer => { + answer.votes = [] + }) + game.voteCount = 0 + } + function endVoting(game) { + game.state = STATES.WAITING + game.players.forEach(player => { + player.ready = false + }) + game.answers.forEach(answer => { + var player = findPlayerByCookie(game, answer.cookie) + player.score += answer.votes.length + // extra points for high scoring answer + if (answer.votes.length >= 3) { + player.score += 2 + } + }) + } + function endRound(game) { + game.round += 1 + if (game.round >= game.prompts.length) { + game.state = STATES.OVER + } else { + startRound(game) + } + } + // player with cookie votes for answer + function voteFor(cookie, answerIndex) { + let game = findGameByCookie(cookie) + let playerWhoVoted = findPlayerByCookie(game, cookie) + if (playerWhoVoted.voted) { + return false + } + playerWhoVoted.voted = true + let answer = game.answers[answerIndex] + answer.votes.push(playerWhoVoted) + game.voteCount++ + if (game.voteCount == game.players.length) { + endVoting(game) + } + return true + } + function ready(cookie) { + let game = findGameByCookie(cookie) + let player = findPlayerByCookie(game, cookie) + player.ready = true + if (game.players.every(player => player.ready)) { + endRound(game) + } + } + // Requested by host once + server.get('/quiz-bunny/host-game', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie) { + cookie = uuidv4(); + res.cookie('session', cookie, { expires: new Date(Date.now() + (1000 * 60 * 60)) }); + } + let username = req.query.name + var game = getNewGame(cookie, username) + games.push(game) + res.status(200).send(getPublicGame(cookie)) + }) + // Requested by players joining from game code + server.get('/quiz-bunny/join-game', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie) { + cookie = uuidv4(); + res.cookie('session', cookie, { expires: new Date(Date.now() + (1000 * 60 * 60)) }); + } + let username = req.query.name + let code = req.query.code + if (addToGame(code, cookie, username)) { + res.status(200).send(getPublicGame(cookie)) + } else { + res.status(200).send({ message: "Invalid game code" }) + } + }) + // starts the game + server.get('/quiz-bunny/start-game', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie || !startGame(cookie)) { + res.status(400).send({ message: "you cannot start a game" }); + } else { + res.status(200).send(getPublicGame(cookie)) + } + }) + // constantly requested by client while in lobby + server.get('/quiz-bunny/lobby-status', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie) { + res.status(400).send({ message: "you are not in a game" }); + } else { + res.status(200).send(getPublicGame(cookie)) + } + }) + // constantly requested by client while game started + server.get('/quiz-bunny/game-status', (req, res, next) => { + // TODO + let cookie = req.cookies.session; + if (!cookie) { + res.status(400).send({ message: "you are not in a game" }); + } else { + var game = findGameByCookie(cookie) + res.status(200).send(getPublicGame(cookie)) + // if(game.state == STATES.TYPING) { + // } else if(game.state == STATES.VOTING) { + // } else if(game.state == STATES.WAITING) { + // } + } + }) + server.get('/quiz-bunny/vote', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie || req.query.index == undefined) { + res.status(400).send({ message: "you are not in a game" }); + } else { + voteFor(cookie, req.query.index) + res.status(200).send() + } + }) + server.get('/quiz-bunny/submit', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie || req.query.text == undefined) { + res.status(400).send({ message: "you are not in a game" }); + } else { + submitAnswer(cookie, req.query.text) + res.status(200).send() + } + }) + server.get('/quiz-bunny/ready', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie) { + res.status(400).send({ message: "you are not in a game" }); + } else { + ready(cookie) + res.status(200).send() + } + }) + server.get('/quiz-bunny/ready', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie) { + res.status(400).send({ message: "you are not in a game" }); + } else { + ready(cookie) + res.status(200).send() + } + }) + server.get('/quiz-bunny/leave', (req, res, next) => { + let cookie = req.cookies.session; + if (!cookie) { + res.status(400).send({ message: "you are not in a game" }); + } else { + var game = findGameByCookie(cookie) + game.players = game.players.filter(player => player.cookie != cookie) + if(game.players.length == 0){ + games = games.filter(g => g != game) + } + res.status(200).send() + } + }) +} + +module.exports = { + setUpRoutes +}; + + |