/* * Copyright (C) 2021 Thomas Van Acker * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . * * This project is hosted on https://git.bitscuit.be/bitscuit/ReverseQuiz * */ // Imports const http = require("http"); const url = require("url"); const fs = require("fs"); const util = require("util"); const fetch = require("node-fetch"); // Vars const hostname = "127.0.0.1"; // Enter your local IP address here const port = 5000; // Enter a port number here const STATE_LOBBY = 0; const STATE_MANUAL = 10; const STATE_WRITE = 20; const STATE_PICK = 30; const STATE_ANSWER = 40; const STATE_END = 50; var state = STATE_LOBBY; var userSockets = []; var userNames = []; var userOK = []; var questionNr = 0; // Current question var questionsTotal = 10; // Total nr of questions var questionData = {}; var questionCorrectAnswerIndex; var answers; const QUESTION_CATEGORIES = [9,15,16,17,18,19,20,22,23,27,28,30]; // Default enabled categories var userWrite = []; var userPick = []; var userPoints = []; var config = { categories: [], // Filled in later answerPreview: true, timer: 60, }; // Get question categories function isCategoryEnabledByDefault(id){ return QUESTION_CATEGORIES.includes(id); } fetch("https://opentdb.com/api_category.php") .then(res => res.json()) // Convert to JSON .then(json => { // Question loaded console.log("Fetched question categories from OpenTDB"); console.log(json); // TODO: check response code // Save data var cats = []; for(var i=0; i { // Parse url const requrl = url.parse(req.url); var reqpath = requrl.pathname; if(reqpath == "/") reqpath = "/index.html"; // Respond to requests try{ // Return requested page res.statusCode = 200; res.write(fs.readFileSync("html"+reqpath)); res.end(); }catch(error){ // 404 if page not found res.statusCode = 404; res.setHeader("Content-Type", "text/plain"); res.end("404 - Page Not Found"); } }); // Create socket.io server const io = require("socket.io")(server); // Can only be done when server is created io.on("connection", (socket) => { console.log("New user connected!"); // Init socket listeners // Disconnect socket.on("disconnect", () => { console.log("User disconnected!"); // Remove from user lists if(userSockets.indexOf(socket) != -1){ // When in users list name = userNames[userSockets.indexOf(socket)]; userNames.splice(userSockets.indexOf(socket), 1); userSockets.splice(userSockets.indexOf(socket), 1); if(state == STATE_LOBBY){ // Send new lobby userSockets.forEach(function(s){s.emit("LOBBY", userNames);}); }else{ // Send disconnect message userSockets.forEach(function(s){s.emit("DISCONNECT", name);}); } } }); // JOIN socket.on("JOIN", (username) => { console.log("JOIN request for "+username); // Check if can enter in lobby if(state == STATE_LOBBY){ // Add user to lists userSockets.push(socket); userNames.push(username); console.log(userNames); // Send lobby data userSockets.forEach(function(s){s.emit("LOBBY", userNames);}); // Send config to new user socket.emit("CONFIG", {config: config}); }else{ // When can't enter socket.emit("LOBBY_CLOSED"); } }); // CONFIG socket.on("CONFIG", (data) => { console.log("CONFIG request"); // Update server config config = data.config; // Send new config to all users userSockets.forEach(function(s){s.emit("CONFIG", {config: config});}); }); // START socket.on("START", () => { console.log("START request"); // Send START to all users userSockets.forEach(function(s){s.emit("START");}); // Set state state = STATE_MANUAL; // Reset vars questionNr = 0; userPoints = []; for(i=0; i { ok(socket); }); // WRITE socket.on("WRITE", (data) => { // When received write from player // Check if empty if(data.write == ""){ socket.emit("WRITE_REPLY", {error:"Please enter a false answer!"}); return; } // Check if valid var valid = true; valid = valid && data.write.toUpperCase() != questionData.correct_answer.toUpperCase(); for(i=0; i { // When received pick form player userPick[userSockets.indexOf(socket)] = id; // Perform ok ok(socket); }); }); // Start HTTP server server.listen(port, hostname, () => { console.log("Server running at http://"+hostname+":"+port); }); // Game methods function next(){ // Go to next step of game // Send LOADING userSockets.forEach(function(s){s.emit("LOADING");}); if(state == STATE_MANUAL || state == STATE_ANSWER){ // Write state = STATE_WRITE; // Update vars questionNr++; userWrite = []; for(i=0; i questionsTotal){ // End state = STATE_END; // Gather data var sorted = []; for(i=0; i b.score-a.score); console.log(sorted); var ranks = []; var r = 1; var ls = sorted[0].score; for(i=0; i res.json()) // Convert to JSON .then(json => { // Question loaded console.log("Question loaded!"); console.log(json); // TODO: check response code // Save data questionData = json.results[0]; // Send question to players userSockets.forEach(function(s){s.emit("WRITE", {questionNr:questionNr, questionsTotal:questionsTotal, question:questionData.question});}); }); } }else if(state == STATE_WRITE){ // Pick state = STATE_PICK; console.log("Preparing PICK"); // Send question and answers to players answers = []; for(i=0; i