Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trabajar con la rama Develop con las nuevas modificaciones #61

Merged
merged 36 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6057cec
Question generation service started
UO287687 Feb 11, 2024
d18b082
Cities questions added
UO287687 Feb 12, 2024
25c9350
Template "city in country" added
UO287687 Feb 12, 2024
f6b1619
Refactor and template "higher city"
UO287687 Feb 12, 2024
5d707c3
Error in cities queries solved
UO287687 Feb 12, 2024
07541a0
Error solved in cities queries
UO287687 Feb 12, 2024
bcba025
Improvement by preloading data questions
UO287687 Feb 12, 2024
ba8768b
Merge pull request #33 from Arquisoft/question_generator
UO287687 Feb 12, 2024
22ba60d
Merge pull request #53 from Arquisoft/UO287747-Develop
UO287687 Feb 19, 2024
178c7f1
Changes on docker-compose file
UO287687 Feb 21, 2024
68a8770
Merge pull request #54 from Arquisoft/question_generator
UO287747 Feb 21, 2024
302bdb4
access to the question generation service from the gateway service
UO287687 Feb 21, 2024
d891e57
Merge pull request #57 from Arquisoft/question_generator
UO287747 Feb 21, 2024
d622297
Added first version of Participation and Participation test
uo276976 Feb 22, 2024
1b7c693
Added first version of question model
uo276976 Feb 22, 2024
b21f986
Added first version of question service
uo276976 Feb 22, 2024
b359c9b
Merge branch 'Develop' into FeatureQuestions
UO287687 Feb 22, 2024
24a591a
docker-compose añadido question service
uo276976 Feb 22, 2024
d7fa19f
arreglado fallo question-service, nombre de variable
uo276976 Feb 22, 2024
29d1b6a
Merge branch 'Develop' into FeatureQuestions
UO287687 Feb 22, 2024
36ecadb
question service funcionando por primera vez. Primera version de sus …
uo276976 Feb 22, 2024
cf69f42
Question generation test added
UO287687 Feb 22, 2024
2fe4607
Question generation tests added
UO287687 Feb 22, 2024
d134a7e
Tests updated
UO287687 Feb 23, 2024
0119bab
Merge branch 'Develop' into FeatureQuestions
UO287687 Feb 23, 2024
cbde6cb
Tests timeout changed
UO287687 Feb 23, 2024
4e6cbf1
Error in timeout solved
UO287687 Feb 23, 2024
20e9124
Another timeout change
UO287687 Feb 23, 2024
de57f9e
/health test added and others commented
UO287687 Feb 23, 2024
777ee13
Control exceptions on question generation service
UO287687 Feb 23, 2024
f355e05
decommented test
UO287687 Feb 23, 2024
c42435f
Tests workflow updated
UO287687 Feb 23, 2024
141a9d0
package.json updated
UO287687 Feb 23, 2024
b7aee22
build.yml updated
UO287687 Feb 23, 2024
7b05f3c
Test fix
UO287687 Feb 23, 2024
08a31ba
Merge pull request #60 from Arquisoft/FeatureQuestions
UO287747 Feb 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ jobs:
node-version: 20
- run: npm --prefix users/authservice ci
- run: npm --prefix users/userservice ci
- run: npm --prefix question_generator ci
- run: npm --prefix questionservice ci
- run: npm --prefix gatewayservice ci
- run: npm --prefix webapp ci
- run: npm --prefix users/authservice test -- --coverage
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ The deploy action is the following:
deploy:
name: Deploy over SSH
runs-on: ubuntu-latest
needs: [docker-push-userservice,docker-push-authservice,docker-push-gatewayservice,docker-push-webapp]
needs: [docker-push-userservice,docker-push-authservice,docker-push-gatewayservice,docker-push-webapp,docker-push-questiongenerationservice, docker-push-questionservice]
steps:
- name: Deploy over SSH
uses: fifsky/ssh-action@master
Expand Down
28 changes: 28 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,30 @@ services:
environment:
MONGODB_URI: mongodb://mongodb:27017/userdb

questiongenerationservice:
container_name: questiongenerationservice-${teamname:-defaultASW}
image: ghcr.io/arquisoft/wiq_es3b/questiongenerationservice:latest
profiles: ["dev", "prod"]
build: ./question_generator
ports:
- "8003:8003"
networks:
- mynetwork

questionservice:
container_name: questionservice-${teamname:-defaultASW}
image: ghcr.io/arquisoft/wiq_es3b/questionservice:latest
profiles: ["dev", "prod"]
build: ./questionservice
depends_on:
- mongodb
ports:
- "8004:8004"
networks:
- mynetwork
environment:
MONGODB_URI: mongodb://mongodb:27017/questionsdb

gatewayservice:
container_name: gatewayservice-${teamname:-defaultASW}
image: ghcr.io/arquisoft/wiq_es3b/gatewayservice:latest
Expand All @@ -48,13 +72,17 @@ services:
- mongodb
- userservice
- authservice
- questiongenerationservice
- questionservice
ports:
- "8000:8000"
networks:
- mynetwork
environment:
AUTH_SERVICE_URL: http://authservice:8002
USER_SERVICE_URL: http://userservice:8001
QUESTION_GENERATION_SERVICE_URL: http://questiongenerationservice:8003
QUESTIONS_SERVICE_URL: http://questionservice:8004

webapp:
container_name: webapp-${teamname:-defaultASW}
Expand Down
25 changes: 25 additions & 0 deletions gatewayservice/gateway-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const port = 8000;

const authServiceUrl = process.env.AUTH_SERVICE_URL || 'http://localhost:8002';
const userServiceUrl = process.env.USER_SERVICE_URL || 'http://localhost:8001';
const questionGenerationServiceUrl = process.env.QUESTION_GENERATION_SERVICE_URL || 'http://localhost:8003';
const questionServiceUrl = process.env.QUESTIONS_SERVICE_URL || 'http://localhost:8004';

app.use(cors());
app.use(express.json());
Expand Down Expand Up @@ -41,6 +43,29 @@ app.post('/adduser', async (req, res) => {
}
});

app.get('/api/questions/create', async (req, res) => {
console.log('Create Question')
try {
// Forward the add user request to the user service
const userResponse = await axios.get(questionGenerationServiceUrl+'/api/questions/create');
console.log(userResponse.data);
res.json(userResponse.data);
} catch (error) {
res.status(error.response.status).json({ error: error.response.data.error });
}
});

// Ruta para agregar una nueva pregunta
app.post('/addquestion', async (req, res) => {
try {
// Forward the add question request to the questions service
const questionResponse = await axios.post(questionServiceUrl + '/addquestion', req.body);
res.json(questionResponse.data);
} catch (error) {
res.status(error.response.status).json({ error: error.response.data.error });
}
});

// Start the gateway service
const server = app.listen(port, () => {
console.log(`Gateway Service listening at http://localhost:${port}`);
Expand Down
58 changes: 56 additions & 2 deletions gatewayservice/gateway-service.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const request = require('supertest');
const axios = require('axios');
const app = require('./gateway-service');

let app;
beforeAll(async () => {
app = require('./gateway-service');
});
afterAll(async () => {
app.close();
});
Expand All @@ -15,8 +17,35 @@ describe('Gateway Service', () => {
return Promise.resolve({ data: { token: 'mockedToken' } });
} else if (url.endsWith('/adduser')) {
return Promise.resolve({ data: { userId: 'mockedUserId' } });
}else if (url.endsWith('/addquestion')) {
return Promise.resolve({
data: {
question: 'What is the capital of France?',
options: ['Paris', 'Berlin', 'Madrid', 'Rome'],
correctOptionIndex: 0
}
});
}
});
axios.get.mockImplementation((url) => {
if (url.endsWith('/api/questions/create')) {
return Promise.resolve({
data: {
question: 'Mocked Question',
correct: 'Mocked Correct Answer',
incorrects: ['Mocked Option 1', 'Mocked Option 2']
}
});
}
});
// Test /health endpoint
it('should give information of the status', async () => {
const response = await request(app)
.get('/health');

expect(response.statusCode).toBe(200);
expect(response.body.status).toBe('OK');
});

// Test /login endpoint
it('should forward login request to auth service', async () => {
Expand All @@ -37,4 +66,29 @@ describe('Gateway Service', () => {
expect(response.statusCode).toBe(200);
expect(response.body.userId).toBe('mockedUserId');
});

// Test /api/questions/create endpoint
it('should forward create question request to question generation service', async () => {
const response = await request(app)
.get('/api/questions/create');
expect(response.statusCode).toBe(200);
expect(response.body).toHaveProperty('question');
expect(response.body).toHaveProperty('correct');
expect(response.body).toHaveProperty('incorrects');
},10000);


// Test /addquestion endpoint
it('should add a new question', async () => {
const response = await request(app)
.post('/addquestion')
.send({
question: 'What is the capital of France?',
options: ['Paris', 'Berlin', 'Madrid', 'Rome'],
correctOptionIndex: 0,
});

expect(response.statusCode).toBe(200);
expect(response.body).toHaveProperty('question', 'What is the capital of France?');
});
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
"devDependencies": {
"serve": "^14.2.1"
}
}
}
20 changes: 20 additions & 0 deletions question_generator/Dockerfile
Original file line number Diff line number Diff line change
@@ -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/questiongenerationservice

# 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 8003

# Define the command to run your app
CMD ["node", "questionGenerationService.js"]
134 changes: 134 additions & 0 deletions question_generator/cities/citiesQuestions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
const queryExecutor=require("../queryExecutor")
class CitiesQuestions{
#citiesQuestions=null;
static getInstance(){
if (!this.citiesQuestions) {
this.citiesQuestions = new CitiesQuestions();
}
return this.citiesQuestions;
}
constructor(){
this.cities={};
}
async loadData(){
if (Object.keys(this.cities).length === 0) {//Se obtienen 100 ciudades relevantes
const query=`
SELECT ?city ?cityLabel ?population ?countryLabel ?elevation_above_sea_level
WITH{
SELECT ?city ?cityLabel
WHERE{
?city wdt:P31 wd:Q515
}
LIMIT 1000
} AS %i
WHERE {
INCLUDE %i
OPTIONAL{
?city wdt:P1082 ?population.
?city wdt:P17 ?country.
?city wdt:P2044 ?elevation_above_sea_level
}
FILTER EXISTS{
?city wdt:P1082 ?population.
?city wdt:P17 ?country.
?city wdt:P2044 ?elevation_above_sea_level
}
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}
ORDER BY DESC(?population)
LIMIT 100
`
let cities = await queryExecutor.execute(query);
cities.forEach(city => {
const cityId = city.city.value;
const cityName = city.cityLabel.value;
const population = city.population.value;
const country = city.countryLabel.value;
const elevationAboveSeaLevel = city.elevation_above_sea_level.value;

if (!this.cities[cityId]) {
this.cities[cityId] = {
cityId: cityId,
cityName: cityName,
population: population,
country: country,
elevation_above_sea_level: []
};
}

this.cities[cityId].elevation_above_sea_level.push(parseFloat(elevationAboveSeaLevel));
});

}
}
async getRandomCities(numberOfCities){
await this.loadData();
const citiesArray = Object.values(this.cities);
const randomResults = citiesArray.sort(() => Math.random() - 0.5).slice(0, numberOfCities);
return randomResults
}
async getMostPopulatedCity(){
let numberOfCities=4
const results=await this.getRandomCities(numberOfCities);
const formattedResults = await results.map(result => {
return {
item: result.cityName,
value:parseFloat(result.population),
};
}).sort((a, b) => b.value - a.value);
const finalResults={
correct: null,
incorrects: []
}
for(let i=0;i<numberOfCities;i++){
if(i==0){
finalResults.correct=formattedResults[i].item
}
else{
finalResults.incorrects.push(formattedResults[i].item)
}
}
return finalResults
}
async getCityForCountry(){
let numberOfCities=4;
let result =(await this.getRandomCities(1))[0];
let country=result.country;

let correct = result.cityName;
let incorrects = []
let i=1;
while(i<numberOfCities){
let city=(await this.getRandomCities(1))[0];
if(city.country!=country){
incorrects.push(city.cityName);
i++;
}
}
return {
country:country,
correct:correct,
incorrects:incorrects
}
}
async getHigherCity(){
let numberOfCities=4;
let result =await this.getRandomCities(numberOfCities);
//Using first value in the array for elevation_above_sea_level
const formattedResults = await result.sort((a, b) => b.elevation_above_sea_level[0] - a.elevation_above_sea_level[0]);
const finalResults={
correct: null,
incorrects: []
}
for(let i=0;i<numberOfCities;i++){
if(i==0){
finalResults.correct=formattedResults[i].cityName
}
else{
finalResults.incorrects.push(formattedResults[i].cityName)
}
}
return finalResults;
}
}
module.exports=CitiesQuestions;
38 changes: 38 additions & 0 deletions question_generator/cities/citiesTemplates.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const cities=require('./citiesQuestions');
const citiesQuery=cities.getInstance();
function loadData(){
citiesQuery.loadData();
}
const templates=[
async ()=>
{
const results= await citiesQuery.getMostPopulatedCity();
return{
"question":"Which city has more population?",
"correct":results.correct,
"incorrects":results.incorrects
}
},
async ()=>
{
const results= await citiesQuery.getCityForCountry();
return{
"question":"Which city is in "+results.country+"?",
"correct":results.correct,
"incorrects":results.incorrects
}
},
async ()=>
{
const results= await citiesQuery.getHigherCity();
return{
"question":"Which city is higher above sea level?",
"correct":results.correct,
"incorrects":results.incorrects
}
}


]
module.exports.getRandomQuestion = () => templates[Math.floor(Math.random()*templates.length)]();
module.exports.loadData = () =>loadData();
Loading