Compare commits
34 Commits
master
...
demo_bourg
Author | SHA1 | Date |
---|---|---|
![]() |
2b31997bc7 | 1 year ago |
![]() |
19957da05c | 1 year ago |
![]() |
f48168639a | 1 year ago |
![]() |
d68b80d96d | 1 year ago |
![]() |
cb2e6570e3 | 1 year ago |
![]() |
9b05d184ce | 1 year ago |
![]() |
aaa2f237b7 | 1 year ago |
|
7e46ea6e74 | 1 year ago |
![]() |
e1e7d6ef5c | 1 year ago |
![]() |
54f8f715b0 | 1 year ago |
![]() |
d8b9337236 | 1 year ago |
|
e655ae2ab5 | 1 year ago |
|
3f9878bad0 | 1 year ago |
|
2faaaafa72 | 1 year ago |
|
be4b6db1b7 | 1 year ago |
![]() |
07ffe52c2b | 1 year ago |
![]() |
4836fff541 | 1 year ago |
![]() |
cb31635a22 | 1 year ago |
![]() |
470899897b | 1 year ago |
![]() |
3aa121a2c2 | 1 year ago |
|
d57416b9f8 | 1 year ago |
![]() |
c692f7b2ad | 1 year ago |
|
cbeb14257a | 1 year ago |
![]() |
466e3b7d0e | 1 year ago |
![]() |
6ddd2e5a29 | 1 year ago |
|
92fa06313c | 1 year ago |
![]() |
3632320ffd | 1 year ago |
|
86c4edfb94 | 1 year ago |
|
a8409743e7 | 1 year ago |
|
be5c80de86 | 1 year ago |
|
33b2a6e3f3 | 1 year ago |
![]() |
d747f63318 | 1 year ago |
|
cff2a9b085 | 1 year ago |
|
2f4e0fc300 | 1 year ago |
@ -1,92 +0,0 @@
|
|||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: default
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: build
|
|
||||||
image: node:20
|
|
||||||
commands:
|
|
||||||
- cd cryptide_project
|
|
||||||
- npm install --legacy-peer-deps
|
|
||||||
- CI=false npm run build
|
|
||||||
|
|
||||||
- name: code-analysis
|
|
||||||
image: node:20
|
|
||||||
environment:
|
|
||||||
SONAR_TOKEN:
|
|
||||||
from_secret: SECRET_SONAR_LOGIN_CRYPTIDE
|
|
||||||
commands:
|
|
||||||
- export SONAR_SCANNER_VERSION=4.7.0.2747
|
|
||||||
- export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux
|
|
||||||
- curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip
|
|
||||||
- unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
|
|
||||||
- export PATH=$SONAR_SCANNER_HOME/bin:$PATH
|
|
||||||
- export SONAR_SCANNER_OPTS="-server"
|
|
||||||
- sonar-scanner -D sonar.projectKey=Cryptid -D sonar.sources=. -D sonar.host.url=https://codefirst.iut.uca.fr/sonar
|
|
||||||
secrets: [SECRET_SONAR_LOGIN_CRYPTIDE]
|
|
||||||
settings:
|
|
||||||
sonar_host: https://codefirst.iut.uca.fr/sonar/
|
|
||||||
sonar_token:
|
|
||||||
from_secret: SECRET_SONAR_LOGIN_CRYPTIDE
|
|
||||||
|
|
||||||
#
|
|
||||||
- name: deploy-container-mysql
|
|
||||||
image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
environment:
|
|
||||||
IMAGENAME: mysql:latest
|
|
||||||
CONTAINERNAME: mysql
|
|
||||||
COMMAND: create
|
|
||||||
#OVERWRITE: true
|
|
||||||
PRIVATE: false
|
|
||||||
CODEFIRST_CLIENTDRONE_ENV_MYSQL_ROOT_PASSWORD:
|
|
||||||
from_secret: MYSQL_ROOT_PASSWORD
|
|
||||||
CODEFIRST_CLIENTDRONE_ENV_MYSQL_DATABASE:
|
|
||||||
from_secret: MYSQL_DATABASE
|
|
||||||
CODEFIRST_CLIENTDRONE_ENV_MYSQL_USER:
|
|
||||||
from_secret: MYSQL_USER
|
|
||||||
CODEFIRST_CLIENTDRONE_ENV_MYSQL_PASSWORD:
|
|
||||||
from_secret: MYSQL_PASSWORD
|
|
||||||
ADMINS: thomaschazot2,pierreferreira,baptistemarcel
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- CI/CD
|
|
||||||
|
|
||||||
- name: container-web
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
dockerfile: ./cryptide_project/Dockerfile
|
|
||||||
context: ./cryptide_project
|
|
||||||
registry: hub.codefirst.iut.uca.fr
|
|
||||||
repo: hub.codefirst.iut.uca.fr/thomas.chazot2/cryptide/web
|
|
||||||
username:
|
|
||||||
from_secret: SECRET_REGISTRY_USERNAME
|
|
||||||
password:
|
|
||||||
from_secret: SECRET_REGISTRY_PASSWORD
|
|
||||||
environment:
|
|
||||||
BASEPATH: "/containers/Crypteam-website"
|
|
||||||
#depends_on: [ build ]
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- CI/CD
|
|
||||||
|
|
||||||
|
|
||||||
#container deployment
|
|
||||||
- name: deploy-server-containers
|
|
||||||
image: hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientdrone:latest
|
|
||||||
environment:
|
|
||||||
IMAGENAME: hub.codefirst.iut.uca.fr/thomas.chazot2/cryptide/web:latest
|
|
||||||
CONTAINERNAME: website
|
|
||||||
COMMAND: create
|
|
||||||
OVERWRITE: true
|
|
||||||
#PRIVATE: true
|
|
||||||
ADMINS: thomaschazot2,pierreferreira,baptistemarcel
|
|
||||||
depends_on: [ container-web ]
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
@ -1,33 +0,0 @@
|
|||||||
# Utilisez l'image Node.js LTS comme base
|
|
||||||
FROM node:14-alpine
|
|
||||||
|
|
||||||
# Définissez le répertoire de travail dans le conteneur
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copiez le package.json et le package-lock.json dans le conteneur
|
|
||||||
COPY package*.json ./
|
|
||||||
|
|
||||||
# Installez les dépendances du projet
|
|
||||||
RUN npm install
|
|
||||||
|
|
||||||
# Copiez le reste des fichiers de l'application dans le conteneur
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Construisez l'application React
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# Utilisez l'image légère Nginx pour servir l'application construite
|
|
||||||
FROM nginx:alpine
|
|
||||||
|
|
||||||
# Copiez les fichiers construits de l'étape précédente dans le répertoire de travail de Nginx
|
|
||||||
COPY --from=0 /app/build /usr/share/nginx/html
|
|
||||||
|
|
||||||
# Copiez la configuration Nginx personnalisée
|
|
||||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
|
||||||
|
|
||||||
# Exposez le port 80 pour que l'application puisse être accessible
|
|
||||||
EXPOSE 80
|
|
||||||
|
|
||||||
# Définissez ENTRYPOINT pour démarrer Nginx lorsque le conteneur est lancé
|
|
||||||
ENTRYPOINT ["nginx", "-g", "daemon off;"]
|
|
||||||
#
|
|
@ -1,33 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
|
|
||||||
# Récupérer le répertoire du script (où que le script soit appelé)
|
|
||||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
# Aller au répertoire du projet
|
|
||||||
#cd "$SCRIPT_DIR/../"
|
|
||||||
|
|
||||||
#* Lancement des serveurs
|
|
||||||
node $SCRIPT_DIR/../server/server.js &
|
|
||||||
|
|
||||||
# Attendre un court instant pour laisser le serveur démarrer
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
node $SCRIPT_DIR/../src/server/server.js &
|
|
||||||
|
|
||||||
# Attendre un court instant pour laisser le serveur démarrer
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cd $SCRIPT_DIR/..
|
|
||||||
|
|
||||||
#* Génération de version de production
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
#* Installation d'un serveur http simple
|
|
||||||
npm install -g serve
|
|
||||||
|
|
||||||
#* Execution du serveur sur le répertoire de build
|
|
||||||
serve -s build
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Vérifier si l'adresse IP est fournie en tant que paramètre
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo "Usage: $0 <adresse_ip>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Stocker l'adresse IP fournie en tant que variable
|
|
||||||
adresse_ip="$1"
|
|
||||||
|
|
||||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
# Utiliser l'adresse IP dans la commande find avec Perl
|
|
||||||
find $SCRIPT_DIR/../ -type f -exec perl -pi -e 's|http://[0-9.]+:([0-9]+)|http://localhost:$1|g' {} +
|
|
||||||
|
|
||||||
find $SCRIPT_DIR/../ -type f -exec perl -pi -e "s|http://localhost:([0-9]+)|http://$adresse_ip:\$1|g" {} +
|
|
@ -1,15 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 80;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
index index.html;
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_page 404 /index.html;
|
|
||||||
|
|
||||||
location ~ /\. {
|
|
||||||
deny all;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"headers": [
|
|
||||||
{ "source": "**/*.js", "headers": [{ "key": "Content-Type", "value": "application/javascript; charset=utf-8" }] }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
const port = process.env.PORT || 80;
|
|
||||||
|
|
||||||
// Servir les fichiers statiques depuis le dossier 'build'
|
|
||||||
app.use(express.static(path.join(__dirname, 'build')));
|
|
||||||
|
|
||||||
// Définir le type MIME pour les fichiers JavaScript
|
|
||||||
app.use('/static/js', (req, res, next) => {
|
|
||||||
res.type('application/javascript; charset=utf-8');
|
|
||||||
next();
|
|
||||||
}, express.static(path.join(__dirname, 'build/static/js')));
|
|
||||||
|
|
||||||
// Définir le type MIME pour les fichiers CSS
|
|
||||||
app.use('/static/css', (req, res, next) => {
|
|
||||||
res.type('text/css; charset=utf-8');
|
|
||||||
next();
|
|
||||||
}, express.static(path.join(__dirname, 'build/static/css')));
|
|
||||||
|
|
||||||
// Route par défaut pour servir l'application React
|
|
||||||
app.get('*', (req, res) => {
|
|
||||||
res.sendFile(path.join(__dirname, 'build', 'index.html'));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Démarrer le serveur
|
|
||||||
app.listen(port, () => {
|
|
||||||
console.log(`Serveur en cours d'exécution sur le port ${port}`);
|
|
||||||
console.log(path.join(__dirname, 'build'))
|
|
||||||
});
|
|
@ -1,198 +0,0 @@
|
|||||||
const bcrypt = require('bcrypt');
|
|
||||||
const path = require('path');
|
|
||||||
const DatabaseService = require(path.resolve(__dirname, '../services/DatabaseService.js'));
|
|
||||||
const UserService = require(path.resolve(__dirname, '../services/UserService.js'));
|
|
||||||
|
|
||||||
class AuthController {
|
|
||||||
static async signUp(req, res) {
|
|
||||||
const databaseService = new DatabaseService();
|
|
||||||
const pseudo = req.body.pseudo;
|
|
||||||
const date = new Date();
|
|
||||||
const hour = date.getHours();
|
|
||||||
const minutes = date.getMinutes();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await databaseService.connect();
|
|
||||||
|
|
||||||
// Vérifier que le pseudo n'existe pas déjà
|
|
||||||
const verif = await databaseService.getUserByPseudo(pseudo);
|
|
||||||
if (verif) {
|
|
||||||
res.status(400).json({ error: 'Le pseudo est déjà utilisé.' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Créer un nouvel utilisateur
|
|
||||||
const currentUser = await UserService.createUser(req.body);
|
|
||||||
const insertedUser = await databaseService.insertUser(currentUser);
|
|
||||||
|
|
||||||
const user = await databaseService.getUserByPseudo(pseudo);
|
|
||||||
|
|
||||||
console.log("[" + hour + ":" + minutes + "] " + user.pseudo + " have been registered.");
|
|
||||||
res.status(201).json({ message: 'Inscription réussie', user: insertedUser});
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
// Gérer les erreurs
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de l\'inscription.' });
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
await databaseService.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async signIn(req, res) {
|
|
||||||
const databaseService = new DatabaseService();
|
|
||||||
const date = new Date();
|
|
||||||
const hour = date.getHours();
|
|
||||||
const minutes = date.getMinutes();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await databaseService.connect();
|
|
||||||
|
|
||||||
// Vérifier que le pseudo existe
|
|
||||||
const pseudo = req.body.pseudo;
|
|
||||||
const user = await databaseService.getUserByPseudo(pseudo);
|
|
||||||
if (!user) {
|
|
||||||
res.status(400).json({ error: 'Le pseudo n\'existe pas.' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vérifier que le mot de passe est correct
|
|
||||||
const password = req.body.password;
|
|
||||||
const validPassword = await bcrypt.compare(password, user.password);
|
|
||||||
if (!validPassword) {
|
|
||||||
res.status(400).json({ error: 'Le mot de passe est incorrect.' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stocker l'utilisateur dans la session)
|
|
||||||
req.session.user = user;
|
|
||||||
req.session.user.nbNodes = 25
|
|
||||||
req.session.user.nbIndices = 3
|
|
||||||
|
|
||||||
|
|
||||||
// Envoyer une réponse réussie
|
|
||||||
console.log("[" + hour + ":" + minutes + "] " + user.pseudo + " have been connected.");
|
|
||||||
res.status(200).json({ message: 'Connexion réussie', user: user });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
// Gérer les erreurs
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la connexion.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await databaseService.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async UpdateNbNodesIndices(req, res){
|
|
||||||
try{
|
|
||||||
if (req.session.user){
|
|
||||||
req.session.user.nbNodes = req.body.nbNodes;
|
|
||||||
req.session.user.nbIndices = req.body.nbIndices;
|
|
||||||
res.status(200).json({ message: 'Nombre de noeuds mis à jour.' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la mise à jour du nombre de noeuds.' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async logout(req, res) {
|
|
||||||
const pseudo = req.session.user.pseudo;
|
|
||||||
const date = new Date();
|
|
||||||
const hour = date.getHours();
|
|
||||||
const minutes = date.getMinutes();
|
|
||||||
// Détruire la session pour déconnecter l'utilisateur
|
|
||||||
req.session.destroy((err) => {
|
|
||||||
if (err) {
|
|
||||||
console.error(err);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la déconnexion.' });
|
|
||||||
} else {
|
|
||||||
console.log("[" + hour + ":" + minutes + "] " + pseudo + " have been disconnected.");
|
|
||||||
res.status(200).json({ message: 'Déconnexion réussie' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static async delAccount(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const user = await db.getUserByPseudo(req.body.pseudo);
|
|
||||||
|
|
||||||
if(!user){
|
|
||||||
res.status(400).json({ error: 'Le pseudo n\'existe pas.' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.deleteUser(user.idUser);
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la supression du compte.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async validatePassword(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const user = await db.getUserByPseudo(req.body.pseudo);
|
|
||||||
if(!user){
|
|
||||||
res.status(400).json({ error: 'Le pseudo n\'existe pas.' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const password = req.body.password;
|
|
||||||
const validPassword = await bcrypt.compare(password, user.password);
|
|
||||||
if(!validPassword){
|
|
||||||
res.status(400).json({ error: 'Le mot de passe est incorrect.' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
res.status(200).json({ message: 'Mot de passe correct.' });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la vérification du mot de passe.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async updatePassword(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const user = await db.getUserByPseudo(req.body.pseudo);
|
|
||||||
if(!user){
|
|
||||||
res.status(400).json({ error: 'Le pseudo n\'existe pas.' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hashedPassword = await bcrypt.hash(req.body.newPassword, 10);
|
|
||||||
|
|
||||||
await db.updatePassword(user.idUser, hashedPassword);
|
|
||||||
|
|
||||||
res.status(200).json({ message: 'Mot de passe mis à jour.' });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la mise à jour du mot de passe.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = AuthController;
|
|
@ -1,209 +0,0 @@
|
|||||||
const path = require('path');
|
|
||||||
const DatabaseService = require(path.resolve(__dirname, '../services/DatabaseService'));
|
|
||||||
|
|
||||||
const ENIGME_FACILE = "enigme_facile";
|
|
||||||
const ENIGME_MOYEN = "enigme_moyenne";
|
|
||||||
const ENIGME_DIFFICILE = "enigme_difficile";
|
|
||||||
|
|
||||||
class SessionController {
|
|
||||||
// ---------------------------------------------------
|
|
||||||
// ----------------- GET DAILY STATS -----------------
|
|
||||||
// ---------------------------------------------------
|
|
||||||
|
|
||||||
static async getDailyMastermind(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const dailyMastermindStats = await db.getDailyMastermindStats();
|
|
||||||
|
|
||||||
res.status(200).json({ tab : dailyMastermindStats });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la récupération des stats dailyMastermind.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getDailyEasyEnigma(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const dailyEasyEnigmaStats = await db.getDailyEnigmaStats(ENIGME_FACILE);
|
|
||||||
|
|
||||||
res.status(200).json({ tab : dailyEasyEnigmaStats });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la récupération des stats dailyEasyEnigma.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getDailyMediumEnigma(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const dailyMediumEnigmaStats = await db.getDailyEnigmaStats(ENIGME_MOYEN);
|
|
||||||
|
|
||||||
res.status(200).json({ tab : dailyMediumEnigmaStats });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la récupération des stats dailyMediumEnigma.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getDailyHardEnigma(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const dailyHardEnigmaStats = await db.getDailyEnigmaStats(ENIGME_DIFFICILE);
|
|
||||||
|
|
||||||
res.status(200).json({ tab : dailyHardEnigmaStats });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la récupération des stats dailyHardEnigma.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getDailyOnline(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const dailyOnlineStats = await db.getDailyOnlineStats();
|
|
||||||
|
|
||||||
res.status(200).json({ tab : dailyOnlineStats });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la récupération des stats dailyOnline' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------
|
|
||||||
// ---------------- GET WEEKLY STATS -----------------
|
|
||||||
// ---------------------------------------------------
|
|
||||||
|
|
||||||
static async getWeeklyMastermind(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const weeklyMastermindStats = await db.getWeeklyMastermindStats();
|
|
||||||
|
|
||||||
res.status(200).json({ tab : weeklyMastermindStats });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la récupération des stats weeklyMastermind.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getWeeklyEasyEnigma(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const weeklyEasyEnigmaStats = await db.getWeeklyEnigmaStats(ENIGME_FACILE);
|
|
||||||
|
|
||||||
res.status(200).json({ tab : weeklyEasyEnigmaStats });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la récupération des stats weeklyEasyEnigma.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getWeeklyMediumEnigma(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const weeklyMediumEnigmaStats = await db.getWeeklyEnigmaStats(ENIGME_MOYEN);
|
|
||||||
|
|
||||||
res.status(200).json({ tab : weeklyMediumEnigmaStats });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la récupération des stats weeklyMediumEnigma.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getWeeklyHardEnigma(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const weeklyHardEnigmaStats = await db.getWeeklyEnigmaStats(ENIGME_DIFFICILE);
|
|
||||||
|
|
||||||
res.status(200).json({ tab : weeklyHardEnigmaStats });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la récupération des stats weeklyHardEnigma.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getWeeklyOnline(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const weeklyOnlineStats = await db.getWeeklyOnlineStats();
|
|
||||||
|
|
||||||
res.status(200).json({ tab : weeklyOnlineStats });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la récupération des stats weeklyOnline' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = SessionController;
|
|
@ -1,235 +0,0 @@
|
|||||||
const path = require('path');
|
|
||||||
const DatabaseService = require(path.resolve(__dirname, '../services/DatabaseService'));
|
|
||||||
|
|
||||||
const ENIGME_FACILE = "enigme_facile";
|
|
||||||
const ENIGME_MOYEN = "enigme_moyenne";
|
|
||||||
const ENIGME_DIFFICILE = "enigme_difficile";
|
|
||||||
|
|
||||||
class SessionController {
|
|
||||||
static async getUserInformation(req, res) {
|
|
||||||
const db = new DatabaseService();
|
|
||||||
const date = new Date();
|
|
||||||
const hour = date.getHours();
|
|
||||||
const minutes = date.getMinutes();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
if (!req.session.user) {
|
|
||||||
res.status(200).json({ error: "true", message: 'User not found' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Récupérer les stats mastermind de l'utilisateur
|
|
||||||
let nbGamesMM = await db.getNbGamesMastermindByUserId(req.session.user.idUser);
|
|
||||||
nbGamesMM = nbGamesMM.nbGames || 0;
|
|
||||||
let bestScoreMM = await db.getBestScoreMastermindByUserId(req.session.user.idUser);
|
|
||||||
bestScoreMM = bestScoreMM.bestScore || 0;
|
|
||||||
let avgNbTryMM = await db.getAvgNbTryMastermindByUserId(req.session.user.idUser);
|
|
||||||
avgNbTryMM = avgNbTryMM.avgNbTry || 0;
|
|
||||||
|
|
||||||
req.session.user.mastermindStats = {nbGames: nbGamesMM,
|
|
||||||
bestScore: bestScoreMM,
|
|
||||||
avgNbTry: avgNbTryMM};
|
|
||||||
|
|
||||||
// Récupérer les stats enigme facile
|
|
||||||
let nbGamesEF = await db.getNbGamesEnigmeByUserId(req.session.user.idUser, ENIGME_FACILE);
|
|
||||||
nbGamesEF = nbGamesEF.nbGames || 0;
|
|
||||||
let nbWinsEF = await db.getNbWinsEnigmeByUserId(req.session.user.idUser, ENIGME_FACILE);
|
|
||||||
nbWinsEF = nbWinsEF.nbWins || 0;
|
|
||||||
let ratioEF = (nbWinsEF.nbWins / nbGamesEF.nbGames) * 100 || 0;
|
|
||||||
let bestTimeEF = await db.getBestTimeEnigmeByUserId(req.session.user.idUser, ENIGME_FACILE);
|
|
||||||
bestTimeEF = bestTimeEF.bestTime || 0;
|
|
||||||
let avgTimeEF = await db.getAvgTimeEnigmeByUserId(req.session.user.idUser, ENIGME_FACILE);
|
|
||||||
avgTimeEF = avgTimeEF.avgTime || 0;
|
|
||||||
|
|
||||||
req.session.user.easyEnigmaStats = {nbGames: nbGamesEF,
|
|
||||||
nbWins: nbWinsEF,
|
|
||||||
ratio: ratioEF,
|
|
||||||
bestTime: bestTimeEF,
|
|
||||||
avgTime: avgTimeEF};
|
|
||||||
|
|
||||||
// Récupérer les stats enigme moyenne
|
|
||||||
let nbGamesEM = await db.getNbGamesEnigmeByUserId(req.session.user.idUser, ENIGME_MOYEN);
|
|
||||||
nbGamesEM = nbGamesEM.nbGames || 0;
|
|
||||||
let bestScoreEM = await db.getBestScoreEnigmeByUserId(req.session.user.idUser, ENIGME_MOYEN);
|
|
||||||
bestScoreEM = bestScoreEM.bestScore || 0;
|
|
||||||
let avgNbTryEM = await db.getAvgScoreEnigmeByUserId(req.session.user.idUser, ENIGME_MOYEN);
|
|
||||||
avgNbTryEM = avgNbTryEM.avgScore || 0;
|
|
||||||
|
|
||||||
req.session.user.mediumEnigmaStats = {nbGames: nbGamesEM,
|
|
||||||
bestScore: bestScoreEM,
|
|
||||||
avgNbTry: avgNbTryEM};
|
|
||||||
|
|
||||||
// Récupérer les stats enigme difficile
|
|
||||||
let nbGamesED = await db.getNbGamesEnigmeByUserId(req.session.user.idUser, ENIGME_DIFFICILE);
|
|
||||||
nbGamesED = nbGamesED.nbGames || 0;
|
|
||||||
let nbWinsED = await db.getNbWinsEnigmeByUserId(req.session.user.idUser, ENIGME_DIFFICILE);
|
|
||||||
nbWinsED = nbWinsED.nbWins || 0;
|
|
||||||
let ratioED = (nbWinsED.nbWins / nbGamesED.nbGames) * 100 || 0;
|
|
||||||
let bestTimeED = await db.getBestTimeEnigmeByUserId(req.session.user.idUser, ENIGME_DIFFICILE);
|
|
||||||
bestTimeED = bestTimeED.bestTime || 0;
|
|
||||||
let avgTimeED = await db.getAvgTimeEnigmeByUserId(req.session.user.idUser, ENIGME_DIFFICILE);
|
|
||||||
avgTimeED = avgTimeED.avgTime || 0;
|
|
||||||
|
|
||||||
req.session.user.hardEnigmaStats = {nbGames: nbGamesED,
|
|
||||||
nbWins: nbWinsED,
|
|
||||||
ratio: ratioED,
|
|
||||||
bestTime: bestTimeED,
|
|
||||||
avgTime: avgTimeED};
|
|
||||||
|
|
||||||
// Récupérer les stats en ligne de l'utilisateur
|
|
||||||
let nbGamesOL = await db.getNbGamesOnlineByUserId(req.session.user.idUser);
|
|
||||||
nbGamesOL = nbGamesOL.nbGames || 0;
|
|
||||||
let nbWinsOL = await db.getNbWinsOnlineByUserId(req.session.user.idUser);
|
|
||||||
nbWinsOL = nbWinsOL.nbWins || 0;
|
|
||||||
let ratioOL = (nbWinsOL.nbWins / nbGamesOL.nbGames) * 100 || 0;
|
|
||||||
req.session.user.onlineStats = {nbGames: nbGamesOL,
|
|
||||||
nbWins: nbWinsOL,
|
|
||||||
ratio: ratioOL};
|
|
||||||
|
|
||||||
res.status(200).json({ user: req.session.user });
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la récupération de l\'utilisateur.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async UpdatePseudo(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const user = await db.getUserByPseudo(req.body.pseudo);
|
|
||||||
console.log("utilisateur" + user.idUser + " pseudo" + user.pseudo)
|
|
||||||
if (!user) {
|
|
||||||
res.status(200).json({ error: "true", message: 'User not found' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.updatePseudo(user.idUser, req.body.newPseudo); //* update
|
|
||||||
|
|
||||||
const updatedUser = await db.getUserByPseudo(req.body.newPseudo);
|
|
||||||
console.log("updaetdutilisateur" + updatedUser.idUser + " pseudo" + updatedUser.pseudo)
|
|
||||||
req.session.user.pseudo = updatedUser.pseudo;
|
|
||||||
console.log("req.session.user.pseudo" + req.session.user.pseudo)
|
|
||||||
res.status(200).json({ user: req.session.user }); //verif rep
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la modification du pseudo de l\'utilisateur.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async addMastermindStats(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const user = await db.getUserByPseudo(req.body.pseudo);
|
|
||||||
if (!user) {
|
|
||||||
res.status(200).json({ error: "true", message: 'User not found' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.addMastermindStats(user.idUser, req.body.score, req.body.time);
|
|
||||||
|
|
||||||
res.status(200).json({ user: req.session.user }); //verif rep
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la modification des stats mastermind de l\'utilisateur.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async addEasyEnigmaStats(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const user = await db.getUserByPseudo(req.body.pseudo);
|
|
||||||
if (!user) {
|
|
||||||
res.status(200).json({ error: "true", message: 'User not found' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.addEasyEnigmaStats(user.idUser, ENIGME_FACILE, req.body.win, req.body.time);
|
|
||||||
|
|
||||||
res.status(200).json({ user: req.session.user }); //verif rep
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la modification des stats de l\'énigme facile de l\'utilisateur.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// static async addMediumEnigmaStats(req, res)
|
|
||||||
|
|
||||||
static async addHardEnigmaStats(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const user = await db.getUserByPseudo(req.body.pseudo);
|
|
||||||
if (!user) {
|
|
||||||
res.status(200).json({ error: "true", message: 'User not found' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.addHardEnigmaStats(user.idUser, ENIGME_DIFFICILE, req.body.win, req.body.time);
|
|
||||||
|
|
||||||
res.status(200).json({ user: req.session.user }); //verif rep
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la modification des stats de l\'énigme difficile de l\'utilisateur.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async addOnlineStats(req, res){
|
|
||||||
const db = new DatabaseService();
|
|
||||||
|
|
||||||
try{
|
|
||||||
await db.connect();
|
|
||||||
|
|
||||||
const user = await db.getUserByPseudo(req.body.pseudo);
|
|
||||||
if (!user) {
|
|
||||||
res.status(200).json({ error: "true", message: 'User not found' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await db.addOnlineStats(user.idUser, req.body.win, req.body.time);
|
|
||||||
|
|
||||||
res.status(200).json({ user: req.session.user }); //verif rep
|
|
||||||
}
|
|
||||||
catch(error){
|
|
||||||
console.error(error);
|
|
||||||
res.status(500).json({ error: 'Erreur lors de la modification des stats en ligne de l\'utilisateur.' });
|
|
||||||
}
|
|
||||||
finally{
|
|
||||||
await db.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = SessionController;
|
|
@ -1,41 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
const AuthController = require('../controllers/AuthController');
|
|
||||||
const SessionController = require('../controllers/SessionController');
|
|
||||||
const ScoreboardController = require('../controllers/ScoreboardController');
|
|
||||||
|
|
||||||
// Routes pour l'authentification
|
|
||||||
router.post('/auth/signup', AuthController.signUp);
|
|
||||||
router.post('/auth/signin', AuthController.signIn);
|
|
||||||
router.delete('/auth/logout', AuthController.logout)
|
|
||||||
router.delete('/auth/delAccount', AuthController.delAccount)
|
|
||||||
router.post('/auth/validatePassword', AuthController.validatePassword);
|
|
||||||
router.put('/auth/updatePassword', AuthController.updatePassword);
|
|
||||||
router.put('/session/updateNbNodes', AuthController.UpdateNbNodesIndices);
|
|
||||||
|
|
||||||
// Routes pour les sessions
|
|
||||||
router.get('/session', SessionController.getUserInformation);
|
|
||||||
router.post('/session/addMastermindStats', SessionController.addMastermindStats);
|
|
||||||
router.post('/session/addEasyEnigmaStats', SessionController.addEasyEnigmaStats);
|
|
||||||
// router.post('/session/addMediumEnigmaStats', SessionController.addMediumEnigmaStats);
|
|
||||||
router.post('/session/addHardEnigmaStats', SessionController.addHardEnigmaStats);
|
|
||||||
router.post('/session/addOnlineStats', SessionController.addOnlineStats);
|
|
||||||
router.put('/session/updatePseudo', SessionController.UpdatePseudo);
|
|
||||||
|
|
||||||
|
|
||||||
// Routes pour le daily scoreboard
|
|
||||||
router.get('/scoreboard/getDailyMastermind', ScoreboardController.getDailyMastermind);
|
|
||||||
router.get('/scoreboard/getDailyEasyEnigma', ScoreboardController.getDailyEasyEnigma);
|
|
||||||
router.get('/scoreboard/getDailyMediumEnigma', ScoreboardController.getDailyMediumEnigma);
|
|
||||||
router.get('/scoreboard/getDailyHardEnigma', ScoreboardController.getDailyHardEnigma);
|
|
||||||
router.get('/scoreboard/getDailyOnline', ScoreboardController.getDailyOnline);
|
|
||||||
|
|
||||||
// Routes pour le weekly scoreboard
|
|
||||||
router.get('/scoreboard/getWeeklyMastermind', ScoreboardController.getWeeklyMastermind);
|
|
||||||
router.get('/scoreboard/getWeeklyEasyEnigma', ScoreboardController.getWeeklyEasyEnigma);
|
|
||||||
router.get('/scoreboard/getWeeklyMediumEnigma', ScoreboardController.getWeeklyMediumEnigma);
|
|
||||||
router.get('/scoreboard/getWeeklyHardEnigma', ScoreboardController.getWeeklyHardEnigma);
|
|
||||||
router.get('/scoreboard/getWeeklyOnline', ScoreboardController.getWeeklyOnline);
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -1,473 +0,0 @@
|
|||||||
const sqlite3 = require('sqlite3');
|
|
||||||
const path = require('path');
|
|
||||||
const { rejects } = require('assert');
|
|
||||||
|
|
||||||
class DatabaseService {
|
|
||||||
constructor(){
|
|
||||||
this.db_name = "socialgraph";
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------
|
|
||||||
// ------------------- UTILITAIRE ---------------------
|
|
||||||
// ----------------------------------------------------
|
|
||||||
|
|
||||||
async connect(client){
|
|
||||||
const dbPath = path.resolve(__dirname, `../../../db/${this.db_name}.db`)
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client = new sqlite3.Database(dbPath,
|
|
||||||
sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE,
|
|
||||||
(err) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async disconnect(){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.close((err) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------
|
|
||||||
// ------------------- UTILISATEUR --------------------
|
|
||||||
// ----------------------------------------------------
|
|
||||||
|
|
||||||
// Récupère l'utilisateur par son id
|
|
||||||
async getUserByID(id){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT * FROM users WHERE idUser = ?', id, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Récupère l'utilisateur par son pseudo
|
|
||||||
async getUserByPseudo(pseudo){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT * FROM users WHERE pseudo = ?', pseudo, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// insère un utilisateur dans la base de données
|
|
||||||
async insertUser(user) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const { pseudo, password } = user;
|
|
||||||
this.client.run('INSERT INTO users (pseudo, password) VALUES (?, ?)', [pseudo, password], (err, result) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteUser(userId){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.run('DELETE FROM users WHERE idUser=?', userId, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async updatePseudo(userId, newPseudo){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.run('UPDATE users SET pseudo = ? WHERE idUser = ?', newPseudo, userId, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async updatePassword(userId, newPassword){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.run('UPDATE users SET password = ? WHERE idUser = ?', newPassword, userId, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
// ------------------- STATS JOURNALIERE -------------------------
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
|
|
||||||
async getDailyMastermindStats() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// Obtenez la date actuelle au format AAAA-MM-JJ
|
|
||||||
const currentDate = new Date().toISOString().slice(0, 10);
|
|
||||||
|
|
||||||
// Récupérer les 5 meilleurs scores de la journée
|
|
||||||
this.client.all(
|
|
||||||
'SELECT pseudo, score FROM users INNER JOIN games ON users.idUser = games.idUser WHERE gameType = ? AND SUBSTR(playedDate, 1, 10) = ? ORDER BY score ASC LIMIT 10',
|
|
||||||
"mastermind",
|
|
||||||
currentDate,
|
|
||||||
(err, result) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getDailyEnigmaStats(enigmaLevel) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const currentDate = new Date().toISOString().slice(0, 10);
|
|
||||||
|
|
||||||
this.client.all(
|
|
||||||
'SELECT pseudo, time FROM users INNER JOIN games ON users.idUser = games.idUser WHERE gameType = ? AND SUBSTR(playedDate, 1, 10) = ? ORDER BY time ASC LIMIT 10',
|
|
||||||
enigmaLevel,
|
|
||||||
currentDate,
|
|
||||||
(err, result) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getDailyOnlineStats() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const currentDate = new Date().toISOString().slice(0, 10);
|
|
||||||
|
|
||||||
this.client.all(
|
|
||||||
'SELECT pseudo, COUNT(*) AS wins FROM users INNER JOIN games ON users.idUser = games.idUser WHERE gameType = ? AND SUBSTR(playedDate, 1, 10) = ? AND win = ? GROUP BY users.idUser ORDER BY wins ASC LIMIT 10',
|
|
||||||
"multijoueur", currentDate, 1,
|
|
||||||
(err, result) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
// ------------------- STATS HEBDOMADAIRE ------------------------
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
|
|
||||||
async getWeeklyMastermindStats() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const currentDate = new Date().toISOString().slice(0, 10);
|
|
||||||
const currentDay = new Date().getDay();
|
|
||||||
const firstDayOfWeek = new Date(new Date().setDate(new Date().getDate() - currentDay)).toISOString().slice(0, 10);
|
|
||||||
|
|
||||||
this.client.all(
|
|
||||||
'SELECT pseudo, score FROM users INNER JOIN games ON users.idUser = games.idUser WHERE gameType = ? AND SUBSTR(playedDate, 1, 10) BETWEEN ? AND ? ORDER BY score ASC LIMIT 10',
|
|
||||||
"mastermind",
|
|
||||||
firstDayOfWeek,
|
|
||||||
currentDate,
|
|
||||||
(err, result) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getWeeklyEnigmaStats(enigmaLevel) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const currentDate = new Date().toISOString().slice(0, 10);
|
|
||||||
const currentDay = new Date().getDay();
|
|
||||||
const firstDayOfWeek = new Date(new Date().setDate(new Date().getDate() - currentDay)).toISOString().slice(0, 10);
|
|
||||||
|
|
||||||
this.client.all(
|
|
||||||
'SELECT pseudo, time FROM users INNER JOIN games ON users.idUser = games.idUser WHERE gameType = ? AND SUBSTR(playedDate, 1, 10) BETWEEN ? AND ? ORDER BY time ASC LIMIT 10',
|
|
||||||
enigmaLevel,
|
|
||||||
firstDayOfWeek,
|
|
||||||
currentDate,
|
|
||||||
(err, result) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getWeeklyOnlineStats() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const currentDate = new Date().toISOString().slice(0, 10);
|
|
||||||
const currentDay = new Date().getDay();
|
|
||||||
const firstDayOfWeek = new Date(new Date().setDate(new Date().getDate() - currentDay)).toISOString().slice(0, 10);
|
|
||||||
|
|
||||||
this.client.all(
|
|
||||||
'SELECT pseudo, COUNT(*) as wins FROM users INNER JOIN games ON users.idUser = games.idUser WHERE gameType = ? AND SUBSTR(playedDate, 1, 10) BETWEEN ? AND ? AND win = ? ORDER BY wins ASC LIMIT 10',
|
|
||||||
"multijoueur",
|
|
||||||
firstDayOfWeek,
|
|
||||||
currentDate,
|
|
||||||
1,
|
|
||||||
(err, result) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------------------------------------
|
|
||||||
// ------------------- STATS MASTERMIND ------------------------
|
|
||||||
// -------------------------------------------------------------
|
|
||||||
|
|
||||||
async getNbGamesMastermindByUserId(userId){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT COUNT(*) AS nbGames FROM games WHERE idUser = ? AND gameType = ?', userId, "mastermind", (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getBestScoreMastermindByUserId(userId){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT MIN(score) AS bestScore FROM games WHERE idUser = ? AND gameType = ?', userId, "mastermind", (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAvgNbTryMastermindByUserId(userId){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT AVG(score) AS avgNbTry FROM games WHERE idUser = ? AND gameType = ?', userId, "mastermind", (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async addMastermindStats(userId, score, time){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.run('INSERT INTO games (idUser, gameType, win, score, time) VALUES (?, ?, ?, ?, ?)', userId, "mastermind", 1, score, time, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// -------------------------------------------------------------
|
|
||||||
// ------------------- STATS EN LIGNE --------------------------
|
|
||||||
// -------------------------------------------------------------
|
|
||||||
|
|
||||||
async getNbGamesOnlineByUserId(userId){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT COUNT(*) AS nbGames FROM games WHERE idUser = ? AND gameType = ?', userId, "multijoueur", (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getNbWinsOnlineByUserId(userId){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT COUNT(*) AS nbWins FROM games WHERE idUser = ? AND gameType = ? AND win = ?', userId, "multijoueur", 1, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async addOnlineStats(userId, win, time){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.run('INSERT INTO games (idUser, gameType, win, score, time) VALUES (?, ?, ?, ?, ?)', userId, "multijoueur", win, 0, time, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------------------------------------
|
|
||||||
// ------------------- STATS ENIGME ----------------------------
|
|
||||||
// -------------------------------------------------------------
|
|
||||||
|
|
||||||
async getNbGamesEnigmeByUserId(userId, enigmaLevel){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT COUNT(*) AS nbGames FROM games WHERE idUser = ? AND gameType = ?', userId, enigmaLevel, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getNbWinsEnigmeByUserId(userId, enigmaLevel){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT COUNT(*) AS nbWins FROM games WHERE idUser = ? AND gameType = ? AND win = ?', userId, enigmaLevel, 1, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getBestScoreEnigmeByUserId(userId, enigmaLevel){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT MAX(score) AS bestScore FROM games WHERE idUser = ? AND gameType = ?', userId, enigmaLevel, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAvgScoreEnigmeByUserId(userId, enigmaLevel){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT AVG(score) AS avgScore FROM games WHERE idUser = ? AND gameType = ?', userId, enigmaLevel, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getBestTimeEnigmeByUserId(userId, enigmaLevel){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT MIN(time) AS bestTime FROM games WHERE idUser = ? AND gameType = ?', userId, enigmaLevel, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async getAvgTimeEnigmeByUserId(userId, enigmaLevel){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.get('SELECT AVG(time) AS avgTime FROM games WHERE idUser = ? AND gameType = ?', userId, enigmaLevel, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async addEasyEnigmaStats(userId, enigmaLevel, win, time){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.run('INSERT INTO games (idUser, gameType, win, score, time) VALUES (?, ?, ?, ?, ?)', userId, enigmaLevel, win, 0, time, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// async addMediumEnigmaStats(userId, enigmaLevel, score)
|
|
||||||
|
|
||||||
async addHardEnigmaStats(userId, enigmaLevel, win, time){
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.client.run('INSERT INTO games (idUser, gameType, win, score, time) VALUES (?, ?, ?, ?, ?)', userId, enigmaLevel, win, 0, time, (err, result) => {
|
|
||||||
if(err){
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = DatabaseService;
|
|
@ -0,0 +1,139 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const http = require('http');
|
||||||
|
const socketIO = require('socket.io');
|
||||||
|
const cors = require('cors');
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const server = http.createServer(app);
|
||||||
|
const io = socketIO(server, {
|
||||||
|
cors: {
|
||||||
|
origin: ["http://localhost:3000", "http://localhost:3000"], // Remplacez par l'URL de votre application React
|
||||||
|
methods: ["GET", "POST"],
|
||||||
|
credentials: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const map = new Map()
|
||||||
|
|
||||||
|
server.listen(3002, () => {
|
||||||
|
console.log('Serveur Socket.IO écoutant sur le port 3002');
|
||||||
|
});
|
||||||
|
|
||||||
|
io.on('connection', (socket) => {
|
||||||
|
console.log(socket.id);
|
||||||
|
|
||||||
|
socket.on('network created', (network, person, indices, room, start) =>{
|
||||||
|
io.to(room).emit("game created", network, person, indices, start)
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on("lobby joined", (room, player) =>{
|
||||||
|
console.log(player)
|
||||||
|
if (player.type=="User"){
|
||||||
|
socket.join(room)
|
||||||
|
}
|
||||||
|
if (map.get(room) == undefined){
|
||||||
|
map.set(room, [{type: player.type, id: socket.id, pseudo: player.pseudo, profilePicture: player.profilePicture}])
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
const tab = map.get(room)
|
||||||
|
for(let i = 0; i<tab.length; i++){
|
||||||
|
if (tab[i].id === socket.id && player.type==="User"){
|
||||||
|
tab.splice(i, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.type!=="User"){
|
||||||
|
map.get(room).push({type: player.type, id: player.id, pseudo: player.pseudo, profilePicture: player.profilePicture})
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
map.get(room).push({type: player.type, id: socket.id, pseudo: player.pseudo, profilePicture: player.profilePicture})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
io.to(room).emit("new player", map.get(room))
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
socket.on("bot deleted", (bot, room) =>{
|
||||||
|
const tab = map.get(room)
|
||||||
|
for(let i = 0; i<tab.length; i++){
|
||||||
|
if (tab[i].id === bot.id){
|
||||||
|
tab.splice(i, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
io.to(room).emit("new player", map.get(room))
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
socket.on("lobby created", () =>{
|
||||||
|
io.to(socket.id).emit("lobby created", Math.floor(Math.random() * 10000))
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("already asked", (nodeId, askingPlayer, askedPlayer) =>{
|
||||||
|
io.to(askingPlayer.id).emit("already asked", nodeId, askedPlayer)
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("ask player", (nodeId, playerId, askingPlayer) =>{
|
||||||
|
io.to(playerId).emit("asked", nodeId, askingPlayer)
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("asked all 1by1", (id, playerId) =>{
|
||||||
|
io.to(playerId).emit("asked all", id)
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("asked wrong", (askingPlayer) =>{
|
||||||
|
io.to(askingPlayer.id).emit("asked wrong")
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("disconnect", () =>{
|
||||||
|
for (const k of map.keys()){
|
||||||
|
const tab = map.get(k)
|
||||||
|
for (let i = 0; i<tab.length; i++){
|
||||||
|
if (tab[i].id === socket.id){
|
||||||
|
tab.splice(i, 1)
|
||||||
|
io.to(k).emit("player left", tab, i)
|
||||||
|
if (tab.filter((p) => p.type=="User").length == 0){
|
||||||
|
map.delete(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("node checked", (id, works, color, room, playerIndex) =>{
|
||||||
|
io.to(room).emit("node checked", id, works, color, playerIndex, socket.id)
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("put correct background", (id) =>{
|
||||||
|
io.to(id).emit("put correct background")
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("put grey background", (id, player) =>{
|
||||||
|
io.to(id).emit("put grey background", player)
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("put imossible grey", (id) =>{
|
||||||
|
io.to(id).emit("put imossible grey")
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("can't put square", (askingPlayer, room) => {
|
||||||
|
io.to(room).emit("can't put square" , askingPlayer)
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("opacity activated", (id) => {
|
||||||
|
io.to(id).emit("opacity activated")
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("opacity deactivated", (id) => {
|
||||||
|
io.to(id).emit("opacity deactivated")
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("reset graph", (id) => {
|
||||||
|
io.to(id).emit("reset graph")
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on("end game", (winnerIndex, room) =>{
|
||||||
|
io.to(room).emit("end game", winnerIndex)
|
||||||
|
})
|
||||||
|
});
|
@ -1,284 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const http = require('http');
|
|
||||||
const socketIO = require('socket.io');
|
|
||||||
const cors = require('cors');
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
const server = http.createServer(app);
|
|
||||||
const io = socketIO(server, {
|
|
||||||
cors: {
|
|
||||||
origin: "*", // Remplacez par l'URL de votre application React
|
|
||||||
methods: ["GET", "POST"],
|
|
||||||
credentials: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
let lastSocketJoined = ""
|
|
||||||
const map = new Map()
|
|
||||||
|
|
||||||
server.listen(3002, () => {
|
|
||||||
console.log('Serveur Socket.IO écoutant sur le port 3002');
|
|
||||||
});
|
|
||||||
|
|
||||||
io.on('connection', (socket) => {
|
|
||||||
console.log(socket.id);
|
|
||||||
|
|
||||||
socket.on('network created', (network, person, indices, room, start) =>{
|
|
||||||
try{
|
|
||||||
io.to(room).emit("game created", network, person, indices, start)
|
|
||||||
map.get(room).started = true
|
|
||||||
map.get(room).actualPlayer=start
|
|
||||||
const playerArray = Array.from(map.entries()).map(([key, value]) => ({ key, value }))
|
|
||||||
const playerJson = JSON.stringify(playerArray);
|
|
||||||
io.emit("request lobbies", playerJson)
|
|
||||||
}
|
|
||||||
catch{
|
|
||||||
console.log("error")
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("give network", (networkPerson, person, indices, start, room, nodes, playerId) => {
|
|
||||||
io.to(playerId).emit("join during game", networkPerson, person, indices, start, map.get(room).tab, nodes)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("join back game", (player) => {
|
|
||||||
for (const k of map.keys()){
|
|
||||||
const tab = map.get(k)
|
|
||||||
for (let i = 0; i<tab.tab.length; i++){
|
|
||||||
if (tab.tab[i].pseudo === player.pseudo && tab.tab[i].type !== "User"){
|
|
||||||
if (tab.started){
|
|
||||||
io.to(socket.id).emit("join back game", k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("lobby joined", (room, player) =>{
|
|
||||||
|
|
||||||
const game = map.get(room)
|
|
||||||
if (game !== undefined){
|
|
||||||
if (game.tab.length == 6 && !game.started){
|
|
||||||
io.to(socket.id).emit("room full")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (game.started){
|
|
||||||
for(const u of game.tab){
|
|
||||||
if(u.type !== "User" && u.pseudo===player.pseudo){
|
|
||||||
u.type = "User"
|
|
||||||
u.id=socket.id
|
|
||||||
io.to(game.tab[game.actualPlayer].id).emit("give network", socket.id)
|
|
||||||
io.to(room).emit("player joined ingame", game.tab)
|
|
||||||
socket.join(room)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
io.to(socket.id).emit("game already started")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (game == undefined){
|
|
||||||
map.set(room, {tab: [{type: player.type, id: socket.id, pseudo: player.pseudo, profilePicture: player.profilePicture}], started: false, actualPlayer: 0, lastWorks: false})
|
|
||||||
socket.join(room)
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
const tab = game.tab
|
|
||||||
for(let i = 0; i<tab.length; i++){
|
|
||||||
if (tab[i].id === socket.id && player.type==="User"){
|
|
||||||
tab.splice(i, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player.type!=="User"){
|
|
||||||
tab.push({type: player.type, id: player.id, pseudo: player.pseudo, profilePicture: player.profilePicture})
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
tab.push({type: player.type, id: socket.id, pseudo: player.pseudo, profilePicture: player.profilePicture})
|
|
||||||
socket.join(room)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
io.to(room).emit("new player", map.get(room))
|
|
||||||
const playerArray = Array.from(map.entries()).map(([key, value]) => ({ key, value }))
|
|
||||||
const playerJson = JSON.stringify(playerArray);
|
|
||||||
io.emit("request lobbies", playerJson)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("request lobbies", () => {
|
|
||||||
const playerArray = Array.from(map.entries()).map(([key, value]) => ({ key, value }))
|
|
||||||
const playerJson = JSON.stringify(playerArray);
|
|
||||||
io.to(socket.id).emit("request lobbies", playerJson)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
socket.on("bot deleted", (bot, room) =>{
|
|
||||||
const tab = map.get(room).tab
|
|
||||||
for(let i = 0; i<tab.length; i++){
|
|
||||||
if (tab[i].id === bot.id){
|
|
||||||
tab.splice(i, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
io.to(room).emit("new player", map.get(room))
|
|
||||||
const playerArray = Array.from(map.entries()).map(([key, value]) => ({ key, value }))
|
|
||||||
const playerJson = JSON.stringify(playerArray);
|
|
||||||
io.emit("request lobbies", playerJson)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
socket.on("lobby created", () =>{
|
|
||||||
io.to(socket.id).emit("lobby created", Math.floor(Math.random() * 10000))
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("already asked", (nodeId, askingPlayer, askedPlayer) =>{
|
|
||||||
io.to(askingPlayer.id).emit("already asked", nodeId, askedPlayer)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("ask player", (nodeId, playerId, askingPlayer) =>{
|
|
||||||
io.to(playerId).emit("asked", nodeId, askingPlayer)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("asked all 1by1", (id, playerId) =>{
|
|
||||||
io.to(playerId).emit("asked all", id)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("asked wrong", (askingPlayer) =>{
|
|
||||||
io.to(askingPlayer.id).emit("asked wrong")
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("who plays", (room) => {
|
|
||||||
try{
|
|
||||||
if (map.get(room) !== undefined){
|
|
||||||
let player = map.get(room).actualPlayer
|
|
||||||
if (map.get(room).tab[player].type != "User"){
|
|
||||||
player = player + 1
|
|
||||||
if (player == map.get(room).tab.length){
|
|
||||||
player=0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// console.log(player)
|
|
||||||
io.to(room).emit("who plays", player, map.get(room).lastWorks)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("disconnect", () =>{
|
|
||||||
for (const k of map.keys()){
|
|
||||||
const tab = map.get(k)
|
|
||||||
for (let i = 0; i<tab.tab.length; i++){
|
|
||||||
if (tab.tab[i].id === socket.id){
|
|
||||||
if (!tab.started){
|
|
||||||
tab.tab.splice(i, 1)
|
|
||||||
if (i==0){
|
|
||||||
tab.tab.sort(comparePlayersByType).reverse()
|
|
||||||
}
|
|
||||||
io.to(k).emit("player left", tab, i)
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
tab.tab[i].type="EasyBot"
|
|
||||||
io.to(k).emit("player left ingame", tab, i)
|
|
||||||
}
|
|
||||||
if (tab.tab.filter((p) => p.type=="User").length == 0){
|
|
||||||
map.delete(k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const playerArray = Array.from(map.entries()).map(([key, value]) => ({ key, value }))
|
|
||||||
const playerJson = JSON.stringify(playerArray);
|
|
||||||
io.emit("request lobbies", playerJson)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
socket.on("player quit", () => {
|
|
||||||
lastSocketJoined=""
|
|
||||||
for (const k of map.keys()){
|
|
||||||
const tab = map.get(k)
|
|
||||||
for (let i = 0; i<tab.tab.length; i++){
|
|
||||||
if (tab.tab[i].id === socket.id){
|
|
||||||
if (!tab.started){
|
|
||||||
tab.tab.splice(i, 1)
|
|
||||||
if (i==0){
|
|
||||||
tab.tab.sort(comparePlayersByType).reverse()
|
|
||||||
|
|
||||||
}
|
|
||||||
io.to(k).emit("player left", tab, i)
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
tab.tab[i].type="EasyBot"
|
|
||||||
io.to(k).emit("player left ingame", tab, i)
|
|
||||||
}
|
|
||||||
if (tab.tab.filter((p) => p.type=="User").length == 0){
|
|
||||||
map.delete(k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const playerArray = Array.from(map.entries()).map(([key, value]) => ({ key, value }))
|
|
||||||
const playerJson = JSON.stringify(playerArray);
|
|
||||||
io.emit("request lobbies", playerJson)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("node checked", (id, works, color, room, playerIndex) =>{
|
|
||||||
try{
|
|
||||||
map.get(room).actualPlayer=playerIndex
|
|
||||||
map.get(room).lastWorks=works
|
|
||||||
io.to(room).emit("node checked", id, works, color, playerIndex, socket.id)
|
|
||||||
}
|
|
||||||
catch{
|
|
||||||
console.log("error")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("put correct background", (id) =>{
|
|
||||||
io.to(id).emit("put correct background")
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("put grey background", (id, player) =>{
|
|
||||||
io.to(id).emit("put grey background", player)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("put imossible grey", (id) =>{
|
|
||||||
io.to(id).emit("put imossible grey")
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("can't put square", (askingPlayer, room) => {
|
|
||||||
io.to(room).emit("can't put square" , askingPlayer)
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("opacity activated", (id) => {
|
|
||||||
io.to(id).emit("opacity activated")
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("opacity deactivated", (id) => {
|
|
||||||
io.to(id).emit("opacity deactivated")
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("reset graph", (id) => {
|
|
||||||
io.to(id).emit("reset graph")
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.on("end game", (winnerIndex, room) =>{
|
|
||||||
io.to(room).emit("end game", winnerIndex)
|
|
||||||
map.delete(room)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
function comparePlayersByType(a, b) {
|
|
||||||
if (a.type < b.type) {
|
|
||||||
return -1;
|
|
||||||
} else if (a.type > b.type) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Vérifier si l'adresse IP est fournie en tant que paramètre
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "Usage: $0 <adresse_ip>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Stocker l'adresse IP fournie en tant que variable
|
||||||
|
adresse_ip="$1"
|
||||||
|
|
||||||
|
# Utiliser l'adresse IP dans la commande find avec Perl
|
||||||
|
find . -type f -exec perl -pi -e 's|http://[0-9.]+:([0-9]+)|http://localhost:$1|g' {} +
|
||||||
|
|
||||||
|
find . -type f -exec perl -pi -e "s|http://localhost:([0-9]+)|http://$adresse_ip:\$1|g" {} +
|
@ -1,87 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
/* Style */
|
|
||||||
import '../Style/Global.css';
|
|
||||||
//import { useTheme } from '../Style/ThemeContext';
|
|
||||||
|
|
||||||
/* Model */
|
|
||||||
import Stub from '../model/Stub';
|
|
||||||
import Indice from '../model/Indices/Indice';
|
|
||||||
|
|
||||||
|
|
||||||
/* lang */
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
/* Boostrap */
|
|
||||||
import Accordion from 'react-bootstrap/Accordion';
|
|
||||||
import Table from 'react-bootstrap/Table';
|
|
||||||
import Case from './CheckCase';
|
|
||||||
|
|
||||||
|
|
||||||
interface AccordionIndiceComponentProps<T extends Indice> {
|
|
||||||
instance: (new (...args: any[]) => T) | (Function & { prototype: T });
|
|
||||||
head: string;
|
|
||||||
lang: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AccordionIndice: React.FC<AccordionIndiceComponentProps<any>> = ({ instance, head, lang }) => {
|
|
||||||
const indices = Stub.GenerateIndice();
|
|
||||||
const [selectedRows, setSelectedRows] = useState<number[]>([]);
|
|
||||||
|
|
||||||
|
|
||||||
const handleRowClick = (index: number) => {
|
|
||||||
|
|
||||||
const newSelectedRows = [...selectedRows];
|
|
||||||
|
|
||||||
const selectedIndex = newSelectedRows.indexOf(index);
|
|
||||||
if (selectedIndex === -1) {
|
|
||||||
newSelectedRows.push(index);
|
|
||||||
} else {
|
|
||||||
newSelectedRows.splice(selectedIndex, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('New Selected Rows:', newSelectedRows);
|
|
||||||
setSelectedRows(newSelectedRows);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Accordion defaultActiveKey={['0']} alwaysOpen style={{ width: '100%' }}>
|
|
||||||
<Accordion.Item eventKey="0">
|
|
||||||
<Accordion.Header>{head}</Accordion.Header>
|
|
||||||
<Accordion.Body>
|
|
||||||
<Table striped bordered hover>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Indice</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{indices
|
|
||||||
.filter((i) => i instanceof instance)
|
|
||||||
.map((indice, index) => (
|
|
||||||
<tr
|
|
||||||
key={index}
|
|
||||||
onClick={() => handleRowClick(index)}
|
|
||||||
style={{
|
|
||||||
cursor: 'pointer',
|
|
||||||
}}>
|
|
||||||
<td
|
|
||||||
style={{
|
|
||||||
border: selectedRows.includes(index) ? '1px solid red' : 'none',
|
|
||||||
backgroundColor: selectedRows.includes(index) ? '#FF9191' : 'white',
|
|
||||||
}}>
|
|
||||||
{indice.ToString(lang)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</Table>
|
|
||||||
</Accordion.Body>
|
|
||||||
</Accordion.Item>
|
|
||||||
</Accordion>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AccordionIndice;
|
|
@ -1,41 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
|
|
||||||
/* style */
|
|
||||||
import { useTheme } from '../Style/ThemeContext';
|
|
||||||
import '../Pages/DeducGrid.css';
|
|
||||||
|
|
||||||
/* res */
|
|
||||||
import Check from '../res/icon/checkboxGreen.png';
|
|
||||||
|
|
||||||
/* trad */
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
function Case() {
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
const [bg, setbg] = useState('whitesmoke');
|
|
||||||
|
|
||||||
//let check = ""; //? avec image
|
|
||||||
//let bg = 'whitesmoke';
|
|
||||||
|
|
||||||
function changeOnCheck(){
|
|
||||||
// if (check == "")check = Check;
|
|
||||||
// else check = "";
|
|
||||||
|
|
||||||
if(bg == "whitesmoke")setbg(theme.colors.tertiary);
|
|
||||||
else setbg("whitesmoke");
|
|
||||||
|
|
||||||
console.log("clic")
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button className='case' onClick={changeOnCheck} style={{backgroundColor: bg, borderColor:'grey'}}>
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Case;
|
|
@ -1,159 +0,0 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { useTheme } from '../Style/ThemeContext';
|
|
||||||
import Player from '../model/Player';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
|
|
||||||
import Modal from 'react-bootstrap/Modal';
|
|
||||||
import Offcanvas from 'react-bootstrap/Offcanvas';
|
|
||||||
import Button from 'react-bootstrap/Button';
|
|
||||||
import { socket } from '../SocketConfig';
|
|
||||||
import Tooltip from 'react-bootstrap/esm/Tooltip';
|
|
||||||
import OverlayTrigger from 'react-bootstrap/esm/OverlayTrigger';
|
|
||||||
import {basePath} from "../AdressSetup"
|
|
||||||
|
|
||||||
interface LobbyContainerProps {
|
|
||||||
roomNum : string
|
|
||||||
HeadPlayer : Player
|
|
||||||
nbPlayer : number
|
|
||||||
setFirst: (first: boolean) => void
|
|
||||||
started : boolean
|
|
||||||
//? mettre un "nbplayermax" si le nombre de joueur max peut etre fixé ?
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const LobbyContainer: React.FC<LobbyContainerProps> = ({roomNum, HeadPlayer, nbPlayer, setFirst, started}) => {
|
|
||||||
const theme=useTheme();
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const dest = 'lobby?room=' + roomNum;
|
|
||||||
|
|
||||||
//* Modal
|
|
||||||
const [showFull, setShowFull] = useState(false);
|
|
||||||
const [showStart, setShowStart] = useState(false);
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
setShowFull(false)
|
|
||||||
setShowStart(false)
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleShowFull = () => setShowFull(true);
|
|
||||||
const handleShowStart = () => setShowStart(true);
|
|
||||||
|
|
||||||
const handleContainerClick = () => {
|
|
||||||
|
|
||||||
if (showFull || showStart){
|
|
||||||
handleClose()
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if (nbPlayer < 6 && !started) {
|
|
||||||
socket.off("request lobbies")
|
|
||||||
setFirst(true)
|
|
||||||
navigate(`${basePath}/${dest}`);
|
|
||||||
}
|
|
||||||
else if(started){
|
|
||||||
handleShowStart()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
handleShowFull()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//* popup pour salle pleine
|
|
||||||
//@ts-ignore
|
|
||||||
const renderTooltipFull = (props) => (
|
|
||||||
<Tooltip id="button-tooltip" {...props}>
|
|
||||||
Salle Pleine !
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
|
|
||||||
//* popup pour partie déjà lancé
|
|
||||||
//@ts-ignore
|
|
||||||
const renderTooltipInGame = (props) => (
|
|
||||||
<Tooltip id="button-tooltip" {...props}>
|
|
||||||
En Jeu !
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
|
|
||||||
//* autre
|
|
||||||
//@ts-ignore
|
|
||||||
const renderTooltip = (props) => (
|
|
||||||
<Tooltip id="button-tooltip" {...props}>
|
|
||||||
Rejoindre le lobby !
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
|
|
||||||
//let IsInGame = true;
|
|
||||||
|
|
||||||
let stylefull;
|
|
||||||
let colorfull;
|
|
||||||
let actualRender = renderTooltip;
|
|
||||||
let bgcol = 'white';
|
|
||||||
|
|
||||||
if (nbPlayer >= 6) {
|
|
||||||
stylefull = "darkred"
|
|
||||||
colorfull = "darkred"
|
|
||||||
actualRender = renderTooltipFull
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
stylefull = "whitesmoke"
|
|
||||||
colorfull = "black"
|
|
||||||
}
|
|
||||||
|
|
||||||
if(started){
|
|
||||||
bgcol = 'lightgrey' //! le hover ne marche plus
|
|
||||||
actualRender = renderTooltipInGame
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return(
|
|
||||||
<OverlayTrigger
|
|
||||||
placement="top"
|
|
||||||
delay={{ show: 250, hide: 400 }}
|
|
||||||
overlay={actualRender}>
|
|
||||||
|
|
||||||
<div className='lobbyMainContainer' onClick={handleContainerClick} style={{borderColor:stylefull, backgroundColor:bgcol}}>
|
|
||||||
<header style={{height:'20%', display:'flex', justifyContent:'end'}}>
|
|
||||||
<h6><i>Room : {roomNum}</i></h6>
|
|
||||||
</header>
|
|
||||||
<hr/>
|
|
||||||
<h3><b>{HeadPlayer.pseudo}</b></h3>
|
|
||||||
<div style={{display:'flex', justifyContent:'end', alignItems:'end'}}>
|
|
||||||
<h2 style={{color:colorfull}}>{nbPlayer}/6</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Modals */}
|
|
||||||
<Modal show={showFull} onHide={handleClose}>
|
|
||||||
<Modal.Header closeButton>
|
|
||||||
<Modal.Title>Salle pleine</Modal.Title>
|
|
||||||
</Modal.Header>
|
|
||||||
<Modal.Body>La salle est pleine, il est impossible d'y aller pour le moment !</Modal.Body>
|
|
||||||
<Modal.Footer>
|
|
||||||
<Button variant="secondary" onClick={handleClose}>
|
|
||||||
Ok
|
|
||||||
</Button>
|
|
||||||
</Modal.Footer>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<Modal show={showStart} onHide={handleClose}>
|
|
||||||
<Modal.Header closeButton>
|
|
||||||
<Modal.Title>La partie a déjà commencée</Modal.Title>
|
|
||||||
</Modal.Header>
|
|
||||||
<Modal.Body>La partie a déjà commencée, il est impossible d'y aller pour le moment !</Modal.Body>
|
|
||||||
<Modal.Footer>
|
|
||||||
<Button variant="secondary" onClick={handleClose}>
|
|
||||||
Ok
|
|
||||||
</Button>
|
|
||||||
</Modal.Footer>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</OverlayTrigger>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LobbyContainer;
|
|
@ -1,28 +0,0 @@
|
|||||||
/* Ajoutez ces styles dans votre fichier CSS ou utilisez un préprocesseur comme SCSS */
|
|
||||||
.tabsStats {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stats {
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Personnalisez davantage selon vos préférences */
|
|
||||||
|
|
||||||
.carousselButton{
|
|
||||||
border:none;
|
|
||||||
background-color:darkgray;
|
|
||||||
color:white;
|
|
||||||
opacity: 60%;
|
|
||||||
width: 50px;
|
|
||||||
height: 70px;
|
|
||||||
font-size: 40px;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
@ -1,335 +0,0 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
|
||||||
import { DataSet, Network} from "vis-network/standalone/esm/vis-network";
|
|
||||||
import GraphCreator from "../model/Graph/GraphCreator";
|
|
||||||
import "./GraphContainer.css";
|
|
||||||
import IndiceTesterFactory from "../model/Factory/IndiceTesterFactory";
|
|
||||||
import Person from "../model/Person";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import { useGame } from "../Contexts/GameContext";
|
|
||||||
import { socket } from "../SocketConfig"
|
|
||||||
import { colorToEmoji, positionToColor, positionToEmoji } from "../ColorHelper";
|
|
||||||
import { ColorToHexa } from "../model/EnumExtender";
|
|
||||||
import Bot from "../model/Bot";
|
|
||||||
import NodePerson from "../model/Graph/NodePerson";
|
|
||||||
import { useAuth } from "../Contexts/AuthContext";
|
|
||||||
import Indice from "../model/Indices/Indice";
|
|
||||||
import Pair from "../model/Pair";
|
|
||||||
import Player from "../model/Player";
|
|
||||||
import JSONParser from "../JSONParser";
|
|
||||||
import User from "../model/User";
|
|
||||||
import { json } from "body-parser";
|
|
||||||
import html2canvas from 'html2canvas';
|
|
||||||
import jsPDF from 'jspdf';
|
|
||||||
import {basePath} from "../AdressSetup"
|
|
||||||
import PersonNetwork from "../model/PersonsNetwork";
|
|
||||||
import { useIntl } from "react-intl";
|
|
||||||
|
|
||||||
interface TutorialGraphProps {
|
|
||||||
setNetwork: (network: Network) => void
|
|
||||||
showLast: boolean
|
|
||||||
setPlayerIndex: (playerIndex: number) => void
|
|
||||||
handleShowTurnBar: (bool: boolean) => void
|
|
||||||
handleTurnBarTextChange: (text: string) => void
|
|
||||||
addToHistory: (text: string) => void
|
|
||||||
setPlayerTouched: (playerIndex: number) => void
|
|
||||||
playerTouched: number
|
|
||||||
tutoStep: number
|
|
||||||
setTutoStep: (step: number) => void
|
|
||||||
setGreyForEveryone: (func: () => void) => void
|
|
||||||
displayModalstep: (step: number) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
let lastNodes: NodePerson[] = []
|
|
||||||
let firstIndex = true
|
|
||||||
let first = true
|
|
||||||
let touchedPlayer = -1
|
|
||||||
let stepTuto = -1
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const TutorialGraph: React.FC<TutorialGraphProps> = ({showLast, setNetwork, setPlayerIndex, handleShowTurnBar, handleTurnBarTextChange, addToHistory, setPlayerTouched, playerTouched, tutoStep, setTutoStep, setGreyForEveryone, displayModalstep}) => {
|
|
||||||
let cptTour: number = 0
|
|
||||||
|
|
||||||
//* Gestion du temps :
|
|
||||||
let initMtn = 0
|
|
||||||
|
|
||||||
//* traduction
|
|
||||||
const intl = useIntl();
|
|
||||||
|
|
||||||
const {isLoggedIn, user, manager} = useAuth();
|
|
||||||
const {setIndiceData, setIndicesData, setActualPlayerIndexData, setWinnerData, setPlayersData, setNetworkDataData, setPersonData} = useGame();
|
|
||||||
const params = new URLSearchParams(window.location.search);
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const [lastIndex, setLastIndex] = useState(-1)
|
|
||||||
|
|
||||||
if (first){
|
|
||||||
first = false
|
|
||||||
setActualPlayerIndexData(0)
|
|
||||||
handleTurnBarTextChange(intl.formatMessage({ id: 'game.yourTurn' }))
|
|
||||||
handleShowTurnBar(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() =>{
|
|
||||||
touchedPlayer=playerTouched
|
|
||||||
}, [playerTouched])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
stepTuto = tutoStep
|
|
||||||
if(stepTuto===1){
|
|
||||||
handleShowTurnBar(true)
|
|
||||||
}
|
|
||||||
}, [tutoStep])
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const tab: NodePerson[] = []
|
|
||||||
for(const n of lastNodes.reverse()){
|
|
||||||
|
|
||||||
}
|
|
||||||
lastNodes = tab
|
|
||||||
if (showLast){
|
|
||||||
socket.emit("opacity activated", socket.id)
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
socket.emit("opacity deactivated", socket.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
}, [showLast])
|
|
||||||
|
|
||||||
let playerIndex: number = 0
|
|
||||||
|
|
||||||
if (firstIndex){
|
|
||||||
firstIndex=false
|
|
||||||
setPlayerIndex(playerIndex)
|
|
||||||
}
|
|
||||||
let index = 0
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
|
|
||||||
|
|
||||||
let jsonGraph = require("../tuto/graph.json")
|
|
||||||
let jsonIndice = require("../tuto/indices.json")
|
|
||||||
|
|
||||||
const personNetwork = JSONParser.JSONToNetwork(JSON.stringify(jsonGraph))
|
|
||||||
const indices = JSONParser.JSONToIndices(jsonIndice)
|
|
||||||
|
|
||||||
setIndiceData(indices[0])
|
|
||||||
if (personNetwork == null){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const graph = GraphCreator.CreateGraph(personNetwork)
|
|
||||||
|
|
||||||
const nodes = new DataSet(graph.nodesPerson);
|
|
||||||
|
|
||||||
setIndicesData(indices)
|
|
||||||
setPersonData(personNetwork.getPersons()[4])
|
|
||||||
|
|
||||||
let n = graph.nodesPerson;
|
|
||||||
let e = graph.edges;
|
|
||||||
const graphState = { n, e };
|
|
||||||
|
|
||||||
// Sauvegarder l'état dans localStorage
|
|
||||||
localStorage.setItem('graphState', JSON.stringify(graphState));
|
|
||||||
|
|
||||||
const container = document.getElementById('graph-container');
|
|
||||||
if (!container) {
|
|
||||||
console.error("Container not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Charger les données dans le graph
|
|
||||||
|
|
||||||
// Configuration des options du Graphe
|
|
||||||
const initialOptions = {
|
|
||||||
|
|
||||||
layout: {
|
|
||||||
improvedLayout: true,
|
|
||||||
hierarchical: {
|
|
||||||
enabled: false,
|
|
||||||
direction: 'LR', // LR (Left to Right) ou autre selon votre préférence
|
|
||||||
sortMethod: 'hubsize'
|
|
||||||
},
|
|
||||||
randomSeed: 3
|
|
||||||
},
|
|
||||||
physics: {
|
|
||||||
enabled: true,
|
|
||||||
barnesHut: {
|
|
||||||
gravitationalConstant: -1000,
|
|
||||||
springConstant: 0.001,
|
|
||||||
springLength: 100
|
|
||||||
},
|
|
||||||
solver: "repulsion",
|
|
||||||
repulsion: {
|
|
||||||
nodeDistance: 100 // Put more distance between the nodes.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const networkData = { nodes: nodes, edges: graph.edges };
|
|
||||||
const network = new Network(container, networkData, initialOptions);
|
|
||||||
network.stabilize();
|
|
||||||
setNetwork(network)
|
|
||||||
|
|
||||||
const myFunctionInsideEffect = () => {
|
|
||||||
if (stepTuto === 3){
|
|
||||||
const tabGrey = [0, 1, 2, 3, 5, 6, 7, 8, 9]
|
|
||||||
for (const i of tabGrey){
|
|
||||||
nodes.update({id: i, color: "#808080"})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
setGreyForEveryone(() => myFunctionInsideEffect);
|
|
||||||
|
|
||||||
|
|
||||||
network.on("click", async (params) => {
|
|
||||||
|
|
||||||
if(params.nodes.length > 0){
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
network.on("dragging", (params) => {
|
|
||||||
if (params.nodes.length > 0) {
|
|
||||||
// Un nœud a été cliqué
|
|
||||||
initialOptions.physics.enabled = false;
|
|
||||||
network.setOptions(initialOptions);
|
|
||||||
setNetwork(network)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
network.on("click", async (params) => {
|
|
||||||
if(params.nodes.length > 0){
|
|
||||||
if (stepTuto === 0 && touchedPlayer === 1){
|
|
||||||
const node = nodes.get().find((n: NodePerson) => n.id === params.nodes[0])
|
|
||||||
|
|
||||||
if (node === undefined)return;
|
|
||||||
if (node.id === 7){
|
|
||||||
nodes.update({id: node.id, label: node.label + positionToEmoji(1, true)})
|
|
||||||
handleShowTurnBar(false)
|
|
||||||
setPlayerIndex(1)
|
|
||||||
setPlayerTouched(-1)
|
|
||||||
await delay(500)
|
|
||||||
const node2 = nodes.get().find((n: NodePerson) => n.id === params.nodes[0])
|
|
||||||
if (node2 === undefined)return;
|
|
||||||
nodes.update({id: node.id, label: node2.label + positionToEmoji(2, false)})
|
|
||||||
await delay(500)
|
|
||||||
const node3 = nodes.get().find((n: NodePerson) => n.id === 8)
|
|
||||||
if (node3 === undefined)return;
|
|
||||||
nodes.update({id: node3.id, label: node3.label + positionToEmoji(1, false)})
|
|
||||||
setPlayerIndex(2)
|
|
||||||
await delay(500)
|
|
||||||
const node4 = nodes.get().find((n: NodePerson) => n.id === 0)
|
|
||||||
if (node4 === undefined)return;
|
|
||||||
nodes.update({id: node4.id, label: node4.label + positionToEmoji(1, true)})
|
|
||||||
setPlayerIndex(0)
|
|
||||||
setTutoStep(1)
|
|
||||||
|
|
||||||
displayModalstep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(stepTuto === 1 && touchedPlayer === 2){
|
|
||||||
const node = nodes.get().find((n: NodePerson) => n.id === params.nodes[0])
|
|
||||||
if (node === undefined){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (node.id === 0){
|
|
||||||
nodes.update({id: node.id, label: node.label + positionToEmoji(2, false)})
|
|
||||||
setPlayerTouched(-1)
|
|
||||||
displayModalstep(2);
|
|
||||||
handleTurnBarTextChange(intl.formatMessage({ id: 'game.wrong' }))
|
|
||||||
const tabGrey = [7, 0, 4, 1, 8]
|
|
||||||
for (const id of tabGrey){
|
|
||||||
const node = nodes.get().find((n: NodePerson) => n.id === id)
|
|
||||||
if (node === undefined)return;
|
|
||||||
nodes.update({id: node.id, color: "#808080"})
|
|
||||||
}
|
|
||||||
setTutoStep(2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(stepTuto === 2){
|
|
||||||
const node = nodes.get().find((n: NodePerson) => n.id === params.nodes[0])
|
|
||||||
if (node === undefined)return;
|
|
||||||
if (node.id === 9){
|
|
||||||
const tabColor = [7, 0, 4, 1, 8]
|
|
||||||
nodes.update({id: node.id, label: node.label + positionToEmoji(0, false)})
|
|
||||||
for(const id of tabColor){
|
|
||||||
const pers = personNetwork.getPersons().find((p: Person) => p.getId() === id)
|
|
||||||
if (pers !== undefined){
|
|
||||||
nodes.update({id: id, color: ColorToHexa(pers.getColor())})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handleShowTurnBar(false)
|
|
||||||
setPlayerIndex(1)
|
|
||||||
await delay(500)
|
|
||||||
const node2 = nodes.get().find((n: NodePerson) => n.id === 4)
|
|
||||||
if (node2 === undefined)return;
|
|
||||||
nodes.update({id: node2.id, label: node2.label + positionToEmoji(2, true)})
|
|
||||||
setPlayerIndex(2)
|
|
||||||
await delay(500)
|
|
||||||
const node3 = nodes.get().find((n: NodePerson) => n.id === 3)
|
|
||||||
if (node3 === undefined)return;
|
|
||||||
nodes.update({id: node3.id, label: node3.label + positionToEmoji(0, false)})
|
|
||||||
await delay(500)
|
|
||||||
const node4 = nodes.get().find((n: NodePerson) => n.id === 1)
|
|
||||||
if (node4 === undefined)return;
|
|
||||||
nodes.update({id: node4.id, label: node4.label + positionToEmoji(2, false)})
|
|
||||||
setPlayerIndex(0)
|
|
||||||
handleTurnBarTextChange(intl.formatMessage({ id: 'game.yourTurn' }))
|
|
||||||
handleShowTurnBar(true)
|
|
||||||
setTutoStep(3)
|
|
||||||
displayModalstep(3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(stepTuto === 3 && touchedPlayer === 3){
|
|
||||||
const node = nodes.get().find((n: NodePerson) => n.id === params.nodes[0])
|
|
||||||
if (node === undefined)return;
|
|
||||||
if (node.id === 4){
|
|
||||||
nodes.update({id: node.id, label: node.label + positionToEmoji(0, true)})
|
|
||||||
setPlayerTouched(-1)
|
|
||||||
await delay(500)
|
|
||||||
const node2 = nodes.get().find((n: NodePerson) => n.id === 4)
|
|
||||||
if (node2 === undefined)return;
|
|
||||||
nodes.update({id: node2.id, label: node2.label + positionToEmoji(1, true)})
|
|
||||||
await delay(500)
|
|
||||||
|
|
||||||
for(const person of personNetwork.getPersons()){
|
|
||||||
nodes.update({id: person.getId(), color: ColorToHexa(person.getColor())})
|
|
||||||
}
|
|
||||||
if (user != null){
|
|
||||||
const winner = user;
|
|
||||||
setNetworkDataData(networkData)
|
|
||||||
setActualPlayerIndexData(-1)
|
|
||||||
setLastIndex(-1)
|
|
||||||
setPlayerTouched(-1)
|
|
||||||
setWinnerData(winner)
|
|
||||||
first = true
|
|
||||||
navigate(`${basePath}/endgame`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
setPlayerTouched(-1)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}, []); // Le tableau vide signifie que cela ne s'exécutera qu'une fois après le premier rendu
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div id="graph-container"/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
function delay(ms: number): Promise<void> {
|
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default TutorialGraph;
|
|
@ -1,67 +0,0 @@
|
|||||||
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
|
||||||
import ErrorPage from './ErrorPage';
|
|
||||||
|
|
||||||
|
|
||||||
interface ErrorBoundaryProps {
|
|
||||||
fallback: (error: Error, errorInfo: ErrorInfo) => ReactNode;
|
|
||||||
children: ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ErrorBoundaryState {
|
|
||||||
hasError: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
||||||
constructor(props: ErrorBoundaryProps) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
hasError: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getDerivedStateFromError(): ErrorBoundaryState {
|
|
||||||
return { hasError: true };
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
|
||||||
console.error('Error caught by ErrorBoundary:', error, errorInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
render(): ReactNode {
|
|
||||||
if (this.state.hasError) {
|
|
||||||
return this.props.fallback(new Error('Error caught by ErrorBoundary'), {});
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.props.children;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ErrorBoundary;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// interface ErrorBoundaryProps {
|
|
||||||
// children: ReactNode;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// class ErrorBoundary extends React.Component <ErrorBoundaryProps>{
|
|
||||||
// state = { hasError : true }
|
|
||||||
// //@ts-ignore
|
|
||||||
// static getDerivedStateFromError(error){
|
|
||||||
// return { hasError : true};
|
|
||||||
// }
|
|
||||||
|
|
||||||
// componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
|
|
||||||
// console.log(error, errorInfo);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// render(){
|
|
||||||
// if (this.state.hasError){
|
|
||||||
// return <ErrorPage/>;
|
|
||||||
// }
|
|
||||||
// return this.props.children;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export default ErrorBoundary;
|
|
@ -1,37 +0,0 @@
|
|||||||
|
|
||||||
import React from 'react';
|
|
||||||
import { useTheme } from '../Style/ThemeContext';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import './ErrorStyle.css';
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
import { Button } from 'react-bootstrap';
|
|
||||||
|
|
||||||
const basePath = process.env.REACT_APP_BASE_PATH || '/containers/Crypteam-website';
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
function ErrorPage({ code = "", msg = "Something is wrong"}) {
|
|
||||||
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='mainErrorDiv'>
|
|
||||||
<div className='titleError'>
|
|
||||||
<div>
|
|
||||||
<h1>ERROR</h1>
|
|
||||||
<hr style={{width:"100%"}}/>
|
|
||||||
</div>
|
|
||||||
{ code != "" &&
|
|
||||||
<h1 style={{color:'darkred', margin:'10px'}}>{code}</h1>
|
|
||||||
}
|
|
||||||
<h2>{msg}</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='centerDivH' style={{margin: "20px"}}>
|
|
||||||
<Button href={`${basePath}/`} variant='danger'><FormattedMessage id='BackHome'/></Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ErrorPage;
|
|
@ -1,29 +0,0 @@
|
|||||||
|
|
||||||
.mainErrorDiv{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.titleError{
|
|
||||||
border: solid 2px #C70039;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin: 15px;
|
|
||||||
padding: 10px;
|
|
||||||
box-shadow: 5px 5px 5px #900C3F;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
width: 400px;
|
|
||||||
height: 250px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.titleError h1 {
|
|
||||||
color: #900C3F;
|
|
||||||
margin: 10px !important;
|
|
||||||
}
|
|
@ -1,120 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
/* Style */
|
|
||||||
import './DeducGrid.css';
|
|
||||||
import { useTheme } from '../Style/ThemeContext';
|
|
||||||
|
|
||||||
/* Component */
|
|
||||||
|
|
||||||
/* Boostrap */
|
|
||||||
import Table from 'react-bootstrap/Table';
|
|
||||||
import Form from 'react-bootstrap/Form';
|
|
||||||
|
|
||||||
/* lang */
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
/* model */
|
|
||||||
import Stub from '../model/Stub';
|
|
||||||
|
|
||||||
import { useGame } from '../Contexts/GameContext';
|
|
||||||
import { positionToEmoji } from '../ColorHelper';
|
|
||||||
|
|
||||||
function DeducCheck({lang}: {lang: string}) {
|
|
||||||
const theme = useTheme();
|
|
||||||
//const indices = Stub.GenerateIndice();
|
|
||||||
|
|
||||||
const params = new URLSearchParams(window.location.search);
|
|
||||||
|
|
||||||
const NbPlayer = params.get('nbPlayer');
|
|
||||||
const actualPlayerIndex = params.get('actualId') ?? '0';
|
|
||||||
|
|
||||||
//const { actualPlayerIndex, players } = useGame();
|
|
||||||
|
|
||||||
// let playerstmp
|
|
||||||
// if (players.length == 0) playerstmp = ["1", "2", "3", "4", "5", "4"];
|
|
||||||
// else { playerstmp = players}
|
|
||||||
|
|
||||||
//* Gestion players
|
|
||||||
const playerList = Array.from({ length: parseInt(NbPlayer ?? '1') }, (_, index) => (index + 1).toString());
|
|
||||||
const playerColors = playerList.map((_, index) => positionToEmoji(index, true));
|
|
||||||
const players = playerColors.filter((_, index) => index !== parseInt(actualPlayerIndex ?? '0'));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// const players = [
|
|
||||||
// "🔵",
|
|
||||||
// "🟢",
|
|
||||||
// "🟡",
|
|
||||||
// "🟣",
|
|
||||||
// "🔴"
|
|
||||||
//]
|
|
||||||
//console.log(players)
|
|
||||||
// console.log(playerColors)
|
|
||||||
// console.log(actualPlayerIndex)
|
|
||||||
|
|
||||||
//* Gestion indices
|
|
||||||
const indices = Stub.GenerateIndice();
|
|
||||||
|
|
||||||
const halfLength = Math.ceil(indices.length / 2);
|
|
||||||
const firstHalfIndices = indices.slice(0, halfLength);
|
|
||||||
const secondHalfIndices = indices.slice(halfLength);
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{ margin: '20px', display: 'flex', flexDirection: 'column' }}>
|
|
||||||
<div style={{ display: 'flex', flexDirection: 'row', overflowX: 'auto' }}>
|
|
||||||
{/* Premier tableau */}
|
|
||||||
<Table striped bordered hover style={{ marginRight: '20px' }}>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Indices</th>
|
|
||||||
{players.map((player, index) => (
|
|
||||||
<th key={index}>{player}</th>
|
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{firstHalfIndices.map((indice, rowIndex) => (
|
|
||||||
<tr key={rowIndex}>
|
|
||||||
<td>{indice.ToString(lang)}</td>
|
|
||||||
{players.map((player, colIndex) => (
|
|
||||||
<td key={colIndex}>
|
|
||||||
{/* <input type="checkbox"/> */}
|
|
||||||
<Form.Check aria-label="option 1" />
|
|
||||||
</td>
|
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</Table>
|
|
||||||
|
|
||||||
{/* Deuxième tableau */}
|
|
||||||
<Table striped bordered hover>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Indices</th>
|
|
||||||
{players.map((player, index) => (
|
|
||||||
<th key={index}>{player}</th>
|
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{secondHalfIndices.map((indice, rowIndex) => (
|
|
||||||
<tr key={rowIndex}>
|
|
||||||
<td>{indice.ToString(lang)}</td>
|
|
||||||
{players.map((player, colIndex) => (
|
|
||||||
<td key={colIndex}>
|
|
||||||
{/* <input type="checkbox"/> */}
|
|
||||||
<Form.Check aria-label="option 1" />
|
|
||||||
</td>
|
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</Table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DeducCheck;
|
|
@ -1,17 +0,0 @@
|
|||||||
.case{
|
|
||||||
min-width: 50px;
|
|
||||||
min-height: 50px;
|
|
||||||
border: solid 1px whitesmoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
.deducDiv{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sectionAccordion{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-around;
|
|
||||||
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
|
|
||||||
/* Style */
|
|
||||||
import './DeducGrid.css';
|
|
||||||
import { useTheme } from '../Style/ThemeContext';
|
|
||||||
|
|
||||||
/* Component */
|
|
||||||
|
|
||||||
/* Boostrap */
|
|
||||||
import Accordion from 'react-bootstrap/Accordion';
|
|
||||||
import Table from 'react-bootstrap/Table';
|
|
||||||
import Tab from 'react-bootstrap/Tab';
|
|
||||||
import Tabs from 'react-bootstrap/Tabs';
|
|
||||||
|
|
||||||
/* nav */
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
/* lang */
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
import Case from '../Components/CheckCase';
|
|
||||||
|
|
||||||
import Age from '../model/Indices/AgeIndice'
|
|
||||||
import Stub from '../model/Stub';
|
|
||||||
import Edge from '../model/Graph/Edge';
|
|
||||||
import EdgesIndice from '../model/Indices/EdgesIndice';
|
|
||||||
import AccordionIndice from '../Components/AccordionIndice';
|
|
||||||
import AgeIndice from '../model/Indices/AgeIndice';
|
|
||||||
import ColorIndice from '../model/Indices/ColorIndice';
|
|
||||||
import ColorEdgesIndice from '../model/Indices/ColorEdgesIndice';
|
|
||||||
import SportIndice from '../model/Indices/SportIndice';
|
|
||||||
import NbEdgesIndice from '../model/Indices/NbEdgesIndice';
|
|
||||||
import NbSportIndice from '../model/Indices/NbSportIndice';
|
|
||||||
import { useGame } from '../Contexts/GameContext';
|
|
||||||
|
|
||||||
function DeducGrid() {
|
|
||||||
const theme = useTheme();
|
|
||||||
//const indices = Stub.GenerateIndice();
|
|
||||||
|
|
||||||
|
|
||||||
// const { players } = useGame();
|
|
||||||
|
|
||||||
const players = [
|
|
||||||
"bla",
|
|
||||||
"bli",
|
|
||||||
"blou"
|
|
||||||
]
|
|
||||||
|
|
||||||
console.log(players)
|
|
||||||
return (
|
|
||||||
<div style={{margin:'20px'}}>
|
|
||||||
<Tabs defaultActiveKey="0" id="uncontrolled-tab-example" className="mb-3">
|
|
||||||
{players.map((joueur, index) => (
|
|
||||||
<Tab key={index} eventKey={index.toString()} title={`${joueur} ${index + 1}`}>
|
|
||||||
<div className='deducDiv'>
|
|
||||||
<div className='sectionAccordion'>
|
|
||||||
<AccordionIndice instance={AgeIndice} head='Age' lang='fr'/>
|
|
||||||
</div>
|
|
||||||
<div className='sectionAccordion'>
|
|
||||||
<AccordionIndice instance={ColorIndice} head='Couleur de cheveux' lang='fr'/>
|
|
||||||
<AccordionIndice instance={ColorEdgesIndice} head='Couleur de cheveux voisine' lang='fr'/>
|
|
||||||
</div>
|
|
||||||
<div className='sectionAccordion'>
|
|
||||||
<AccordionIndice instance={SportIndice} head='Sport' lang='fr'/>
|
|
||||||
<AccordionIndice instance={NbSportIndice} head='Nombre de Sport' lang='fr'/>
|
|
||||||
</div>
|
|
||||||
<div className='sectionAccordion'>
|
|
||||||
<AccordionIndice instance={EdgesIndice} head='Caractéristique des voisin' lang='fr'/>
|
|
||||||
<AccordionIndice instance={NbEdgesIndice} head='Nombre de voisin' lang='fr'/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Tab>
|
|
||||||
))}
|
|
||||||
</Tabs>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DeducGrid;
|
|
@ -1,90 +1,123 @@
|
|||||||
/* Styles for the Winner and Indice section */
|
.head{
|
||||||
.head {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.leaderboard-header {
|
.leaderboard-header{
|
||||||
border: 2px solid;
|
|
||||||
border-color: #0064E0;
|
|
||||||
padding: 20px;
|
|
||||||
text-align: center;
|
|
||||||
border-radius: 0px 0px 10px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Styles for the Winner's details */
|
|
||||||
.winner-details {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
.winner-details img {
|
|
||||||
width: 75px;
|
width: fit-content;
|
||||||
height: 75px;
|
|
||||||
border-radius: 50%;
|
border-radius: 0px 0px 30px 30px;
|
||||||
margin-right: 10px;
|
border: solid;
|
||||||
}
|
border-width: 0 5px;
|
||||||
|
|
||||||
/* Styles for the Indice Display */
|
padding: 20px;
|
||||||
.indiceDisplay {
|
}
|
||||||
border: 2px solid whitesmoke;
|
|
||||||
border-radius: 10px;
|
.bottomEnd{
|
||||||
margin: 5px; /* Réduire la marge */
|
|
||||||
padding: 8px; /* Réduire le rembourrage */
|
|
||||||
box-shadow: 3px 3px 3px rgb(246, 246, 246); /* Réduire l'ombre */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Styles for the Losing Players Container */
|
|
||||||
.losingPlayersContainer {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
justify-content: space-around;
|
||||||
justify-content: space-evenly;
|
}
|
||||||
margin: 5px;
|
|
||||||
}
|
.winner{
|
||||||
|
|
||||||
/* Styles for individual Player Containers */
|
|
||||||
.playerContainer {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 30px;
|
}
|
||||||
margin-bottom: 30px;
|
|
||||||
border: 1px solid whitesmoke;
|
|
||||||
border-radius: 15px;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.soloContainer {
|
.playersContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%; /* Ajoutez cette ligne pour occuper toute la largeur */
|
/* padding-left: "5px"; */
|
||||||
}
|
|
||||||
|
width: 100px;
|
||||||
.solostat{
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playerContainer{
|
||||||
|
/* display: flex;
|
||||||
|
align-items: center; */
|
||||||
|
/* flex-direction: column; */
|
||||||
|
|
||||||
|
/* width: 300px; */
|
||||||
|
width: 30%;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
/* margin-bottom: 10px; */
|
||||||
|
|
||||||
border: solid 1px whitesmoke;
|
border: solid 1px whitesmoke;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
|
|
||||||
background-color: white;
|
background-color: white;
|
||||||
padding: 10px;
|
}
|
||||||
margin: 5px;
|
|
||||||
width: fit-content; /* Ajoutez cette ligne pour ajuster la largeur au contenu */
|
|
||||||
}
|
|
||||||
|
|
||||||
.center {
|
.losingPlayersContainer{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
|
||||||
|
margin: 10px 0;
|
||||||
|
|
||||||
|
max-width: 50%;
|
||||||
|
|
||||||
|
overflow-y: scroll;
|
||||||
|
max-height: 200px;
|
||||||
|
/* background-color: yellow; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.indiceDisplay{
|
||||||
|
border: solid 2px whitesmoke;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 0 15px 0 15px;
|
||||||
|
padding: 10px;
|
||||||
|
box-shadow: 5px 5px 5px rgb(246, 246, 246);
|
||||||
|
}
|
||||||
|
|
||||||
|
.SoloContainer{
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
|
||||||
|
border: solid 1px whitesmoke;
|
||||||
|
border-radius: 15px;
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
max-width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.indicesolo{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
|
||||||
|
/* margin: 10px 0; */
|
||||||
|
/* max-height: 200px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.solostat{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.solostat p {
|
||||||
|
border: solid 1px whitesmoke;
|
||||||
|
border-radius: 15px;
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Styles for the Graph Container */
|
#vis-graph {
|
||||||
#vis-graph {
|
|
||||||
height: 500px;
|
height: 500px;
|
||||||
margin: 5px;
|
margin: 50px;
|
||||||
border: 2px solid #ccc;
|
border: 2px solid #ccc;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
@ -1,46 +0,0 @@
|
|||||||
.lobbyMainContainer{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
background-color: white;
|
|
||||||
|
|
||||||
border: solid 1px whitesmoke;
|
|
||||||
border-radius: 15px;
|
|
||||||
box-shadow: 5px 5px 5px rgb(246, 246, 246);
|
|
||||||
|
|
||||||
width: 300px;
|
|
||||||
/* max-width: 300px; */
|
|
||||||
/* max-width: 20%; */
|
|
||||||
max-height: 200px;
|
|
||||||
|
|
||||||
padding: 20px;
|
|
||||||
margin: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lobbyMainContainer:hover{
|
|
||||||
background-color: whitesmoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lobbyList{
|
|
||||||
display: flex;
|
|
||||||
/* justify-content: space-around; */
|
|
||||||
/* columns: 4; */
|
|
||||||
flex-wrap: wrap;
|
|
||||||
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchLobby{
|
|
||||||
border: solid 1px whitesmoke;
|
|
||||||
border-radius: 15px;
|
|
||||||
padding: 15px;
|
|
||||||
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
h1{
|
|
||||||
margin: 50px !important;
|
|
||||||
font-family: "Raleway", sans-serif;
|
|
||||||
}
|
|
@ -1,175 +0,0 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
|
|
||||||
|
|
||||||
/* Style */
|
|
||||||
import './Lobbies.css';
|
|
||||||
import "../Style/Global.css"
|
|
||||||
import { useTheme } from '../Style/ThemeContext';
|
|
||||||
import LobbyContainer from '../Components/LobbyContainer';
|
|
||||||
import Player from '../model/Player';
|
|
||||||
import User from '../model/User';
|
|
||||||
import { socket } from '../SocketConfig';
|
|
||||||
import JSONParser from '../JSONParser';
|
|
||||||
import Person from '../model/Person';
|
|
||||||
import { useNavigationType } from 'react-router-dom';
|
|
||||||
import { FormattedMessage, useIntl } from 'react-intl';
|
|
||||||
|
|
||||||
class LobbyDataProps {
|
|
||||||
roomNum : string
|
|
||||||
headPlayer: Player
|
|
||||||
nbPlayer: number
|
|
||||||
started: boolean
|
|
||||||
|
|
||||||
constructor(roomNum: string, player: Player, nbPlayer: number, started: boolean){
|
|
||||||
this.roomNum = roomNum
|
|
||||||
this.headPlayer = player
|
|
||||||
this.nbPlayer = nbPlayer
|
|
||||||
this.started=started
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let cptNavigation = 0
|
|
||||||
|
|
||||||
function Lobbies() {
|
|
||||||
const theme=useTheme();
|
|
||||||
|
|
||||||
|
|
||||||
const [first, setFirst] = useState(true)
|
|
||||||
|
|
||||||
const [lobbyData, setLobbyData] = useState<LobbyDataProps[]>([])
|
|
||||||
|
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
|
||||||
|
|
||||||
const [showAvailable, setShowAvailable] = useState(true);
|
|
||||||
|
|
||||||
|
|
||||||
const handleShowAllClick = () => {
|
|
||||||
setShowAvailable(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleShowAvailableClick = () => {
|
|
||||||
setShowAvailable(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSetFirst = () => {
|
|
||||||
setFirst(false);
|
|
||||||
socket.emit("request lobbies");
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSetCptNavigation = () => {
|
|
||||||
cptNavigation++
|
|
||||||
|
|
||||||
if (cptNavigation % 2 >= 0 && navigationType.toString() === "POP") {
|
|
||||||
socket.emit("player quit");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const filteredLobbies = lobbyData.filter((lobby) =>
|
|
||||||
lobby.roomNum.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
||||||
lobby.headPlayer.pseudo.toLowerCase().includes(searchTerm.toLowerCase())
|
|
||||||
);
|
|
||||||
|
|
||||||
const filteredLobbiesToShow = showAvailable
|
|
||||||
? filteredLobbies.filter((lobby) => lobby.started == false && lobby.nbPlayer < 6) //* retire les lobbies pleins ou commencés
|
|
||||||
: filteredLobbies;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const setFirstData = (first: boolean) => {
|
|
||||||
setFirst(first)
|
|
||||||
}
|
|
||||||
|
|
||||||
const navigationType = useNavigationType();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
handleSetCptNavigation();
|
|
||||||
|
|
||||||
if (first){
|
|
||||||
handleSetFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
socket.on("request lobbies", (map) => {
|
|
||||||
const jsonMap = JSON.parse(map)
|
|
||||||
const tmpTab: LobbyDataProps[]=[]
|
|
||||||
|
|
||||||
for(const item of jsonMap){
|
|
||||||
tmpTab.push(new LobbyDataProps(item.key, JSONParser.JSONToPlayer(item.value.tab[0]), item.value.tab.length, item.value.started))
|
|
||||||
}
|
|
||||||
|
|
||||||
setLobbyData(tmpTab)
|
|
||||||
})
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
function createLobby(){
|
|
||||||
socket.emit("lobby created")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const intl = useIntl();
|
|
||||||
|
|
||||||
|
|
||||||
return(
|
|
||||||
<div style={{display:'flex', flexDirection:'column', alignItems:'center'}}>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className='searchLobby'
|
|
||||||
placeholder={intl.formatMessage({ id: 'placeholder.searchLobby' })}
|
|
||||||
value={searchTerm}
|
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
|
||||||
style={{width:'80%', margin:'10px'}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div style={{border:'solid 3px', borderColor:'lightgray', borderRadius:'20px', margin:'10px'}}>
|
|
||||||
<button
|
|
||||||
style={{
|
|
||||||
width:'120px',
|
|
||||||
border:'solid',
|
|
||||||
borderStyle:'none',
|
|
||||||
borderRadius: '15px 0px 0px 15px',
|
|
||||||
borderWidth: '2px',
|
|
||||||
padding: '10px 15px',
|
|
||||||
backgroundColor: !showAvailable ? 'white' : 'lightgray',
|
|
||||||
}}
|
|
||||||
onClick={handleShowAllClick}
|
|
||||||
>
|
|
||||||
<FormattedMessage id='lobbies.all'/>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
style={{
|
|
||||||
width:'120px',
|
|
||||||
border:'solid',
|
|
||||||
borderStyle:'none',
|
|
||||||
borderRadius: '0px 15px 15px 0px',
|
|
||||||
padding: '10px 15px',
|
|
||||||
backgroundColor: showAvailable ? 'white' : 'lightgray',
|
|
||||||
}}
|
|
||||||
onClick={handleShowAvailableClick}
|
|
||||||
>
|
|
||||||
<FormattedMessage id='lobbies.dispo'/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{filteredLobbiesToShow.length === 0 ? (
|
|
||||||
<button onClick={createLobby} className='ButtonNav' style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}><FormattedMessage id='play.create' /></button>
|
|
||||||
) : (
|
|
||||||
<div className="lobbyList">
|
|
||||||
{filteredLobbiesToShow.map((lobby, index) => (
|
|
||||||
<LobbyContainer
|
|
||||||
key={index}
|
|
||||||
roomNum={lobby.roomNum}
|
|
||||||
HeadPlayer={lobby.headPlayer}
|
|
||||||
nbPlayer={lobby.nbPlayer}
|
|
||||||
setFirst={setFirstData}
|
|
||||||
started={lobby.started}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Lobbies;
|
|
@ -1,270 +0,0 @@
|
|||||||
import React, { useEffect, useRef, useState } from 'react';
|
|
||||||
|
|
||||||
/* Context */
|
|
||||||
import { useAuth } from '../Contexts/AuthContext';
|
|
||||||
/* Style */
|
|
||||||
import './Play.css';
|
|
||||||
import { useTheme } from '../Style/ThemeContext';
|
|
||||||
|
|
||||||
/* Component */
|
|
||||||
import ButtonImgNav from "../Components/ButtonImgNav";
|
|
||||||
|
|
||||||
/* Img */
|
|
||||||
/* Icon */
|
|
||||||
import { socket } from '../SocketConfig';
|
|
||||||
import { NavigationType, useNavigate, useNavigationType } from 'react-router-dom';
|
|
||||||
import GameCreator from '../model/GameCreator';
|
|
||||||
import { useGame } from '../Contexts/GameContext';
|
|
||||||
import ScoreBoard from '../Components/ScoreBoard';
|
|
||||||
|
|
||||||
import defaultImg from "../res/img/Person.png"
|
|
||||||
|
|
||||||
/* Types */
|
|
||||||
import User from '../model/User';
|
|
||||||
import EnigmeDuJourCreator from '../model/EnigmeDuJourCreator';
|
|
||||||
import Stub from '../model/Stub';
|
|
||||||
|
|
||||||
import SessionService from '../services/SessionService';
|
|
||||||
import { loadImageAsync } from '../ImageHelper';
|
|
||||||
import { Overlay, ToggleButton, ToggleButtonGroup } from 'react-bootstrap';
|
|
||||||
import Button from 'react-bootstrap/Button';
|
|
||||||
import ButtonGroup from 'react-bootstrap/ButtonGroup';
|
|
||||||
import Lobbies from './Lobbies';
|
|
||||||
import {basePath} from "../AdressSetup"
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let cptNavigation = 0
|
|
||||||
|
|
||||||
|
|
||||||
function NewPlay() {
|
|
||||||
let first = true
|
|
||||||
|
|
||||||
const theme=useTheme()
|
|
||||||
const {isLoggedIn, login, user, setUserData, manager } = useAuth();
|
|
||||||
const {setDailyEnigmeData, setIndicesData, setPersonData, setPersonNetworkData, setGameStartData } = useGame()
|
|
||||||
|
|
||||||
const target = useRef(null);
|
|
||||||
|
|
||||||
const navigationType = useNavigationType()
|
|
||||||
cptNavigation++
|
|
||||||
if (cptNavigation % 2 == 0){
|
|
||||||
if (navigationType.toString() == "POP"){
|
|
||||||
first=true
|
|
||||||
socket.emit("player quit")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (user == null){
|
|
||||||
manager.userService.fetchUserInformation().then(([user, loggedIn]) =>{
|
|
||||||
if (user!=null){
|
|
||||||
if (loggedIn){
|
|
||||||
login()
|
|
||||||
setUserData(user)
|
|
||||||
socket.emit("join back game", user)
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
loadImageAsync(defaultImg).then((blob) => {
|
|
||||||
user.profilePicture=blob
|
|
||||||
setUserData(user)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
socket.emit("join back game", user)
|
|
||||||
}
|
|
||||||
}, [isLoggedIn]);
|
|
||||||
|
|
||||||
const [goBackRoom, setGoBackRoom] = useState(-1)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
socket.on("join back game", (room) => {
|
|
||||||
setGoBackRoom(room)
|
|
||||||
})
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
|
|
||||||
const [room, setRoom] = useState(null);
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
function createLobby(){
|
|
||||||
socket.emit("lobby created")
|
|
||||||
}
|
|
||||||
|
|
||||||
function launchMastermind(){
|
|
||||||
const [networkPerson, choosenPerson, choosenIndices] = GameCreator.CreateGame(user?.nbIndices || 3, user?.nbNodes || 25)
|
|
||||||
setPersonData(choosenPerson)
|
|
||||||
setPersonNetworkData(networkPerson)
|
|
||||||
setIndicesData(choosenIndices)
|
|
||||||
setIndicesData(choosenIndices)
|
|
||||||
setGameStartData(true)
|
|
||||||
navigate(`${basePath}/game?solo=true&daily=false`);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function launchEngimeJour(){
|
|
||||||
//* overlay
|
|
||||||
|
|
||||||
if (!showOverlay)setShowOverlay(true)
|
|
||||||
else setShowOverlay(true)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function launchTuto(){
|
|
||||||
navigate(`${basePath}/tutorial`);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const handleLobbyCreated = (newRoom: any) => {
|
|
||||||
setRoom(newRoom);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ajouter l'event listener
|
|
||||||
socket.on('lobby created', handleLobbyCreated);
|
|
||||||
|
|
||||||
// Nettoyer l'event listener lors du démontage du composant
|
|
||||||
return () => {
|
|
||||||
socket.off('lobby created', handleLobbyCreated);
|
|
||||||
};
|
|
||||||
|
|
||||||
}, []); // Aucune dépendance ici
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (room !== null) {
|
|
||||||
const nouvelleURL = `/lobby?room=${room}`;
|
|
||||||
navigate(`${basePath}${nouvelleURL}`)
|
|
||||||
}
|
|
||||||
}, [room, navigate]);
|
|
||||||
|
|
||||||
const goBack = () => {
|
|
||||||
navigate(`${basePath}/lobby?room=${goBackRoom}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const [showOverlay, setShowOverlay] = useState(false);
|
|
||||||
const [selectedDifficulty, setSelectedDifficulty] = useState(null);
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
const handleDifficultyChange = (value) => {
|
|
||||||
setSelectedDifficulty(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleStartEasyGame = () => {
|
|
||||||
|
|
||||||
//* Mode facile
|
|
||||||
//todo différencier les deux
|
|
||||||
const [networkPerson, choosenPerson, choosenIndices] = GameCreator.CreateGame(user?.nbIndices || 3, user?.nbNodes || 25)
|
|
||||||
setPersonData(choosenPerson)
|
|
||||||
setPersonNetworkData(networkPerson)
|
|
||||||
setIndicesData(choosenIndices)
|
|
||||||
setIndicesData(choosenIndices)
|
|
||||||
setGameStartData(true)
|
|
||||||
navigate(`${basePath}/game?solo=true&daily=true&difficulty=easy`);
|
|
||||||
setShowOverlay(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleStartMediumGame = () => {
|
|
||||||
|
|
||||||
//* Mode facile
|
|
||||||
//todo différencier les deux
|
|
||||||
const [networkPerson, choosenPerson, choosenIndices] = GameCreator.CreateGame(user?.nbIndices || 3, user?.nbNodes || 25)
|
|
||||||
setPersonData(choosenPerson)
|
|
||||||
setPersonNetworkData(networkPerson)
|
|
||||||
setIndicesData(choosenIndices)
|
|
||||||
setGameStartData(true)
|
|
||||||
|
|
||||||
|
|
||||||
navigate(`${basePath}/game?solo=true&daily=true&difficulty=intermediate`);
|
|
||||||
if (first){
|
|
||||||
first = false
|
|
||||||
const map = EnigmeDuJourCreator.createEnigme(networkPerson, choosenIndices, choosenPerson, Stub.GenerateIndice())
|
|
||||||
setDailyEnigmeData(map)
|
|
||||||
}
|
|
||||||
setShowOverlay(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleStartHardGame = () => {
|
|
||||||
//* Mode difficile
|
|
||||||
|
|
||||||
//todo différencier les deux
|
|
||||||
const [networkPerson, choosenPerson, choosenIndices] = GameCreator.CreateGame(user?.nbIndices || 3, user?.nbNodes || 25)
|
|
||||||
setPersonData(choosenPerson)
|
|
||||||
setPersonNetworkData(networkPerson)
|
|
||||||
setIndicesData(choosenIndices)
|
|
||||||
setGameStartData(true)
|
|
||||||
if (first){
|
|
||||||
first = false
|
|
||||||
const map = EnigmeDuJourCreator.createEnigme(networkPerson, choosenIndices, choosenPerson, Stub.GenerateIndice())
|
|
||||||
setDailyEnigmeData(map)
|
|
||||||
}
|
|
||||||
navigate(`${basePath}/game?solo=true&daily=true&difficulty=hard`);
|
|
||||||
setShowOverlay(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if (goBackRoom != -1){
|
|
||||||
// var returnVisibility = "visible"
|
|
||||||
// }
|
|
||||||
// else{
|
|
||||||
// var returnVisibility = "hidden"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const returnVisibility: Visibility = goBackRoom !== -1 ? "visible" : "hidden";
|
|
||||||
|
|
||||||
const returnVisibility = goBackRoom !== -1 ? "block" : "none" ;
|
|
||||||
|
|
||||||
return (
|
|
||||||
|
|
||||||
<div className="MainContainer">
|
|
||||||
<div className="leftContainer">
|
|
||||||
{/* Boutons pour jouer */}
|
|
||||||
<div className='NewbuttonGroupVertical'>
|
|
||||||
<button onClick={launchMastermind} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> <FormattedMessage id="play.jouerseul"/> </button>
|
|
||||||
<button ref={target} onClick={launchEngimeJour} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> <FormattedMessage id="play.enigme"/> </button>
|
|
||||||
<Overlay show={showOverlay} target={target.current} placement="bottom" rootClose={true} rootCloseEvent='click' onHide={() => setShowOverlay(false)}>
|
|
||||||
{({ placement, arrowProps, show: _show, popper, ...props }) => (
|
|
||||||
<div
|
|
||||||
{...props}
|
|
||||||
style={{
|
|
||||||
backgroundColor: theme.colors.secondary,
|
|
||||||
padding: '2px 10px',
|
|
||||||
borderRadius: 3,
|
|
||||||
...props.style,
|
|
||||||
}}>
|
|
||||||
|
|
||||||
<ButtonGroup aria-label="difficulty">
|
|
||||||
<Button onClick={handleStartEasyGame}><FormattedMessage id='play.enigme.easy'/></Button>
|
|
||||||
<Button onClick={handleStartMediumGame}><FormattedMessage id='play.enigme.medium'/></Button>
|
|
||||||
<Button onClick={handleStartHardGame}><FormattedMessage id='play.enigme.hard'/></Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Overlay>
|
|
||||||
|
|
||||||
<button onClick={createLobby} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> <FormattedMessage id='play.create'/> </button>
|
|
||||||
<button onClick={launchTuto} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> <FormattedMessage id='play.tuto'/> </button>
|
|
||||||
<button onClick={goBack} className="ButtonNavRejoin" style={{ display:returnVisibility}}><FormattedMessage id='play.return'/> </button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Lobbies */}
|
|
||||||
<div style={{border:'solid 1px lightgray', borderRadius:'15px', marginTop:'20px', minHeight:'400px'}}>
|
|
||||||
<Lobbies/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='rightContainer'>
|
|
||||||
{user && <ScoreBoard Player={user}/>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default NewPlay;
|
|
@ -0,0 +1,107 @@
|
|||||||
|
.upperInfo{
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
width: 30%;
|
||||||
|
|
||||||
|
border-radius: 0px 0px 30px 30px;
|
||||||
|
border: solid;
|
||||||
|
border-width: 2px 5px;
|
||||||
|
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
font-size: 30px;
|
||||||
|
|
||||||
|
top: 20px;;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mainDiv{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.paramDiv{
|
||||||
|
z-index: 1;
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#graphDiv{
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bottom-container{
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
background-color: white;
|
||||||
|
padding:20px;
|
||||||
|
border-radius: 20px 20px 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nbLaps{
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
left: 10px;
|
||||||
|
top :50px;
|
||||||
|
|
||||||
|
margin: 10px 20px;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
border: solid 2px;
|
||||||
|
|
||||||
|
font-size: 30px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endgamebutton{
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
bottom: 0;
|
||||||
|
right: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upperInfo,
|
||||||
|
#bottom-container,
|
||||||
|
.menuGame {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuGame{
|
||||||
|
display: flex;
|
||||||
|
align-items: space-between;
|
||||||
|
justify-content: end;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
top:30%;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuGame Button {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button{
|
||||||
|
/*background-color: #85C9C2;*/
|
||||||
|
|
||||||
|
border: solid 2px #85C9C2;
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
|
width: 100px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
@ -0,0 +1,236 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import Switch from "react-switch";
|
||||||
|
|
||||||
|
/* Style */
|
||||||
|
import "./SoloGame.css"
|
||||||
|
import {useTheme} from '../Style/ThemeContext'
|
||||||
|
/* Component */
|
||||||
|
import GraphContainer from '../Components/GraphContainer';
|
||||||
|
import ChoiceBar from '../Components/ChoiceBar';
|
||||||
|
import ButtonImgNav from '../Components/ButtonImgNav';
|
||||||
|
import PersonStatus from '../Components/PersonStatus';
|
||||||
|
import PlayerList from '../Components/PlayerList';
|
||||||
|
|
||||||
|
/* Icon */
|
||||||
|
import Leave from "../res/icon/leave.png";
|
||||||
|
import Param from "../res/icon/param.png";
|
||||||
|
import Replay from "../res/icon/replay.png";
|
||||||
|
import Info from "../res/icon/infoGreen.png";
|
||||||
|
import Check from "../res/icon/checkboxGreen.png";
|
||||||
|
import Alpha from "../res/GreekLetters/alphaW.png";
|
||||||
|
|
||||||
|
/* nav */
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
/* Boostrap */
|
||||||
|
import Button from 'react-bootstrap/Button';
|
||||||
|
import Offcanvas from 'react-bootstrap/Offcanvas';
|
||||||
|
|
||||||
|
/* Model */
|
||||||
|
import Stub from '../model/Stub';
|
||||||
|
import { HiLanguage } from 'react-icons/hi2';
|
||||||
|
import { Nav, NavDropdown } from 'react-bootstrap';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
import Color from '../model/Color';
|
||||||
|
import TurnBar from '../Components/TurnBar';
|
||||||
|
import { useGame } from '../Contexts/GameContext';
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
const SoloGame = ({locale, changeLocale}) => {
|
||||||
|
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
|
const [showChoiceBar, setShowChoiceBar] = useState(false);
|
||||||
|
const [showTurnBar, setShowTurnBar] = useState(false);
|
||||||
|
|
||||||
|
|
||||||
|
const handleNodeClick = (shouldShowChoiceBar: boolean) => {
|
||||||
|
setShowChoiceBar(shouldShowChoiceBar);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleShowTurnBar = (shouldShowTurnBar: boolean) => {
|
||||||
|
setShowTurnBar(shouldShowTurnBar);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* offcanvas */
|
||||||
|
//? faire une fonction pour close et show en fonction de l'etat du canva ?
|
||||||
|
//? comment faire pour eviter la recopie de tout le code a chaque canvas boostrap ?
|
||||||
|
const [show, setShow] = useState(false);
|
||||||
|
const handleClose = () => setShow(false);
|
||||||
|
const handleShow = () => setShow(true);
|
||||||
|
|
||||||
|
// const [showP, setShowP] = useState(false);
|
||||||
|
// const handleCloseP = () => setShowP(false);
|
||||||
|
// const handleShowP = () => setShowP(true);
|
||||||
|
|
||||||
|
const [showS, setShowS] = useState(false);
|
||||||
|
const handleCloseS = () => setShowS(false);
|
||||||
|
const handleShowS = () => setShowS(true);
|
||||||
|
|
||||||
|
const handleChange = () => {
|
||||||
|
if (show){
|
||||||
|
handleClose()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleShow()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// const handleChangeP = () => {
|
||||||
|
// if (showP){
|
||||||
|
// handleCloseP()
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// handleShowP()
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
const handleChangeS = () => {
|
||||||
|
if (showS){
|
||||||
|
handleCloseS()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleShowS()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Windows open */
|
||||||
|
//@ts-ignore
|
||||||
|
const openInNewTab = (url) => { //! avec url ==> dangereux
|
||||||
|
window.open(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
const [SwitchEnabled, setSwitchEnabled] = useState(false)
|
||||||
|
const indices = Stub.GenerateIndice()
|
||||||
|
const { indice, players } = useGame();
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="mainDiv">
|
||||||
|
<TurnBar text="je suis dans la page solo"/>
|
||||||
|
<div id='graphDiv'>
|
||||||
|
{/* <GraphContainer onNodeClick={handleNodeClick} handleShowTurnBar={handleShowTurnBar} FromSolo={true}/> */}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='nbLaps' style={{
|
||||||
|
backgroundColor: theme.colors.primary,
|
||||||
|
borderColor: theme.colors.secondary
|
||||||
|
}}>
|
||||||
|
Tour : 5
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='paramDiv'>
|
||||||
|
<button className='button'
|
||||||
|
style={{
|
||||||
|
backgroundColor: theme.colors.primary,
|
||||||
|
borderColor: theme.colors.secondary
|
||||||
|
}}
|
||||||
|
onClick={handleChangeS}>
|
||||||
|
<img src={Param} alt="paramètres" height='40'/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='menuGame'>
|
||||||
|
<Link to='/info' target='_blank'>
|
||||||
|
<button className='button'
|
||||||
|
style={{
|
||||||
|
backgroundColor: theme.colors.primary,
|
||||||
|
borderColor: theme.colors.secondary
|
||||||
|
}}>
|
||||||
|
<img src={Info} alt="info" height="40"/>
|
||||||
|
</button>
|
||||||
|
</Link>
|
||||||
|
{/* <button className='button' onClick={() => openInNewTab('http://localhost:3000/play')}> //! avec url =={'>'} dangereux
|
||||||
|
<img src={Check} alt="check" height="40"/>
|
||||||
|
</button> */}
|
||||||
|
|
||||||
|
<Link to='/info' target='_blank'>
|
||||||
|
<button className='button'
|
||||||
|
style={{
|
||||||
|
backgroundColor: theme.colors.primary,
|
||||||
|
borderColor: theme.colors.secondary
|
||||||
|
}}>
|
||||||
|
<img src={Check} alt="check" height="40"/>
|
||||||
|
</button>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<button className='button' onClick={handleChange}
|
||||||
|
style={{
|
||||||
|
backgroundColor: theme.colors.primary,
|
||||||
|
borderColor: theme.colors.secondary
|
||||||
|
}}>
|
||||||
|
<img src={Alpha} alt="indice" height="40"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <Offcanvas show={showP}
|
||||||
|
onHide={handleCloseP}>
|
||||||
|
<Offcanvas.Header closeButton>
|
||||||
|
<Offcanvas.Title>Joueurs</Offcanvas.Title>
|
||||||
|
<h3>Il y a {players.length} joueurs</h3>
|
||||||
|
</Offcanvas.Header>
|
||||||
|
<Offcanvas.Body>
|
||||||
|
<PlayerList players={players} />
|
||||||
|
</Offcanvas.Body>
|
||||||
|
</Offcanvas> */}
|
||||||
|
|
||||||
|
<Offcanvas show={show}
|
||||||
|
onHide={handleClose}
|
||||||
|
placement='end'
|
||||||
|
scroll={true}
|
||||||
|
backdrop={false}
|
||||||
|
style={{ height: '20%', width: '25%', top: '60vh' }}>
|
||||||
|
<Offcanvas.Header closeButton>
|
||||||
|
<Offcanvas.Title>Indice</Offcanvas.Title>
|
||||||
|
</Offcanvas.Header>
|
||||||
|
<Offcanvas.Body>
|
||||||
|
{/* Possède les cheveux noir <u>ou</u> joue au basket */}
|
||||||
|
{indice?.ToString(locale)}
|
||||||
|
</Offcanvas.Body>
|
||||||
|
</Offcanvas>
|
||||||
|
|
||||||
|
{
|
||||||
|
//* canva pour les paramètres
|
||||||
|
}
|
||||||
|
<Offcanvas show={showS}
|
||||||
|
onHide={handleCloseS}
|
||||||
|
placement='top'
|
||||||
|
style={{height: '30%', width: '30%', left: '70%' }}>
|
||||||
|
<Offcanvas.Header closeButton>
|
||||||
|
<Offcanvas.Title><img src={Param} alt='param'/> Paramètres</Offcanvas.Title>
|
||||||
|
</Offcanvas.Header>
|
||||||
|
<Offcanvas.Body>
|
||||||
|
<Nav className="me-auto">
|
||||||
|
<NavDropdown
|
||||||
|
title={<span><HiLanguage/> Language </span>}
|
||||||
|
className="navbar-title" id="basic-nav-dropdown">
|
||||||
|
<NavDropdown.Item onClick={() => changeLocale('fr')}>
|
||||||
|
<FormattedMessage id="languageSelector.french"/>
|
||||||
|
</NavDropdown.Item>
|
||||||
|
<NavDropdown.Item onClick={() => changeLocale('en')}>
|
||||||
|
<FormattedMessage id="languageSelector.english"/>
|
||||||
|
</NavDropdown.Item>
|
||||||
|
</NavDropdown>
|
||||||
|
</Nav>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<Switch checked={SwitchEnabled} onChange={setSwitchEnabled}/>
|
||||||
|
<p>Afficher les noeuds possibles</p>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
</Offcanvas.Body>
|
||||||
|
</Offcanvas>
|
||||||
|
<div id="bottom-container">
|
||||||
|
{showChoiceBar && <ChoiceBar />}
|
||||||
|
</div>
|
||||||
|
{/*
|
||||||
|
<div id="endgamebutton" > {/* tmp
|
||||||
|
<ButtonImgNav dest="/endgame" img={Leave} text='endgame'/>
|
||||||
|
</div>
|
||||||
|
*/}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default SoloGame;
|
@ -1,754 +0,0 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import Switch from "react-switch";
|
|
||||||
import {saveAs} from "file-saver"
|
|
||||||
|
|
||||||
/* Style */
|
|
||||||
import "./InGame.css"
|
|
||||||
import {useTheme} from '../Style/ThemeContext'
|
|
||||||
/* Component */
|
|
||||||
import GraphContainer from '../Components/GraphContainer';
|
|
||||||
import PlayerList from '../Components/PlayerList';
|
|
||||||
import TurnBar from '../Components/TurnBar';
|
|
||||||
|
|
||||||
/* Icon */
|
|
||||||
import Param from "../res/icon/param.png";
|
|
||||||
import Info from "../res/icon/infoGreen.png";
|
|
||||||
import Check from "../res/icon/checkboxGreen.png";
|
|
||||||
import MGlass from "../res/icon/magnifying-glass.png";
|
|
||||||
import Reset from "../res/icon/reset.png";
|
|
||||||
import Oeye from "../res/icon/eye.png";
|
|
||||||
import Ceye from "../res/icon/hidden.png";
|
|
||||||
import ImgBot from "../res/img/bot.png";
|
|
||||||
|
|
||||||
import detective from "../res/img/tuto/tuto-detective.jpg";
|
|
||||||
import ava from "../res/img/tuto/tuto-ava2.png";
|
|
||||||
import indicetxt from "../res/img/tuto/tuto-indiceTxt.png"
|
|
||||||
import rep from "../res/img/tuto/tuto-rep.png";
|
|
||||||
import joueurs from "../res/img/tuto/tuto-joueurs.png";
|
|
||||||
import graph from "../res/img/tuto/tuto-graph.png";
|
|
||||||
|
|
||||||
import step1 from "../res/img/tuto/tuto2-1.png";
|
|
||||||
import step2 from "../res/img/tuto/tuto2-2.png";
|
|
||||||
import step3 from "../res/img/tuto/tuto2-3.png";
|
|
||||||
import step4 from "../res/img/tuto/tuto2-4.png";
|
|
||||||
import step5 from "../res/img/tuto/tuto2-5.png";
|
|
||||||
import step6 from "../res/img/tuto/tuto2-6.png";
|
|
||||||
|
|
||||||
/* nav */
|
|
||||||
import { Link, Navigate, useNavigate, useNavigationType } from 'react-router-dom';
|
|
||||||
|
|
||||||
/* Boostrap */
|
|
||||||
import Offcanvas from 'react-bootstrap/Offcanvas';
|
|
||||||
import Modal from 'react-bootstrap/Modal';
|
|
||||||
import Card from 'react-bootstrap/Card';
|
|
||||||
import Button from 'react-bootstrap/Button';
|
|
||||||
|
|
||||||
/* Model */
|
|
||||||
import Stub from '../model/Stub';
|
|
||||||
import { useGame } from '../Contexts/GameContext';
|
|
||||||
import { socket } from '../SocketConfig';
|
|
||||||
import { Network } from 'vis-network';
|
|
||||||
import {generateLatexCode, generateLatexCodeEnigme} from '../Script/LatexScript';
|
|
||||||
import Pair from '../model/Pair';
|
|
||||||
import Indice from '../model/Indices/Indice';
|
|
||||||
import {basePath} from "../AdressSetup"
|
|
||||||
import TutorialGraph from '../Components/TutorialGraph';
|
|
||||||
import { useAuth } from '../Contexts/AuthContext';
|
|
||||||
import EasyBot from '../model/EasyBot';
|
|
||||||
import { set } from 'lodash';
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
|
|
||||||
let cptNavigation = 0
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
const Tutorial = ({locale, changeLocale}) => {
|
|
||||||
const {personNetwork, person, indices, players, setPlayersData, indice, actualPlayerIndex} = useGame()
|
|
||||||
const {user} = useAuth()
|
|
||||||
|
|
||||||
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
const navigate = useNavigate()
|
|
||||||
|
|
||||||
const [greyForEveryone, setGreyForEveryone] = useState<() => void>(() => {});
|
|
||||||
|
|
||||||
const setGreyForEveryoneData = (func: () => void) => {
|
|
||||||
setGreyForEveryone(func)
|
|
||||||
}
|
|
||||||
|
|
||||||
const navigationType = useNavigationType()
|
|
||||||
cptNavigation++
|
|
||||||
if (cptNavigation % 2 == 0){
|
|
||||||
if (navigationType.toString() == "POP"){
|
|
||||||
socket.emit("player quit")
|
|
||||||
navigate(`${basePath}/`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//* Historique
|
|
||||||
const [history, setHistory] = useState<string[]>([]);
|
|
||||||
const [showLast, setShowLast] = useState(false)
|
|
||||||
const [askedWrong, setAskedWrong] = useState(false)
|
|
||||||
const [importToPdf, setImportToPdf] = useState(false)
|
|
||||||
const [importToJSON, setImportToJSON] = useState(false)
|
|
||||||
const [tutoStep, setTutoStep] = useState(0)
|
|
||||||
|
|
||||||
const setTutoStepData = (step: number) => {
|
|
||||||
setTutoStep(step)
|
|
||||||
}
|
|
||||||
|
|
||||||
const setImportToJSONData = (imp: boolean) => {
|
|
||||||
setImportToJSON(imp)
|
|
||||||
}
|
|
||||||
|
|
||||||
const setImportToPdfData = (imp: boolean) => {
|
|
||||||
setImportToPdf(imp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour ajouter un élément à l'historique
|
|
||||||
const addToHistory = (message: string) => {
|
|
||||||
setHistory(prevHistory => [...prevHistory, message]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const setShowLastData = () =>{
|
|
||||||
setLastVisible(!showLast);
|
|
||||||
setShowLast(!showLast);
|
|
||||||
}
|
|
||||||
|
|
||||||
const setAskedWrongData = (askedWrong: boolean) => {
|
|
||||||
setAskedWrong(askedWrong)
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const historyContainer = document.getElementById('history-container');
|
|
||||||
if (historyContainer) {
|
|
||||||
historyContainer.scrollTop = historyContainer.scrollHeight;
|
|
||||||
}
|
|
||||||
}, [history]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (user == null){
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setPlayersData([user, new EasyBot("Scooby-Doo", "Scooby-Doo", ImgBot), new EasyBot("Batman", "Batman", ImgBot)])
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const [showChoiceBar, setShowChoiceBar] = useState(false);
|
|
||||||
const [showTurnBar, setShowTurnBar] = useState(false);
|
|
||||||
const [turnBarText, setTurnBarText] = useState("");
|
|
||||||
const [playerTouched, setPlayerTouched] = useState(-2)
|
|
||||||
const [playerIndex, setPlayerIndex] = useState(-2)
|
|
||||||
|
|
||||||
|
|
||||||
const [network, setNetwork] = useState<Network | null>(null)
|
|
||||||
const [networkEnigme, setNetworkEnigme] = useState<Map<number, Pair<Indice, boolean>[]> | null>(null)
|
|
||||||
|
|
||||||
const setNetworkData = (network: Network) => {
|
|
||||||
setNetwork(network)
|
|
||||||
}
|
|
||||||
|
|
||||||
const setNetworkEnigmeData = (networkEnigme: Map<number, Pair<Indice, boolean>[]>) => {
|
|
||||||
setNetworkEnigme(networkEnigme)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleNodeClick = (shouldShowChoiceBar: boolean) => {
|
|
||||||
setShowChoiceBar(shouldShowChoiceBar);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSetPlayerTouched = (newPlayerTouched: number) => {
|
|
||||||
setPlayerTouched(newPlayerTouched);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const handleShowTurnBar = (shouldShowTurnBar: boolean) => {
|
|
||||||
setShowTurnBar(shouldShowTurnBar);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTurnBarTextChange = (newTurnBarText: string) =>{
|
|
||||||
setTurnBarText(newTurnBarText)
|
|
||||||
}
|
|
||||||
|
|
||||||
const setPlayerIndexData = (playerIndex: number) => {
|
|
||||||
setPlayerIndex(playerIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const resetGraph = () => {
|
|
||||||
setisLoading(true);
|
|
||||||
socket.emit("reset graph", socket.id)
|
|
||||||
setTimeout(() => {
|
|
||||||
setisLoading(false);
|
|
||||||
}, 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* offcanvas */
|
|
||||||
//? faire une fonction pour close et show en fonction de l'etat du canva ?
|
|
||||||
//? comment faire pour eviter la recopie de tout le code a chaque canvas boostrap ?
|
|
||||||
const [show, setShow] = useState(false);
|
|
||||||
const handleClose = () => setShow(false);
|
|
||||||
const handleShow = () => setShow(true);
|
|
||||||
|
|
||||||
const [showP, setShowP] = useState(false);
|
|
||||||
const handleCloseP = () => setShowP(false);
|
|
||||||
const handleShowP = () => setShowP(true);
|
|
||||||
|
|
||||||
const [showS, setShowS] = useState(false);
|
|
||||||
const handleCloseS = () => setShowS(false);
|
|
||||||
const handleShowS = () => setShowS(true);
|
|
||||||
|
|
||||||
const [cptTour, setcptTour] = useState(0);
|
|
||||||
|
|
||||||
const [LastVisible, setLastVisible] = useState(false);
|
|
||||||
|
|
||||||
const [isLoading, setisLoading] = useState(false);
|
|
||||||
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
const changecptTour = (newcptTour) => {
|
|
||||||
setcptTour(newcptTour);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleChange = () => {
|
|
||||||
if (show){
|
|
||||||
handleClose()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
handleShow()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleChangeS = () => {
|
|
||||||
if (showS){
|
|
||||||
handleCloseS()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
handleShowS()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const eye = LastVisible ? Oeye : Ceye; //icon que l'on affiche pour l'oeil : fermé ou ouvert.
|
|
||||||
|
|
||||||
/* Windows open */
|
|
||||||
//@ts-ignore
|
|
||||||
const openInNewTab = (url) => { //! avec url ==> dangereux
|
|
||||||
window.open(url);
|
|
||||||
};
|
|
||||||
|
|
||||||
const [SwitchEnabled, setSwitchEnabled] = useState(false)
|
|
||||||
const allIndices = Stub.GenerateIndice()
|
|
||||||
|
|
||||||
const nbPlayer = players.length;
|
|
||||||
const navdeduc = 'deduc?actualId=' + actualPlayerIndex + '&nbPlayer=' + nbPlayer;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//* gestion demo */
|
|
||||||
const [showM, setShowM] = useState(false);
|
|
||||||
const [showTuto2, setShowTuto2] = useState(false);
|
|
||||||
const [showTuto21, setShowTuto21] = useState(false);
|
|
||||||
const [showTuto22, setShowTuto22] = useState(false);
|
|
||||||
const [showTuto3, setShowTuto3] = useState(false);
|
|
||||||
|
|
||||||
const handleCloseM = () => {
|
|
||||||
setShowM(false);
|
|
||||||
handleShowHelp()
|
|
||||||
}
|
|
||||||
const handleShowM = () => setShowM(true);
|
|
||||||
|
|
||||||
const handleCloseHelp = () => {
|
|
||||||
switch(tutoStep){
|
|
||||||
case 0:
|
|
||||||
setShowTuto2(false);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
setShowTuto21(false);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
setShowTuto22(false);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
setShowTuto3(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const handleShowHelp = () => {
|
|
||||||
switch(tutoStep){
|
|
||||||
case 0:
|
|
||||||
setShowTuto2(true);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
setShowTuto21(true);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
setShowTuto22(true);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
setShowTuto3(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const handleCloseTuto2 = () => setShowTuto2(false);
|
|
||||||
const handleShowTuto2 = () => setShowTuto2(true);
|
|
||||||
|
|
||||||
const handleCloseTuto21 = () => setShowTuto21(false);
|
|
||||||
const handleShowTuto21 = () => setShowTuto21(true);
|
|
||||||
|
|
||||||
const handleCloseTuto22 = () => setShowTuto22(false);
|
|
||||||
const handleShowTuto22 = () => setShowTuto22(true);
|
|
||||||
|
|
||||||
const handleCloseTuto3 = () => setShowTuto3(false);
|
|
||||||
const handleShowTuto3 = () => setShowTuto3(true);
|
|
||||||
|
|
||||||
|
|
||||||
const [step, setStep] = useState(-1);
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
const displayModalstep = (step: number) => {
|
|
||||||
//* for step 2
|
|
||||||
setStep(0); // remise a 0 de step
|
|
||||||
switch(step) {
|
|
||||||
case 1:
|
|
||||||
setShowTuto21(true);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
setShowTuto22(true);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
setShowTuto3(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
handleShowM();
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div id="mainDiv">
|
|
||||||
{showTurnBar && <TurnBar text={turnBarText}/>}
|
|
||||||
<div id='graphDiv'>
|
|
||||||
<TutorialGraph tutoStep={tutoStep}
|
|
||||||
setTutoStep={setTutoStepData}
|
|
||||||
handleShowTurnBar={handleShowTurnBar}
|
|
||||||
handleTurnBarTextChange={handleTurnBarTextChange}
|
|
||||||
addToHistory={addToHistory}
|
|
||||||
setPlayerTouched={handleSetPlayerTouched}
|
|
||||||
playerTouched={playerTouched}
|
|
||||||
setNetwork={setNetworkData}
|
|
||||||
showLast={showLast}
|
|
||||||
setPlayerIndex={setPlayerIndexData}
|
|
||||||
setGreyForEveryone={setGreyForEveryoneData}
|
|
||||||
displayModalstep={displayModalstep}/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='historique' id="history-container">
|
|
||||||
{history.map((item, index) => (
|
|
||||||
<div key={index}>{item}</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div className='menuGame'>
|
|
||||||
{/* <Button variant="primary" onClick={handleShowM}>
|
|
||||||
tuto 1
|
|
||||||
</Button>
|
|
||||||
<Button variant="primary" onClick={handleShowTuto2} disabled={tuto1disable}>
|
|
||||||
tuto 2
|
|
||||||
</Button> */}
|
|
||||||
|
|
||||||
<Button variant="primary" onClick={handleShowHelp}>
|
|
||||||
<FormattedMessage id='aide'/>
|
|
||||||
</Button>
|
|
||||||
<Link to={`${basePath}/info`} target='_blank'>
|
|
||||||
<button className='button'
|
|
||||||
style={{
|
|
||||||
backgroundColor: theme.colors.tertiary,
|
|
||||||
borderColor: theme.colors.secondary
|
|
||||||
}}>
|
|
||||||
<img src={Info} alt="info" height="40"/>
|
|
||||||
</button>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<button className='button' onClick={handleChange}
|
|
||||||
style={{
|
|
||||||
backgroundColor: theme.colors.tertiary,
|
|
||||||
borderColor: theme.colors.secondary
|
|
||||||
}}>
|
|
||||||
<img src={MGlass} alt="indice" height="40"/>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button className='button' onClick={setShowLastData}
|
|
||||||
style={{
|
|
||||||
backgroundColor: theme.colors.tertiary,
|
|
||||||
borderColor: theme.colors.secondary
|
|
||||||
}}>
|
|
||||||
<img src={ eye } alt="indice" height="40"/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div className='playerlistDiv'>
|
|
||||||
<PlayerList players={players} setPlayerTouched={handleSetPlayerTouched} playerTouched={playerTouched} playerIndex={playerIndex} askedWrong={askedWrong} greyForEveryone={greyForEveryone}/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<Offcanvas show={show}
|
|
||||||
onHide={handleClose}
|
|
||||||
placement='end'
|
|
||||||
scroll={true}
|
|
||||||
backdrop={false}
|
|
||||||
style={{ height: '20%', width: '25%', top: '60vh' }}>
|
|
||||||
<Offcanvas.Header closeButton>
|
|
||||||
<Offcanvas.Title><FormattedMessage id='indice'/></Offcanvas.Title>
|
|
||||||
</Offcanvas.Header>
|
|
||||||
<Offcanvas.Body>
|
|
||||||
{indice?.ToString(locale)}
|
|
||||||
</Offcanvas.Body>
|
|
||||||
</Offcanvas>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Modal
|
|
||||||
show={showM}
|
|
||||||
onHide={handleCloseM}
|
|
||||||
backdrop="static"
|
|
||||||
keyboard={false}
|
|
||||||
size="lg"
|
|
||||||
style={{ maxHeight: '100vh'}}>
|
|
||||||
<Modal.Header>
|
|
||||||
<Modal.Title><FormattedMessage id='tutorial.title'/></Modal.Title>
|
|
||||||
</Modal.Header>
|
|
||||||
<Modal.Body style={{ display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
|
|
||||||
{step === -1 && (
|
|
||||||
<Card style={{ width: '90%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Img variant="top" src={detective} style={{width:'300px', height:'300px'}}/>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title> <FormattedMessage id='tuto.title.1'/> </Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.1.1'/> <br/>
|
|
||||||
<FormattedMessage id='tuto.txt.1.2'/> <br/>
|
|
||||||
<FormattedMessage id='tuto.txt.1.3'/> <br/>
|
|
||||||
<FormattedMessage id='tuto.txt.1.4'/> <br/>
|
|
||||||
<FormattedMessage id='tuto.txt.1.5'/> <br/>
|
|
||||||
<i><FormattedMessage id='tuto.txt.1.6'/></i>
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
{step === 0 && (
|
|
||||||
<Card style={{ width: '90%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Img variant="top" src={ava} style={{width:'300px', height:'300px'}}/>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title> <FormattedMessage id='tuto.title.2'/> </Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.2.1'/>
|
|
||||||
<br />
|
|
||||||
<FormattedMessage id='tuto.txt.2.2' /><b>Ava</b><FormattedMessage id='tuto.txt.2.2.1'/><b>40 <FormattedMessage id='age_indice_end'/></b><FormattedMessage id='tuto.txt.2.2.2'/><b><FormattedMessage id='basketball'/></b><FormattedMessage id='tuto.txt.2.2.3'/><b><FormattedMessage id='tennis'/></b><FormattedMessage id='tuto.txt.2.2.4'/><b><FormattedMessage id='redhead'/></b><FormattedMessage id='tuto.txt.2.2.5'/><b>2 <FormattedMessage id='nb_friends_indice_end'/></b> : Carter <FormattedMessage id='and'/> Liam.
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 1 && (
|
|
||||||
<Card style={{ width: '90%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Img variant="top" src={indicetxt} style={{width:'300px', height:'auto'}}/>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title><FormattedMessage id='tuto.title.3'/></Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.3.1'/>
|
|
||||||
<br />
|
|
||||||
"<u><FormattedMessage id='tuto.txt.3.2'/></u>".
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 3 && (
|
|
||||||
<Card style={{ width: '90%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Img variant="top" src={joueurs} style={{width:'auto', height:'300px'}}/>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title><FormattedMessage id='tuto.title.4'/></Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.4.1'/>
|
|
||||||
<br />
|
|
||||||
<FormattedMessage id='tuto.txt.4.2'/>
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 4 && (
|
|
||||||
<Card style={{ width: '90%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Img variant="top" src={rep} style={{width:'300px', height:'300px'}}/>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title><FormattedMessage id='tuto.title.5'/></Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.5.1'/>
|
|
||||||
<br />
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<FormattedMessage id='majUn'/> <u><FormattedMessage id='square'/></u> <FormattedMessage id='tuto.txt.5.2'/>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<FormattedMessage id='majUn'/> <u><FormattedMessage id='round'/></u> <FormattedMessage id='tuto.txt.5.3'/>.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<FormattedMessage id='tuto.txt.5.4'/><br />
|
|
||||||
<FormattedMessage id='tuto.txt.5.5.1'/>(<u><FormattedMessage id='color.green'/></u>) <FormattedMessage id='tuto.txt.5.5.2'/>.
|
|
||||||
<br/><FormattedMessage id='tuto.txt.5.6'/> (<u><FormattedMessage id='color.yellow'/></u>).
|
|
||||||
<br/><FormattedMessage id='tuto.txt.5.7.1'/><u><FormattedMessage id='tuto.txt.5.7.2'/></u>.
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 5 && (
|
|
||||||
<Card style={{ width: '90%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Header>
|
|
||||||
<button className='button'
|
|
||||||
style={{
|
|
||||||
backgroundColor: theme.colors.tertiary,
|
|
||||||
borderColor: theme.colors.secondary
|
|
||||||
}}>
|
|
||||||
<img src={Info} alt="info" height="40"/>
|
|
||||||
</button>
|
|
||||||
</Card.Header>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title><FormattedMessage id='tuto.title.6'/></Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.6.1.1'/><b><FormattedMessage id='tuto.txt.6.1.2'/></b><FormattedMessage id='tuto.txt.6.1.3'/>
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 2 && (
|
|
||||||
<Card style={{ width: '90%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Header>
|
|
||||||
<button className='button'
|
|
||||||
style={{
|
|
||||||
backgroundColor: theme.colors.tertiary,
|
|
||||||
borderColor: theme.colors.secondary
|
|
||||||
}}>
|
|
||||||
<img src={MGlass} alt="info" height="40"/>
|
|
||||||
</button>
|
|
||||||
</Card.Header>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title><FormattedMessage id='tuto.title.7'/></Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.7.1'/>
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 6 && (
|
|
||||||
<Card style={{ width: '90%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Img variant="top" src={graph} style={{width:'auto', height:'300px'}}/>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title><FormattedMessage id='tuto.title.8'/></Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.8.1'/>
|
|
||||||
<br/>
|
|
||||||
<FormattedMessage id='tuto.txt.8.2'/>
|
|
||||||
<br/>
|
|
||||||
<FormattedMessage id='tuto.txt.8.3'/>
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Modal.Body>
|
|
||||||
<Modal.Footer style={{display:'flex'}}>
|
|
||||||
<div style={{ width:'100%', display:'flex', justifyContent:'start'}}>
|
|
||||||
<label style={{ color:'gray'}}><FormattedMessage id='step'/> {step+1}/7</label>
|
|
||||||
</div>
|
|
||||||
{ step != -1 && (<Button variant="primary" onClick={() => setStep(step - 1)}><FormattedMessage id='previous'/></Button>)}
|
|
||||||
{ step === 6 ? (<Button variant="primary" onClick={handleCloseM}><FormattedMessage id='continue'/></Button>) :
|
|
||||||
<Button variant="primary" onClick={() => setStep(step + 1)}><FormattedMessage id='next'/></Button>}
|
|
||||||
|
|
||||||
</Modal.Footer>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<Modal
|
|
||||||
show={showTuto2}
|
|
||||||
onHide={handleCloseTuto2}
|
|
||||||
backdrop="static"
|
|
||||||
keyboard={false}
|
|
||||||
size="lg"
|
|
||||||
style={{ maxHeight: '100vh'}}>
|
|
||||||
<Modal.Header>
|
|
||||||
<Modal.Title><FormattedMessage id='tutorial.title'/></Modal.Title>
|
|
||||||
</Modal.Header>
|
|
||||||
<Modal.Body style={{ display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
|
|
||||||
<Card style={{ width: '100%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Img variant="top" src={step1} style={{width:'auto', height:'300px'}}/>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title><FormattedMessage id='tuto.title.9'/></Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.9.1'/>
|
|
||||||
<br/>
|
|
||||||
<FormattedMessage id='tuto.txt.9.2.1'/><b>Scooby-Doo</b><FormattedMessage id='tuto.txt.9.2.2'/><b>Violet</b><FormattedMessage id='tuto.txt.9.2.3'/>
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
</Modal.Body>
|
|
||||||
<Modal.Footer style={{display:'flex'}}>
|
|
||||||
<Button variant="primary" onClick={handleCloseTuto2}><FormattedMessage id='compris'/></Button>
|
|
||||||
</Modal.Footer>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<Modal
|
|
||||||
show={showTuto21}
|
|
||||||
onHide={handleCloseTuto21}
|
|
||||||
backdrop="static"
|
|
||||||
keyboard={false}
|
|
||||||
size="lg"
|
|
||||||
style={{ maxHeight: '100vh'}}>
|
|
||||||
<Modal.Header>
|
|
||||||
<Modal.Title><FormattedMessage id='tutorial.title'/></Modal.Title>
|
|
||||||
</Modal.Header>
|
|
||||||
<Modal.Body style={{ display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
{step === 0 && (
|
|
||||||
<Card style={{ width: '100%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Img variant="top" src={step2} style={{width:'300px', height:'auto'}}/>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title><FormattedMessage id='tuto.title.10'/></Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.10.1.1'/> <u><FormattedMessage id='tuto.txt.10.1.2'/></u><FormattedMessage id='tuto.txt.10.1.3'/><i><FormattedMessage id='tuto.txt.10.1.4'/></i><FormattedMessage id='tuto.txt.10.1.5'/>
|
|
||||||
<br/>
|
|
||||||
<FormattedMessage id='tuto.txt.10.2'/>
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 1 && (
|
|
||||||
<Card style={{ width: '100%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Img variant="top" src={step3} style={{width:'200px', height:'auto'}}/>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title><FormattedMessage id='tuto.title.11'/></Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.11.1.1'/><b><FormattedMessage id='non'/></b><FormattedMessage id='tuto.txt.11.1.2'/>
|
|
||||||
<br/>
|
|
||||||
<FormattedMessage id='tuto.txt.11.2.1'/><b><FormattedMessage id='tuto.txt.11.2.2'/></b><FormattedMessage id='tuto.txt.11.2.3'/>
|
|
||||||
<br/>
|
|
||||||
<FormattedMessage id='tuto.txt.11.3'/>
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 2 && (
|
|
||||||
<Card style={{ width: '100%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Img variant="top" src={step4} style={{width:'300px', height:'auto'}}/>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title><FormattedMessage id='tuto.title.12'/></Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.12.1.1'/><u><FormattedMessage id='tuto.txt.12.1.2'/></u><FormattedMessage id='tuto.txt.12.1.3'/>
|
|
||||||
<br/>
|
|
||||||
<FormattedMessage id='tuto.txt.12.2'/>
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
|
|
||||||
</Modal.Body>
|
|
||||||
<Modal.Footer style={{display:'flex'}}>
|
|
||||||
<div style={{ width:'100%', display:'flex', justifyContent:'start'}}>
|
|
||||||
<label style={{ color:'gray'}}><FormattedMessage id='step'/> {step+1}/3</label>
|
|
||||||
</div>
|
|
||||||
{ step != 0 && (<Button variant="primary" onClick={() => setStep(step - 1)}><FormattedMessage id='previous'/></Button>)}
|
|
||||||
{ step === 2 ? (<Button variant="primary" onClick={handleCloseTuto21}><FormattedMessage id='close'/></Button>) :
|
|
||||||
<Button variant="primary" onClick={() => setStep(step + 1)}><FormattedMessage id='next'/></Button>}
|
|
||||||
</Modal.Footer>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<Modal
|
|
||||||
show={showTuto22}
|
|
||||||
onHide={handleCloseTuto22}
|
|
||||||
backdrop="static"
|
|
||||||
keyboard={false}
|
|
||||||
size="lg"
|
|
||||||
style={{ maxHeight: '100vh'}}>
|
|
||||||
<Modal.Header>
|
|
||||||
<Modal.Title><FormattedMessage id='tutorial.title'/></Modal.Title>
|
|
||||||
</Modal.Header>
|
|
||||||
<Modal.Body style={{ display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
|
|
||||||
<Card style={{ width: '100%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Img variant="top" src={step5} style={{width:'300px', height:'auto'}}/>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title><FormattedMessage id='tuto.title.13'/></Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.13.1.1'/><b><FormattedMessage id='tuto.txt.13.1.2'/></b><FormattedMessage id='tuto.txt.13.1.3'/>
|
|
||||||
<br/>
|
|
||||||
<FormattedMessage id='tuto.txt.13.2.1'/><u><FormattedMessage id='tuto.txt.13.2.2'/></u><FormattedMessage id='tuto.txt.13.2.3'/>
|
|
||||||
<br/>
|
|
||||||
<FormattedMessage id='tuto.txt.13.3.1'/><b>Liam</b> <FormattedMessage id='tuto.txt.13.3.2'/>
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
</Modal.Body>
|
|
||||||
<Modal.Footer style={{display:'flex'}}>
|
|
||||||
<Button variant="primary" onClick={handleCloseTuto22}><FormattedMessage id='compris'/></Button>
|
|
||||||
</Modal.Footer>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<Modal
|
|
||||||
show={showTuto3}
|
|
||||||
onHide={handleCloseTuto3}
|
|
||||||
backdrop="static"
|
|
||||||
keyboard={false}
|
|
||||||
size="lg"
|
|
||||||
style={{ maxHeight: '100vh'}}>
|
|
||||||
<Modal.Header>
|
|
||||||
<Modal.Title>The End Game</Modal.Title>
|
|
||||||
</Modal.Header>
|
|
||||||
<Modal.Body style={{ display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card style={{ width: '100%', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column'}}>
|
|
||||||
<Card.Img variant="top" src={step6} style={{width:'250px', height:'auto'}}/>
|
|
||||||
<Card.Body>
|
|
||||||
<Card.Title><FormattedMessage id='tuto.title.14'/></Card.Title>
|
|
||||||
<Card.Text>
|
|
||||||
<FormattedMessage id='tuto.txt.14.1'/>
|
|
||||||
<br/>
|
|
||||||
<FormattedMessage id='tuto.txt.14.2'/>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<FormattedMessage id='tuto.txt.14.3'/><i>{indices[1]?.ToString(locale)}</i>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<FormattedMessage id='tuto.txt.14.4'/><i>{indices[2]?.ToString(locale)}</i>.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<FormattedMessage id='tuto.txt.14.5'/><i>{indices[0]?.ToString(locale)}</i>.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<FormattedMessage id='tuto.txt.14.6.1'/><b><FormattedMessage id='tuto.txt.14.6.2'/></b><FormattedMessage id='tuto.txt.14.6.3'/><b><FormattedMessage id='tuto.txt.14.6.4'/></b><FormattedMessage id='tuto.txt.14.6.5'/>
|
|
||||||
</Card.Text>
|
|
||||||
</Card.Body>
|
|
||||||
</Card>
|
|
||||||
</Modal.Body>
|
|
||||||
<Modal.Footer style={{display:'flex'}}>
|
|
||||||
<Button variant="primary" onClick={handleCloseTuto3}><FormattedMessage id='compris'/></Button>
|
|
||||||
</Modal.Footer>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default Tutorial;
|
|
@ -1,163 +0,0 @@
|
|||||||
{
|
|
||||||
"languageSelector.french": "Francés",
|
|
||||||
"languageSelector.english": "Inglés",
|
|
||||||
"languageSelector.espagnol": "Español",
|
|
||||||
"languageSelector.portuguese": "Portugués",
|
|
||||||
"languageSelector.russian": "Ruso",
|
|
||||||
|
|
||||||
"home.histoire.title": "HISTORIA",
|
|
||||||
"home.histoire": "La criptozoología estudia las huellas de monstruos legendarios: criptidos. Yetis, Chupacabra, bestia de Gévaudan, Dahut, etc. son temas muy serios para ti... Cruza las pistas y sé el primero en descubrirlos.",
|
|
||||||
|
|
||||||
"home.jeu.title": "EL JUEGO",
|
|
||||||
"home.jeu": "Cada jugador tiene una pista en el campo donde se encuentra la criatura. Cruzando tu información, solo puede haber una casilla. Pero el objetivo es ser el primero en encontrarla. Pregunta a tus colegas y, sin embargo, competidores. Solo pueden responderte con un 'no' o un 'quizás', con mucha lógica y un poco de audacia, ¡puedes entrar en la leyenda!",
|
|
||||||
|
|
||||||
"home.plus.title": "FORTALEZAS",
|
|
||||||
"home.plus.1": "Un mecanismo de deducción asombroso.",
|
|
||||||
"home.plus.2": "Una inmensa rejugabilidad.",
|
|
||||||
"home.plus.3": "Un tema sorprendente y fuerte.",
|
|
||||||
|
|
||||||
"game.time": "Tiempo: 45 minutos",
|
|
||||||
"game.players": "Jugadores: de 3 a 5 jugadores",
|
|
||||||
"game.age": "Edad: 10 años en adelante",
|
|
||||||
"game.createdBy": "Creado por:",
|
|
||||||
"game.illustratedBy": "Ilustrado por:",
|
|
||||||
|
|
||||||
"log_in": "Iniciar sesión",
|
|
||||||
"sign_up": "Registrarse",
|
|
||||||
"log_out": "Cerrar sesión",
|
|
||||||
|
|
||||||
"join": "Unirse",
|
|
||||||
"create_room": "Crear sala",
|
|
||||||
"play_solo": "Jugador individual",
|
|
||||||
|
|
||||||
"play": "JUGAR",
|
|
||||||
|
|
||||||
"football": "Fútbol",
|
|
||||||
"basketball": "Baloncesto",
|
|
||||||
"baseball": "Béisbol",
|
|
||||||
"tennis": "Tenis",
|
|
||||||
"bowling": "Bolos",
|
|
||||||
|
|
||||||
"white": "Blanco",
|
|
||||||
"black": "Negro",
|
|
||||||
"blond": "Rubio",
|
|
||||||
"redhead": "Pelirrojo",
|
|
||||||
"brown": "Marrón",
|
|
||||||
|
|
||||||
"and": "y",
|
|
||||||
"or": "o",
|
|
||||||
"or_sport": "o",
|
|
||||||
|
|
||||||
"age_indice_start": "El sospechoso tiene entre",
|
|
||||||
"age_indice_more_start": "El sospechoso tiene al menos",
|
|
||||||
"age_indice_end": "años",
|
|
||||||
|
|
||||||
"color_edges_start": "El sospechoso tiene al menos un amigo con cabello",
|
|
||||||
"color_edges_end": "",
|
|
||||||
|
|
||||||
"color_start": "El sospechoso tiene cabello",
|
|
||||||
"color_end": "",
|
|
||||||
|
|
||||||
"nb_friends_indice_start": "El sospechoso tiene",
|
|
||||||
"nb_friends_indice_end": "amigos",
|
|
||||||
|
|
||||||
"nb_sports_indice_start": "El sospechoso juega",
|
|
||||||
"nb_sports_indice_end": "deporte(s)",
|
|
||||||
|
|
||||||
"sport_start": "El sospechoso juega al menos",
|
|
||||||
"sport_end": "",
|
|
||||||
|
|
||||||
"navbar.play" : "Jugar",
|
|
||||||
"navbar.presentation":"Presentación",
|
|
||||||
"navbar.info":"Información",
|
|
||||||
|
|
||||||
"round":"Vuelta",
|
|
||||||
|
|
||||||
"informations": "Información",
|
|
||||||
"info.intro.title": "Introducción al juego:",
|
|
||||||
"info.intro.text": "¡Bienvenido a nuestro emocionante juego de deducción, donde la intriga y la travesura se combinan en una emocionante aventura! Sumérgete en un mundo de misterio e intriga, donde cada interacción cuenta y cada pista te acerca a la verdad. Imagina un gráfico complejo donde cada vértice representa a una persona, cada eje una relación, y cada detalle cuenta. Te sumerges en un desafiante reto para descubrir quién entre estas personas es el misterioso asesino. Cada jugador tiene una pista crucial y solo el intercambio estratégico de estas pistas te llevará a resolver el misterio. Explora nuestra página de reglas para entender las complejidades del juego, descubre pistas que pueden guiarte y desarrolla estrategias inteligentes para identificar al culpable. ¡Manipula a tus amigos para ser el primero en descubrir quién es el asesino oculto en el gráfico! ¿Estás listo para aceptar el desafío y desenmascarar al asesino oculto en el gráfico? ¡Que comience la investigación!",
|
|
||||||
|
|
||||||
"info.sommaire": "Contenidos",
|
|
||||||
|
|
||||||
"info.title.composant": "Componentes del juego",
|
|
||||||
"info.title.objectif": "Objetivo del juego",
|
|
||||||
"info.title.deroulement": "Desarrollo del juego",
|
|
||||||
"info.title.indice_possible": "Posible pista del juego",
|
|
||||||
|
|
||||||
"info.pions": "Peones",
|
|
||||||
"info.composant.text": "A cada jugador se le asignará un color específico que distinguirá las acciones representadas por los peones de la siguiente manera:",
|
|
||||||
|
|
||||||
"info.composant.carre.title": "Fichas cuadradas",
|
|
||||||
"info.composant.carre": "Estas fichas indican una negación. Cuando un jugador coloca una ficha cuadrada, significa que su pista elimina a la persona designada.",
|
|
||||||
|
|
||||||
"info.composant.rond.title": "Fichas redondas",
|
|
||||||
"info.composant.rond": "Estas fichas representan un 'quizás'. El jugador que deposita esta ficha afirma que la persona es sospechosa, pero esto no garantiza su culpabilidad. ¡Solo hay un sospechoso que lleva una ficha redonda para todos los jugadores en el juego, y ese es el culpable!",
|
|
||||||
|
|
||||||
"info.car_perso": "Características",
|
|
||||||
"info.composant.textcar": "Además de sus nombres, los personajes están representados con otras características:",
|
|
||||||
|
|
||||||
"info.composant.age.title": "Edades",
|
|
||||||
"info.composant.age": "Cada persona tiene una edad para autenticarlos, que varía entre 0 y 60 años. La edad es una característica que se confirmará con pistas en forma de ",
|
|
||||||
"info.composant.age.link": "grupos de edad",
|
|
||||||
|
|
||||||
"info.composant.hair_col.title": "Colores de cabello",
|
|
||||||
"info.composant.hair_col": "Los personajes también tienen un color de cabello, que puede ser de los siguientes colores:",
|
|
||||||
|
|
||||||
"hair.blanc": "Blanco",
|
|
||||||
"hair.blond": "Rubio",
|
|
||||||
"hair.roux": "Pelirrojo",
|
|
||||||
"hair.chatain": "Marrón",
|
|
||||||
"hair.noir": "Negro",
|
|
||||||
|
|
||||||
"info.composant.sport.title": "Deportes",
|
|
||||||
"info.composant.sport": "Los hobbies de los personajes están representados por cinco deportes respectivamente:",
|
|
||||||
"info.composant.baseball": "Béisbol",
|
|
||||||
"info.composant.basketball": "Baloncesto",
|
|
||||||
"info.composant.bowling": "Bowling",
|
|
||||||
"info.composant.football": "Fútbol",
|
|
||||||
"info.composant.tennis": "Tenis",
|
|
||||||
"info.composant.sport.bis": "Entre estos deportes, cada personaje puede tener entre 0 y 3 deportes, lo que facilita su identificación utilizando las pistas que tienes.",
|
|
||||||
|
|
||||||
"info.objectif.intro": "Bienvenido al ingenioso universo de nuestro juego de deducción, donde el engaño y la astucia son las claves del éxito. Tu misión es desentrañar el misterio detrás de cada interacción del complejo gráfico que representa las relaciones entre individuos.",
|
|
||||||
"info.objectif.t1": "Manipulación Sutil",
|
|
||||||
"info.objectif.t1.text": "El objetivo final es descubrir quién entre los individuos es el asesino, pero no a través de una colaboración abierta. Por el contrario, utilizarás una manipulación sutil para difuminar las líneas y distraer a tus oponentes. Haz preguntas estratégicas, responde con malicia y siembra pistas engañosas para acercarte al resultado.",
|
|
||||||
"info.objectif.t2": "Trucos",
|
|
||||||
"info.objectif.t2.text": "Cada ronda ofrece la oportunidad de sembrar dudas entre tus oponentes. Cuando un jugador te hace preguntas, responde colocando inteligentemente un token cuadrado para indicar que 'según tu pista, esa persona no puede ser el culpable' o un token redondo para sugerir que permanezcan en la lista de sospechosos. Ten cuidado, porque cada gesto puede interpretarse, y la verdad a menudo está oculta detrás de una fachada de pistas engañosas.",
|
|
||||||
"info.objectif.t3": "Contramanipulación",
|
|
||||||
"info.objectif.t3.text": "Si un jugador coloca un token cuadrado, el que hace la pregunta también debe jugar su juego colocando un token cuadrado de su color en un nodo del gráfico. La contramanipulación se convierte en un arma formidable para desviar la acusación y sembrar la confusión.",
|
|
||||||
|
|
||||||
"info.interface": "Interfaz de juego",
|
|
||||||
"info.interface.text": "Para cada juego, tendrás disponibles ciertos elementos de interfaz:",
|
|
||||||
"info.interface.param": "El botón 'Configuración' permite mostrar y gestionar varias configuraciones del juego, como activar o desactivar efectos de sonido. También es posible elegir el número de nodos para el modo de juego 'Enigma' con este botón.",
|
|
||||||
"info.interface.reset": "El botón 'Restablecer' restablece el estado actual del gráfico. Si lo has movido demasiado o quieres que su visualización sea más ordenada, ¡este botón es para ti!",
|
|
||||||
"info.interface.info": "El botón 'Información' redirige a la página de reglas del juego (esta).",
|
|
||||||
"info.interface.fiche": "El botón 'Hoja de Deducción de Pistas' muestra una tabla que, junto con el progreso del juego, permite deducir qué pistas son más probables para cada jugador.",
|
|
||||||
"info.interface.indice": "El botón 'Pista Personal' es el más importante; muestra tu pista secreta. ¡Solo tú lo sabes! Tendrás que ser astuto para engañar a tus amigos y mantenerlo en secreto el mayor tiempo posible!",
|
|
||||||
"info.interface.vision": "El botón 'Visión de los Últimos Movimientos' permite al usuario visualizar los últimos 5 movimientos realizados. Actúa como una herramienta visual.",
|
|
||||||
|
|
||||||
"etape": "Paso",
|
|
||||||
"info.deroulement.e1": "Hacer preguntas estratégicas",
|
|
||||||
"info.deroulement.e1.text": "Cada ronda comienza con un jugador haciendo preguntas a otro jugador sobre una persona en el gráfico. Las respuestas se formulan colocando fichas cuadradas o redondas para indicar certeza o duda sobre la participación de esa persona.",
|
|
||||||
"info.deroulement.e2": "Contramanipulación y Contra-pregunta",
|
|
||||||
"info.deroulement.e2.text": "Si un jugador coloca una ficha cuadrada, el que hace la pregunta también debe colocar una ficha cuadrada en un nodo del gráfico. Las contra-preguntas son una forma de confundir a los jugadores y desviar la acusación.",
|
|
||||||
"info.deroulement.e3": "La Adivinanza Final",
|
|
||||||
"info.deroulement.e3.text": "El juego alcanza su clímax cuando un jugador intenta la 'Adivinanza' final, afirmando que tal persona es el asesino. Otros jugadores",
|
|
||||||
|
|
||||||
"info.indice-possible.age": "Edad de la persona",
|
|
||||||
"info.indice-possible.hair": "Color de pelo de una persona",
|
|
||||||
"info.indice-possible.sport": "Deporte(s) de una persona",
|
|
||||||
"info.indice-possible.voisin": "Personaje de los vecinos",
|
|
||||||
|
|
||||||
"info.mdj": "Modos de juego",
|
|
||||||
"info.mdj.text": "Existen varios modos de juego que te permiten agregar variedad y hacer el juego más o menos complejo.",
|
|
||||||
"info.mdj.mastermind": "Mastermind",
|
|
||||||
"info.mdj.mastermind.text": "El modo de juego 'Mastermind' es un modo para un solo jugador donde debes ser capaz de adivinar al culpable utilizando el menor número de suposiciones. En este modo, no tendrás ninguna pista, pero deberás adivinarlas durante el juego. Seleccionar a un sospechoso revela el estado de todas las pistas para ese sospechoso. ¡Se vuelve posible adivinar las pistas y luego identificar al culpable!",
|
|
||||||
"info.mdj.enigme": "Enigma",
|
|
||||||
"info.mdj.enigme.text": "Este es un modo para un solo jugador con tres niveles de dificultad:",
|
|
||||||
"info.mdj.enigme.easy": "Enigma Fácil",
|
|
||||||
"info.mdj.enigme.easy.txt": "En este modo de juego, tienes acceso a todas las pistas y debes adivinar al culpable que coincide con todas estas pistas. Puedes practicar adivinando al culpable en este modo.",
|
|
||||||
"info.mdj.enigme.medium": "Enigma Intermedio",
|
|
||||||
"info.mdj.enigme.medium.txt": "En este modo de juego, no tienes acceso a pistas, pero tienes información suficiente sobre algunos sospechosos para poder adivinar al culpable. Esta información te ayudará a adivinar las pistas, y el culpable es el sospechoso para el cual todas las pistas coinciden. Si seleccionas al sospechoso equivocado, ¡no te preocupes! Tendrás información sobre ese sospechoso, lo que facilitará encontrar al culpable. El objetivo es encontrar al culpable en el menor número de suposiciones.",
|
|
||||||
"info.mdj.enigme.hard": "Enigma Difícil",
|
|
||||||
"info.mdj.enigme.hard.txt": "Esta variante final es similar al enigma intermedio; sin embargo, ¡debes encontrar al culpable en el primer intento, o pierdes! ¡Depende de ti jugar! El objetivo es encontrar al culpable en el menor tiempo posible."
|
|
||||||
}
|
|
@ -1,167 +0,0 @@
|
|||||||
{
|
|
||||||
"languageSelector.french": "Francês",
|
|
||||||
"languageSelector.english": "Inglês",
|
|
||||||
"languageSelector.espagnol": "Espanhol",
|
|
||||||
"languageSelector.portuguese": "Português",
|
|
||||||
"languageSelector.russian": "Russo",
|
|
||||||
|
|
||||||
"home.histoire.title": "HISTÓRIA",
|
|
||||||
"home.histoire": "A criptozoologia estuda as pegadas de monstros lendários: criptídeos. Yetis, Chupacabra, a besta de Gévaudan, Dahut, etc., são tópicos muito sérios para você... Cruze as pistas e seja o primeiro a descobri-los!",
|
|
||||||
|
|
||||||
"home.jeu.title": "O JOGO",
|
|
||||||
"home.jeu": "Cada jogador tem uma pista no campo onde a criatura está localizada. Ao cruzar suas informações, só pode haver uma caixa. Mas o objetivo é ser o primeiro a encontrá-la. Pergunte aos seus colegas, e ainda assim aos concorrentes. Eles só podem responder com 'não' ou 'talvez', com muita lógica e um pouco de audácia, você pode entrar na lenda!",
|
|
||||||
|
|
||||||
"home.plus.title": "FORÇA",
|
|
||||||
"home.plus.1": "Um mecanismo de dedução incrível.",
|
|
||||||
"home.plus.2": "Uma imensa rejogabilidade.",
|
|
||||||
"home.plus.3": "Um tema surpreendente e forte.",
|
|
||||||
|
|
||||||
"game.time": "Tempo: 45 minutos",
|
|
||||||
"game.players": "Jogadores: 3 a 5 jogadores",
|
|
||||||
"game.age": "Idade: 10 anos ou mais",
|
|
||||||
"game.createdBy": "Criado por:",
|
|
||||||
"game.illustratedBy": "Ilustrado por:",
|
|
||||||
|
|
||||||
"log_in":" Entrar ",
|
|
||||||
"sign_up":" Inscrever-se ",
|
|
||||||
"log_out":" Sair ",
|
|
||||||
|
|
||||||
"join" : "Participar",
|
|
||||||
"create_room" : "Criar sala",
|
|
||||||
"play_solo" : "Jogador único",
|
|
||||||
|
|
||||||
"play" : "JOGAR",
|
|
||||||
|
|
||||||
"football": "Futebol",
|
|
||||||
"basketball": "Basquete",
|
|
||||||
"baseball": "Beisebol",
|
|
||||||
"tennis": "Tênis",
|
|
||||||
"bowling": "Boliche",
|
|
||||||
|
|
||||||
"white": "Branco",
|
|
||||||
"black": "Preto",
|
|
||||||
"blond": "Loiro",
|
|
||||||
"redhead": "Ruivo",
|
|
||||||
"brown": "Castanho",
|
|
||||||
|
|
||||||
"and": "e",
|
|
||||||
"or": "ou",
|
|
||||||
"or_sport": "ou",
|
|
||||||
|
|
||||||
|
|
||||||
"age_indice_start": "O suspeito tem entre",
|
|
||||||
"age_indice_more_start": "O suspeito tem pelo menos",
|
|
||||||
"age_indice_end": "anos",
|
|
||||||
|
|
||||||
"color_edges_start": "O suspeito tem pelo menos um amigo com",
|
|
||||||
"color_edges_end": "cabelo",
|
|
||||||
|
|
||||||
"color_start": "O suspeito tem",
|
|
||||||
"color_end": "cabelo",
|
|
||||||
|
|
||||||
"nb_friends_indice_start": "O suspeito tem",
|
|
||||||
"nb_friends_indice_end": "amigos",
|
|
||||||
|
|
||||||
"nb_sports_indice_start": "O suspeito pratica",
|
|
||||||
"nb_sports_indice_end": "esporte(s)",
|
|
||||||
|
|
||||||
"sport_start": "O suspeito joga pelo menos",
|
|
||||||
"sport_end": "",
|
|
||||||
|
|
||||||
"navbar.play" : "Jogar",
|
|
||||||
"navbar.presentation":"Apresentação",
|
|
||||||
"navbar.info":"Informação",
|
|
||||||
|
|
||||||
"round":"ronda",
|
|
||||||
|
|
||||||
|
|
||||||
"informations" : "Informação",
|
|
||||||
"info.intro.title":"Introdução ao jogo:",
|
|
||||||
"info.intro.text":"Bem-vindo ao nosso empolgante jogo de dedução, onde intriga e malícia se unem em uma aventura emocionante! Mergulhe em um mundo de mistério e intriga, onde cada interação conta, e cada pista o aproxima da verdade. Imagine um gráfico complexo onde cada vértice representa uma pessoa, cada eixo uma relação, e cada detalhe conta. Você está imerso em um desafio desafiador para descobrir quem, entre esses indivíduos, é o misterioso assassino. Cada jogador tem uma pista crucial, e apenas o compartilhamento estratégico dessas pistas o levará a resolver o mistério. Explore nossa página de regras para entender as complexidades do jogo, descobrir pistas que podem orientá-lo e desenvolver estratégias inteligentes para identificar o culpado. Manipule seus amigos para ser o primeiro a descobrir quem é o assassino escondido no gráfico. Você está pronto para aceitar o desafio e desmascarar o assassino oculto no gráfico? Que a investigação comece!",
|
|
||||||
|
|
||||||
"info.sommaire":"Conteúdo",
|
|
||||||
|
|
||||||
"info.title.composant":"Componentes do Jogo",
|
|
||||||
"info.title.objectif":"Objetivo do Jogo",
|
|
||||||
"info.title.deroulement":"Desenvolvimento do Jogo",
|
|
||||||
"info.title.indice_possible":"Possíveis Pistas do Jogo",
|
|
||||||
|
|
||||||
"info.pions" : "Peões",
|
|
||||||
"info.composant.text" : "Cada jogador será associado a uma cor específica que distinguirá as ações representadas pelos peões da seguinte forma:",
|
|
||||||
|
|
||||||
"info.composant.carre.title":"Fichas quadradas",
|
|
||||||
"info.composant.carre":"Essas fichas indicam uma negação. Quando um jogador coloca uma ficha quadrada, significa que sua pista elimina a pessoa designada.",
|
|
||||||
|
|
||||||
"info.composant.rond.title":"Fichas redondas",
|
|
||||||
"info.composant.rond":"Essas fichas representam um 'talvez'. O jogador que deposita esta ficha afirma que a pessoa é suspeita, mas isso não garante sua culpa. Há apenas um suspeito com uma ficha redonda para todos os jogadores no jogo, e este é o culpado!",
|
|
||||||
|
|
||||||
"info.car_perso":"Características",
|
|
||||||
"info.composant.textcar":"Além de seus nomes, os personagens são representados com outras características:",
|
|
||||||
|
|
||||||
"info.composant.age.title":"Idades",
|
|
||||||
"info.composant.age":"Cada pessoa tem uma idade para autenticá-la, variando entre 0 e 60 anos. A idade é uma característica que será confirmada por pistas na forma de ",
|
|
||||||
"info.composant.age.link":"grupos etários",
|
|
||||||
|
|
||||||
"info.composant.hair_col.title":"Cores de cabelo",
|
|
||||||
"info.composant.hair_col":"Os personagens também têm uma cor de cabelo, que pode ser encontrada nas seguintes cores:",
|
|
||||||
|
|
||||||
"hair.blanc":"Branco",
|
|
||||||
"hair.blond":"Loiro",
|
|
||||||
"hair.roux":"Ruivo",
|
|
||||||
"hair.chatain":"Castanho",
|
|
||||||
"hair.noir":"Preto",
|
|
||||||
|
|
||||||
"info.composant.sport.title":"Esportes",
|
|
||||||
"info.composant.sport":"Os hobbies dos personagens são representados por cinco esportes, respectivamente:",
|
|
||||||
|
|
||||||
"info.composant.baseball":"Beisebol",
|
|
||||||
"info.composant.basketball":"Basquete",
|
|
||||||
"info.composant.bowling":"Boliche",
|
|
||||||
"info.composant.football":"Futebol",
|
|
||||||
"info.composant.tennis":"Tênis",
|
|
||||||
"info.composant.sport.bis":"Entre esses esportes, cada personagem pode ter entre 0 e 3 esportes, o que facilita sua identificação usando as pistas que você possui.",
|
|
||||||
|
|
||||||
"info.objectif.intro":"Bem-vindo ao universo inteligente do nosso jogo de dedução, onde a decepção e a astúcia são as chaves para o sucesso. Sua missão é desvendar o mistério por trás de cada interação do gráfico complexo que representa as relações entre os indivíduos.",
|
|
||||||
"info.objectif.t1":"Manipulação Sutil",
|
|
||||||
"info.objectif.t1.text":"O objetivo final é descobrir quem, entre os indivíduos, é o assassino, mas não por meio de colaboração aberta. Pelo contrário, você usará manipulação sutil para turvar as linhas e distrair seus oponentes. Faça perguntas estratégicas, responda com malícia e plante pistas enganosas para se aproximar do resultado.",
|
|
||||||
"info.objectif.t2":"Trapaça",
|
|
||||||
"info.objectif.t2.text":"Cada rodada oferece a oportunidade de semear dúvidas entre seus oponentes. Quando um jogador faz perguntas a você, responda colocando astutamente uma ficha quadrada para indicar que 'dependendo da sua pista, essa pessoa não pode ser o culpado' ou uma ficha redonda para sugerir que eles permanecem na lista de suspeitos. Cuidado, porque cada gesto pode ser interpretado, e a verdade muitas vezes está escondida por trás de uma fachada de pistas enganosas.",
|
|
||||||
"info.objectif.t3":"Contra-manipulação",
|
|
||||||
"info.objectif.t3.text":"Se um jogador colocar uma ficha quadrada, o questionador também deve jogar seu jogo colocando uma ficha quadrada de sua cor em um nó do gráfico. A contra-manipulação se torna uma arma formidável para desviar a acusação e semear confusão.",
|
|
||||||
|
|
||||||
"info.interface": "Interface do Jogo",
|
|
||||||
"info.interface.text": "Para cada jogo, você terá certos elementos de interface disponíveis:",
|
|
||||||
"info.interface.param": "O botão 'Configurações' permite exibir e gerenciar várias configurações do jogo, como ativar ou desativar efeitos sonoros. Também é possível escolher o número de nós para o modo de jogo 'Enigma' usando este botão.",
|
|
||||||
"info.interface.reset": "O botão 'Redefinir' redefine o estado atual do gráfico. Se você o moveu demais ou deseja que sua exibição fique mais organizada, este botão é para você!",
|
|
||||||
"info.interface.info": "O botão 'Informações' redireciona para a página de regras do jogo (esta aqui).",
|
|
||||||
"info.interface.fiche": "O botão 'Folha de Dedução de Pistas' exibe uma tabela que, junto com o progresso do jogo, permite deduzir quais pistas são mais prováveis para cada jogador.",
|
|
||||||
"info.interface.indice": "O botão 'Pista Pessoal' é o mais importante; ele exibe sua pista secreta. Só você a conhece! Você terá que ser esperto para enganar seus amigos e mantê-la em segredo o máximo possível!",
|
|
||||||
"info.interface.vision": "O botão 'Últimas Jogadas' permite ao usuário visualizar as últimas 5 jogadas feitas. Ele age como uma ferramenta visual.",
|
|
||||||
|
|
||||||
"etape":"Etapa",
|
|
||||||
"info.deroulement.e1":"Faça Perguntas Estratégicas",
|
|
||||||
"info.deroulement.e1.text":"Cada rodada começa com um jogador fazendo perguntas a outro jogador sobre uma pessoa no gráfico. As respostas são formuladas colocando fichas quadradas ou redondas para indicar certeza ou dúvida quanto ao envolvimento dessa pessoa.",
|
|
||||||
"info.deroulement.e2":"Contra-manipulação e Contra-perguntas",
|
|
||||||
"info.deroulement.e2.text":"Se um jogador colocar uma ficha quadrada, o questionador também deve colocar uma ficha quadrada em um nó no gráfico. Contra-perguntas são uma maneira de confundir os jogadores e desviar a acusação.",
|
|
||||||
"info.deroulement.e3":"O Palpite Final",
|
|
||||||
"info.deroulement.e3.text":"O jogo atinge seu clímax quando um jogador tenta o 'Palpite' final, alegando que tal pessoa é o assassino. Outros jogadores podem contradizer essa declaração colocando suas próprias fichas quadradas. Se nenhuma refutação for feita, o jogador que fez o 'Palpite' vence o jogo, demonstrando sua maestria na arte da manipulação.",
|
|
||||||
|
|
||||||
"info.indice-possible.age":"Idade da Pessoa",
|
|
||||||
"info.indice-possible.hair":"Cor do cabelo de uma pessoa",
|
|
||||||
"info.indice-possible.sport":"Esporte(s) de uma pessoa",
|
|
||||||
"info.indice-possible.voisin":"Personagem dos vizinhos",
|
|
||||||
|
|
||||||
"info.mdj": "Modos de Jogo",
|
|
||||||
"info.mdj.text": "Existem vários outros modos de jogo que permitem adicionar variedade e tornar o jogo mais ou menos complexo.",
|
|
||||||
"info.mdj.mastermind": "Mestre das Pistas",
|
|
||||||
"info.mdj.mastermind.text": "O modo de jogo 'Mestre das Pistas' é um modo solo onde você deve ser capaz de adivinhar o culpado usando o número mínimo de palpites. Neste modo, você não terá pistas, mas precisará adivinhá-las durante o jogo. Selecionar um suspeito revela o estado de todas as pistas para esse suspeito. Torna-se possível adivinhar as pistas e depois identificar o culpado!",
|
|
||||||
"info.mdj.enigme": "Enigma",
|
|
||||||
"info.mdj.enigme.text": "Este é um modo solo com três níveis de dificuldade:",
|
|
||||||
"info.mdj.enigme.easy": "Enigma Fácil",
|
|
||||||
"info.mdj.enigme.easy.txt": "Neste modo de jogo, você tem acesso a todas as pistas e deve adivinhar o culpado que corresponde a todas essas pistas. Você pode praticar adivinhando o culpado neste modo.",
|
|
||||||
"info.mdj.enigme.medium": "Enigma Intermediário",
|
|
||||||
"info.mdj.enigme.medium.txt": "Neste modo de jogo, você não tem acesso a pistas, mas tem informações suficientes sobre alguns suspeitos para poder adivinhar o culpado. Essas informações o ajudarão a adivinhar as pistas, e o culpado é o suspeito para quem todas as pistas correspondem. Se você selecionar o suspeito errado, não se preocupe! Você terá informações sobre aquele suspeito, o que facilitará encontrar o culpado. O objetivo é encontrar o culpado no mínimo de palpites.",
|
|
||||||
"info.mdj.enigme.hard": "Enigma Difícil",
|
|
||||||
"info.mdj.enigme.hard.txt": "Esta variante final é semelhante ao enigma intermediário; no entanto, você deve encontrar o culpado na primeira tentativa, ou você perde! Depende de você jogar! O objetivo é encontrar o culpado no mínimo de tempo."
|
|
||||||
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"names": [
|
|
||||||
"Sherlock Holmes",
|
|
||||||
"Inspecteur Gadget",
|
|
||||||
"Scooby-Doo",
|
|
||||||
"Marple",
|
|
||||||
"Spocky",
|
|
||||||
"Phoenix",
|
|
||||||
"Batman",
|
|
||||||
"James Bond",
|
|
||||||
"Sherlockio",
|
|
||||||
"Verra",
|
|
||||||
"Hercule Poirot",
|
|
||||||
"Colombo",
|
|
||||||
"MacGyver",
|
|
||||||
"Lupin",
|
|
||||||
"D. Conan",
|
|
||||||
"Pr. Layton",
|
|
||||||
"Dr. Watson"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 822 B |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 189 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 9.2 KiB |