Skip to content

Commit

Permalink
Info Page, Small fixes, More test
Browse files Browse the repository at this point in the history
  • Loading branch information
UO289930 authored Apr 29, 2024
2 parents 12a73a1 + 629a126 commit 9eaa82a
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 78 deletions.
25 changes: 12 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,28 @@
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Arquisoft_wiq_en3a&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Arquisoft_wiq_en3a)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=Arquisoft_wiq_en3a&metric=coverage)](https://sonarcloud.io/summary/new_code?id=Arquisoft_wiq_en3a)

# wiq_en3a
Thank you for checking out wiq_en3a! Below are some useful links to get started:
# Are you smarter than a penguin? 🐧
Thank you for checking out our game! Below are some useful links to get started:

- **[Application](http://51.103.210.249:3000/)**: Click this link to start playing!

- **[Documentation](https://arquisoft.github.io/wiq_en3a/)**: Explore detailed documentation to learn more about the game and its features.

- **[OpenAPI](http://51.103.210.249:8000/api-doc/)**: Explore detailed documentation of our API.

Feel free to explore the application and documentation, and don't hesitate to reach out if you have any questions or feedback. Enjoy playing wiq_en3a!
Feel free to explore the application and documentation, and don't hesitate to reach out if you have any questions or feedback. Enjoy playing STAP!

## Welcome to WIQ👩‍🎓👨‍🎓
## Introduction

The WIQ is a web application where you can show off your knowledge.
This is a web application where you can show off your knowledge.🧠
Experience the best of both worlds in "Are You Smarter Than a Penguin?🐧" with two exciting game modes: Normal and Trivia.

In the Normal Game, answer general knowledge questions within a time limit🕐. If you choose Easy mode, you have more time to think through your answers, while Hard mode speeds things up with shorter time limits, adding an extra challenge.

The Trivia Game tests your skills across five categories—Sports, Science, History, Geography, and Entertainment. Earn a "cheese🧀" for every correct answer, and collect all five to win. But watch out—you start with 6 hearts in Easy mode and only 3 in Hard mode, and if you lose them all, it's game over💕.

Creat an account or log in if you are already a member and start the engaging quiz!
Enjoy the variaty of questions, which are automatically generated from a vast pool of data available in Wikidata🌎. Each question offers multiple-choice options, including correct answer and several distractors🔍. Choose a right answer and win the prize🏆. Stay sharp and focused, there are also the time limits, --> the clock is ticking🕐 ⏳.


The more you know the more you win 🥇!
Play with your friends and compare the scores. Who is the smartest❓

🤓Let the game begin!👀🧠
Create an account or log in to play with friends and find out who knows the most. Enjoy the variaty of questions, which are automatically generated from a vast pool of data available in Wikidata🌎.
Let's get started!



Expand Down
21 changes: 15 additions & 6 deletions docs/src/01_introduction_and_goals.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ ifndef::imagesdir[:imagesdir: ../images]
[[section-introduction-and-goals]]
== Introduction and Goals

The WIQ web application is developed by HappySw for RTVE to create an experimental version of the Saber y Ganar quiz show.
The primary goal of WIQ is to provide users with an engaging platform where they can participate in quiz games,
The STAP (are you Smarter Than A Penguin) web application is developed for RTVE to create an experimental version of the 'Saber y Ganar' quiz show.
The primary goal of STAP is to provide users with an engaging platform where they can participate in quiz games,
answer questions generated from Wikidata, and win prizes.

This document outlines the essential requirements guiding the software architects and development team in creating WIQ.
This document outlines the essential requirements guiding the software architects and development team in creating STAP.

[role="arc42help"]
****
Expand Down Expand Up @@ -119,9 +119,18 @@ Table with role names, person names, and their expectations with respect to the
|===
| Role/Name | Contact | Expectations
| Users | N/A | Intuitive and enjoyable quiz experience
| Professors | Pablo González ([email protected]), Jose Emilio Labra ([email protected]) | The well-designed web application that fulfills the requirements
| RTVE | www.rtve.es | Reliable and engaging platform for users
| Development | Sergio Truébano Robles ([email protected]), Pedro Limeres Granado ([email protected]), Alberto Guerra Rodas ([email protected]), Ángel Macías Rodríguez ([email protected]), Rita Fernández-Catuxo Ortiz ([email protected]), Vira Terletska ([email protected]), Sergio Llenderrozos Piñera ([email protected]) | Clear documentation and reliable, performant and available system
| Professors | Pablo González ([email protected]) +
Jose Emilio Labra ([email protected]) +
Cristian Augusto Alonso ([email protected]) +
Jorge Álvarez Fidalgo ([email protected]) | The well-designed web application that fulfills the requirements
| RTVE | https://www.rtve.es | Reliable and engaging platform for users
| Development | Sergio Truébano Robles ([email protected]) +
Pedro Limeres Granado ([email protected]) +
Alberto Guerra Rodas ([email protected]) +
Ángel Macías Rodríguez ([email protected]) +
Rita Fernández-Catuxo Ortiz ([email protected]) +
Vira Terletska ([email protected]) +
Sergio Llenderrozos Piñera ([email protected]) | Clear documentation and reliable, performant and available system
|===


Expand Down
16 changes: 1 addition & 15 deletions gatewayservice/gateway-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,21 +91,7 @@ app.post('/getUser', async (req, res) => {


app.get('/GetQuestions', async (_req, res) => {
try {
const wikiResponse = await axios.get(wikidataServiceUrl + '/getQuestions', { timeout: 10000 });
if (wikiResponse.status !== 200) {
let statusCode = wikiResponse.status ? wikiResponse.status : 500;

console.error('Error with the wikidata service:', statusCode);
res.status(statusCode).json({ error: 'Error with the wikidata service' });

} else {
res.json(wikiResponse.data);
}
} catch (error) {
console.error(error);
res.status(500).json({ error: error });
}
getQuestions('/getQuestions', res);
});

app.get('/GetCapitalsQuestions', async (_req, res) => {
Expand Down
Binary file added webapp/public/penguins.webp
Binary file not shown.
2 changes: 2 additions & 0 deletions webapp/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { loginWithToken } from './services/auth-service';
import Authentication from './components/auth/Authentication';
import { useUserStore } from './stores/user-store';
import { Home } from './components/general/Home';
import Info from './components/general/Info';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { SimpleNav } from './components/general/SimpleNav';
import { TriviaGame } from './components/Game/Trivia/TriviaGame';
Expand Down Expand Up @@ -36,6 +37,7 @@ function App() {
<Route path="trivia/hard" element={<TriviaGame difficulty={getHardString()}/>} />
<Route path="/leaderboard" element={<LeaderBoard />}/>
<Route path="/stats" element={<Statistics />}/>
<Route path="/info" element={<Info/>} />
<Route path="logout" element={<Logout/>} />
<Route path="*" element={<Home/>} />

Expand Down
2 changes: 1 addition & 1 deletion webapp/src/components/Game/GameOver.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const GameOver = (props: props) => {
) {
imageToShow = images.lowScore;
message = "You are NOT smarter than a penguin";
} else if (scorePercentage < 75) {
} else if (scorePercentage < 100) {
imageToShow = images.mediumScore;
message = "You ARE smarter than a penguin";
} else {
Expand Down
14 changes: 10 additions & 4 deletions webapp/src/components/auth/AddUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ const AddUser = (props: props) => {

}

const handleKeyPress = (event: { key: string; }) => {
if (event.key === 'Enter') {
registerUser();
}
};


return (
<Card className="">
Expand All @@ -45,22 +51,22 @@ const AddUser = (props: props) => {
<div className="space-y-1">
<Label htmlFor="Username">Username</Label>
<Input value={username}
onChange={(e) => setUsername(e.target.value)} id="Username" />
onChange={(e) => setUsername(e.target.value)} onKeyDown={handleKeyPress} id="Username" />
</div>
<div className="space-y-1">
<Label htmlFor="Email">Email</Label>
<Input value={email}
onChange={(e) => setEmail(e.target.value)} id="Email" />
onChange={(e) => setEmail(e.target.value)} onKeyDown={handleKeyPress} id="Email" />
</div>
<div className="space-y-1">
<Label htmlFor="password">Password</Label>
<Input value={password}
onChange={(e) => setPassword(e.target.value)} type="password" id="password" />
onChange={(e) => setPassword(e.target.value)} onKeyDown={handleKeyPress} type="password" id="password" />
</div>
<div className="space-y-1">
<Label htmlFor="confirmPassword">Confirm Password</Label>
<Input value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)} type="password" id="confirmPassword" />
onChange={(e) => setConfirmPassword(e.target.value)} onKeyDown={handleKeyPress} type="password" id="confirmPassword" />
</div>
{error && (
<Label className="text-danger">
Expand Down
14 changes: 10 additions & 4 deletions webapp/src/components/auth/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// src/components/Login.js
import React, { useState } from 'react';
import React, { ReactEventHandler, useState } from 'react';
import {login} from '../../services/auth-service';
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "../ui/card";
import { Label } from "@radix-ui/react-label";
Expand Down Expand Up @@ -30,6 +30,12 @@ const Login = (props:props) => {
}
}

const handleKeyPress = (event: { key: string; }) => {
if (event.key === 'Enter') {
loginUser();
}
};


return (
<Card className="">
Expand All @@ -41,12 +47,12 @@ const Login = (props:props) => {
<div className="space-y-1">
<Label htmlFor="Username">Username</Label>
<Input value={username}
onChange={(e) => setUsername(e.target.value)} id="Username" />
onChange={(e) => setUsername(e.target.value)} onKeyDown={handleKeyPress} id="Username" />
</div>
<div className="space-y-1">
<Label htmlFor="password">Password</Label>
<Input value={password}
onChange={(e) => setPassword(e.target.value)} type="password" id="password" />
onChange={(e) => setPassword(e.target.value)} onKeyDown={handleKeyPress} type="password" id="password" />
</div>
{error && (
<Label className="text-danger">
Expand All @@ -68,4 +74,4 @@ const Login = (props:props) => {

};

export default Login;
export default Login;
45 changes: 45 additions & 0 deletions webapp/src/components/general/Info.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import Info from './Info';

test('renders Info component', () => {
render(<Info />);

// Check if the header is present
const headerElement = screen.getByText(/INFORMATION/i);
expect(headerElement).toBeInTheDocument();

// Check if the image is present
const imageElement = screen.getByAltText(/Descripción de la imagen/i);
expect(imageElement).toBeInTheDocument();

// Check if the rules are present
const rulesElement = screen.getByText(/Rules:/i);
expect(rulesElement).toBeInTheDocument();

// Check if the game modes are present
const normalGameElement = screen.getByText(/Normal Game:/i);
expect(normalGameElement).toBeInTheDocument();

const triviaGameElement = screen.getByText(/Trivia game:/i);
expect(triviaGameElement).toBeInTheDocument();

// Check if the links are present
const linksElement = screen.getByText(/Links:/i);
expect(linksElement).toBeInTheDocument();

// Check if the GitHub link is present
const githubLinkElement = screen.getByText(/GitHub/i);
expect(githubLinkElement).toBeInTheDocument();
expect(githubLinkElement).toHaveAttribute('href', 'https://github.com/Arquisoft/wiq_en3a');

// Check if the Documentation link is present
const documentationLinkElement = screen.getByText(/Documentation/i);
expect(documentationLinkElement).toBeInTheDocument();
expect(documentationLinkElement).toHaveAttribute('href', 'https://arquisoft.github.io/wiq_en3a/');

// Check if the OpenAPI link is present
const openApiLinkElement = screen.getByText(/OpenAPI/i);
expect(openApiLinkElement).toBeInTheDocument();
expect(openApiLinkElement).toHaveAttribute('href', 'http://51.103.210.249:8000/api-doc/');
});
72 changes: 72 additions & 0 deletions webapp/src/components/general/Info.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react';
import { FaLink, FaSkullCrossbones, FaSmile, FaGithub, FaBook, FaFileAlt, FaBrain, FaGamepad } from 'react-icons/fa';

const Info = () => {
return (
<div className="flex flex-col justify-center text-text p-4 mt-4 gap-4">
<h1 className="text-5xl font-bold self-center">INFORMATION</h1>
<img className="w-96 h-full self-center object-cover transition-transform duration-100 transform hover:scale-110" src='/penguins.webp' alt='Descripción de la imagen' />

<div className='flex items-center font-semibold text-4xl gap-2'><FaBook />
<h2>Rules: </h2></div>
<p className="text-text text-2xl" >Welcome to the game when you can became the penguins emperor! But... it will not be so easy...</p>
<p className="text-text text-2xl" >For you to become the king, you should pass the game without errors. Show off your knowledge 🧠 in our two exciting game modes:</p>
<div className='flex flex-col gap-4'>
<div className='flex items-center text-3xl gap-2'><FaGamepad />
<h2>Normal Game: </h2></div>
<p className="text-2xl">
You will have to go through 10 different questions of random topics. Each of the questions will have 4 different options but only 1 is correct!
</p>
<div className='flex items-center text-2xl gap-2' style={{ marginLeft: '2em' }}><FaSmile />
<h3>Easy :</h3>
<p> You have 10 seconds to answer each question. </p>
</div>
<div className='flex items-center text-2xl gap-2' style={{ marginLeft: '2em' }}><FaSkullCrossbones />
<h3> Hard:</h3>
<p className="text-2xl"> You have 4 second to answer each question.</p>
</div>

<div className='flex items-center text-3xl gap-2'><FaBrain />
<h2>Trivia game:</h2> </div>
<p className="text-2xl">Our favorite, the trivial mode. Test your skills across five categories: Sports, Science, History, Geography, and Entertainment.
Earn a "cheese🧀" for every correct answer, and collect all five to win.
The game will end when you gain all the chesses or if you fail a number of questions depending of the difficulty.
</p>
<div className='flex items-center gap-2 text-2xl' style={{ marginLeft: '2em' }}><FaSmile />
<h3>Easy: </h3>
<p> If you fail 6 questions, you will lose the game. </p>
</div>
<div className='flex items-center text-2xl gap-2' style={{ marginLeft: '2em' }}><FaSkullCrossbones />
<h3> Hard:</h3>
<p> If you fail 3 questions, you will lose the game. </p>
</div>
</div>

<div className='flex items-center text-4xl font-semibold gap-2'><FaLink />
<h2>Links: </h2></div>
<ul>
<li className="flex items-center gap-2">
<FaGithub />
<a className="text-text text-2xl hover:text-primary" href="https://github.com/Arquisoft/wiq_en3a" target="_blank">
GitHub
</a>
</li>
<li className="flex items-center gap-2">
<FaBook />
<a className="text-text text-2xl hover:text-primary" href="https://arquisoft.github.io/wiq_en3a/" target="_blank">
Documentation
</a>
</li>
<li className="flex items-center gap-2">
<FaFileAlt />
<a className="text-text text-2xl hover:text-primary" href="http://51.103.210.249:8000/api-doc/" target="_blank">
OpenAPI
</a>
</li>
</ul>

</div>
);
}

export default Info;
27 changes: 0 additions & 27 deletions webapp/src/components/general/SimpleNav.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,31 +64,4 @@ describe('SimpleNav', () => {
fireEvent.click(getByTestId('audio-button'));
});


/*test('toggles audio playback when button is clicked', () => {
const { getByTestId } = render(<Router> <SimpleNav /> </Router>);
// Mock HTML audio element
const playMock = jest.fn();
const pauseMock = jest.fn();
const audioMock = {
current: {
play: playMock,
pause: pauseMock
}
};
jest.spyOn(React, 'useRef').mockReturnValue(audioMock);
// Click on audio button
fireEvent.click(getByTestId('audio-button'));
// Check if audio play function is called
expect(playMock).toHaveBeenCalled();
// Click on audio button again
fireEvent.click(getByTestId('audio-button'));
// Check if audio pause function is called
expect(pauseMock).toHaveBeenCalled();
});*/
});
17 changes: 9 additions & 8 deletions webapp/src/components/general/SimpleNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
import { Avatar, AvatarFallback } from "../ui/avatar";
import React, { useState, useRef } from 'react';
import { Link } from "react-router-dom";
import { useUserStore, getUsername } from '../../stores/user-store';

import { getUsername } from '../../stores/user-store';
import { FaInfoCircle, FaVolumeUp, FaVolumeMute } from 'react-icons/fa';

export const SimpleNav = () => {
//let user = useUserStore(state => state.user!);

const getLinkStyle = ():string => {
return "text-text text-sm font-bold hover:text-primary transition-colors duration-300 ease-in-out"
}
Expand Down Expand Up @@ -41,14 +39,17 @@ export const SimpleNav = () => {

</div>
</div>
<div className="flex gap-5">
<div className="flex items-center gap-5">
<Link className={getLinkStyle()} to={`/`}>Home</Link>
<Link id="leaderboard" className={getLinkStyle()} to={`/leaderboard`}>Leaderboard</Link>
<Link id="stats" className={getLinkStyle()} to={`/stats`}>Statistics</Link>
<Link id="logout" className={getLinkStyle()} to={`/logout`}>Logout</Link>
<Link id="logout" className={getLinkStyle()} to={`/logout`}>Logout</Link>
<button data-testid="audio-button" id="audio-button" onClick={togglePlay} style={{ color: 'white' } }>
{isPlaying ? '🔊' : '🔇'}
</button>
{ isPlaying ? <FaVolumeUp /> : <FaVolumeMute />}
</button>
<Link id="info" className={getLinkStyle()} to={`/info`}>
<FaInfoCircle />
</Link>
</div>
<audio ref={audioRef} src={songs[currentSong]} />
</div>
Expand Down

0 comments on commit 9eaa82a

Please sign in to comment.