From 68c6c9ae46a67a65109edd2e0247fe0e034f6c74 Mon Sep 17 00:00:00 2001 From: baraganio Date: Tue, 26 Mar 2024 22:09:09 +0100 Subject: [PATCH 1/5] =?UTF-8?q?A=C3=B1adida=20la=20funcionalidad=20de=20gu?= =?UTF-8?q?ardar=20las=20preguntas=20generadas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- questions/creationservice/creation-model.js | 2 +- questions/creationservice/creation-service.js | 34 +++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/questions/creationservice/creation-model.js b/questions/creationservice/creation-model.js index a8a3723c..bc9e641e 100644 --- a/questions/creationservice/creation-model.js +++ b/questions/creationservice/creation-model.js @@ -6,7 +6,7 @@ const questionSchema = new mongoose.Schema({ correctAnswer: String, incorrectAnswer1: String, incorrectAnswer2: String, - incorrectAnswer3: String, + incorrectAnswer3: String }); const Question = mongoose.model('Question', questionSchema); diff --git a/questions/creationservice/creation-service.js b/questions/creationservice/creation-service.js index 8e9ab4eb..7fc89323 100644 --- a/questions/creationservice/creation-service.js +++ b/questions/creationservice/creation-service.js @@ -1,17 +1,21 @@ const express = require('express'); const mongoose = require('mongoose'); const fetch = require('node-fetch'); +const Question = require('./creation-model'); const app = express(); const port = 8005; app.use(express.json()); +const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/questiondb'; +mongoose.connect(mongoUri); + const optionsNumber = 4; -// It will be the country of the question +// It will be the questionObject var questionObject= ""; -// It will be the correct capital of the question +// It will be the correct answer var correctOption = ""; // It will be the different options for the answers var answerOptions = []; @@ -22,7 +26,7 @@ var queries = ['SELECT DISTINCT ?questionObject ?questionObjectLabel ?answer ?an // Array of the possible questions var questions = ["¿Cual es la capital de "]; -// Recieves the information of the query and select wich data use on the question (country and capitals) +// Recieves the information of the query and select wich data use on the question function getQuestionInfo(info){ answerOptions = []; var fourRows = []; @@ -47,6 +51,28 @@ function selectRandomQuery(){ randomQuerySelector = Math.floor(Math.random() * queries.length); } +async function saveQuestion(){ + var incorrectAnswers=[]; + answerOptions.forEach(e => { + if(e!=correctOption) + incorrectAnswers.push(e); + }); + + try { + const newQuestion = new Question({ + question: questionObject, + correctAnswer: correctOption, + incorrectAnswer1: incorrectAnswers[0], + incorrectAnswer2: incorrectAnswers[1], + incorrectAnswer3: incorrectAnswers[2] + }); + await newQuestion.save(); + + }catch (error){ + console.error("Error al guardar la pregunta: " + error); + } +} + app.post('/createquestion', async (req, res) => { selectRandomQuery(); const apiUrl = `https://query.wikidata.org/sparql?query=${encodeURIComponent(queries[randomQuerySelector])}&format=json`; @@ -77,6 +103,8 @@ app.post('/createquestion', async (req, res) => { responseCorrectOption : correctOption, responseAnswerOptions : answerOptions }; + + saveQuestion(); // Return the resoult with a 200 status res.status(200).json(solution); From 15b0284f1c587015030e71abd3c857883610967f Mon Sep 17 00:00:00 2001 From: baraganio Date: Wed, 27 Mar 2024 16:43:42 +0100 Subject: [PATCH 2/5] Quitar dependencias y variables que no se usan con el fin de que no falle el deploy --- webapp/src/components/Game.js | 31 ++++++++++--------------- webapp/src/components/HistoricalData.js | 4 +--- webapp/src/components/MainPage.js | 5 ++-- 3 files changed, 15 insertions(+), 25 deletions(-) diff --git a/webapp/src/components/Game.js b/webapp/src/components/Game.js index 0fa8bb48..99951e66 100644 --- a/webapp/src/components/Game.js +++ b/webapp/src/components/Game.js @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import axios from 'axios'; -import { Container, Typography, Button, Paper, TimerIcon } from '@mui/material'; +import { Container, Typography, Button, Paper} from '@mui/material'; import './Game.css'; @@ -15,6 +15,7 @@ const Game = () => { const [correctOption, setCorrectOption] = useState(''); const [answerOptions, setAnswerOptions] = useState([]); const [correctCounter, setCorrectCounter] = useState(0); + const [numberOfOptions, setNumberOfOptions] = useState(); const [questionCounter, setQuestionCounter] = useState(0); const [incorrectCounter, setIncorrectCounter] = useState(0); @@ -63,7 +64,6 @@ const Game = () => { // Method that checks if the answer clicked is the correct one const handleAnswerClick = (option, index) => { // Get what component is the button to change its color later - //const button = document.getElementById(`button_${index}`); if(option === correctOption) { const buttonId = `button_${index}`; const correctButton = document.getElementById(buttonId); @@ -112,12 +112,12 @@ const Game = () => { Pregunta {questionCounter}: ¿Cuál es la capital de {questionObject}?
- {answerOptions.map((option, index) => ( - - ))} -
+ {answerOptions.map((option, index) => ( + + ))} +
- - + -
- Time Remaining: {Math.floor(seconds / 60)}:{(seconds % 60).toLocaleString('en-US', { minimumIntegerDigits: 2 })} -
+
+ Time Remaining: {Math.floor(seconds / 60)}:{(seconds % 60).toLocaleString('en-US', { minimumIntegerDigits: 2 })} +
- - {/* */} - - ); }; diff --git a/webapp/src/components/HistoricalData.js b/webapp/src/components/HistoricalData.js index c96207ca..39700bfe 100644 --- a/webapp/src/components/HistoricalData.js +++ b/webapp/src/components/HistoricalData.js @@ -1,6 +1,4 @@ -import React, { useState } from 'react'; -import axios from 'axios'; -import { Container, Typography, TextField, Button, Snackbar } from '@mui/material'; +import { Typography} from '@mui/material'; const HistoricalData = () => { diff --git a/webapp/src/components/MainPage.js b/webapp/src/components/MainPage.js index a862e675..17f1dffe 100644 --- a/webapp/src/components/MainPage.js +++ b/webapp/src/components/MainPage.js @@ -1,6 +1,5 @@ -import React, { useState } from 'react'; -import { Container, Typography, TextField, Button, Snackbar } from '@mui/material'; -import { useNavigate, useParams } from 'react-router-dom'; +import { Container, Typography, Button} from '@mui/material'; +import { useNavigate} from 'react-router-dom'; const MainPage = () => { const navigate = useNavigate(); From 8a5dde366e73fbcf051ce290b21bf5d5b01f0d82 Mon Sep 17 00:00:00 2001 From: baraganio Date: Wed, 27 Mar 2024 17:06:13 +0100 Subject: [PATCH 3/5] Crear servicio para recuperar las preguntas guardadas en base de datos --- docker-compose.yml | 16 +++++ questions/creationservice/package.json | 2 +- questions/retrieveservice/.dockerignore | 2 + questions/retrieveservice/Dockerfile | 20 ++++++ questions/retrieveservice/creation-model.js | 14 +++++ questions/retrieveservice/package.json | 32 ++++++++++ questions/retrieveservice/retrieve-service.js | 63 +++++++++++++++++++ 7 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 questions/retrieveservice/.dockerignore create mode 100644 questions/retrieveservice/Dockerfile create mode 100644 questions/retrieveservice/creation-model.js create mode 100644 questions/retrieveservice/package.json create mode 100644 questions/retrieveservice/retrieve-service.js diff --git a/docker-compose.yml b/docker-compose.yml index 2caf2f81..d8af9638 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,6 +25,20 @@ services: environment: MONGODB_URI: mongodb://mongodb:27017/userdb + retrieveservice: + container_name: retrieveservice-${teamname:-defaultASW} + image: ghcr.io/arquisoft/wiq_es2b/retrieveservice:latest + profiles: ["dev", "prod"] + build: ./questions/retrieveservice + depends_on: + - mongodb + ports: + - "8004:8004" + networks: + - mynetwork + environment: + MONGODB_URI: mongodb://mongodb:27017/userdb + authservice: container_name: authservice-${teamname:-defaultASW} image: ghcr.io/arquisoft/wiq_es2b/authservice:latest @@ -63,6 +77,7 @@ services: - userservice - authservice - creationservice + - retrieveservice ports: - "8000:8000" networks: @@ -71,6 +86,7 @@ services: AUTH_SERVICE_URL: http://authservice:8002 USER_SERVICE_URL: http://userservice:8001 CREATION_SERVICE_URL: http://creationservice:8005 + RETRIEVE_SERVICE_URL: http://retrieveservice:8004 webapp: container_name: webapp-${teamname:-defaultASW} diff --git a/questions/creationservice/package.json b/questions/creationservice/package.json index aeddd4c6..7c85d114 100644 --- a/questions/creationservice/package.json +++ b/questions/creationservice/package.json @@ -1,7 +1,7 @@ { "name": "creationservice", "version": "1.0.0", - "description": " Creation service, in charge of ", + "description": " Creation service, in charge of create the questions of the game and store them", "main": "service.js", "scripts": { "start": "node creation-service.js", diff --git a/questions/retrieveservice/.dockerignore b/questions/retrieveservice/.dockerignore new file mode 100644 index 00000000..3091757a --- /dev/null +++ b/questions/retrieveservice/.dockerignore @@ -0,0 +1,2 @@ +node_modules +coverage \ No newline at end of file diff --git a/questions/retrieveservice/Dockerfile b/questions/retrieveservice/Dockerfile new file mode 100644 index 00000000..838d0d31 --- /dev/null +++ b/questions/retrieveservice/Dockerfile @@ -0,0 +1,20 @@ +# Use an official Node.js runtime as a parent image +FROM node:20 + +# Set the working directory in the container +WORKDIR /usr/src/retrieveservice + +# Copy package.json and package-lock.json to the working directory +COPY package*.json ./ + +# Install app dependencies +RUN npm install + +# Copy the app source code to the working directory +COPY . . + +# Expose the port the app runs on +EXPOSE 8004 + +# Define the command to run your app +CMD ["node", "retrieve-service.js"] diff --git a/questions/retrieveservice/creation-model.js b/questions/retrieveservice/creation-model.js new file mode 100644 index 00000000..bc9e641e --- /dev/null +++ b/questions/retrieveservice/creation-model.js @@ -0,0 +1,14 @@ +const mongoose = require('mongoose'); + +// Crea la base de datos con las columnas especificadas +const questionSchema = new mongoose.Schema({ + question: String, + correctAnswer: String, + incorrectAnswer1: String, + incorrectAnswer2: String, + incorrectAnswer3: String +}); + +const Question = mongoose.model('Question', questionSchema); + +module.exports = Question \ No newline at end of file diff --git a/questions/retrieveservice/package.json b/questions/retrieveservice/package.json new file mode 100644 index 00000000..c2cf50e7 --- /dev/null +++ b/questions/retrieveservice/package.json @@ -0,0 +1,32 @@ +{ + "name": "retrieveservice", + "version": "1.0.0", + "description": " Retrieve service, in charge of claim the questions information stored on de database", + "main": "service.js", + "scripts": { + "start": "node retrieve-service.js", + "test": "jest" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/arquisoft/wiq_es2b.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/arquisoft/wiq_es2b/issues" + }, + "homepage": "https://github.com/arquisoft/wiq_es2b#readme", + "dependencies": { + "bcrypt": "^5.1.1", + "body-parser": "^1.20.2", + "express": "^4.18.2", + "jsonwebtoken": "^9.0.2", + "mongoose": "^8.0.4" + }, + "devDependencies": { + "jest": "^29.7.0", + "mongodb-memory-server": "^9.1.5", + "supertest": "^6.3.4" + } +} diff --git a/questions/retrieveservice/retrieve-service.js b/questions/retrieveservice/retrieve-service.js new file mode 100644 index 00000000..288fc7ec --- /dev/null +++ b/questions/retrieveservice/retrieve-service.js @@ -0,0 +1,63 @@ +const express = require('express'); +const mongoose = require('mongoose'); +const fetch = require('node-fetch'); + +const app = express(); +const port = 8004; + +app.use(express.json()); + +const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/questiondb'; +mongoose.connect(mongoUri); + + + +app.post('/retrievequestion', async (req, res) => { + /*const apiUrl = `https://query.wikidata.org/sparql?query=${encodeURIComponent(queries[randomQuerySelector])}&format=json`; + + try { + // Makes the petition to the url + const response = await fetch(apiUrl, { + headers: { + 'Accept': 'application/json' + } + }); + + // Check if everything was good on the petition + if (!response.ok) { + console.error('Error al realizar la consulta a Wikidata:', response.statusText); + return; + } + + // Parse the response + const data = await response.json(); + + // Send the parsed response to be selected + getQuestionInfo(data.results.bindings); + + // Declare what will be return + solution = { + responseQuestionObject : questionObject, + responseCorrectOption : correctOption, + responseAnswerOptions : answerOptions + }; + + saveQuestion(); + + // Return the resoult with a 200 status + res.status(200).json(solution); + } catch (error) { + console.error('Error al realizar la consulta:', error); + res.status(500).json({ error: 'Internal Server Error' }); + }*/ +}); + +const server = app.listen(port, () => { + console.log(`Creation Service listening at http://localhost:${port}`); +}); + +server.on('close', () => { + mongoose.connection.close(); +}); + +module.exports = server; From 458a4e595167a8ed044dc60a3b75efc6782f02ba Mon Sep 17 00:00:00 2001 From: baraganio Date: Wed, 27 Mar 2024 17:29:02 +0100 Subject: [PATCH 4/5] Conectando el servicio retrieve-service al gateway y a la aplicacion --- gatewayservice/gateway-service.js | 15 +++++-- ...ion-model.js => questionshistory-model.js} | 0 questions/retrieveservice/retrieve-service.js | 41 ++----------------- webapp/src/components/HistoricalData.js | 28 +++++++++++-- 4 files changed, 40 insertions(+), 44 deletions(-) rename questions/retrieveservice/{creation-model.js => questionshistory-model.js} (100%) diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 6d38f474..a20b94cc 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -9,6 +9,7 @@ const port = 8000; const authServiceUrl = process.env.AUTH_SERVICE_URL || 'http://localhost:8002'; const userServiceUrl = process.env.USER_SERVICE_URL || 'http://localhost:8001'; const creationServiceUrl = process.env.CREATION_SERVICE_URL || 'http://localhost:8005'; +const retrieveServiceUrl = process.env.RETRIEVE_SERVICE_URL || 'http://localhost:8004'; app.use(cors()); app.use(express.json()); @@ -43,10 +44,18 @@ app.post('/adduser', async (req, res) => { app.post('/createquestion', async (req, res) => { try { // Create a petition to the URL (le llegará a creation-service.js) with the option /createquestion and the req.body params - console.log("salgo de gateway hacia creation"); const questionResponse = await axios.post(creationServiceUrl+'/createquestion', req.body); - console.log("vengo de creation y estoy en gateway"); - console.log(questionResponse.status); + // Return a json response with what we obtained on the petition + res.json(questionResponse.data); + } catch (error) { + res.status(error.response.status).json({ error: error.response.data.error }); + } +}); + +app.post('/getquestionshistory', async (req, res) => { + try { + // Create a petition to the URL (le llegará a retrieve-service.js) with the option /getgeneratedquestions and the req.body params + const questionResponse = await axios.post(retrieveServiceUrl+'/getquestionshistory', req.body); // Return a json response with what we obtained on the petition res.json(questionResponse.data); } catch (error) { diff --git a/questions/retrieveservice/creation-model.js b/questions/retrieveservice/questionshistory-model.js similarity index 100% rename from questions/retrieveservice/creation-model.js rename to questions/retrieveservice/questionshistory-model.js diff --git a/questions/retrieveservice/retrieve-service.js b/questions/retrieveservice/retrieve-service.js index 288fc7ec..7d761233 100644 --- a/questions/retrieveservice/retrieve-service.js +++ b/questions/retrieveservice/retrieve-service.js @@ -12,44 +12,9 @@ mongoose.connect(mongoUri); -app.post('/retrievequestion', async (req, res) => { - /*const apiUrl = `https://query.wikidata.org/sparql?query=${encodeURIComponent(queries[randomQuerySelector])}&format=json`; - - try { - // Makes the petition to the url - const response = await fetch(apiUrl, { - headers: { - 'Accept': 'application/json' - } - }); - - // Check if everything was good on the petition - if (!response.ok) { - console.error('Error al realizar la consulta a Wikidata:', response.statusText); - return; - } - - // Parse the response - const data = await response.json(); - - // Send the parsed response to be selected - getQuestionInfo(data.results.bindings); - - // Declare what will be return - solution = { - responseQuestionObject : questionObject, - responseCorrectOption : correctOption, - responseAnswerOptions : answerOptions - }; - - saveQuestion(); - - // Return the resoult with a 200 status - res.status(200).json(solution); - } catch (error) { - console.error('Error al realizar la consulta:', error); - res.status(500).json({ error: 'Internal Server Error' }); - }*/ +app.post('/getquestionshistory', async (req, res) => { + + res.status(200).json('todo bien'); }); const server = app.listen(port, () => { diff --git a/webapp/src/components/HistoricalData.js b/webapp/src/components/HistoricalData.js index 39700bfe..aa5f588d 100644 --- a/webapp/src/components/HistoricalData.js +++ b/webapp/src/components/HistoricalData.js @@ -1,11 +1,33 @@ -import { Typography} from '@mui/material'; +import axios from 'axios'; +import { Container, Typography, Button} from '@mui/material'; const HistoricalData = () => { + const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; + + const handleShowHistory = async () => { + try{ + // It makes a petition to the api and store the response + const response = await axios.post(`${apiEndpoint}/getquestionshistory`, { }); + console.log(response); + }catch (error){ + console.error('Error:', error); + } + } return ( - + + +
+ Pagina del HistoricalData - + + + +
+
+ ); }; From 78ede8274be81bfce00a187330fcda826df5c83a Mon Sep 17 00:00:00 2001 From: baraganio Date: Wed, 27 Mar 2024 19:00:23 +0100 Subject: [PATCH 5/5] Crear ventana de historial de preguntas y acabar de configurar el servicio retrieve-service --- docker-compose.yml | 4 +- questions/creationservice/creation-model.js | 25 ++++++++--- questions/retrieveservice/retrieve-service.js | 11 +++-- webapp/src/components/Game.js | 2 +- webapp/src/components/HistoricalData.js | 43 ++++++++++++++++--- 5 files changed, 69 insertions(+), 16 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index d8af9638..04eca969 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,7 +23,7 @@ services: networks: - mynetwork environment: - MONGODB_URI: mongodb://mongodb:27017/userdb + MONGODB_URI: mongodb://mongodb:27017/questiondb retrieveservice: container_name: retrieveservice-${teamname:-defaultASW} @@ -37,7 +37,7 @@ services: networks: - mynetwork environment: - MONGODB_URI: mongodb://mongodb:27017/userdb + MONGODB_URI: mongodb://mongodb:27017/questiondb authservice: container_name: authservice-${teamname:-defaultASW} diff --git a/questions/creationservice/creation-model.js b/questions/creationservice/creation-model.js index bc9e641e..378bf26d 100644 --- a/questions/creationservice/creation-model.js +++ b/questions/creationservice/creation-model.js @@ -2,11 +2,26 @@ const mongoose = require('mongoose'); // Crea la base de datos con las columnas especificadas const questionSchema = new mongoose.Schema({ - question: String, - correctAnswer: String, - incorrectAnswer1: String, - incorrectAnswer2: String, - incorrectAnswer3: String + question: { + type: String, + required: true, + }, + correctAnswer: { + type: String, + required: true, + }, + incorrectAnswer1: { + type: String, + required: true, + }, + incorrectAnswer2: { + type: String, + required: true, + }, + incorrectAnswer3: { + type: String, + required: true, + }, }); const Question = mongoose.model('Question', questionSchema); diff --git a/questions/retrieveservice/retrieve-service.js b/questions/retrieveservice/retrieve-service.js index 7d761233..3ece0bc3 100644 --- a/questions/retrieveservice/retrieve-service.js +++ b/questions/retrieveservice/retrieve-service.js @@ -1,6 +1,6 @@ const express = require('express'); const mongoose = require('mongoose'); -const fetch = require('node-fetch'); +const Question = require('./questionshistory-model') const app = express(); const port = 8004; @@ -11,10 +11,15 @@ const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/questiond mongoose.connect(mongoUri); - app.post('/getquestionshistory', async (req, res) => { + const questions = await Question.find({}); - res.status(200).json('todo bien'); + var solution = []; + questions.forEach(row => { + solution.push([row.question,row.correctAnswer,row.incorrectAnswer1,row.incorrectAnswer2,row.incorrectAnswer3]); + }); + + res.status(200).json(solution); }); const server = app.listen(port, () => { diff --git a/webapp/src/components/Game.js b/webapp/src/components/Game.js index 99951e66..ccbda51e 100644 --- a/webapp/src/components/Game.js +++ b/webapp/src/components/Game.js @@ -109,7 +109,7 @@ const Game = () => { Saber y Ganar Juego
- Pregunta {questionCounter}: ¿Cuál es la capital de {questionObject}? + Pregunta {questionCounter}: {questionObject}
{answerOptions.map((option, index) => ( diff --git a/webapp/src/components/HistoricalData.js b/webapp/src/components/HistoricalData.js index aa5f588d..904836c4 100644 --- a/webapp/src/components/HistoricalData.js +++ b/webapp/src/components/HistoricalData.js @@ -1,31 +1,64 @@ import axios from 'axios'; +import React, { useState} from 'react'; +import { useNavigate} from 'react-router-dom'; import { Container, Typography, Button} from '@mui/material'; const HistoricalData = () => { + const navigate = useNavigate(); const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; + const [questionsHistory, setQuestionsHistory] = useState([]); + const handleShowHistory = async () => { try{ // It makes a petition to the api and store the response const response = await axios.post(`${apiEndpoint}/getquestionshistory`, { }); - console.log(response); + setQuestionsHistory(response.data); }catch (error){ console.error('Error:', error); } } + const handlePreviousPage = async () => { + let path= '/MainPage'; + navigate(path); + } + return ( +
- - Pagina del HistoricalData - +
+
+ + + + + + + + + + + + {questionsHistory.map((row, rowIndex) => ( + + {row.map((cell, cellIndex) => ( + + ))} + + ))} + +
PreguntaOpción correctaOpción incorrecta 1Opción incorrecta 2Opción incorrecta 3
{cell}
+
);