const express = require('express'); const fs = require('fs'); const {instrument} = require("@socket.io/admin-ui"); const app = express(); const server = require('http').createServer(app); const {Server} = require("socket.io"); const io = new Server(server); let cards = JSON.parse(fs.readFileSync(__dirname + '/../data/fragen_10_06_21_final_new_format.json')); class Player { constructor(socketUsername) { this.socketUsername = socketUsername; this.position = 0; this.alive = true; } move(amount) { this.position += amount; if (this.position === 15) { // todo: win } } } class Hunter { constructor() { this.position = 0; } move(amount) { this.position += amount; } hunt(players) { for (let i = 0; i < players.length; i++) { if (players[i].position <= this.position) { players[i].alive = false; } } } } let gameState = { players: [], whosNext: 0, started: false }; let port = 5000; server.listen(port, function () { generate_log_message("MAIN", "Server", 'RUNNING', "PORT " + port); }); // Monitor websockets if (process.env.WEBSOCKET_MONITOR_USERNAME && process.env.WEBSOCKET_MONITOR_PASSWORD) { instrument(io, { auth: { type: "basic", username: process.env.WEBSOCKET_MONITOR_USERNAME, password: process.env.WEBSOCKET_MONITOR_PASSWORD }, serverId: `${require("os").hostname()}#${process.pid}` }); } else { instrument(io, { auth: false, serverId: `${require("os").hostname()}#${process.pid}` }); } // Serve static files (html, css, js) app.use(express.static(__dirname + '/../public')); // Websockets io.on('connection', socket => { let addedUser = false; socket.on('add user', function (data) { if (gameState['players'].length < 4 && !gameState['started']) { socket.username = data.username; socket.room = data.room_name; gameState['players'].push(new Player(socket.username)); addedUser = true; socket.emit('login'); socket.join(socket.room); socket.broadcast.to(socket.room).emit('user joined', socket.username); generate_log_message(socket.room, socket.username, "JOINED", ""); } else { // TODO } }); socket.on('new message', function (data) { socket.broadcast.to(socket.room).emit('new message', { username: socket.username, message: data }); generate_log_message(socket.room, socket.username, "MESSAGE", data); }); socket.on('disconnect', function () { if (addedUser) { socket.broadcast.to(socket.room).emit('user left', socket.username); let index = -1; for (let i = 0; i < gameState['players'].length; i++) { if (gameState['players'][i].socketUsername === socket.username) { index = i; break; } } if (index > -1) { gameState['players'].splice(index, 1); } socket.leave(socket.room); if (gameState['players'].length === 0) { gameState['players'] = []; gameState['whosNext'] = 0; gameState['started'] = false; } } generate_log_message(socket.room, socket.username, "LEFT", ""); }); // Game socket.on('roll dice', function () { if (gameState['players'][gameState['whosNext']].socketUsername === socket.username) { gameState['started'] = true; let sides = 3; let randomNumber = Math.floor(Math.random() * sides) + 1; io.in(socket.room).emit('dice', randomNumber); generate_log_message(socket.room, socket.username, "DICE", randomNumber); } else { // TODO } }); socket.on('get card', function (difficulty) { if (gameState['players'][gameState['whosNext']].socketUsername === socket.username) { io.in(socket.room).emit('card', {'username': socket.username, 'card': getRandomCard(difficulty)}); generate_log_message(socket.room, socket.username, "CARD", difficulty); } else { // TODO } }); socket.on('card finished', function (difficulty, answerIsCorrect) { if (answerIsCorrect) gameState['players'][gameState['whosNext']].move(difficulty); gameState['whosNext'] += 1; if(gameState['whosNext'] === gameState['players'].length) gameState['whosNext'] = 0; io.in(socket.room).emit('card destroyed'); }); }); function generate_log_message(room, user, type, message) { let color; switch (type) { case 'LEFT': color = '\x1b[31m'; break; case 'JOINED': color = '\x1b[32m'; break; case 'MESSAGE': color = '\x1b[36m'; break; case 'RUNNING': color = '\x1b[35m'; break; case 'DICE': color = '\x1b[34m'; break; default: color = '\x1b[0m'; } room = pad(10, room, ' ').substr(0, 10); user = pad(10, user, ' ').substr(0, 10); type = pad(10, type, ' ').substr(0, 10); let reset_color = '\x1b[0m'; console.info("%s[%s] [%s] [%s]\x1b[0m %s", color, room, user, type, reset_color, message); } function getRandomCard(difficulty) { let filtered_cards = cards.filter(card => { return card.difficulty === difficulty; }); return shuffleAnswers(filtered_cards[Math.floor(Math.random() * filtered_cards.length)]); } function shuffleAnswers(card) { for (let i = card.answers.length - 1; i > 0; i--) { let j = Math.floor(Math.random() * (i + 1)); [card.answers[i], card.answers[j]] = [card.answers[j], card.answers[i]]; } return card; } function pad(width, string, padding) { if (string === undefined || string === null) return pad(width, " ", " "); return (width <= string.length) ? string : pad(width, string + padding, padding); }