Skip to content

Commit

Permalink
Merge pull request #143 from Arquisoft/UO289659
Browse files Browse the repository at this point in the history
Ranking de usuarios
  • Loading branch information
UO289659 authored Apr 15, 2024
2 parents 387a236 + ca491f8 commit 3dc6a64
Show file tree
Hide file tree
Showing 15 changed files with 592 additions and 4 deletions.
27 changes: 27 additions & 0 deletions gatewayservice/gateway-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,33 @@ app.get('/users', async (req, res) => {
}
});

app.get('/ranking/accuracy', async (req, res) => {
try {
const statResponse = await axios.get(statisticssServiceUrl+'/ranking/accuracy');
res.json(statResponse.data);
} catch (error) {
res.status(error.response.status).json({ error: error.response.data.error });
}
});

app.get('/ranking/correctAnswers', async (req, res) => {
try {
const statResponse = await axios.get(statisticssServiceUrl+'/ranking/correctAnswers');
res.json(statResponse.data);
} catch (error) {
res.status(error.response.status).json({ error: error.response.data.error });
}
});

app.get('/ranking/gamesPlayed', async (req, res) => {
try {
const statResponse = await axios.get(statisticssServiceUrl+'/ranking/gamesPlayed');
res.json(statResponse.data);
} catch (error) {
res.status(error.response.status).json({ error: error.response.data.error });
}
});


// Read the OpenAPI YAML file synchronously
openapiPath='./openapi.yaml'
Expand Down
75 changes: 75 additions & 0 deletions gatewayservice/gateway-service.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ describe('Gateway Service', () => {
wrongAnswers:'mockedWrongAnswers' }});
} else if (url.endsWith('/users')) {
return Promise.resolve({ data: { users: ['mockedUser1', 'mockedUser2'] } });
}else if(url.endsWith('/ranking/accuracy')){
return Promise.resolve({ data: { user: 'mockedUser', accuracy:'mockedAccuracy' }});
}else if(url.endsWith('/ranking/correctAnswers')){
return Promise.resolve({ data: { user: 'mockedUser', accuracy:'mockedCorrectAnswers' }});
}else if(url.endsWith('/ranking/gamesPlayed')){
return Promise.resolve({ data: { user: 'mockedUser', accuracy:'mockedGamesPlayed' }});
}
});

Expand Down Expand Up @@ -209,4 +215,73 @@ describe('Gateway Service', () => {
expect(response.body).toEqual(mockErrorResponse);
});

// Test /ranking/accuracy endpoint
it('should forward get ranking/accuracy request to statistics service', async () => {
const response = await request(app)
.get('/ranking/accuracy');

expect(response.statusCode).toBe(200);
expect(response.body.user).toBe('mockedUser');
expect(response.body.accuracy).toBe('mockedAccuracy');

});

it('debería manejar errores al intentar obtener ranking con métrica Porcentaje de Aciertos', async () => {
const mockErrorResponse = { error: 'Error al obtener ranking' };
const mockStatus = 500;

axios.get.mockRejectedValueOnce({ response: { status: mockStatus, data: mockErrorResponse } });

const response = await request(app).get('/ranking/accuracy');

expect(response.status).toBe(mockStatus);
expect(response.body).toEqual(mockErrorResponse);
});

// Test /ranking/correctAnswers endpoint
it('should forward get ranking/correctAnswers request to statistics service', async () => {
const response = await request(app)
.get('/ranking/correctAnswers');

expect(response.statusCode).toBe(200);
expect(response.body.user).toBe('mockedUser');
expect(response.body.accuracy).toBe('mockedCorrectAnswers');

});

it('debería manejar errores al intentar obtener ranking con métrica Respuestas Correctas', async () => {
const mockErrorResponse = { error: 'Error al obtener ranking' };
const mockStatus = 500;

axios.get.mockRejectedValueOnce({ response: { status: mockStatus, data: mockErrorResponse } });

const response = await request(app).get('/ranking/correctAnswers');

expect(response.status).toBe(mockStatus);
expect(response.body).toEqual(mockErrorResponse);
});

// Test /ranking/gamesPlayed endpoint
it('should forward get ranking/gamesPlayed request to statistics service', async () => {
const response = await request(app)
.get('/ranking/gamesPlayed');

expect(response.statusCode).toBe(200);
expect(response.body.user).toBe('mockedUser');
expect(response.body.accuracy).toBe('mockedGamesPlayed');

});

it('debería manejar errores al intentar obtener ranking con métrica Partidas Jugadas', async () => {
const mockErrorResponse = { error: 'Error al obtener ranking' };
const mockStatus = 500;

axios.get.mockRejectedValueOnce({ response: { status: mockStatus, data: mockErrorResponse } });

const response = await request(app).get('/ranking/gamesPlayed');

expect(response.status).toBe(mockStatus);
expect(response.body).toEqual(mockErrorResponse);
});

});
16 changes: 16 additions & 0 deletions statistics/statisticsservice/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions statistics/statisticsservice/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.6.8",
"bcrypt": "^5.1.1",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
Expand Down
50 changes: 50 additions & 0 deletions statistics/statisticsservice/statistics-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,56 @@ app.post('/addStatistic', async (req, res) => {

});


app.get('/ranking/accuracy', async (req, res) => {
try {
const users = await Statistic.find(); // Obtener todos los usuarios
const rankedUsers = users.map(user => {
const accuracy = (user.rigthAnswers / (user.gamesPlayed*10)) * 100; // Calcular porcentaje de aciertos
const roundedAccuracy = accuracy % 1 === 0 ? accuracy : accuracy.toFixed(2); // Redondear solo si tiene decimales
return { username: user.username, accuracy: roundedAccuracy }; // Crear objeto con nombre de usuario y porcentaje de aciertos redondeado si es necesario
});
const sortedRanking = rankedUsers.sort((a, b) => b.accuracy - a.accuracy); // Ordenar usuarios por porcentaje de aciertos
res.json(sortedRanking); // Devolver ranking ordenado
} catch (err) {
res.status(500).json({ message: err.message });
}
});



app.get('/ranking/correctAnswers', async (req, res) => {
try {
const users = await Statistic.find(); // Obtener todos los usuarios
// Ordenar usuarios por respuestas correctas
const sortedRanking = users.sort((a, b) => b.rigthAnswers - a.rigthAnswers);
// Mapear los usuarios para devolver el ranking ordenado junto con el número de respuestas correctas de cada usuario
const rankedUsers = sortedRanking.map(user => ({
username: user.username,
correctAnswers: user.rigthAnswers,
}));
res.json(rankedUsers); // Devolver ranking ordenado con número de respuestas correctas de cada usuario
} catch (err) {
res.status(500).json({ message: err.message });
}
});
app.get('/ranking/gamesPlayed', async (req, res) => {
try {
const users = await Statistic.find();
const sortedRanking = users.sort((a, b) => b.gamesPlayed - a.gamesPlayed);
const rankedUsers = sortedRanking.map(user => ({
username: user.username,
gamesPlayed: user.gamesPlayed,
}));
res.json(rankedUsers);
} catch (err) {
res.status(500).json({ message: err.message });
}
});





const server = app.listen(port, () => {
console.log(`Statistics Service listening at http://localhost:${port}`);
Expand Down
75 changes: 75 additions & 0 deletions statistics/statisticsservice/statistics-service.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const request = require('supertest');
const { MongoMemoryServer } = require('mongodb-memory-server');
const Stat = require('./user-model');
const axios = require('axios')

let mongoServer;
let app;
Expand All @@ -22,6 +23,12 @@ async function addStatistic(stat){
})

await newstat.save();

await Stat.create([
{ username: 'user1', password:"test", rigthAnswers: 8, gamesPlayed: 10 },
{ username: 'user2', password:"test", rigthAnswers: 15, gamesPlayed: 20 },
]);

}

beforeAll(async () => {
Expand Down Expand Up @@ -91,3 +98,71 @@ describe('Statistics Service', () => {
});
});
});

describe('GET /ranking/accuracy', () => {
it('should return ranked users based on accuracy', async () => {


// Realizar una solicitud GET al endpoint /ranking/accuracy
const response = await request(app).get('/ranking/accuracy');

// Verificar el código de estado de la respuesta
expect(response.status).toBe(200);

// Verificar el cuerpo de la respuesta para testuser
expect(response.body[0]).toHaveProperty('username', 'testuser');
expect(response.body[0]).toHaveProperty('accuracy', 100);

// Verificar el cuerpo de la respuesta para user1
expect(response.body[1]).toHaveProperty('username', 'user1');
expect(response.body[1]).toHaveProperty('accuracy', 8);

// Verificar el cuerpo de la respuesta para user2
expect(response.body[2]).toHaveProperty('username', 'user2');
expect(response.body[2]).toHaveProperty('accuracy', '7.50');
});


it('should return ranked users based on correct answers', async () => {

// Realizar una solicitud GET al endpoint /ranking/correctAnswers
const response = await request(app).get('/ranking/correctAnswers');

// Verificar el código de estado de la respuesta
expect(response.status).toBe(200);

// Verificar el cuerpo de la respuesta para user2
expect(response.body[0]).toHaveProperty('username', 'user2');
expect(response.body[0]).toHaveProperty('correctAnswers', 15);

// Verificar el cuerpo de la respuesta para testuser
expect(response.body[1]).toHaveProperty('username', 'testuser');
expect(response.body[1]).toHaveProperty('correctAnswers', 10);

// Verificar el cuerpo de la respuesta para user1
expect(response.body[2]).toHaveProperty('username', 'user1');
expect(response.body[2]).toHaveProperty('correctAnswers', 8);
});


it('should return ranked users based on games played', async () => {

// Realizar una solicitud GET al endpoint /ranking/gamesPlayed
const response = await request(app).get('/ranking/gamesPlayed');

// Verificar el código de estado de la respuesta
expect(response.status).toBe(200);

// Verificar el cuerpo de la respuesta para user2
expect(response.body[0]).toHaveProperty('username', 'user2');
expect(response.body[0]).toHaveProperty('gamesPlayed', 20);

// Verificar el cuerpo de la respuesta para testuser
expect(response.body[2]).toHaveProperty('username', 'testuser');
expect(response.body[2]).toHaveProperty('gamesPlayed', 1);

// Verificar el cuerpo de la respuesta para user1
expect(response.body[1]).toHaveProperty('username', 'user1');
expect(response.body[1]).toHaveProperty('gamesPlayed', 10);
});
});
8 changes: 8 additions & 0 deletions webapp/src/components/Navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ const Navbar = () => {
id="nav-menu"
>
<ul className="nav-list">
<li className="nav-item">

<NavLink to={process.env.RUTA_RANKING ||"/ranking"}className="nav__link">
Ranking

</NavLink>
</li>

<li className="nav-item">

<NavLink to={process.env.RUTA_USER ||"/statistics"}className="nav__link">
Expand Down
11 changes: 11 additions & 0 deletions webapp/src/components/QuizGame.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,17 @@ const QuizGame = () => {

const handleTimeOver = () => {
setIsFinished(true);
const username=localStorage.getItem('username')
const rigthAnswers = answeredQuestions.filter(question => question.isCorrect).length;
const wrongAnswers=numberOfQuestions+1-rigthAnswers;
const completedTime = totalTime - time;
const statisticsData = {
username: username,
rigthAnswers: rigthAnswers,
wrongAnswers:wrongAnswers,
time:completedTime
};
saveStatistics(statisticsData);
alert('¡Tiempo agotado!');
};

Expand Down
Loading

0 comments on commit 3dc6a64

Please sign in to comment.