diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 668c3052..8bd82923 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -55,7 +55,7 @@ app.post('/adduser', async (req, res) => { app.get(`/generateQuestion`, async (req, res) => { try { // Forward the add user request to the user service - const URL = generatorUrl + '/generateQuestion?user=' + req.query.user; + const URL = generatorUrl + '/generateQuestion?user=' + req.query.user + "&thematic=" + req.query.thematic; const response = await axios.get(URL); res.json(response.data); } catch (error) { diff --git a/gatewayservice/openapi.yaml b/gatewayservice/openapi.yaml index 8075ba4b..76676322 100644 --- a/gatewayservice/openapi.yaml +++ b/gatewayservice/openapi.yaml @@ -131,6 +131,277 @@ paths: type: string description: Shows the error info.. example: Invalid credentials + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error + /generateQuestion: + get: + summary: Generate a question. + operationId: generateQuestion + responses: + '200': + description: Generation successful. Returns the question, the options, the correct option, the image (if neccessary) and the question id + content: + application/json: + schema: + type: object + properties: + responseQuestion: + type: string + description: Question. + example: ¿Cual es la capital de España? + responseOptions: + type: array + description: Options of the question. + example: [Barcelona, Madrid, Oviedo, Valladolid] + responseCorrectOption: + type: string + description: Correct option. + example: Madrid + responseImage: + type: URL + description: URL of the image of the question if neccessary. + example: https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Joe_Biden_presidential_portrait.jpg/220px-Joe_Biden_presidential_portrait.jpg + '400': + description: Error during the question generator. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Shows the error info. + example: numberOfQuestions is not defined + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error + /updateQuestion: + get: + summary: Update a question. + operationId: updateQuestion + parameters: + time: + in: query + description: Time of the question. + example: 10 + required: true + schema: + type: string + correct: + in: query + description: If the question was answered correctly. + example: true + required: true + schema: + type: boolean + responses: + '200': + description: Update successful. Returns a message ans the updated question + content: + application/json: + schema: + type: object + properties: + message: + type: string + description: A message indicating the operation was succesful. + example: Tiempo de pregunta actualizado exitosamente + updatedQuestion: + type: object + description: The question updated. + example: {enunciado: ¿Cual es la capital de España?, respuesta_correcta: Madrid, respuesta_falsa1: Barcelona, respuesta_falsa2: Oviedo, respuesta_falsa3: Valladolid, + time: 10, correct: true} + '404': + description: Cannot find the question. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Shows the error info. + example: La pregunta no fue encontrada + '400': + description: Error when update the question + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Shows the error info. + example: Cannot read property 'time' of undefined + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error + /saveGameHistory: + post: + summary: Save the game history. + operationId: saveGameHistory + responses: + '200': + description: Succesful saving the game history + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates if the operation has been succesful. + example: true + '400': + description: Error when saving the game history + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Shows the error info. + example: Error al guardar el historial del juego + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error + /configureGame: + post: + summary: Configure the game. + operationId: configureGame + responses: + '200': + description: Succesful configure the game number of questions + content: + application/json: + schema: + type: object + properties: + maxQuestions: + type: int + description: The new number of questions of the question. + example: 10 + '400': + description: Error when configuring the game + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Shows the error info. + example: Cannot read property 'valueQuestion' of undefined + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error + /gamehistory: + get: + summary: Charge the game history. + operationId: gamehistory + parameters: + username: + in: query + description: User which game history we want to recover. + example: Pepito + required: true + schema: + type: string + responses: + '200': + description: Succesful charge the game history + '400': + description: Error when charging the game history + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error + /topUsers: + get: + summary: Charge the top users. + operationId: topUsers + responses: + '200': + description: Succesful charge the top users + '400': + description: Error when charging the top users + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error + /endgamestats: + get: + summary: Charge the end game statistics. + operationId: endgamestats + parameters: + username: + in: query + description: User which game statistics we want to charge. + example: Pepito + required: true + schema: + type: string + responses: + '200': + description: Succesful charge the end game statitics + '400': + description: Error when charging the end game statistics '500': description: Internal server error. content: diff --git a/questiongenerator/image_questions.js b/questiongenerator/image_questions.js index 0e2b558c..80a5e795 100644 --- a/questiongenerator/image_questions.js +++ b/questiongenerator/image_questions.js @@ -1,28 +1,89 @@ // Todas las consultas -var queries = - // pregunta = Imagen de un presidente de EE.UU., opcion = Nombres de presidentes de EE.UU. - [`SELECT ?option ?optionLabel ?imageLabel - WHERE { - ?option wdt:P31 wd:Q5; - wdt:P39 wd:Q11696; - wdt:P18 ?imageLabel. +var queries = {}; + +queries['Geografia'] = + [ + // pregunta = Imagen de un país, opcion = Pais + [ + ` + SELECT DISTINCT ?option ?optionLabel ?imageLabel + WHERE { + ?option wdt:P31 wd:Q6256; + rdfs:label ?optionLabel; + + OPTIONAL { ?option wdt:P18 ?imageLabel. } + FILTER(lang(?optionLabel) = "es") + FILTER EXISTS { ?option wdt:P18 ?imageLabel } + } + `, "¿Que país es el que aparece en la siguiente imagen?"] + ]; + +queries['Cultura'] = + [ + // pregunta = iamgen monumento, opcion = nombre + [ + ` + SELECT ?option ?optionLabel ?imageLabel + WHERE { + ?option wdt:P31 wd:Q4989906; + wdt:P17 wd:Q29; + wdt:P18 ?imageLabel. SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } - } - `, - // pregunta = Imagen de un país, opcion = Pais - `SELECT DISTINCT ?option ?optionLabel ?imageLabel - WHERE { - ?option wdt:P31 wd:Q6256; - rdfs:label ?optionLabel; - - OPTIONAL { ?option wdt:P18 ?imageLabel. } - FILTER(lang(?optionLabel) = "es") - FILTER EXISTS { ?option wdt:P18 ?imageLabel } - } - `]; + } + LIMIT 100 + `, "¿Que monumento español es este?"] + ]; -// Todas las preguntas, en el mismo orden que las consultas -var questions = ["¿Que presidente de EE.UU es el que se muestra en la imagen?", - "¿Que país es el que aparece en la siguiente imagen?"]; +queries['Personajes'] = + [ + // pregunta = imagen pintor, opcion = nombre pintor + [ + ` + SELECT ?optionLabel ?imageLabel + WHERE { + ?option wdt:P106 wd:Q1028181; + wdt:P569 ?birthdate. + FILTER(YEAR(?birthdate) >= 1500) + ?option wdt:P18 ?imageLabel. + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } + } + LIMIT 100 + `, "¿Cuál es el nombre de este pintor?"], + // pregunta = imagen futbolista, opcion = nombre futbolista + [ + ` + SELECT ?optionLabel ?imageLabel + WHERE { + ?option wdt:P106 wd:Q937857; + wdt:P569 ?birthdate. + FILTER(YEAR(?birthdate) >= 1960) + ?option wdt:P18 ?imageLabel. + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } + } + LIMIT 100 + `, "¿Cuál es el nombre de este futbolista?"], + // pregunta = imagen cantante, opcion = nombre cantante + [ + ` + SELECT ?optionLabel ?imageLabel + WHERE { + ?option wdt:P106/wdt:P279* wd:Q177220; + wdt:P18 ?imageLabel. + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } + } + LIMIT 100 + `, "¿Cuál es el nombre de este cantante?"], + // pregunta = Imagen de un presidente de EE.UU., opcion = Nombres de presidentes de EE.UU. + [ + ` + SELECT ?option ?optionLabel ?imageLabel + WHERE { + ?option wdt:P31 wd:Q5; + wdt:P39 wd:Q11696; + wdt:P18 ?imageLabel. + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } + } + `, "¿Que presidente de EE.UU es el que se muestra en la imagen?"] + ]; -module.exports = { queries, questions }; \ No newline at end of file +module.exports = { queries }; \ No newline at end of file diff --git a/questiongenerator/question.js b/questiongenerator/question.js index 5b3e7fe9..a128df46 100644 --- a/questiongenerator/question.js +++ b/questiongenerator/question.js @@ -4,8 +4,8 @@ const mongoose = require('mongoose'); const bodyParser = require('body-parser'); const Question = require('./question-model'); const Game = require('./game-model'); -const { queries:textQueries, questions:textQuestions } = require('./text_questions'); -const { queries:imagesQueries, questions:imagesQuestions } = require('./image_questions'); +const { queries:textQueries } = require('./text_questions'); +const { queries:imagesQueries } = require('./image_questions'); const generatorEndpoint = process.env.REACT_APP_API_ORIGIN_ENDPOINT || 'http://localhost:3000'; @@ -24,12 +24,11 @@ app.use((req, res, next) => { next(); }); +// Consultas generales +var generalQueries = getQueriesAndQuestions(textQueries, imagesQueries); + +// Consultas concretas var queries = []; -queries = queries.concat(textQueries); -queries = queries.concat(imagesQueries); -var questions = []; -questions = questions.concat(textQuestions); -questions = questions.concat(imagesQuestions); var correctOption = ""; var options = []; @@ -48,12 +47,32 @@ var maxQuestions = 5; const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/questiondb'; mongoose.connect(mongoUri); +function getQueriesAndQuestions(textData, imageData) { + let results = {}; + for (var thematic in textData) { + results[thematic] = textData[thematic]; + } + + for (var thematic in imageData) { + if (results[thematic]) { + results[thematic] = results[thematic].concat(imageData[thematic]); + } else { + results[thematic] = imageData[thematic]; + } + } + + return results; +} + app.get('/generateQuestion', async (req, res) => { try { + queries = []; + questions = []; if(numberOfQuestions == 0){ gameId = null; } const user = req.query.user; + await getQueriesByThematic(req.query.thematic); await generarPregunta(); numberOfQuestions++; if(numberOfQuestions>=maxQuestions){ @@ -92,6 +111,32 @@ var server = app.listen(port, () => { console.log(`Questions Generation Service listening at http://localhost:${port}`); }); +async function getQueriesByThematic(thematic) { + if(thematic == "Geografia") { + changeQueriesAndQuestions("Geografia"); + } else if(thematic == "Cultura") { + changeQueriesAndQuestions("Cultura"); + } else if(thematic == "Informatica") { + changeQueriesAndQuestions("Informatica"); + } else if(thematic == "Personajes") { + changeQueriesAndQuestions("Personajes"); + } else { + queries = getAllValues(); + } +} + +function changeQueriesAndQuestions(thematic) { + queries = generalQueries[thematic]; +} + +function getAllValues() { + let results = []; + for (var thematic in generalQueries) { + results = results.concat(generalQueries[thematic]); + } + + return results; +} async function generarPregunta() { @@ -101,7 +146,7 @@ async function generarPregunta() { randomNumber = Math.floor(Math.random() * queries.length); var response = await axios.get(url, { params: { - query: queries[randomNumber], + query: queries[randomNumber][0], format: 'json' }, headers: { @@ -111,7 +156,6 @@ async function generarPregunta() { procesarDatos(response.data); - } catch (error) { console.error('Error al realizar la solicitud:', error); throw new Error('Error al obtener datos ' + error); @@ -124,6 +168,9 @@ function procesarDatos(data) { var data = data.results.bindings; var randomIndexes = []; + // Mantenemos a los options que ya se han seleccionado para que no se repitan + var optionsSelected = []; + // Obtenemos cuatro índices aleatorios sin repetición while (randomIndexes.length < 4) { var randomIndex = Math.floor(Math.random() * data.length); @@ -139,11 +186,13 @@ function procesarDatos(data) { // Comprobamos que tanto la opción como la pregunta no sean entidades de WikiData ni enlaces o que la pregunta ya // venga en el array (estara vacia) if (!randomIndexes.includes(randomIndex) && (quest == "" - || (!(option.startsWith("Q") || option.startsWith("http")) - && !(quest.startsWith("Q") || quest.startsWith("http")) - ) - )) { + || (!(option.startsWith("Q") || option.startsWith("http")) + && !(quest.startsWith("Q") || quest.startsWith("http")) + ) + ) + && !optionsSelected.includes(option)) { randomIndexes.push(randomIndex); + optionsSelected.push(option); } } @@ -152,19 +201,20 @@ function procesarDatos(data) { correctOption = data[randomIndexes[correctIndex]].optionLabel.value; if(quest == "") { - question = questions[randomNumber]; + question = queries[randomNumber][1]; image = data[randomIndexes[correctIndex]].imageLabel.value; } else { image = ""; questionValue = data[randomIndexes[correctIndex]].questionLabel.value; - question = questions[randomNumber] + questionValue + "?"; + question = queries[randomNumber][1] + questionValue + "?"; } // Varriamos las opciones, incluyendo la correcta for (let i = 0; i < 4; i++) { - var optionIndex = randomIndexes[i]; - options.push(data[optionIndex].optionLabel.value); + let optionIndex = randomIndexes[i]; + let option = data[optionIndex].optionLabel.value; + options.push(option); } } diff --git a/questiongenerator/text_questions.js b/questiongenerator/text_questions.js index 3e353113..7ef284ed 100644 --- a/questiongenerator/text_questions.js +++ b/questiongenerator/text_questions.js @@ -1,50 +1,138 @@ // Todas las consultas -var queries = - // pregunta = Pais, opcion = capitales - [`SELECT ?question ?questionLabel ?option ?optionLabel - WHERE { - ?question wdt:P31 wd:Q6256; wdt:P36 ?option. - SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } - } - LIMIT 200 - `, - // pregunta = Club de futbol, opcion = estadio - ` - SELECT ?question ?questionLabel ?option ?optionLabel - WHERE { - ?question wdt:P31 wd:Q476028. - ?question wdt:P115 ?option. - ?question wdt:P17 wd:Q29. - SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } - } - LIMIT 100 - `, - // Pregunta = Numero en la tabla periodica, opcion = Elemento - ` - SELECT ?option ?optionLabel ?questionLabel (SUBSTR(?símbolo, 1, 1) AS ?sym) - WHERE { - ?option wdt:P31 wd:Q11344; - wdt:P1086 ?questionLabel. - SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE], es". } - } - LIMIT 100 - `, - // Pregunta = Batalla historica, opcion = año - `SELECT ?question ?questionLabel ?optionLabel - WHERE { - ?question wdt:P31 wd:Q178561. - ?question wdt:P580 ?date. - FILTER (YEAR(?date) >= 1500 && YEAR(?date) <= 2000) - BIND(YEAR(?date) as ?optionLabel) +var queries = {}; + +queries['Geografia'] = + [ + // pregunta = Pais, opcion = capitales + [`SELECT ?question ?questionLabel ?option ?optionLabel + WHERE { + ?question wdt:P31 wd:Q6256; wdt:P36 ?option. + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } + } + LIMIT 100 + `, "¿Cuál es la capital de "], + // pregunta = pais, opcion = montaña + [ + ` + SELECT ?question ?questionLabel ?option ?optionLabel + WHERE { + ?question wdt:P31 wd:Q6256. + ?question wdt:P610 ?option. + ?option wdt:P2044 ?elevation. + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } + } + `, "¿Que montaña se encuentra en "], + // pregunta = poblacion, opcion = pais + [ + ` + SELECT ?optionLabel ?question ?questionLabel + WHERE { + ?option wdt:P31 wd:Q6256. + ?option wdt:P1082 ?question. + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } + }`, "¿Que pais tiene una poblacion de personas de " + ] + ]; + +queries['Cultura'] = + [ + // pregunta = pelicula, opcion = director + [ + ` + SELECT DISTINCT ?question ?questionLabel ?option ?optionLabel + WHERE { + ?question wdt:P31 wd:Q11424; + wdt:P57 ?option. + ?question wdt:P577 ?publicationDate. + FILTER(?publicationDate >= "2000-01-01T00:00:00Z"^^xsd:dateTime) + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } + } + LIMIT 100 + `, "¿Que director dirigio "], + // pregunta = termino, opcion = universo + [ + ` + SELECT DISTINCT ?question ?questionLabel ?option ?optionLabel + WHERE { + { + ?question wdt:P1080 wd:Q19595297; # Relacionado con Warhammer 40000 + rdfs:label ?questionLabel. + BIND("Warhammer 40000" AS ?option) + } + UNION + { + ?question wdt:P1080 wd:Q19786052; # Relacionado con Star Wars + rdfs:label ?questionLabel. + BIND("Star Wars" AS ?option) + } + UNION + { + ?question wdt:P1080 wd:Q18043309; # Relacionado con Star Trek + rdfs:label ?questionLabel. + BIND("Star Trek" AS ?option) + } + UNION + { + ?question wdt:P1080 wd:Q81738; # Relacionado con Legendarium + rdfs:label ?questionLabel. + BIND("Legendarium" AS ?option) + } + FILTER(LANG(?questionLabel) = "es") + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } + } + LIMIT 100 + `, "¿A que universo de ficción pertenece el siguiente término: "], + [ + // pregunta = genero, opcion = videojuego + ` + SELECT ?option ?optionLabel ?question ?questionLabel + WHERE { + ?option wdt:P31 wd:Q7889. + ?option wdt:P136 ?question. SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } - } - LIMIT 100 - `]; + } + LIMIT 100 + `, "¿Cual de los siguientes juegos pertenece al genero "] + ]; -// Todas las preguntas, en el mismo orden que las consultas -var questions = ["¿Cuál es la capital de ", - "¿En que campo juega el ", - "¿Cuál es el elemento de la tabla periódica número ", - "¿En que año ocurrio la "]; +queries['Informatica'] = + [ + // pregunta = software, opcion = fecha + [ + ` + SELECT ?question ?questionLabel ?option ?optionLabel + WHERE { + ?question wdt:P31 wd:Q7397. + ?question wdt:P571 ?releaseDate. + BIND(SUBSTR(?releaseDate, 9, 2) AS ?day) + BIND(SUBSTR(?releaseDate, 6, 2) AS ?month) + BIND(SUBSTR(?releaseDate, 1, 4) AS ?year) + BIND(CONCAT(?day, "/", ?month, "/", ?year) AS ?option) + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } + } + `, "¿En que fecha se creó "], + [ + // pregunta = creador, opcion = lenguaje de programacion + ` + SELECT ?option ?optionLabel ?question ?questionLabel + WHERE { + ?option wdt:P31 wd:Q9143. + ?option wdt:P178 ?question. + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } + } + LIMIT 100 + `, "¿Que lenguaje de programación fue creado por "], + // pregunta = empresa tecnologica, opcion = pais de origen + [ + ` + SELECT ?question ?questionLabel ?option ?optionLabel + WHERE { + ?question wdt:P31 wd:Q4830453. + ?question wdt:P17 ?option. + SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],es". } + } + LIMIT 100 + `, "¿De que pais procede "] + ]; -module.exports = { queries, questions }; \ No newline at end of file +module.exports = { queries }; \ No newline at end of file diff --git a/sonar-project.properties b/sonar-project.properties index 9080fe9d..192c0c31 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -11,7 +11,7 @@ sonar.language=js sonar.projectName=wiq_es2c sonar.coverage.exclusions=**/*.test.js -sonar.sources=webapp/src/components,users/authservice,users/userservice,gatewayservice +sonar.sources=webapp/src/components,users/authservice,users/userservice,gatewayservice,gamehistoryservice,questiongenerator,perfilservice,apis/allquestionservice,apis/alluserservice sonar.sourceEncoding=UTF-8 sonar.exclusions=node_modules/** sonar.javascript.lcov.reportPaths=**/coverage/lcov.info diff --git a/users/userservice/user-service.test.js b/users/userservice/user-service.test.js index 5c65df10..71f0d8ec 100644 --- a/users/userservice/user-service.test.js +++ b/users/userservice/user-service.test.js @@ -2,19 +2,16 @@ const request = require('supertest'); const { MongoMemoryServer } = require('mongodb-memory-server'); let mongoServer; -let app; - -const newPassword = Math.floor(Math.random() * 10).toString(); // Genera una nueva contraseña aleatoria para evitar el Security Hostpot de SonarCloud en las pruebas - +let const newUser = { username: 'testuser', - email: 'testuser@correo.com', - password: newPassword + email: 'testuser@gmail.com', + password: newString }; const badNewUser = { username: 'testuser', - password: newPassword + password: newString }; beforeAll(async () => { @@ -33,7 +30,7 @@ describe('User Service', () => { it('should add a new user on POST /adduser', async () => { const response = await request(app).post('/adduser').send(newUser); expect(response.status).toBe(200); - expect(response.body).toHaveProperty('email', 'testuser@correo.com'); + expect(response.body).toHaveProperty('email', 'testuser@gmail.com'); }); it('trying to add a new user on POST /adduser withouth an email', async () => { diff --git a/webapp/src/components/Game.js b/webapp/src/components/Game.js index af95d33e..8fb89d50 100644 --- a/webapp/src/components/Game.js +++ b/webapp/src/components/Game.js @@ -22,23 +22,19 @@ const Game = () => { const [answeredQuestions,setAnsweredQuestions] = useState(0); const [isTimeRunning, setIsTimeRunning] = useState(true); - - - // Comentario de prueba para el despliegue - const location = useLocation(); const MAX_TIME = location.state ? location.state.time : null; const MAX_PREGUNTAS = location.state ? location.state.question : null; + const THEMATIC = location.state ? location.state.thematic : null; const navigate = useNavigate(); - - const getQuestion = useCallback(async () => { try { const response = await axios.get(`${apiEndpoint}/generateQuestion`, { params: { - user: usernameGlobal + user: usernameGlobal, + thematic: THEMATIC } }); setQuestion(response.data.responseQuestion); @@ -167,7 +163,7 @@ const Game = () => { {question}