diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 00ed1b42..0fcc3d1c 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -68,6 +68,21 @@ app.get("/questions", async (req, res) => { } }); +app.post("/questions", async (req, res) => { + try { + // Forward the question request to the question service + const questionResponse = await axios.post( + questionServiceUrl + "/questions", + { body: req.body } + ); + res.json(questionResponse.data); + } catch (error) { + res + .status(error.response.status) + .json({ error: error.response.data.error }); + } +}); + app.get("/stats", async (req, res) => { try { // Forward the stats request to the stats service diff --git a/questionservice/question-service.js b/questionservice/question-service.js index 930daa19..95cfe8e7 100644 --- a/questionservice/question-service.js +++ b/questionservice/question-service.js @@ -1,6 +1,6 @@ // user-service.js const express = require("express"); -const cors = require('cors'); +const cors = require("cors"); const bodyParser = require("body-parser"); const cron = require("node-cron"); const GeneratorChooser = require("./questionGen/GeneratorChooser"); @@ -14,12 +14,19 @@ const MAX_QUESTIONS = 10000; // Middleware to parse JSON in request body app.use(bodyParser.json()); +// support encoded bodies +app.use(bodyParser.urlencoded({ extended: true })); app.use(cors()); app.use((req, res, next) => { if (!generadoresCargados) { - return res.status(500).json({ error: "Los generadores de preguntas aún no se han cargado. Por favor, inténtalo de nuevo más tarde." }); + return res + .status(500) + .json({ + error: + "Los generadores de preguntas aún no se han cargado. Por favor, inténtalo de nuevo más tarde.", + }); } next(); }); @@ -27,7 +34,6 @@ app.use((req, res, next) => { app.set("json spaces", 40); app.get("/questions", async (req, res) => { - console.log(req.query) if (req.query.n > MAX_QUESTIONS) { res .status(400) @@ -43,16 +49,39 @@ app.get("/questions", async (req, res) => { } }); +app.post("/questions", async (req, res) => { + const { tematicas, n } = req.body.body; + if (!n || n > MAX_QUESTIONS) { + res + .status(400) + .json({ error: `El límite de preguntas son ${MAX_QUESTIONS}` }); + return; + } + try { + const temas = tematicas ? JSON.parse(tematicas) : []; + const tematicasValidas = + temas.length !== 0 + ? temas + : ["paises", "literatura", "cine", "arte", "programacion"]; + const cantidadPreguntas = parseInt(n, 10); + const data = gen.getQuestionsPost(tematicasValidas, cantidadPreguntas); + res.json(data); + } catch (error) { + res.status(400).json({ error: error.message }); + } +}); + const server = app.listen(port, async () => { console.log(`Question Service listening at http://localhost:${port}`); - gen.loadGenerators() - .then(() => { - console.log("Generators loaded successfully!"); - generadoresCargados = true; - }) - .catch((error) => { - console.error("Error al cargar los generadores de preguntas:", error); - }); + gen + .loadGenerators() + .then(() => { + console.log("Generators loaded successfully!"); + generadoresCargados = true; + }) + .catch((error) => { + console.error("Error al cargar los generadores de preguntas:", error); + }); }); cron.schedule("0 3 * * *", async () => { diff --git a/questionservice/questionGen/GeneratorChooser.js b/questionservice/questionGen/GeneratorChooser.js index b2ccd5bc..3fe1c13a 100644 --- a/questionservice/questionGen/GeneratorChooser.js +++ b/questionservice/questionGen/GeneratorChooser.js @@ -1,53 +1,70 @@ -const GenericGenerator = require('./GenericGenerator') -const fs = require('fs'); - -class GeneratorChooser{ - constructor(){ - this.generators = new Map(); - this.tematicas = []; - this.leer_json("./data/tematicas.json"); - } +const GenericGenerator = require("./GenericGenerator"); +const fs = require("fs"); + +class GeneratorChooser { + constructor() { + this.generators = new Map(); + this.tematicas = []; + this.leer_json("./data/tematicas.json"); + } - leer_json(ruta){ - const datos = fs.readFileSync(ruta); - var tematicas = JSON.parse(datos); - - for(let i in tematicas){ - var tematica = tematicas[i]; - this.tematicas.push(i); - this.generators.set(i, - new GenericGenerator(tematica.entity, tematica.props, tematica.types, tematica.preguntas) - ); - } + leer_json(ruta) { + const datos = fs.readFileSync(ruta); + var tematicas = JSON.parse(datos); + + for (let i in tematicas) { + var tematica = tematicas[i]; + this.tematicas.push(i); + this.generators.set( + i, + new GenericGenerator( + tematica.entity, + tematica.props, + tematica.types, + tematica.preguntas + ) + ); } + } - getQuestions(tematica, n){ - if(tematica === "all"){ - var questions = []; - for(let i = 0 ; i < n ; i++){ - let rand = Math.floor(Math.random() * this.tematicas.length) - let randTematica =this.tematicas[rand]; - let q = this.generators.get(randTematica).generateRandomQuestions(1); - questions.push(q); - } - return questions.flat(); - }else{ - return this.generators.get(tematica).generateRandomQuestions(n); - } + getQuestions(tematica, n) { + if (tematica === "all") { + var questions = []; + for (let i = 0; i < n; i++) { + let rand = Math.floor(Math.random() * this.tematicas.length); + let randTematica = this.tematicas[rand]; + let q = this.generators.get(randTematica).generateRandomQuestions(1); + questions.push(q); + } + return questions.flat(); + } else { + return this.generators.get(tematica).generateRandomQuestions(n); } + } - async loadGenerators(){ - for(let i = 0 ; i < this.tematicas.length ; i++){ - var gen = this.generators.get(this.tematicas[i]); - console.log("Cargando temática: " + this.tematicas[i]); - await gen.getData(); - await this.#sleep(10000); - } + getQuestionsPost(tematicas, n) { + var questions = []; + for (let i = 0; i < n; i++) { + let rand = Math.floor(Math.random() * tematicas.length); + let randTematica = tematicas[rand]; + let q = this.generators.get(randTematica).generateRandomQuestions(1); + questions.push(q); } + return questions.flat(); + } - #sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + async loadGenerators() { + for (let i = 0; i < this.tematicas.length; i++) { + var gen = this.generators.get(this.tematicas[i]); + console.log("Cargando temática: " + this.tematicas[i]); + await gen.getData(); + await this.#sleep(10000); } + } + + #sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } } -module.exports = GeneratorChooser; \ No newline at end of file +module.exports = GeneratorChooser; diff --git a/webapp/src/App.js b/webapp/src/App.js index 0ef18680..dee6ef63 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -9,6 +9,7 @@ import "./App.css"; import { BrowserRouter, Routes, Route } from "react-router-dom"; import { ProtectedRoute } from "./routers/ProtectedRoute.js"; import Sobre from "./pages/Sobre/Sobre.js"; +import Config from "./pages/Config/Config.js"; function App() { return ( @@ -25,6 +26,7 @@ function App() { } /> } /> } /> + } /> {/* Ruta por defecto */} diff --git a/webapp/src/components/Nav/Nav.js b/webapp/src/components/Nav/Nav.js index a44a6b74..e0bd9f0c 100644 --- a/webapp/src/components/Nav/Nav.js +++ b/webapp/src/components/Nav/Nav.js @@ -16,6 +16,10 @@ const Nav = () => { setIsDarkTheme((prev) => !prev); }; + const handleConfig = () => { + navigate("/config"); + } + const Logout = () => { localStorage.removeItem("token"); navigate("/"); @@ -40,7 +44,7 @@ const Nav = () => { - ))} -
Tiempo restante: {Math.floor(tiempoRestante)}
+
+ Tiempo restante: {Math.floor(tiempoRestante)} +
Puntuación: {puntuacion}
{ + const [error, setError] = useState(""); + const [info, setInfo] = useState(""); + const [clasicoTime, setClasicoTime] = useState( + localStorage.getItem("clasicoTime") + ); + const [clasicoPreguntas, setClasicoPreguntas] = useState( + localStorage.getItem("clasicoPreguntas") + ); + const [bateriaTime, setBateriaTime] = useState( + localStorage.getItem("bateriaTime") + ); + + const handleConfig = () => { + const checkboxes = document.querySelectorAll( + '.topicCheckboxes input[type="checkbox"]' + ); + const selectedThemes = []; + + checkboxes.forEach((checkbox) => { + if (checkbox.checked) { + selectedThemes.push(checkbox.id); + } + }); + + if (selectedThemes.length === 0) { + alert("Debe haber al menos una temática seleccionada"); + } else { + localStorage.setItem("selectedThemes", JSON.stringify(selectedThemes)); + localStorage.setItem("clasicoTime", clasicoTime); + localStorage.setItem("clasicoPreguntas", clasicoPreguntas); + localStorage.setItem("bateriaTime", bateriaTime); + + alert("Cambios realizados satisfactoriamente"); + } + }; + + const handleClasicoChange = (event) => { + setClasicoTime(parseInt(event.target.value)); + }; + + const handleClasicoPreguntas = (event) => { + setClasicoPreguntas(parseInt(event.target.value)); + }; + + const handleBateriaChange = (event) => { + setBateriaTime(parseInt(event.target.value)); + }; + + return ( + <> +