Merge branch 'master' into weeklyDaily

pull/97/head^2
Baptiste MARCEL 1 year ago
commit cf10c87d73

@ -31,4 +31,33 @@ steps:
settings:
sonar_host: https://codefirst.iut.uca.fr/sonar/
sonar_token:
from_secret: SECRET_SONAR_LOGIN_CRYPTIDE
from_secret: SECRET_SONAR_LOGIN_CRYPTIDE
#
- 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
#depends_on: [ build ]
#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 ]

4
.gitignore vendored

@ -48,5 +48,7 @@ yarn.lock
package-lock.json
# db
socialgraph.db
# build
cryptide_project/build/

@ -0,0 +1,22 @@
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 80
#
# Installez express
RUN npm install express
# Copiez le script serveur personnalisé
COPY server.js .
# Commande pour démarrer le serveur personnalisé
CMD ["node", "server.js"]

@ -0,0 +1,33 @@
#!/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

@ -0,0 +1,17 @@
#!/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,6 +1,8 @@
#!/bin/sh
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if lsof -Pi :3000 -sTCP:LISTEN -t >/dev/null; then
# Tuer le processus associé au port
pid=$(lsof -Pi :3000 -sTCP:LISTEN -t)
@ -23,8 +25,8 @@ fi
npm start &
node ./server/socket_io/server.js &
node $SCRIPT_DIR/../server/server.js &
node ./server/api/server.js
node $SCRIPT_DIR/../src/server/server.js

@ -0,0 +1,19 @@
{
"files": {
"main.css": "/static/css/main.6888e917.css",
"main.js": "/static/js/main.b6842da5.js",
"static/js/787.a1c84483.chunk.js": "/static/js/787.a1c84483.chunk.js",
"static/media/Person.png": "/static/media/Person.f7ba6be9e4afca5ca897.png",
"static/media/bot.png": "/static/media/bot.057c187a23ead0769e7f.png",
"static/media/eye.png": "/static/media/eye.cd074d043a80f09623ac.png",
"static/media/reset.png": "/static/media/reset.82632189f4cbd1644b7a.png",
"index.html": "/index.html",
"main.6888e917.css.map": "/static/css/main.6888e917.css.map",
"main.b6842da5.js.map": "/static/js/main.b6842da5.js.map",
"787.a1c84483.chunk.js.map": "/static/js/787.a1c84483.chunk.js.map"
},
"entrypoints": [
"static/css/main.6888e917.css",
"static/js/main.b6842da5.js"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

@ -0,0 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.b6842da5.js"></script><link href="/static/css/main.6888e917.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,2 @@
"use strict";(self.webpackChunkcryptide=self.webpackChunkcryptide||[]).push([[787],{787:(e,t,n)=>{n.r(t),n.d(t,{getCLS:()=>y,getFCP:()=>g,getFID:()=>C,getLCP:()=>P,getTTFB:()=>D});var i,r,a,o,u=function(e,t){return{name:e,value:void 0===t?-1:t,delta:0,entries:[],id:"v2-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12)}},c=function(e,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){if("first-input"===e&&!("PerformanceEventTiming"in self))return;var n=new PerformanceObserver((function(e){return e.getEntries().map(t)}));return n.observe({type:e,buffered:!0}),n}}catch(e){}},f=function(e,t){var n=function n(i){"pagehide"!==i.type&&"hidden"!==document.visibilityState||(e(i),t&&(removeEventListener("visibilitychange",n,!0),removeEventListener("pagehide",n,!0)))};addEventListener("visibilitychange",n,!0),addEventListener("pagehide",n,!0)},s=function(e){addEventListener("pageshow",(function(t){t.persisted&&e(t)}),!0)},m=function(e,t,n){var i;return function(r){t.value>=0&&(r||n)&&(t.delta=t.value-(i||0),(t.delta||void 0===i)&&(i=t.value,e(t)))}},v=-1,p=function(){return"hidden"===document.visibilityState?0:1/0},d=function(){f((function(e){var t=e.timeStamp;v=t}),!0)},l=function(){return v<0&&(v=p(),d(),s((function(){setTimeout((function(){v=p(),d()}),0)}))),{get firstHiddenTime(){return v}}},g=function(e,t){var n,i=l(),r=u("FCP"),a=function(e){"first-contentful-paint"===e.name&&(f&&f.disconnect(),e.startTime<i.firstHiddenTime&&(r.value=e.startTime,r.entries.push(e),n(!0)))},o=window.performance&&performance.getEntriesByName&&performance.getEntriesByName("first-contentful-paint")[0],f=o?null:c("paint",a);(o||f)&&(n=m(e,r,t),o&&a(o),s((function(i){r=u("FCP"),n=m(e,r,t),requestAnimationFrame((function(){requestAnimationFrame((function(){r.value=performance.now()-i.timeStamp,n(!0)}))}))})))},h=!1,T=-1,y=function(e,t){h||(g((function(e){T=e.value})),h=!0);var n,i=function(t){T>-1&&e(t)},r=u("CLS",0),a=0,o=[],v=function(e){if(!e.hadRecentInput){var t=o[0],i=o[o.length-1];a&&e.startTime-i.startTime<1e3&&e.startTime-t.startTime<5e3?(a+=e.value,o.push(e)):(a=e.value,o=[e]),a>r.value&&(r.value=a,r.entries=o,n())}},p=c("layout-shift",v);p&&(n=m(i,r,t),f((function(){p.takeRecords().map(v),n(!0)})),s((function(){a=0,T=-1,r=u("CLS",0),n=m(i,r,t)})))},E={passive:!0,capture:!0},w=new Date,L=function(e,t){i||(i=t,r=e,a=new Date,F(removeEventListener),S())},S=function(){if(r>=0&&r<a-w){var e={entryType:"first-input",name:i.type,target:i.target,cancelable:i.cancelable,startTime:i.timeStamp,processingStart:i.timeStamp+r};o.forEach((function(t){t(e)})),o=[]}},b=function(e){if(e.cancelable){var t=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,t){var n=function(){L(e,t),r()},i=function(){r()},r=function(){removeEventListener("pointerup",n,E),removeEventListener("pointercancel",i,E)};addEventListener("pointerup",n,E),addEventListener("pointercancel",i,E)}(t,e):L(t,e)}},F=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach((function(t){return e(t,b,E)}))},C=function(e,t){var n,a=l(),v=u("FID"),p=function(e){e.startTime<a.firstHiddenTime&&(v.value=e.processingStart-e.startTime,v.entries.push(e),n(!0))},d=c("first-input",p);n=m(e,v,t),d&&f((function(){d.takeRecords().map(p),d.disconnect()}),!0),d&&s((function(){var a;v=u("FID"),n=m(e,v,t),o=[],r=-1,i=null,F(addEventListener),a=p,o.push(a),S()}))},k={},P=function(e,t){var n,i=l(),r=u("LCP"),a=function(e){var t=e.startTime;t<i.firstHiddenTime&&(r.value=t,r.entries.push(e),n())},o=c("largest-contentful-paint",a);if(o){n=m(e,r,t);var v=function(){k[r.id]||(o.takeRecords().map(a),o.disconnect(),k[r.id]=!0,n(!0))};["keydown","click"].forEach((function(e){addEventListener(e,v,{once:!0,capture:!0})})),f(v,!0),s((function(i){r=u("LCP"),n=m(e,r,t),requestAnimationFrame((function(){requestAnimationFrame((function(){r.value=performance.now()-i.timeStamp,k[r.id]=!0,n(!0)}))}))}))}},D=function(e){var t,n=u("TTFB");t=function(){try{var t=performance.getEntriesByType("navigation")[0]||function(){var e=performance.timing,t={entryType:"navigation",startTime:0};for(var n in e)"navigationStart"!==n&&"toJSON"!==n&&(t[n]=Math.max(e[n]-e.navigationStart,0));return t}();if(n.value=n.delta=t.responseStart,n.value<0||n.value>performance.now())return;n.entries=[t],e(n)}catch(e){}},"complete"===document.readyState?setTimeout(t,0):addEventListener("load",(function(){return setTimeout(t,0)}))}}}]);
//# sourceMappingURL=787.a1c84483.chunk.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,123 @@
/*!
Copyright (c) 2018 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
*/
/*!
JSZip v3.10.1 - A JavaScript class for generating and reading zip files
<http://stuartk.com/jszip>
(c) 2009-2016 Stuart Knightley <stuart [at] stuartk.com>
Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/main/LICENSE.markdown.
JSZip uses the library pako released under the MIT license :
https://github.com/nodeca/pako/blob/main/LICENSE
*/
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/*! Hammer.JS - v2.0.17-rc - 2019-12-16
* http://naver.github.io/egjs
*
* Forked By Naver egjs
* Copyright (c) hammerjs
* Licensed under the MIT license */
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @remix-run/router v1.11.0
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
/**
* React Router DOM v6.18.0
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
/**
* React Router v6.18.0
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
//! Il faudra possiblement faire une gestion des mode de jeu, pour modifier les regles en fonction de ce dernier.

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@ -0,0 +1,9 @@
<FilesMatch "\.css$">
ForceType text/css
Header set Content-Type "text/css"
</FilesMatch>
<FilesMatch "\.js$">
ForceType application/javascript
Header set Content-Type "application/javascript"
</FilesMatch>

@ -23,6 +23,7 @@
"express": "^4.18.2",
"express-session": "^1.17.3",
"file-saver": "^2.0.5",
"jspdf": "^2.5.1",
"jszip": "^3.10.1",
"lodash": "^4.17.21",
"react": "^18.2.0",
@ -4593,6 +4594,12 @@
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz",
"integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg=="
},
"node_modules/@types/raf": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz",
"integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
"optional": true
},
"node_modules/@types/range-parser": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz",
@ -5732,6 +5739,17 @@
"node": ">= 4.0.0"
}
},
"node_modules/atob": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
"bin": {
"atob": "bin/atob.js"
},
"engines": {
"node": ">= 4.5.0"
}
},
"node_modules/autoprefixer": {
"version": "10.4.16",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz",
@ -6121,6 +6139,15 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/base64-arraybuffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
"optional": true,
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/base64id": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
@ -6336,6 +6363,17 @@
"node-int64": "^0.4.0"
}
},
"node_modules/btoa": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
"integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==",
"bin": {
"btoa": "bin/btoa.js"
},
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@ -6519,6 +6557,31 @@
}
]
},
"node_modules/canvg": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz",
"integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==",
"optional": true,
"dependencies": {
"@babel/runtime": "^7.12.5",
"@types/raf": "^3.4.0",
"core-js": "^3.8.3",
"raf": "^3.4.1",
"regenerator-runtime": "^0.13.7",
"rgbcolor": "^1.0.1",
"stackblur-canvas": "^2.0.0",
"svg-pathdata": "^6.0.3"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/canvg/node_modules/regenerator-runtime": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
"optional": true
},
"node_modules/case-sensitive-paths-webpack-plugin": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz",
@ -7081,6 +7144,15 @@
"postcss": "^8.4"
}
},
"node_modules/css-line-break": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
"optional": true,
"dependencies": {
"utrie": "^1.0.2"
}
},
"node_modules/css-loader": {
"version": "6.8.1",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz",
@ -7873,6 +7945,12 @@
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/dompurify": {
"version": "2.4.7",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.7.tgz",
"integrity": "sha512-kxxKlPEDa6Nc5WJi+qRgPbOAbgTpSULL+vI3NUXsZMlkJxTqYI9wg5ZTay2sFrdZRWHPWNi+EdAhcJf81WtoMQ==",
"optional": true
},
"node_modules/domutils": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
@ -9184,6 +9262,11 @@
"bser": "2.1.1"
}
},
"node_modules/fflate": {
"version": "0.4.8",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz",
"integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA=="
},
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@ -10095,6 +10178,19 @@
"webpack": "^5.20.0"
}
},
"node_modules/html2canvas": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
"optional": true,
"dependencies": {
"css-line-break": "^2.1.0",
"text-segmentation": "^1.0.3"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/htmlparser2": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
@ -13025,6 +13121,23 @@
"node": ">=0.10.0"
}
},
"node_modules/jspdf": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz",
"integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==",
"dependencies": {
"@babel/runtime": "^7.14.0",
"atob": "^2.1.2",
"btoa": "^1.2.1",
"fflate": "^0.4.8"
},
"optionalDependencies": {
"canvg": "^3.0.6",
"core-js": "^3.6.0",
"dompurify": "^2.2.0",
"html2canvas": "^1.0.0-rc.5"
}
},
"node_modules/jsx-ast-utils": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
@ -16913,6 +17026,15 @@
"node": ">=0.10.0"
}
},
"node_modules/rgbcolor": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
"integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
"optional": true,
"engines": {
"node": ">= 0.8.15"
}
},
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@ -17728,6 +17850,15 @@
"node": ">=8"
}
},
"node_modules/stackblur-canvas": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.6.0.tgz",
"integrity": "sha512-8S1aIA+UoF6erJYnglGPug6MaHYGo1Ot7h5fuXx4fUPvcvQfcdw2o/ppCse63+eZf8PPidSu4v1JnmEVtEDnpg==",
"optional": true,
"engines": {
"node": ">=0.1.14"
}
},
"node_modules/stackframe": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
@ -18136,6 +18267,15 @@
"resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz",
"integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ=="
},
"node_modules/svg-pathdata": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
"integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
"optional": true,
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/svgo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
@ -18480,6 +18620,15 @@
"node": ">=8"
}
},
"node_modules/text-segmentation": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
"optional": true,
"dependencies": {
"utrie": "^1.0.2"
}
},
"node_modules/text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@ -19049,6 +19198,15 @@
"node": ">= 0.4.0"
}
},
"node_modules/utrie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
"optional": true,
"dependencies": {
"base64-arraybuffer": "^1.0.2"
}
},
"node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",

@ -17,6 +17,7 @@
"express": "^4.18.2",
"express-session": "^1.17.3",
"file-saver": "^2.0.5",
"jspdf": "^2.5.1",
"jszip": "^3.10.1",
"lodash": "^4.17.21",
"react": "^18.2.0",

@ -0,0 +1,6 @@
{
"headers": [
{ "source": "**/*.js", "headers": [{ "key": "Content-Type", "value": "application/javascript; charset=utf-8" }] }
]
}

@ -0,0 +1,24 @@
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('*.js', (req, res, next) => {
res.type('application/javascript; charset=utf-8');
next();
});
// 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}`);
});

@ -121,6 +121,38 @@ class AuthController {
db.disconnect();
}
}
static async UpdateMDP(req, res){
console.log("UpdateMDP");
// 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();
// }
}
}
module.exports = AuthController;

@ -9,6 +9,8 @@ router.post('/auth/signin', AuthController.signIn);
router.delete('/auth/logout', AuthController.logout)
router.delete('/auth/delAccount', AuthController.delAccount)
router.put('/session/updateMDP', AuthController.UpdateMDP);
// Routes pour les sessions
router.get('/session', SessionController.getUserInformation);
router.post('/session/addMastermindStats', SessionController.addMastermindStats);

@ -14,7 +14,7 @@ const port = 3003;
// Middleware
app.use(cors(
{
origin: ["http://localhost:3000", "http://172.20.10.4:3000"],
origin: ["http://localhost:3000", "http://localhost:3000"],
credentials: true
}
)); // Autoriser les requêtes cross-origin

@ -7,12 +7,14 @@ const app = express();
const server = http.createServer(app);
const io = socketIO(server, {
cors: {
origin: ["http://172.20.10.4:3000", "http://localhost:3000"], // Remplacez par l'URL de votre application React
origin: ["http://localhost:3000", "http://localhost:3000"], // Remplacez par l'URL de votre application React
methods: ["GET", "POST"],
credentials: true
}
});
let lastSocketJoined = ""
const map = new Map()
server.listen(3002, () => {
@ -24,18 +26,61 @@ io.on('connection', (socket) => {
socket.on('network created', (network, person, indices, room, start) =>{
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)
});
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) =>{
console.log(player)
if (player.type=="User"){
socket.join(room)
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 (map.get(room) == undefined){
map.set(room, [{type: player.type, id: socket.id, pseudo: player.pseudo, profilePicture: player.profilePicture}])
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 = map.get(room)
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)
@ -43,25 +88,39 @@ io.on('connection', (socket) => {
}
if (player.type!=="User"){
map.get(room).push({type: player.type, id: player.id, pseudo: player.pseudo, profilePicture: player.profilePicture})
tab.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})
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)
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)
})
@ -85,19 +144,80 @@ io.on('connection', (socket) => {
io.to(askingPlayer.id).emit("asked wrong")
})
socket.on("who plays", (room) => {
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)
}
})
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)
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) =>{
map.get(room).actualPlayer=playerIndex
map.get(room).lastWorks=works
io.to(room).emit("node checked", id, works, color, playerIndex, socket.id)
})
@ -113,6 +233,10 @@ io.on('connection', (socket) => {
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")
})
@ -127,5 +251,17 @@ io.on('connection', (socket) => {
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;
}
}

@ -2,6 +2,10 @@ const ADRESSE_WEBSERVER = "http://localhost:3002"
const ADRESSE_DBSERVER = "http://localhost:3003"
const tmp = ADRESSE_DBSERVER
const tmp2 = ADRESSE_WEBSERVER
const ADRESSE_WEBSITE = ""
export {ADRESSE_DBSERVER, ADRESSE_WEBSERVER, ADRESSE_WEBSITE}

@ -15,7 +15,8 @@ import Lobby from './Pages/Lobby';
import InGame from './Pages/InGame';
import EndGame from './Pages/EndGame';
import InfoPage from './Pages/InfoPage';
import SoloGame from './Pages/SoloGame';
import DeducGrid from './Pages/DeducGrid';
import Lobbies from './Pages/Lobbies';
/* Component */
@ -40,6 +41,11 @@ import 'bootstrap/dist/css/bootstrap.min.css';
import messagesFr from './Translations/fr.json';
import messagesEn from './Translations/en.json';
/* Gestion d' erreur */
import ErrorBoundary from './Error/ErrorBoundary';
import ErrorPage from './Error/ErrorPage';
import NewPlay from './Pages/NewPlay';
const messages = {
fr: messagesFr,
en: messagesEn,
@ -58,42 +64,40 @@ function App() {
//const location = useLocation();
const hasNavbarVisible = ["/", "/login", "/signup", "/play", "/lobby", "/endgame"]//.includes(window.location.pathname);
const hasNavbarVisible = ["/", "/login", "/signup", "/play", "/lobby", "/endgame", "/deduc"]//.includes(window.location.pathname);
return (
// <div className="App">
// <header className="App-header">
// <Home />
// <img src={logo} className="App-logo" alt="logo" />
// </header>
// </div>
<AuthProvider>
<GameProvider>
{/*@ts-ignore*/}
<IntlProvider locale={locale} messages={messages[locale]}>
<ThemeProvider>
<BrowserRouter>
{hasNavbarVisible && <AppNavbar changeLocale={changeLocale} />}
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<SignUp />} />
<Route path="/play" element={<Play/>} />
<Route path="/lobby" element={<Lobby/>} />
<Route path="/endgame" element={<EndGame/>} />
<Route path="/game" element={<InGame locale={locale} changeLocale={changeLocale}/>}/>
<Route path="/info" element={<InfoPage locale={locale} changeLocale={changeLocale}/>} />
<Route path="/profile" element={<Profile/>} />
<Route path="/join" element={<Lobbies/>}/>
{/* <Route path="/solo" element={<SoloGame locale={locale} changeLocale={changeLocale} />}/> */}
</Routes>
</BrowserRouter>
</ThemeProvider>
</IntlProvider>
</GameProvider>
</AuthProvider>
<ErrorBoundary fallback={(error, errorInfo) => <ErrorPage />}>
<AuthProvider>
<GameProvider>
{/*@ts-ignore*/}
<IntlProvider locale={locale} messages={messages[locale]}>
<ThemeProvider>
<BrowserRouter>
{hasNavbarVisible && <AppNavbar changeLocale={changeLocale} />}
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<SignUp />} />
<Route path="/play" element={<NewPlay/>} />
<Route path="/lobby" element={<Lobby/>} />
<Route path="/endgame" element={<EndGame/>} />
<Route path="/game" element={<InGame locale={locale} changeLocale={changeLocale}/>}/>
<Route path="/info" element={<InfoPage locale={locale} changeLocale={changeLocale}/>} />
<Route path="/deduc" element={<DeducGrid/>} />
<Route path="/profile" element={<Profile/>} />
<Route path="/join" element={<Lobbies/>}/>
{/* <Route path="/solo" element={<SoloGame locale={locale} changeLocale={changeLocale} />}/> */}
<Route path="*" element={<ErrorPage code="404" msg='not found' />} /> {/* page 404 */}
</Routes>
</BrowserRouter>
</ThemeProvider>
</IntlProvider>
</GameProvider>
</AuthProvider>
</ErrorBoundary>
);
}

@ -0,0 +1,87 @@
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;

@ -0,0 +1,41 @@
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;

@ -14,7 +14,13 @@ import NodePerson from "../model/Graph/NodePerson";
import { useAuth } from "../Contexts/AuthContext";
import Indice from "../model/Indices/Indice";
import Pair from "../model/Pair";
import { times } from "lodash";
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';
interface MyGraphComponentProps {
onNodeClick: (shouldShowChoiceBar: boolean) => void;
handleShowTurnBar: (shouldShowTurnBar: boolean) => void
@ -29,13 +35,17 @@ interface MyGraphComponentProps {
setNetwork: (network: Network) => void
showLast: boolean
setNetworkEnigme: (networkEnigme: Map<number, Pair<Indice, boolean>[]>) => void
askedWrong: boolean
setAskedWrong: (askedWrong: boolean) => void
setPlayerIndex: (playerIndex: number) => void
importToPdf: boolean
setImportToPdf: (imp: boolean) => void
}
let lastAskingPlayer = 0
let lastNodeId = -1
let first = true
let askedWrong = false
let askedWrongLocal = false
let mapIndexPersons: Map<number, Person[]> = new Map<number, Person[]>()
let touchedPlayer = -1
let botIndex = -1
@ -49,16 +59,23 @@ let firstEnigme = true
let firstIndex = true
let endgame= false
let firstHistory = true
let cptSquare = 0
let cptOnAskedWrong = 0
let cptPlayerLeft = 0
let firstPlayer = 0
let cptBug = 0
let cptUseEffect = 0
let testPlayers: Player[] = []
const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleShowTurnBar, handleTurnBarTextChange, playerTouched, setPlayerTouched, changecptTour, solo, isDaily, isEasy, addToHistory, showLast, setNetwork, setNetworkEnigme, setPlayerIndex}) => {
const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleShowTurnBar, handleTurnBarTextChange, playerTouched, setPlayerTouched, changecptTour, solo, isDaily, isEasy, addToHistory, showLast, setNetwork, setNetworkEnigme, setPlayerIndex, askedWrong, setAskedWrong, importToPdf, setImportToPdf}) => {
let cptTour: number = 0
//* Gestion du temps :
let initMtn = 0
const {isLoggedIn, user, manager} = useAuth();
const { indices, indice, person, personNetwork, setNodeIdData, players, askedPersons, setActualPlayerIndexData, room, actualPlayerIndex, turnPlayerIndex, setTurnPlayerIndexData, setWinnerData, dailyEnigme, setNbCoupData, settempsData, setNetworkDataData, setSeedData} = useGame();
const { indices, indice, person, personNetwork, setNodeIdData, players, setPlayersData, askedPersons, setActualPlayerIndexData, room, actualPlayerIndex, turnPlayerIndex, setTurnPlayerIndexData, setWinnerData, dailyEnigme, setNbCoupData, settempsData, setNetworkDataData, setSeedData, nodesC} = useGame();
const params = new URLSearchParams(window.location.search);
const navigate = useNavigate();
@ -72,6 +89,13 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
setElapsedTime((prevElapsedTime) => prevElapsedTime + 0.5);
settempsData(elapsedTime)
cptBug ++
if (cptBug > 10){
cptBug = 0
socket.emit("who plays", room)
}
// Vérifiez si la durée est écoulée, puis arrêtez le timer
if (endgame) {
clearInterval(intervalId);
@ -83,15 +107,21 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}, [elapsedTime, endgame]);
useEffect(() => {
testPlayers = players
console.log(testPlayers)
}, [players])
useEffect(() =>{
touchedPlayer=playerTouched
console.log(playerTouched)
if (touchedPlayer == -1){
if (!askedWrong){
if (!askedWrongLocal){
socket.emit("put correct background", socket.id)
}
}
else if (touchedPlayer < players.length && touchedPlayer>=0){
if(!askedWrong){
if(!askedWrongLocal){
socket.emit("put correct background", socket.id)
socket.emit("put grey background", socket.id, touchedPlayer)
}
@ -136,8 +166,9 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
useEffect(() =>{
if (actualPlayerIndex==0){
const bot = players[lastIndex]
cptBug=0
if (actualPlayerIndex==firstPlayer){
const bot = testPlayers[lastIndex]
if(bot instanceof Bot && botIndex != lastIndex){
botIndex = lastIndex
if (personNetwork!=null){
@ -161,7 +192,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
const tester = IndiceTesterFactory.Create(indices[playerIndex])
const works = tester.Works(person)
socket.emit("asked all 1by1", person.getId(), players[playerIndex].id)
socket.emit("asked all 1by1", person.getId(), testPlayers[playerIndex].id)
if (i==players.length){
socket.emit("node checked", personIndex, works, playerIndex, room, nextPlayerIndex)
}
@ -170,7 +201,11 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
if(!works){
socket.emit("node checked", personIndex, works, playerIndex, room, nextPlayerIndex)
const ind = bot.placeSquare(personNetwork, players)
const ind = bot.placeSquare(personNetwork, testPlayers)
if (ind == -1 ){
socket.emit("can't put square", lastIndex, room)
return
}
console.log(lastIndex + " pose carré sur " + personNetwork.getPersons()[ind].getName())
playerIndex = lastIndex + 1
if(playerIndex == players.length){
@ -185,7 +220,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
else{
if (person!=undefined){
if (players[choosedPlayerIndex] instanceof Bot){
if (testPlayers[choosedPlayerIndex] instanceof Bot){
console.log("BOT")
const tester = IndiceTesterFactory.Create(indices[choosedPlayerIndex])
const works = tester.Works(person)
@ -200,7 +235,11 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
else{
console.log(lastIndex + " interroge " + choosedPlayerIndex + " a propos de " + person.getName() + " et dit non")
socket.emit("node checked", personIndex, false, choosedPlayerIndex, room, lastIndex)
const ind = bot.placeSquare(personNetwork, players)
const ind = bot.placeSquare(personNetwork, testPlayers)
if (ind == -1 ){
socket.emit("can't put square", playerIndex, room)
return
}
console.log(lastIndex + " pose carré sur " + personNetwork.getPersons()[ind].getName())
playerIndex = lastIndex + 1
if(playerIndex == players.length){
@ -211,11 +250,15 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
else{
console.log(choosedPlayerIndex + " => Pas bot" )
socket.emit("ask player", personIndex, players[choosedPlayerIndex].id, players[lastIndex])
socket.emit("ask player", personIndex, testPlayers[choosedPlayerIndex].id, testPlayers[lastIndex])
console.log(lastIndex + " interroge " + +choosedPlayerIndex + " sur " + personNetwork.getPersons()[personIndex].getName())
const tester = IndiceTesterFactory.Create(indices[choosedPlayerIndex])
if (!tester.Works(person)){
const ind = bot.placeSquare(personNetwork, players)
const ind = bot.placeSquare(personNetwork, testPlayers)
if (ind == -1 ){
socket.emit("can't put square", playerIndex, room)
return
}
console.log(lastIndex + " pose carré sur " + personNetwork.getPersons()[ind].getName())
playerIndex = lastIndex + 1
if(playerIndex == players.length){
@ -256,18 +299,24 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
}
//* fonction qui reinitialise le graphe
const resGraph = () => { //? comment accéder au nework ??
const savedGraphStateString = localStorage.getItem('graphState');
if (savedGraphStateString !== null) {
const savedGraphState = JSON.parse(savedGraphStateString);
//network.setData(savedGraphState);
} else {
// La clé 'graphState' n'existe pas dans le localStorage, prenez une action en conséquence.
console.log("ayoooooo");
useEffect(() => {
if (importToPdf){
setImportToPdf(false)
const graphContainer = document.getElementById("graph-container");
if (graphContainer == null){
return
}
html2canvas(graphContainer).then((canvas) => {
const pdf = new jsPDF({
orientation: 'landscape', // Spécifie l'orientation du PDF en mode paysage
unit: 'mm', // Unité de mesure (par exemple, millimètres)
format: 'a4', // Format du papier (par exemple, a4)
});
pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, 0, pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight());
pdf.save('graph.pdf');
});
}
};
}, [importToPdf])
useEffect(() => {
if (personNetwork == null){
@ -288,7 +337,10 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
return;
}
// Charger les données dans le graph
const nodes = new DataSet(graph.nodesPerson);
let nodes = new DataSet(graph.nodesPerson);
if (nodesC.length != 0){
nodes = new DataSet(nodesC)
}
// Configuration des options du Graphe
const initialOptions = {
@ -300,7 +352,6 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
direction: 'LR', // LR (Left to Right) ou autre selon votre préférence
sortMethod: 'hubsize'
},
distanceMin: 500, // Set the minimum distance between nodes
//randomSeed: 2
},
physics: {
@ -349,6 +400,83 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
}
socket.on("give network", (playerId) => {
socket.emit("give network", JSON.stringify(personNetwork, null, 2), JSON.stringify(person), JSON.stringify(indices), playerIndex, room, JSON.stringify(nodes.get()), playerId);
})
socket.on("player joined ingame", (tab) => {
const tmpTab: Player[] = []
let ind =0
for (const p of tab){
if (p.type === "User"){
tmpTab.push(JSONParser.JSONToPlayer(p))
}
else{
tmpTab.push(testPlayers[ind])
}
ind ++
}
setPlayersData(tmpTab)
})
socket.on("player left ingame", (tab, i) => {
cptPlayerLeft ++
if (cptPlayerLeft % 2 == 0){
const tmpTab: Player[] = []
let ind =0
for (const p of tab.tab){
if (ind === i || p.type === "User"){
tmpTab.push(JSONParser.JSONToPlayer(p))
}
else{
tmpTab.push(testPlayers[ind])
}
ind ++
}
if (i==firstPlayer){
for(let index = 0; index < tmpTab.length; index++){
const test = tmpTab[index]
if (test instanceof User){
firstPlayer=index
break
}
}
if (actualPlayerIndex==firstPlayer){
tmpTab.forEach((p, index) =>{
if (p instanceof Bot && personNetwork!=null){
p.indice=indices[index]
p.index=index
p.initiateMap(personNetwork)
console.log(p.indice.ToString("fr"))
}
})
}
}
else{
const bot = tmpTab[i]
if (bot instanceof Bot && personNetwork != null){
bot.indice=indices[i]
bot.index=index
bot.initiateMap(personNetwork)
console.log(bot.indice.ToString("fr"))
}
}
if (i==playerIndex){
playerIndex = lastIndex + 1
if(playerIndex == players.length){
playerIndex = 0
}
setPlayerIndex(playerIndex)
setLastIndex(playerIndex)
if (playerIndex===actualPlayerIndex){
handleTurnBarTextChange("À vous de jouer")
handleShowTurnBar(true)
}
}
setPlayersData(tmpTab)
}
})
socket.on("reset graph", () => {
console.log("reset graph")
initialOptions.physics.enabled = true
@ -356,6 +484,16 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
})
if (!solo){
socket.on("who plays", (index) => {
playerIndex=index
setPlayerIndex(index)
setLastIndex(index)
if (actualPlayerIndex==index){
handleShowTurnBar(true)
}
})
socket.on("asked all", (id) =>{
//@ts-ignore
const pers = personNetwork.getPersons().find((p) => p.getId() == id)
@ -382,12 +520,15 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
})
socket.on("node checked",(id, works, askedIndex, newPlayerIndex, socketId) => {
cptBug=0
//@ts-ignore
const node = nodes.get().find((n) => id == n.id)
if (node!=undefined){
onNodeClick(false)
playerIndex = newPlayerIndex
setPlayerIndex(playerIndex)
setLastIndex(newPlayerIndex)
console.log(newPlayerIndex)
//@ts-ignore
if (mapIndexPersons.get(askedIndex)?.find((p) => p.getId() == id) == undefined){
//@ts-ignore
@ -396,7 +537,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
if (p!=undefined && tab != undefined){
tab.push(p)
if (actualPlayerIndex == 0){
players.forEach((player) => {
testPlayers.forEach((player) => {
if (player instanceof Bot){
player.newInformation(p, askedIndex, works)
}
@ -410,7 +551,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
cptHistory++
if (cptHistory % 2 == 0){
lastNodes.push(node)
addToHistory(players[askedIndex].pseudo + " à mis un " + positionToEmoji(askedIndex, works) + " à " + personNetwork.getPersons()[id].getName())
addToHistory(testPlayers[askedIndex].pseudo + " à mis un " + positionToEmoji(askedIndex, works) + " à " + personNetwork.getPersons()[id].getName())
}
}
@ -433,15 +574,67 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
})
socket.on("asked wrong", () =>{
askedWrong = true
askedWrongBot=true
handleShowTurnBar(true)
handleTurnBarTextChange("Mauvais choix, posez un carré !")
socket.emit("put grey background", socket.id, actualPlayerIndex)
cptSquare++
if (cptSquare % 2 == 0){
if (indice==null){
return
}
const tester = IndiceTesterFactory.Create(indice)
const tabPossible: Person[] = []
for(const person of personNetwork.getPersons()){
//@ts-ignore
const node = nodes.get().find((n) => n.id == person.getId())
if (node != undefined) {
let isSquare = false
players.forEach((p, index) => {
if (node.label.includes(positionToEmoji(index, false))){
isSquare=true
}
})
if (!tester.Works(person) && !isSquare){
tabPossible.push(person)
}
}
}
if (tabPossible.length>0){
askedWrongLocal= true
setAskedWrong(true)
askedWrongBot=true
handleShowTurnBar(true)
handleTurnBarTextChange("Mauvais choix, posez un carré !")
socket.emit("put grey background", socket.id, actualPlayerIndex)
}
else{
socket.emit("can't put square", actualPlayerIndex, room)
}
}
})
socket.on("can't put square", (askingPlayer) => {
cptBug=0
cptOnAskedWrong ++
if (cptOnAskedWrong % 2 == 0){
addToHistory(testPlayers[askingPlayer].pseudo + " ne peut plus poser de carré")
playerIndex = askingPlayer + 1
if(playerIndex == players.length){
playerIndex = 0
}
setPlayerIndex(playerIndex)
setLastIndex(playerIndex)
if (playerIndex === actualPlayerIndex){
handleTurnBarTextChange("À vous de jouer")
handleShowTurnBar(true)
}
else{
handleShowTurnBar(false)
socket.emit("put correct background", socket.id)
}
}
})
socket.on("asked", (nodeId, askingPlayer) => {
if (askingPlayer.id !== lastAskingPlayer || nodeId !== lastNodeId ){
lastAskingPlayer = askingPlayer.id
lastNodeId = nodeId
@ -458,7 +651,6 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
const node = nodes.get().find((n) => nodeId == n.id)
if (node != undefined && indice != null){
var tester = IndiceTesterFactory.Create(indice)
let maybe = actualPlayerIndex
if (tester.Works(pers)){
playerIndex = playerIndex + 1
if(playerIndex == players.length){
@ -467,13 +659,8 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
socket.emit("node checked", nodeId, true, actualPlayerIndex, room, playerIndex)
}
else{
maybe = actualPlayerIndex - 1
if(maybe == 0){
maybe = players.length - 1
}
//@ts-ignore
let index = players.findIndex((p) => p.id == askingPlayer.id)
if (players[index] instanceof Bot){
let index = testPlayers.findIndex((p) => p.id == askingPlayer.id)
if (testPlayers[index] instanceof Bot){
index = playerIndex + 1
if(index == players.length){
index = 0
@ -519,9 +706,21 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
}
else if(indice != null){
//Pour poser un carré
const tester = IndiceTesterFactory.Create(indice)
for(const person of personNetwork.getPersons().filter((p) => tab.includes(p) || tester.Works(p))){
networkData.nodes.update({id: person.getId(), color: "#808080"})
for(const person of personNetwork.getPersons()){
//@ts-ignore
const node = nodes.get().find((n) => n.id == person.getId())
if (node == undefined) continue
let isSquare = false
players.forEach((p, index) => {
if (node.label.includes(positionToEmoji(index, false))){
isSquare=true
}
})
if (tab.includes(person) || tester.Works(person) || isSquare){
networkData.nodes.update({id: person.getId(), color: "#808080"})
}
}
}
}
@ -567,10 +766,12 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
first = true
cptHistory = 0
askedWrong=false
askedWrongLocal=false
setAskedWrong(false)
askedWrongBot=false
endgame = true
firstHistory=true
cptBug=0
try{
if(isLoggedIn){
if(!solo){
@ -606,6 +807,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
socket.off("put correct background")
socket.off("put grey background")
socket.off("put imossible grey")
socket.off("who plays")
navigate("/endgame")
}
@ -624,7 +826,7 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
if (a==indices.length){
//networkData.nodes.update({id: p.getId(), label: p.getName() + "\n🔵"})
console.log(p)
//console.log(p)
}
});
@ -643,15 +845,24 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
network.on("click", async (params) => {
if(params.nodes.length > 0){
console.log(touchedPlayer)
setNodeIdData(params.nodes[0])
console.log(players)
// addToHistory("Le joueur a cliqué") //! TEST DEBUG
if (!solo){
if (askedWrong){
//@ts-ignore
if (askedWrongLocal){
const person = personNetwork?.getPersons().find((p) => p.getId() == params.nodes[0])
if (person !== undefined && indice !== null){
//@ts-ignore
const node = nodes.get().find((n) => n.id == params.nodes[0])
if (person !== undefined && indice !== null && node!=undefined){
const tester = IndiceTesterFactory.Create(indice)
if (!tester.Works(person) && !askedPersons.includes(person)){
let isSquare = false
players.forEach((p, index) => {
if (node.label.includes(positionToEmoji(index, false))){
isSquare=true
}
})
if (!tester.Works(person) && !askedPersons.includes(person) && !isSquare){
playerIndex = actualPlayerIndex + 1
if(playerIndex == players.length){
playerIndex = 0
@ -660,13 +871,16 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
socket.emit("put correct background", socket.id)
touchedPlayer=-1
askedPersons.push(person)
askedWrong = false
askedWrongLocal=false
setAskedWrong(false)
}
}
}
else if(touchedPlayer != -1 && playerIndex == actualPlayerIndex && touchedPlayer<players.length){
botIndex = -1
if (players[touchedPlayer] instanceof Bot){
console.log(testPlayers[touchedPlayer])
if (testPlayers[touchedPlayer] instanceof Bot){
console.log("BOT TOUCHÉ")
const ind = indices[touchedPlayer]
const test = IndiceTesterFactory.Create(ind)
//@ts-ignore
@ -688,8 +902,8 @@ const MyGraphComponent: React.FC<MyGraphComponentProps> = ({onNodeClick, handleS
}
}
else{
if (touchedPlayer > 0){
console.log(touchedPlayer)
if (touchedPlayer >= 0){
console.log("CE N'EST PAS UN BOT")
//@ts-ignore
socket.emit("ask player", params.nodes[0], players[touchedPlayer].id, players.find((p) => p.id === socket.id, actualPlayerIndex))
socket.emit("put correct background", socket.id)

@ -7,83 +7,150 @@ 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';
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}) => {
const LobbyContainer: React.FC<LobbyContainerProps> = ({roomNum, HeadPlayer, nbPlayer, setFirst, started}) => {
const theme=useTheme();
const navigate = useNavigate();
const dest = '/lobby?room=' + roomNum;
//* Modal
const [show, setShow] = useState(false);
const [showFull, setShowFull] = useState(false);
const [showStart, setShowStart] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const handleClose = () => {
setShowFull(false)
setShowStart(false)
};
const handleShowFull = () => setShowFull(true);
const handleShowStart = () => setShowStart(true);
const handleContainerClick = () => {
if (show){
if (showFull || showStart){
handleClose()
}
else{
if (nbPlayer < 6) {
if (nbPlayer < 6 && !started) {
socket.off("request lobbies")
setFirst(true)
navigate(dest);
} else {
handleShow()
//alert('La salle est pleine. Impossible de rejoindre.');
}
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(
<div className='lobbyMainContainer' onClick={handleContainerClick} style={{borderColor:stylefull}}>
<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>
{/*
<Button onClick={handleContainerClick} variant='danger'>
click
</Button> */}
<Modal show={show} 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>
<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>
</Modal.Footer>
</Modal>
</div>
</OverlayTrigger>
);
}

@ -32,10 +32,6 @@ function AppNavbar({changeLocale}) {
const navigate = useNavigate();
useEffect(() => {
console.log(user)
}, [user])
function navigateToProfile(){
navigate("/profile")
}

@ -18,11 +18,12 @@ interface PlayerStatusProps {
playerTouched: number
showCircle: boolean
playerIndex: number
askedWrong: boolean
}
let touchedPlayer = -1
//@ts-ignore
const PersonStatus: React.FC<PlayerStatusProps> = ({img = Person, state= Person, name = "Dummy", index, playerTouched, setPlayerTouched, showCircle, playerIndex}) => {
const PersonStatus: React.FC<PlayerStatusProps> = ({img = Person, state= Person, name = "Dummy", index, playerTouched, setPlayerTouched, showCircle, playerIndex, askedWrong}) => {
const theme=useTheme();
const {players, actualPlayerIndex} = useGame()
if (players[index] instanceof Bot){
@ -48,8 +49,9 @@ const PersonStatus: React.FC<PlayerStatusProps> = ({img = Person, state= Person,
}, [playerIndex])
function onTouch(){
if (IsActualPlayer){
if (IsActualPlayer && !askedWrong){
setPlayerTouched(index)
setTouchedPlayer(index)
}
}

@ -31,7 +31,7 @@ const PlayerItemList:React.FC<MyPlayerItemListProps> =({ player, room }) => {
// const isBot = pdp === Bot;
let pdp;
const isBot = player instanceof Bot;
isBot ? pdp = BotPDP : pdp = player.profilePicture;
isBot ? pdp = BotPDP : pdp = PersonPDP;
const delBot = () => {

@ -1,6 +1,6 @@
import React from 'react';
import { colorToEmoji, positionToColor } from '../ColorHelper';
import { colorToEmoji, positionToColor, positionToEmoji } from '../ColorHelper';
import Player from '../model/Player';
import { useTheme } from '../Style/ThemeContext';
import PersonStatus from './PersonStatus';
@ -15,11 +15,18 @@ interface PlayerListProps {
playerTouched: number
setPlayerTouched: (newPlayerTouch: number) => void;
playerIndex: number
askedWrong: boolean
}
const PlayerList: React.FC<PlayerListProps> = ({ players, playerTouched, setPlayerTouched, playerIndex}) => {
const PlayerList: React.FC<PlayerListProps> = ({ players, playerTouched, setPlayerTouched, playerIndex, askedWrong}) => {
const theme = useTheme();
function askEveryone(){
if (!askedWrong){
setPlayerTouched(players.length)
}
}
return (
<div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '16px' }}>
@ -32,12 +39,13 @@ const PlayerList: React.FC<PlayerListProps> = ({ players, playerTouched, setPlay
key={index}
name={player.pseudo
+ " " +
colorToEmoji(positionToColor(index), true)}
positionToEmoji(index, true)}
playerTouched={playerTouched}
setPlayerTouched={setPlayerTouched}
index={index}
showCircle={true}
playerIndex={playerIndex}/>
playerIndex={playerIndex}
askedWrong={askedWrong}/>
))
}
</div>
@ -57,7 +65,7 @@ const PlayerList: React.FC<PlayerListProps> = ({ players, playerTouched, setPlay
border: "solid 1px",
textAlign: "center",
padding: "10px"}}
onClick={() => setPlayerTouched(players.length)}>Ask everyone</button>
onClick={() => askEveryone()}>Ask everyone</button>
):
(
<button style={{
@ -67,7 +75,7 @@ const PlayerList: React.FC<PlayerListProps> = ({ players, playerTouched, setPlay
border: "solid 1px",
textAlign: "center",
padding: "10px"}}
onClick={() => setPlayerTouched(players.length)}>Ask everyone</button>
onClick={() => askEveryone()}>Ask everyone</button>
)
}
</div>

@ -1,4 +1,6 @@
import React, { createContext, useContext, useState, ReactNode } from 'react';
import { DataSet, Edge } from 'vis-network';
import NodePerson from '../model/Graph/NodePerson';
import Indice from '../model/Indices/Indice';
import Pair from '../model/Pair';
import Person from '../model/Person';
@ -23,6 +25,7 @@ interface GameContextProps {
temps : number
networkData: any
seed: number | string;
nodesC: NodePerson[]
setIndicesData: (newIndices: Indice[]) => void;
setIndiceData: (newIndice: Indice) => void;
setPersonData: (newPerson: Person) => void;
@ -41,6 +44,7 @@ interface GameContextProps {
settempsData: (newtemps : number) => void
setNetworkDataData: (networkData: any) => void
setSeedData: (seed: number | string) => void
setNodesData: (nodes: NodePerson[]) => void
}
const GameContext = createContext<GameContextProps | undefined>(undefined);
@ -67,6 +71,12 @@ export const GameProvider: React.FC<GameProviderProps> = ({ children }) => {
const [temps, settemps] = useState<number>(0);
const [networkData, setNetworkData] = useState<any>(null);
const [seed, setSeed] = useState<number | string>(0);
const [nodesC, setNodes] = useState<NodePerson[]>([]);
const setNodesData = (nodes: NodePerson[]) => {
setNodes(nodes)
}
const setNetworkDataData = (networkData: any) => {
setNetworkData(networkData);
@ -155,7 +165,7 @@ export const GameProvider: React.FC<GameProviderProps> = ({ children }) => {
}
return (
<GameContext.Provider value={{ indices, setIndicesData, indice, setIndiceData, person, setPersonData, personNetwork, setPersonNetworkData, players, setPlayersData, nodeId, setNodeIdData, askedPersons, setAskedPersonsData, actualPlayerIndex, setActualPlayerIndexData, turnPlayerIndex, setTurnPlayerIndexData, room, setRoomData, onlyFalse, setOnlyFalseData, winner, setWinnerData, reset, dailyEnigme, setDailyEnigmeData, nbCoup, setNbCoupData, temps, settempsData, setNetworkDataData, networkData, seed, setSeedData}}>
<GameContext.Provider value={{ indices, setIndicesData, indice, setIndiceData, person, setPersonData, personNetwork, setPersonNetworkData, players, setPlayersData, nodeId, setNodeIdData, askedPersons, setAskedPersonsData, actualPlayerIndex, setActualPlayerIndexData, turnPlayerIndex, setTurnPlayerIndexData, room, setRoomData, onlyFalse, setOnlyFalseData, winner, setWinnerData, reset, dailyEnigme, setDailyEnigmeData, nbCoup, setNbCoupData, temps, settempsData, setNetworkDataData, networkData, seed, setSeedData, nodesC, setNodesData}}>
{children}
</GameContext.Provider>
);

@ -0,0 +1,67 @@
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;

@ -0,0 +1,37 @@
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';
//@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='/' variant='danger'>Retour à l'accueil</Button>
</div>
</div>
);
}
export default ErrorPage;

@ -0,0 +1,29 @@
.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;
}

@ -11,6 +11,8 @@ import Person from "./model/Person";
import PersonNetwork from "./model/PersonsNetwork";
import Player from "./model/Player";
import User from "./model/User";
import NodePerson from "./model/Graph/NodePerson";
import Font from "./model/Graph/Font";
class JSONParser{
@ -93,6 +95,15 @@ class JSONParser{
throw new Error("PARSER unable to parse player: " + json.type);
}
}
static JSONToNodePersons(json: any): NodePerson[]{
const tmpTab: NodePerson[] = []
json.forEach((element: any) => {
tmpTab.push(new NodePerson(element.id, element.label, element.color, new Font(element.font.color, element.font.size, element.font.align), element.shape))
});
return tmpTab
}
}
export default JSONParser

@ -0,0 +1,17 @@
.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;
}

@ -0,0 +1,79 @@
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;

@ -118,8 +118,6 @@ function EndGame() {
}
const theme = useTheme();
console.log(winner)
console.log(indices)
let indicenull = false;
if (indices.length == 0){
@ -150,7 +148,7 @@ function EndGame() {
<div className="playerContainer" key={index}>
{player.id !== winner?.id && (
<div>
<PersonStatus img={Person} state={Person} key={index} name={player.pseudo} playerTouched={1} setPlayerTouched={() => {}} index={index} playerIndex={-2} showCircle={false}/>
<PersonStatus img={Person} state={Person} key={index} name={player.pseudo} playerTouched={1} setPlayerTouched={() => {}} index={index} playerIndex={-2} showCircle={false} askedWrong={false}/>
{!indicenull && (<h6 className='indiceDisplay'>{indices[players.findIndex((p) => p.id == player?.id)].ToString("fr")}</h6>)}
</div>
)}

@ -9,6 +9,8 @@ import { FormattedMessage } from 'react-intl';
import ButtonImgNav from '../Components/ButtonImgNav';
import defaultImg from "../res/img/Person.png"
import {loadImageAsync} from "../ImageHelper"
import { socket } from '../SocketConfig';
import JSONParser from '../JSONParser';
// @ts-ignore

@ -28,7 +28,7 @@ import Ceye from "../res/icon/hidden.png";
import JSZip from 'jszip';
/* nav */
import { Link } from 'react-router-dom';
import { Link, Navigate, useNavigate, useNavigationType } from 'react-router-dom';
/* Boostrap */
import Button from 'react-bootstrap/Button';
@ -50,13 +50,25 @@ import {generateLatexCode, generateLatexCodeEnigme} from '../Script/LatexScript'
import Pair from '../model/Pair';
import Indice from '../model/Indices/Indice';
let cptNavigation = 0
//@ts-ignore
const InGame = ({locale, changeLocale}) => {
const theme = useTheme();
const navigate = useNavigate()
const params = new URLSearchParams(window.location.search);
const navigationType = useNavigationType()
cptNavigation++
if (cptNavigation % 2 == 0){
if (navigationType.toString() == "POP"){
socket.emit("player quit")
navigate("/play")
}
}
//* Gestion solo
let IsSolo: boolean = true
@ -81,6 +93,12 @@ const InGame = ({locale, changeLocale}) => {
//* Historique
const [history, setHistory] = useState<string[]>([]);
const [showLast, setShowLast] = useState(false)
const [askedWrong, setAskedWrong] = useState(false)
const [importToPdf, setImportToPdf] = useState(false)
const setImportToPdfData = (imp: boolean) => {
setImportToPdf(imp)
}
// Fonction pour ajouter un élément à l'historique
const addToHistory = (message: string) => {
@ -92,6 +110,10 @@ const InGame = ({locale, changeLocale}) => {
setShowLast(!showLast);
}
const setAskedWrongData = (askedWrong: boolean) => {
setAskedWrong(askedWrong)
}
useEffect(() => {
const historyContainer = document.getElementById('history-container');
if (historyContainer) {
@ -276,7 +298,11 @@ const InGame = ({locale, changeLocale}) => {
setNetwork={setNetworkData}
setNetworkEnigme={setNetworkEnigmeData}
showLast={showLast}
setPlayerIndex={setPlayerIndexData}/>
setPlayerIndex={setPlayerIndexData}
askedWrong={askedWrong}
setAskedWrong={setAskedWrongData}
importToPdf={importToPdf}
setImportToPdf={setImportToPdfData}/>
</div>
@ -352,7 +378,7 @@ const InGame = ({locale, changeLocale}) => {
</button> */}
{!IsSolo &&
<Link to='/info' target='_blank'>
<Link to='/deduc' target='_blank'>
<button className='button'
style={{
backgroundColor: theme.colors.tertiary,
@ -388,6 +414,16 @@ const InGame = ({locale, changeLocale}) => {
<img src={Download} alt="indice" height="40"/>
</button>
}
{IsSolo &&
<button className='button' onClick={ () => setImportToPdfData(true)}
style={{
backgroundColor: theme.colors.tertiary,
borderColor: theme.colors.secondary
}}>
<img src={Download} alt="indice" height="40"/>
</button>
}
</div>
{/*
@ -405,7 +441,7 @@ const InGame = ({locale, changeLocale}) => {
{ !IsSolo &&
<div className='playerlistDiv'>
<PlayerList players={players} setPlayerTouched={handleSetPlayerTouched} playerTouched={playerTouched} playerIndex={playerIndex}/>
<PlayerList players={players} setPlayerTouched={handleSetPlayerTouched} playerTouched={playerTouched} playerIndex={playerIndex} askedWrong={askedWrong}/>
</div>
}

@ -18,6 +18,10 @@
cursor: pointer;
}
.lobbyMainContainer:hover{
background-color: whitesmoke;
}
.lobbyList{
display: flex;
/* justify-content: space-around; */

@ -7,51 +7,154 @@ 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';
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 lobbyData = [
{ roomNum: '63194', headPlayer: new User('1', 'Emma', '', null, null, null, null, null), nbPlayer: 6 },
{ roomNum: '81194', headPlayer: new User('2', 'Ray', '', null, null, null, null, null), nbPlayer: 1 },
{ roomNum: '22194', headPlayer: new User('3', 'Norman', '', null, null, null, null, null), nbPlayer: 4 },
{ roomNum: 'null', headPlayer: new User('null', 'tnull', '', null, null, null, null, null), nbPlayer: 1 },
{ roomNum: '111111', headPlayer: new User('11', '1111111', '', null, null, null, null, null), nbPlayer: 1 },
{ roomNum: '741852963', headPlayer: new User('3', 'Guest_741852963', '', null, null, null, null, null), nbPlayer: 6 },
];
const [first, setFirst] = useState(true)
const [lobbyData, setLobbyData] = useState<LobbyDataProps[]>([])
const [searchTerm, setSearchTerm] = useState('');
const filteredLobbies = lobbyData.filter((lobby) =>
lobby.roomNum.toLowerCase().includes(searchTerm.toLowerCase()) ||
lobby.headPlayer.pseudo.toLowerCase().includes(searchTerm.toLowerCase())
);
const [showAvailable, setShowAvailable] = useState(true);
const handleShowAllClick = () => {
setShowAvailable(false);
};
const handleShowAvailableClick = () => {
setShowAvailable(true);
};
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()
cptNavigation++
if (cptNavigation % 2 == 0){
if (navigationType.toString() == "POP"){
socket.emit("player quit")
}
}
if (first){
setFirst(false)
socket.emit("request lobbies")
}
useEffect(() => {
socket.on("request lobbies", (map) => {
console.log("wesh")
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")
}
return(
<div style={{display:'flex', flexDirection:'column', alignItems:'center'}}>
<h1>Bienvenue dans le lobby des lobbies</h1>
<input
type="text"
className='searchLobby'
placeholder="Rechercher un lobby..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
style={{width:'80%', margin:'10px'}}
/>
<div className="lobbyList">
{filteredLobbies.map((lobby, index) => (
<LobbyContainer
key={index}
roomNum={lobby.roomNum}
HeadPlayer={lobby.headPlayer}
nbPlayer={lobby.nbPlayer}
/>
))}
<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}
>
Tous
</button>
<button
style={{
width:'120px',
border:'solid',
borderStyle:'none',
borderRadius: '0px 15px 15px 0px',
padding: '10px 15px',
backgroundColor: showAvailable ? 'white' : 'lightgray',
}}
onClick={handleShowAvailableClick}
>
Disponible
</button>
</div>
{filteredLobbiesToShow.length === 0 ? (
<div style={{border:'solid 2px blue', borderRadius:'15px', boxShadow:'5px 5px 5px rgb(246, 246, 246)', padding:'20px', margin:'20px'}}>
<h3><b>Il n'y a aucun lobby disponible</b></h3>
<button onClick={createLobby} className='ButtonNav' style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}>Créé en un !</button>
</div>
) : (
<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>
);
}

@ -41,6 +41,13 @@
margin: 20px;
}
.NumbDiv{
display: flex;
align-items: start;
justify-content: start;
margin: auto 20px;
}
.codeDiv{
display: flex;
align-items: end;
@ -48,7 +55,7 @@
margin: auto 20px;
}
.codeDiv p{
.codeDiv p, .NumbDiv p{
font-style: italic;
font-weight: bold;
color: gray;

@ -45,15 +45,17 @@ import SessionService from '../services/SessionService';
import { useRef } from 'react';
import Button from 'react-bootstrap/Button';
import Overlay from 'react-bootstrap/Overlay';
import { DataSet } from 'vis-network';
let gameStarted = false
let firstLaunch = true
function Lobby() {
const theme=useTheme();
const navigate = useNavigate();
const { indices, setIndicesData, indice, setIndiceData, person, setPersonData, personNetwork, setPersonNetworkData, players, setPlayersData, setActualPlayerIndexData, setTurnPlayerIndexData, setRoomData } = useGame();
const { indices, setIndicesData, indice, setIndiceData, person, setPersonData, personNetwork, setPersonNetworkData, players, setPlayersData, setActualPlayerIndexData, setTurnPlayerIndexData, setRoomData, setNodesData } = useGame();
const {user, setUserData, manager, login} = useAuth()
let first = true
@ -130,25 +132,77 @@ function Lobby() {
setIndicesData(choosenIndices)
first = true
gameStarted = true
socket.off("player left")
socket.off("new player")
//socket.off("player left")
//socket.off("new player")
navigate('/game?solo=false&daily=false');
});
socket.on("join during game", (jsonNetwork, jsonPersonString, jsonIndicesString, playerIndex, players, nodes)=> {
const jsonPerson = JSON.parse(jsonPersonString)
const networkPerson: PersonNetwork = JSONParser.JSONToNetwork(jsonNetwork)
const choosenOne: Person = networkPerson.getPersons().filter((i) => i.getId() == jsonPerson.id)[0]
const choosenIndices : Indice[] = JSONParser.JSONToIndices(jsonIndicesString)
for (let i=0; i<players.length; i++){
const player = players[i]
if(player.id == socket.id){
setActualPlayerIndexData(i)
setIndiceData(choosenIndices[i])
}
if (player instanceof Bot){
player.indice = choosenIndices[i]
}
}
const tmpPlayers: Player[] = []
console.log(players)
for (const p of players){
tmpPlayers.push(JSONParser.JSONToPlayer(p))
}
setPlayersData(tmpPlayers)
if (room != null){
setRoomData(room)
}
const tab = JSONParser.JSONToNodePersons(JSON.parse(nodes))
setNodesData(tab)
setTurnPlayerIndexData(playerIndex)
setPersonData(choosenOne)
setPersonNetworkData(networkPerson)
setIndicesData(choosenIndices)
first = true
gameStarted = true
navigate('/game?solo=false&daily=false');
});
socket.on("new player", (tab) =>{
const tmpTab: Player[] = []
for (const p of tab){
for (const p of tab.tab){
tmpTab.push(JSONParser.JSONToPlayer(p))
}
console.log(tmpTab)
setPlayersData(tmpTab)
})
socket.on("room full", () => {
//TODO POP UP pour quand la room est pleine
navigate("/play")
})
socket.on("game started", () => {
//TODO POP UP pour quand la room est pleine
navigate("/play")
})
socket.on("game already started", () => {
//TODO POP UP pour quand la room est pleine
navigate("/play")
})
socket.on("player left", (tab, i) => {
const tmpTab: Player[] = []
for (const p of tab){
for (const p of tab.tab){
tmpTab.push(JSONParser.JSONToPlayer(p))
}
console.log(tmpTab)
setPlayersData(tmpTab)
})
@ -182,27 +236,50 @@ function Lobby() {
});
};
const textAreaRef = useRef<HTMLTextAreaElement>(null);
const linkToCopy = "http://localhost:3000/lobby?room="+ room
const handleCopyClick = () => {
setShow(!show)
if(textAreaRef.current != null){
textAreaRef.current.select();
document.execCommand('copy');
}
};
const [show, setShow] = useState(false);
const target = useRef(null);
return (
<div className='lobby-container'>
<div className='left-part'>
<div className='player-board'>
<div className='codeDiv' onClick={() => setCodeShowed(!codeShowed)}>
{
codeShowed ? (
<p>Room : {room}</p>
) : (
<p>Room : ******</p>
)
}
<div>
<div className='codeDiv' onClick={() => setCodeShowed(!codeShowed)}>
{
codeShowed ? (
<p>Room : {room}</p>
) : (
<p>Room : ******</p>
)
}
</div>
<div className='NumbDiv'>
{players.length == 6 ? (
<p style={{color:'darkred'}}>6/6 Players</p>
) : (
<p>{players.length}/6 Players</p>
)
}
</div>
</div>
{/* //! voir pour la gestion avec un liste, utilisateur avec le "+ (vous)" et les pdp avec les lettres grecs (?)*/}
{players.map((player, index) => (
// <PlayerItemList key={player.id} pdp={PersonImg} name={player.name} id={player.id}/>
<PlayerItemList key={player.id} player={player} room={room}/>
))}
<div className='centerButton'>
{(players.length < 6) && <div className='centerButton'>
<button className='button' onClick={addBot}
style={{
backgroundColor: theme.colors.primary,
@ -210,34 +287,13 @@ function Lobby() {
+
</button>
</div>
}
</div>
</div>
<div className="lobby-vertical-divider" style={{backgroundColor: theme.colors.secondary}}></div>
<div className='right-part'>
{/* <div className='title-param-div'>
<img src={param} alt="param"/>
<h2>Paramètre de la partie</h2>
</div>
<ul>
<li><h4> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim</h4></li>
<li><h4>paramètre super important pour la partie</h4></li>
<li><h4>paramètre super important pour la partie</h4></li>
<li><h4>paramètre super important pour la partie</h4></li>
<li><h4>Niveau des bots : Facile </h4></li>
<li><h4>Thèmes : basique </h4></li> */}
{
//? mettre un timer pour chaques personne ?
//? indice avancé ? ==> négation, voisin du 2e degré etc.
}
{/* </ul> */}
{/* <center >
<button className='buttonNabImg' onClick={StartGame}>
<img src={cible} alt="Button Image" height="50" width="50" />
<p>{"la chasse !"}</p>
</button>
</center> */}
<div className='lobbyR'
style={{flexDirection:'column',
alignItems:'space-around'}}>
@ -301,29 +357,6 @@ function Lobby() {
Démarrer la partie !
</button>
</div>
{/* <div className='centerDivH'>
<div>
<label htmlFor="numberInput">Séléctionner le nombre de noeud (entre 20 et 60) :</label>
<input
type="number"
id="numberInput"
value={enteredNumber}
onChange={handleNumberChange}
min={20}
max={60}/>
<p>La valeur saisie : {enteredNumber}</p>
</div>
<div className='centerDivH'>
<button className='button' onClick={StartGame}
style={{
backgroundColor: theme.colors.tertiary,
borderColor: theme.colors.secondary
}}>
<img src={cible} alt="cible" height="40"/>
</button>
</div> */}
</div>
</div>
);

@ -0,0 +1,306 @@
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';
let cptNavigation = 0
function NewPlay() {
let first = true
const theme=useTheme()
const {isLoggedIn, login, user, setUserData, manager } = useAuth();
const {setDailyEnigmeData} = useGame()
const target = useRef(null);
const navigationType = useNavigationType()
cptNavigation++
if (cptNavigation % 2 == 0){
if (navigationType.toString() == "POP"){
socket.emit("player quit")
}
}
useEffect(() => {
const fetchUserInformation = async () => {
try {
const sessionData = await SessionService.getSession();
// Vérifie si il y a une session
if (sessionData.user) {
// Il y a une session on récupère les infos du joueur
const updatedPlayer: User = new User(socket.id, sessionData.user.pseudo, sessionData.user.profilePicture, {
nbGames: sessionData.user.soloStats.nbGames,
bestScore: sessionData.user.soloStats.bestScore,
avgNbTry: sessionData.user.soloStats.avgNbTry,
},
{
nbGames: sessionData.user.onlineStats.nbGames,
nbWins: sessionData.user.onlineStats.nbWins,
ratio: sessionData.user.onlineStats.ratio,
})
login();
setUserData(updatedPlayer);
} else {
// Pas de session on génère un guest random
const guestPlayer: User = new User(socket.id, 'Guest_' + Math.floor(Math.random() * 1000000), '',
{
nbGames: 0,
bestScore: 0,
avgNbTry: 0,
},
{
nbGames: 0,
nbWins: 0,
ratio: 0,
})
setUserData(guestPlayer);
}
} catch (error) {
console.error(error);
}
};
fetchUserInformation();
}, [isLoggedIn]);
const { setIndicesData, setPersonData, setPersonNetworkData } = useGame();
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(3, 30)
setPersonData(choosenPerson)
setPersonNetworkData(networkPerson)
setIndicesData(choosenIndices)
setIndicesData(choosenIndices)
navigate('/game?solo=true&daily=false');
}
function launchEngimeJour(){
//* overlay
if (!showOverlay)setShowOverlay(true)
else setShowOverlay(true)
}
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(nouvelleURL);
}
}, [room, navigate]);
const goBack = () => {
navigate("/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(3, 30)
setPersonData(choosenPerson)
setPersonNetworkData(networkPerson)
setIndicesData(choosenIndices)
setIndicesData(choosenIndices)
navigate('/game?solo=true&daily=true&easy=true');
setShowOverlay(false);
};
const handleStartHardGame = () => {
//* Mode difficile
//todo différencier les deux
const [networkPerson, choosenPerson, choosenIndices] = GameCreator.CreateGame(3, 30)
setPersonData(choosenPerson)
setPersonNetworkData(networkPerson)
setIndicesData(choosenIndices)
setIndicesData(choosenIndices)
if (first){
first = false
const map = EnigmeDuJourCreator.createEnigme(networkPerson, choosenIndices, choosenPerson, Stub.GenerateIndice())
setDailyEnigmeData(map)
}
navigate('/game?solo=true&daily=true&easy=false');
setShowOverlay(false);
};
// if (goBackRoom != -1){
// var returnVisibility = "visible"
// }
// else{
// var returnVisibility = "hidden"
// }
// const returnVisibility: Visibility = goBackRoom !== -1 ? "visible" : "hidden";
const returnVisibility: any= goBackRoom !== -1 ? "visible" : "hidden" ;
return (
<div className="MainContainer">
<div className="NewleftContainer">
{/* Menu de boutons */}
<div className='NewbuttonGroupVertical'>
<button onClick={launchMastermind} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Jouer seul </button>
<button ref={target} onClick={launchEngimeJour} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Résoudre une énigme</button>
<Overlay show={showOverlay} target={target.current} placement="bottom" rootClose={true} rootCloseEvent='click'>
{({ 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}>Facile</Button>
<Button onClick={handleStartHardGame}>Difficile</Button>
</ButtonGroup>
</div>
)}
</Overlay>
<button onClick={createLobby} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Créer une partie </button>
<button onClick= {() => navigate("/join")} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Rejoindre </button>
{/* {goBackRoom != -1 && <button onClick={goBack} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}>Retourner à la partie</button>} */}
<button onClick={goBack} className="ButtonNavRejoin" style={{ visibility:returnVisibility}}>Retourner à la partie</button>
</div>
{/* Lobbies */}
<div style={{border:'solid 1px lightgray', borderRadius:'15px', marginTop:'20px'}}>
<Lobbies/>
</div>
</div>
<div className='NewrightContainer'>
<div style={{ border:'solid 2px lightgray', borderRadius:'15px', display:'flex', justifyContent:'center', alignItems:'center', flexDirection:'column', padding:'20px', margin:'20px 0px'}}>
<h2>
{user && user.pseudo}
</h2>
<img src={user?.profilePicture}
height='150'
width='150'
alt="Person"
/>
</div>
{user && (<ScoreBoard Player={user}/>)}
</div>
</div>
);
}
export default NewPlay;

@ -20,12 +20,6 @@
display: flex;
justify-content: center;
}
/*
.MidContainer div {
display: flex;
justify-content: center;
flex-direction: column;
} */
.leftContainer{
width: 30%;
@ -35,7 +29,18 @@
width: 30%;
}
.NewleftContainer{
margin: 20px 30px;
width: 70%;
}
.NewrightContainer{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 30%;
}
/* .textBoard div{
display: flex;
@ -56,8 +61,15 @@
flex-direction: column;
}
.NewbuttonGroupVertical{
display: flex;
justify-content:space-around;
align-items:start;
}
.ButtonNav{
margin: 15px 0;
margin: 15px 10px;
width:200px;
height: 8vh;
@ -70,4 +82,41 @@
border-width: 2px;
font-size:larger;
}
.ButtonNavRejoin{
margin: 15px 10px;
width:200px;
height: 8vh;
color: white;
background-color: aquamarine;
border: solid 2px rgb(40, 225, 163);
border-radius: 15px;
font-size:larger;
}
.returnDiv{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin:40px 15px;
border: solid 2px whitesmoke;
border-radius: 15px;
background-color: white;
}
.returnDiv p {
margin: 15px;
padding: 10px;
border: solid 1px whitesmoke;
border-radius: 10px;
font-weight:500;
}

@ -2,7 +2,6 @@ import React, { useEffect, useRef, useState } from 'react';
/* Context */
import { useAuth } from '../Contexts/AuthContext';
/* Style */
import './Play.css';
import { useTheme } from '../Style/ThemeContext';
@ -13,7 +12,7 @@ import ButtonImgNav from "../Components/ButtonImgNav";
/* Img */
/* Icon */
import { socket } from '../SocketConfig';
import { useNavigate } from 'react-router-dom';
import { NavigationType, useNavigate, useNavigationType } from 'react-router-dom';
import GameCreator from '../model/GameCreator';
import { useGame } from '../Contexts/GameContext';
import ScoreBoard from '../Components/ScoreBoard';
@ -29,6 +28,9 @@ import { loadImageAsync } from '../ImageHelper';
import { Overlay, ToggleButton, ToggleButtonGroup } from 'react-bootstrap';
import Button from 'react-bootstrap/Button';
import ButtonGroup from 'react-bootstrap/ButtonGroup';
import Info from '../res/icon/infoGreen.png';
let cptNavigation = 0
function Play() {
@ -39,6 +41,16 @@ function Play() {
const {setDailyEnigmeData, setIndicesData, setPersonData, setPersonNetworkData } = useGame()
const target = useRef(null);
const navigationType = useNavigationType()
cptNavigation++
if (cptNavigation % 2 == 0){
if (navigationType.toString() == "POP"){
socket.emit("player quit")
}
}
useEffect(() => {
if (user == null){
manager.userService.fetchUserInformation().then(([user, loggedIn]) =>{
@ -48,6 +60,7 @@ function Play() {
if (loggedIn){
login()
setUserData(user)
socket.emit("join back game", user)
}
else{
loadImageAsync(defaultImg).then((blob) => {
@ -58,8 +71,20 @@ function Play() {
}
})
}
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();
@ -67,10 +92,6 @@ function Play() {
socket.emit("lobby created")
}
useEffect(() => {
console.log(user)
}, [user])
function launchMastermind(){
const [networkPerson, choosenPerson, choosenIndices] = GameCreator.CreateGame(3, 30)
setPersonData(choosenPerson)
@ -112,6 +133,10 @@ function Play() {
}
}, [room, navigate]);
const goBack = () => {
navigate("/lobby?room=" + goBackRoom)
}
const [showOverlay, setShowOverlay] = useState(false);
@ -159,10 +184,22 @@ function Play() {
<div className="MainContainer">
<div className="leftContainer">
{/* <button className='ButtonNav'>
Param
</button> */}
{/* <ButtonImgNav dest='/signup' img={defaultImg} text="Gestion du compte"/> */}
{goBackRoom != -1 &&
<div className='returnDiv'>
<div style={{
display:'flex',
alignItems:'center'
}}>
<img src={Info} alt='info' height='50px' width='50px'/>
<h1>Information</h1>
</div>
<p> Il semblerait que vous avez quitté une partie en cours... <br/> <i>Et si nous y retournions ?</i></p>
<button onClick={goBack} className="ButtonNav"
style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}>
Retourner à la partie
</button>
</div>
}
</div>
<div className="MidContainer">
<div>
@ -202,7 +239,6 @@ function Play() {
<button onClick={createLobby} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Créer une partie </button>
<button onClick= {() => navigate("/join")} className="ButtonNav" style={{backgroundColor: theme.colors.primary, borderColor: theme.colors.secondary}}> Rejoindre </button>
</div>
</div>
<div className='rightContainer'>

@ -46,6 +46,9 @@
border-radius: 15px;
}
.pseudoDisplay{
margin: 0px !important;
}
.username-display{
display: flex;

@ -2,10 +2,10 @@ import React, { useEffect, useState } from 'react';
import ProfilePDP from '../Components/ProfilePDP';
import SessionService from '../services/SessionService';
import AuthService from '../services/AuthService';
import { PlayerProps } from '../types/Player';
import { delay, update } from 'lodash';
import { delay, set, update } from 'lodash';
import { socket } from '../SocketConfig';
import AuthService from '../services/AuthService';
/* Style */
@ -14,6 +14,9 @@ import Edit from "../res/icon/edit-pen.png"
import Coche from '../res/icon/coche.png'
import Cancel from '../res/icon/cancel.png'
/* Nav */
import { useNavigate } from 'react-router-dom';
/* Model */
import User from '../model/User';
@ -25,7 +28,8 @@ import Button from 'react-bootstrap/Button';
import Alert from 'react-bootstrap/Alert';
import Modal from 'react-bootstrap/Modal';
import Form from 'react-bootstrap/Form';
import { useNavigate } from 'react-router-dom';
import ProgressBar from 'react-bootstrap/ProgressBar';
//@ts-ignore
const Profile = () => {
@ -33,11 +37,6 @@ const Profile = () => {
const navigate = useNavigate();
//let player;
const {user, logout} = useAuth()
// let pseudoNotNull;
// if(user?.pseudo != null){
// pseudoNotNull = user.pseudo;
// }
const [editingUsername, setEditingUsername] = useState(false);
const [newUsername, setNewUsername] = useState(user?.pseudo);
@ -57,7 +56,101 @@ const Profile = () => {
// Désactiver le mode d'édition
setEditingUsername(false);
};
//* Gestion de la modification du mot de passe :
// Modal de modification du mot de passe
const [showPasswordModal, setShowPasswordModal] = useState(false);
const [showWrongPassword, setShowWrongPassword] = useState(false);
const [showCorrectPassword, setShowCorrectPassword] = useState(false);
// Etat du mot de passe
const [oldPassword, setOldPassword] = useState('');
const [newPassword, setNewPassword] = useState('');
// Etat de l'étape
const [step, setStep] = useState(1);
const [DisableNextStep, setDisableNextStep] = useState(true);
// Etat du nouveau mot de passe
const [confirmNewPassword, setConfirmNewPassword] = useState('');
const [ percent, setpercent] = useState(0);
const handleShowPasswordModal = () => {
setShowPasswordModal(true);
};
const handleClosePasswordModal = () => {
setShowPasswordModal(false);
};
//* Vérification de l'ancien mot de passe :
const handleConfirmedAuth = () => {
// Vérification de l'ancien mot de passe
// if (oldPassword === user?.password) {
if (oldPassword === 'coucou') { //! pour l'instant c'est 'coucou', mais il faudra mettre le vrai mdp.
console.log('Ancien mot de passe correct.');
setShowWrongPassword(false);
setShowCorrectPassword(true);
setDisableNextStep(false);
setpercent(25);
}
else{
console.log('Ancien mot de passe incorrect.');
setShowWrongPassword(true);
setShowCorrectPassword(false);
setDisableNextStep(true);
}
}
const handleChangeStep = () => {
setShowWrongPassword(false);
setShowCorrectPassword(false);
setpercent(50);
setStep(2)
}
//* Modification du mot de passe :
const handlePasswordChange = () => {
//Effectuer la modification du mot de passe
// sinon, affichez une erreur
if (newPassword === confirmNewPassword) {
// SessionService.UpdatePassword(user?.pseudo, newPassword);
// user.password = newPassword;
console.log('Changement de mot de passe');
setpercent(100);
setTimeout(async () => {
setShowPasswordModal(false);
}, 3000);
} else {
//les mots de passe ne correspondent pas
console.error("Les mots de passe ne correspondent pas.");
setShowWrongPassword(true);
setTimeout(async () => {
setShowWrongPassword(false);
}, 1500);
}
};
//@ts-ignore
const handleOldPasswordChange = (e) => {
setOldPassword(e.target.value);
setpercent(13);
};
//@ts-ignore
const handleNewPasswordChange = (e) => {
setpercent(63);
setNewPassword(e.target.value);
};
//@ts-ignore
const handleConfirmNewPasswordChange = (e) => {
setConfirmNewPassword(e.target.value);
setpercent(75);
};
//* Gestion Modal de suppression :
const [showDeleteModal, setShowDeleteModal] = useState(false);
@ -84,7 +177,6 @@ const Profile = () => {
// Verification de la phrase
if (confirmationPhrase.toLowerCase() === 'supprimer mon compte') {
console.log('Compte supprimé !');
console.log(user);
if(user!= null){
const pseudo = user.pseudo;
@ -107,7 +199,6 @@ const Profile = () => {
}, 3000);
}
};
return (
<>
@ -134,7 +225,7 @@ const Profile = () => {
</div>
) : (
<div className='username-display'>
<h1>{user?.pseudo}</h1>
<h1 className='pseudoDisplay'>{user?.pseudo}</h1>
<button className='editbutton' onClick={() => setEditingUsername(true)}>
<img src={Edit} alt='edit' width='25' height='25'/>
</button>
@ -143,16 +234,95 @@ const Profile = () => {
}
<hr/>
{!editingUsername ? (
<Button variant="secondary">Modifier le mot de passe</Button>
<Button variant="secondary" onClick={() => setShowPasswordModal(true)}>Modifier le mot de passe</Button>
) : (
<Alert key='info' variant='info' style={{width:'100%'}}>
Vous êtes en mode "édition".
</Alert>
)}
{/* Modal de modification de mdp */}
<Modal show={showPasswordModal} onHide={handleClosePasswordModal}>
<Modal.Header closeButton>
<Modal.Title>{`Étape ${step}`}</Modal.Title>
{/* <ProgressBar animated now={50*step} /> */}
</Modal.Header>
<Modal.Body>
<ProgressBar animated now={percent} />
{step === 1 && (
<>
<p>Entrez votre ancien mot de passe :</p>
<Form.Control
type="password"
placeholder="Ancien mot de passe"
value={oldPassword}
onChange={handleOldPasswordChange}
/>
<Button variant="primary" style={{margin:'15px'}} onClick={handleConfirmedAuth}>
Confirmer
</Button>
</>
)}
{step === 2 && (
<>
<p>Entrez votre nouveau mot de passe :</p>
<Form.Control
type="password"
placeholder="Nouveau mot de passe"
value={newPassword}
onChange={handleNewPasswordChange}
/>
<br/>
<p>Confirmez votre nouveau mot de passe :</p>
<Form.Control
type="password"
placeholder="Confirmez le nouveau mot de passe"
value={confirmNewPassword}
onChange={handleConfirmNewPasswordChange}
/>
</>
)}
{showWrongPassword && (
<Alert variant="danger" style={{ width: '100%' }}>
Ancien mot de passe incorrect.
</Alert>
)}
{showCorrectPassword && (
<Alert variant="success" style={{ width: '100%' }}>
Ancien mot de passe correct.
</Alert>
)}
</Modal.Body>
<Modal.Footer>
{step === 1 && (
<Button variant="secondary" onClick={handleClosePasswordModal}>
Annuler
</Button>
)}
{step === 2 ? (
<Button variant="primary" onClick={handlePasswordChange}>
Modifier le mot de passe
</Button>
) : (
<Button variant="primary" onClick={handleChangeStep} disabled={DisableNextStep}>
Étape suivante
</Button>
)}
</Modal.Footer>
</Modal>
<div className='bottom'>
<>
{!editingUsername && (
<Button variant="danger" onClick={handleShowDeleteModal}>Supprimer</Button>
) }
{/* Modal de suppression */}
<Modal show={showDeleteModal} onHide={handleCloseDeleteModal}>
<Modal.Header closeButton>
<Modal.Title>Confirmation de suppression</Modal.Title>

@ -1,107 +0,0 @@
.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;
}

@ -1,236 +0,0 @@
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;

@ -98,6 +98,9 @@ class EasyBot extends Bot{
tabFilterPerson.push(p)
}
})
if (tabFilterPerson.length == 0){
return -1
}
return tabFilterPerson[Math.floor(Math.random() * tabFilterPerson.length)].getId()
}

@ -107,6 +107,38 @@ class AuthService{
throw error;
}
}
static async UpdateMDP(pseudo : string, newmdp : string) {
console.log("pseudo : " + pseudo + " mdp : " + newmdp)
// try {
// const response = await fetch(ADRESSE_DBSERVER + '/session/updateMDP', {
// method: 'PUT',
// headers: {
// 'Content-Type': 'application/json',
// },
// body: JSON.stringify({
// pseudo,
// newmdp
// }),
// credentials: 'include',
// });
// if (response.ok) {
// const result = await response.json();
// return result;
// } else {
// const errorResponse = await response.json();
// throw new Error(errorResponse.error);
// }
// } catch (error) {
// console.error(error);
// throw error;
// }
console.log("UpdateMDP in authserice")
}
}
export default AuthService;

@ -165,6 +165,7 @@ class SessionService {
throw error;
}
}
}
export default SessionService;

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save